virtual_scroller 0.0.2

  • README.md
  • CHANGELOG.md
  • Example
  • Installing
  • Versions
  • new71

virtual_scroller

A Dart implementation of virtual-scroller by Valdrin Koshi (@valdrinkoshi)

Usage - Vanilla Dart

  • Vanilla Dart see /example (run pub run build_runner serve example:8080)
  • AngularDart see here

ResizeObserver

It is recommended to use a polyfill for ResizeObserver due to browser incompatability

1.0.0

  • Initial version, created by Stagehand

example/main.dart

import 'dart:async';
import 'dart:convert';
import 'dart:html';

import 'package:virtual_scroller/layout.dart';
import 'package:virtual_scroller/virtual_scroller.dart';
import 'package:http/http.dart' as http;

class Sample {
  List<dynamic> items;
  Layout layout;
  Element container;
  VirtualScroller scroller;
  List<Element> headerPool = [];
  List<Element> contactPool = [];

  Sample() {
    items = [];
    layout = Layout();
    container = document.body;

    document.body.style.margin = '0';
    document.body.style.minHeight = '1000000px';
    _setUp();
  }

  void _setUp() {
    scroller = new VirtualScroller(
      layout: this.layout,
      container: this.container,
      createElement: (idx) {
        var item = items[idx];
        var type = item.runtimeType;
        if (type == Contact && contactPool.isNotEmpty) {
          return contactPool.removeLast();
        }
        if (type == Header && headerPool.isNotEmpty) {
          return headerPool.removeLast();
        }
        if (type == Contact) {
          var card = document.createElement('div');
          card.style
            ..setProperty('padding', '10px')
            ..setProperty('border-bottom', '1px solid #CCC')
            ..setProperty('width', '100%')
            ..setProperty('box-sizing', 'border-box');
          var name = document.createElement('b');
          var text = document.createElement('p');
          text.contentEditable = 'true';
          text.addEventListener(
              'focus', (e) => _scrollToFocused(target: (e as FocusEvent).target as Element));
          text.addEventListener(
              'blur',
              (e) => _commitChange(
                  int.parse(card.attributes['_idx']), (e.target as Element).text));
          card.append(name);
          card.append(text);
          return card;
        } else {
          var header = document.createElement('div');
          header.style
            ..color = 'white'
            ..background = '#2222DD'
            ..padding = '10px'
            ..borderBottom = '1px solid #CCC'
            ..width = '100%'
            ..boxSizing = 'border-box';
          return header;
        }
      },
      updateElement: (child, idx) {
        var item = items[idx];
        if (item.runtimeType == Contact) {
          var item = this.items[idx];
          child.setAttribute('_idx', idx.toString());
          var b = child.querySelector('b');
          var p = child.querySelector('p');
          if (b == null || p == null) {
            print("updating $child for contact without p or p elements");
            return;
          }
          b.text = '${item.index} - ${item.first} ${item.last}';
          p.text = item.longText;
        } else {
          child.text = (item as Header).title;
        }
      },
      recycleElement: (child, idx) {
        var item = items[idx];
        if (item.runtimeType == Contact) {
          child.setAttribute('_idx', (-1).toString());
          var b = child.querySelector('b');
          var p = child.querySelector('p');
          if (b == null || p == null) {
            print("recycling $child for contact without p or p elements");
            return;
          }
          child.querySelector('b').text = '';
          child.querySelector('p').text = '';
          this.contactPool.add(child);
        } else {
          this.headerPool.add(child);
        }
      },
    );
  }

  void render() {
    scroller.totalItems = items.length;
  }

  Future load(String url) async {
    var response = await http.get(url);
    var body = response.body;
    var data = json.decode(body) as List;
    var contacts = data.map((d) => Contact.fromJson(d));
    var sorted = contacts.toList()..sort((a, b) => a.last.compareTo(b.last));
    List result = [];

    // add headers
    String prev;
    for (var item in sorted) {
      var cur = item.last.substring(0, 1);
      if (prev != cur) {
        result.add(Header(title: cur));
      }
      result.add(item);
      prev = cur;
    }

    items = result;
    render();
  }

  _scrollToFocused({Element target}) {
    new Future(() {
      target.parent.scrollIntoView();
    });
  }

  _commitChange(int idx, newVal) {
    if (idx == -1) return;
    var prevVal = this.items[idx];
    if (newVal != prevVal) {
      (this.items[idx] as Contact).longText = newVal;
      print("changing value to $newVal");
      // HACK(valdrin) Ideally we'd only do this.scroller.requestReset(),
      // but since lit-repeater & preact-repeater don't give access to that
      // method, we force reset by altering the items length.
      this.items.length++;
      this.render();
      this.items.length--;
      this.render();
    }
  }
}

void main() {
  var sample = new Sample();
  sample.load('./contacts.json');
}

class Contact {
  int index;
  String first;
  String last;
  String longText;

  Contact();

  factory Contact.fromJson(Map<String, dynamic> json) {
    return Contact()
      ..index = json['index']
      ..first = json['first']
      ..last = json['last']
      ..longText = json['longText'];
  }
}

class Header {
  String title;
  Header({this.title});
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  virtual_scroller: ^0.0.2

2. Install it

You can install packages from the command line:

with pub:


$ pub get

Alternatively, your editor might support pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:virtual_scroller/virtual_scroller.dart';
  
Version Uploaded Documentation Archive
0.0.2 Dec 6, 2018 Go to the documentation of virtual_scroller 0.0.2 Download virtual_scroller 0.0.2 archive
0.0.1+3 Nov 26, 2018 Go to the documentation of virtual_scroller 0.0.1+3 Download virtual_scroller 0.0.1+3 archive
0.0.1+2 Nov 20, 2018 Go to the documentation of virtual_scroller 0.0.1+2 Download virtual_scroller 0.0.1+2 archive
0.0.1+1 Nov 15, 2018 Go to the documentation of virtual_scroller 0.0.1+1 Download virtual_scroller 0.0.1+1 archive
0.0.1 Nov 15, 2018 Go to the documentation of virtual_scroller 0.0.1 Download virtual_scroller 0.0.1 archive
Popularity:
Describes how popular the package is relative to other packages. [more]
52
Health:
Code health derived from static analysis. [more]
89
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
90
Overall:
Weighted score of the above. [more]
71
Learn more about scoring.

We analyzed this package on Dec 6, 2018, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.1.0
  • pana: 0.12.7

Platforms

Detected platforms: web

Primary library: package:virtual_scroller/virtual_scroller.dart with components: html, js.

Health issues and suggestions

Document public APIs (-9.91 points)

110 out of 111 API elements (library, class, field or method) have no adequate dartdoc content. Good documentation improves code readability and discoverability through search.

Fix lib/virtual_scroller.dart. (-1.49 points)

Analysis of lib/virtual_scroller.dart reported 3 hints:

line 267 col 18: Unnecessary cast.

line 271 col 28: Unnecessary cast.

line 274 col 26: Unnecessary cast.

Maintenance suggestions

Package is pre-v0.1 release. (-10 points)

While there is nothing inherently wrong with versions of 0.0.*, it usually means that the author is still experimenting with the general direction of the API.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0 <3.0.0
js ^0.6.1 0.6.1+1
meta ^1.1.6 1.1.6
Dev dependencies
build_runner ^0.10.0
build_web_compilers ^0.4.0
http ^0.12.0