Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Simplify the rendering/calculations. Remove the manager and make the …

…constructor public
  • Loading branch information...
commit fe8699b0e0540f665325a9ecbd5a17fda9a146c8 1 parent f2f87e7
@turnertime authored
View
7 examples/horizontal.html
@@ -9,8 +9,9 @@
* { -moz-box-sizing:border-box; -webkit-box-sizing:border-box; box-sizing:border-box; }
html, body { font-family:Arial,sans-serif; color:#333; margin:0; padding:0; }
.virtualist { position:absolute; top:4px; left:4px; bottom:4px; right:4px; overflow:auto; }
- .virtualist .viewport { height:2px; }
- .virtualist .item { color:#fff; background:#1ba557; width:24px; padding:0 5px 0 5px; word-wrap:break-word; text-align:center; }
+ .virtualist-canvas { position:absolute; height:2px; }
+ .virtualist-page { position:absolute; }
+ .virtualist-item { position:absolute; color:#fff; background:#1ba557; width:24px; padding:0 5px 0 5px; word-wrap:break-word; text-align:center; }
</style>
</head>
<body>
@@ -20,7 +21,7 @@
<script type="text/javascript" src="../virtualist.js"></script>
<script type="text/javascript">
(function () {
- window.virtualist.init({ el: "container", size: 25, length: 1000, render: function render(i) { return i; }, isHorizontal: true });
+ new Virtualist.init({ el: document.getElementById("container"), size: 25, length: 1000, render: function render(i) { return i; }, isHorizontal: true });
}());
</script>
</body>
View
10 examples/vertical.html
@@ -6,10 +6,12 @@
<title>vertical - examples - virtualist</title>
<link href="../favicon.ico" rel="icon" type="image/x-icon" />
<style>
- * { -moz-box-sizing:border-box; -webkit-box-sizing:border-box; box-sizing:border-box; }
- html, body { font-family:Arial,sans-serif; color:#333; margin:0; padding:0; }
+ html, body { font-family:sans-serif; margin:0; padding:0; }
.virtualist { position:absolute; top:4px; left:4px; bottom:4px; right:4px; overflow:auto; }
- .virtualist .item { color:#fff; background:#1ba557; height:24px; line-height:24px; padding:0 5px 0 5px; }
+
+ .virtualist-canvas { overflow:hidden; background:pink; }
+ .virtualist-item { position:absolute; color:#fff; background:#1ba557; height:24px; line-height:24px; padding:0 5px 0 5px; margin:0; }
+
</style>
</head>
<body>
@@ -19,7 +21,7 @@
<script type="text/javascript" src="../virtualist.js"></script>
<script type="text/javascript">
(function () {
- window.virtualist.init({ el: "container", size: 25, length: 1000, render: function render(i) { return i; } });
+ new Virtualist({ el: document.getElementById("container"), size: 25, length: 1000, maxCanvasSize: 12500, render: function render(i) { return i; } });
}());
</script>
</body>
View
2  tests/index.html
@@ -8,7 +8,7 @@
<link href="../favicon.ico" rel="icon" type="image/x-icon" />
<link type="text/css" rel="Stylesheet" media="all" href="http://code.jquery.com/qunit/qunit-git.css" />
<style>
- #test { position:absolute; bottom:0; right:0; width:250px; height:250px; }
+ #container { position:absolute; bottom:0; right:0; width:250px; height:250px; }
</style>
</head>
<body>
View
24 tests/virtualist.tests.js
@@ -1,6 +1,6 @@
-/*global document: false, screen: false, QUnit: false, virtualist: false */
+/*global document: false, screen: false, QUnit: false, Virtualist: false */
-(function scriptInitKeysTests(document, screen, qunit, virtualist) {
+(function scriptInitKeysTests(document, screen, qunit, Virtualist) {
"use strict";
qunit.module("virtualist");
@@ -15,20 +15,20 @@
// Test error cases.
qunit.raises(
- function init() { virtualist.init(); },
+ function init() { list = new Virtualist(); },
"settings must be defined",
"empty constructor should fail"
);
qunit.raises(
- function init() { virtualist.init({ el: null }); },
+ function init() { list = new Virtualist({ el: null }); },
"el must be an HTMLElement",
"null el should fail"
);
qunit.raises(
function init() {
- virtualist.init({ el: container, length: null });
+ list = new Virtualist({ el: container, length: null });
},
"length must be number",
"null settings.length should fail"
@@ -36,7 +36,7 @@
qunit.raises(
function init() {
- virtualist.init({ el: container, length: 1, render: null });
+ list = new Virtualist({ el: container, length: 1, render: null });
},
"render must be function",
"null settings.render should fail"
@@ -44,7 +44,7 @@
qunit.raises(
function init() {
- virtualist.init({ el: container, length: 1, render: noop, size: null });
+ list = new Virtualist({ el: container, length: 1, render: noop, size: null });
},
"size must be number",
"null settings.size should fail"
@@ -53,7 +53,7 @@
// Test valid cases.
// defaults and valid values
- list = virtualist.init({ el: container, length: 1, render: noop, size: 1 });
+ list = new Virtualist({ el: container, length: 1, render: noop, size: 1 });
qunit.strictEqual(list.config.bufferSize, 1, "bufferSize should be initialized to 1");
qunit.strictEqual(list.config.el, container, "container should be initialized to container");
qunit.strictEqual(list.config.explicitSize, screen.availHeight, "container should be initialized to screen.availHeight");
@@ -64,7 +64,7 @@
qunit.strictEqual(list.config.size, 1, "size should be initialized to 1");
// negative numbers
- list = virtualist.init({ bufferSize: -1, explicitSize: -1, el: container, length: -1, maxCanvasSize: -1, render: noop, size: -1 });
+ list = new Virtualist({ bufferSize: -1, explicitSize: -1, el: container, length: -1, maxCanvasSize: -1, render: noop, size: -1 });
qunit.strictEqual(list.config.bufferSize, 1, "bufferSize should be initialized to 1");
qunit.strictEqual(list.config.explicitSize, 1, "explicitSize should be initialized to 1");
qunit.strictEqual(list.config.length, 0, "length should be initialized to 0");
@@ -72,7 +72,7 @@
qunit.strictEqual(list.config.size, 1, "size should be initialized to 1");
// decimal numbers
- list = virtualist.init({ bufferSize: 1.2, explicitSize: 1.5, el: container, length: 1.6, maxCanvasSize: 1.8, render: noop, size: 1.3 });
+ list = new Virtualist({ bufferSize: 1.2, explicitSize: 1.5, el: container, length: 1.6, maxCanvasSize: 1.8, render: noop, size: 1.3 });
qunit.strictEqual(list.config.bufferSize, 2, "bufferSize should be initialized to 2");
qunit.strictEqual(list.config.explicitSize, 2, "explicitSize should be initialized to 2");
qunit.strictEqual(list.config.length, 2, "length should be initialized to 2");
@@ -80,11 +80,11 @@
qunit.strictEqual(list.config.size, 2, "size should be initialized to 2");
// isHorizontal
- list = virtualist.init({ el: container, isHorizontal: true, length: 1, render: noop, size: 1 });
+ list = new Virtualist({ el: container, isHorizontal: true, length: 1, render: noop, size: 1 });
qunit.ok(list.config.isHorizontal, "isHorizontal should be initialized to true");
qunit.strictEqual(list.config.explicitSize, screen.availWidth, "container should be initialized to screen.availWidth");
});
-}(document, screen, QUnit, virtualist)); // end of (function () {
+}(document, screen, QUnit, Virtualist)); // end of (function () {
View
134 virtualist.js
@@ -1,6 +1,6 @@
-/*global HTMLElement: false, screen: false, window: false */
+/*global document: false, HTMLElement: false, screen: false, window: false */
-window.virtualist = window.virtualist || (function (HTMLElement, screen) { // execute immediately on script load (not waiting for DOM), prevent multiple initializations, introduce scope container
+window.Virtualist = window.Virtualist || (function (document, HTMLElement, screen) { // execute immediately on script load (not waiting for DOM), prevent multiple initializations, introduce scope container
"use strict";
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -8,15 +8,73 @@ window.virtualist = window.virtualist || (function (HTMLElement, screen) { // ex
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------
+ function buildAddEvent() {
+ return typeof document.addEventListener === "function"
+ ? function add(el, eventName, handler) {
+ return el.addEventListener(eventName, handler, false);
+ }
+ : function add(el, eventName, handler) {
+ return el.attachEvent("on".concat(eventName), handler);
+ };
+ }
+
+
+ //-------------------------------------------
+ function render(config, scrollPosition) {
+ var html = "", i, length;
+
+ if (scrollPosition < config.calculated.low) {
+ // scrolling up
+ i = Math.max(0, Math.ceil((scrollPosition + config.explicitSize) / config.size) - config.calculated.itemLength);
+
+ } else if (scrollPosition > config.calculated.high) {
+ // scrolling down
+ i = Math.min(config.calculated.maxItemIndex, Math.floor(scrollPosition / config.size));
+
+ } else {
+ // list is still valid (do nothing)
+ return;
+ }
+
+ // Determine the boundaries to trigger invalidating
+ config.calculated.low = (i * config.size);
+ config.calculated.high = config.calculated.low + config.calculated.itemSize - config.explicitSize;
+
+ // Loop through and render items
+ for (length = Math.min(i + config.calculated.itemLength, config.length); i < length; i += 1) {
+ html = html.concat("<p class=\"virtualist-item\" style=\"")
+ .concat(config.calculated.edge)
+ .concat(config.size * i)
+ .concat("px\">")
+ .concat(config.render(i))
+ .concat("</p>");
+ }
+
+ return html;
+ }
+
+
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // Public
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+ //-------------------------------------------
function Virtualist(settings) {
+ //-------------------------------------------
+ // Validate and parse parameters
+
if (!settings) { throw new Error("settings must be defined"); }
if (typeof settings.el instanceof HTMLElement) { throw new Error("el must be an HTMLElement"); }
if (typeof settings.length !== "number") { throw new Error("length must be a number"); }
if (typeof settings.render !== "function") { throw new Error("render must be a function"); }
if (typeof settings.size !== "number") { throw new Error("size must be a number"); }
- this.config = {
+ var config = {
+
+ // adds a new event handler to the dom element specified
+ addEvent: buildAddEvent(),
// the number of pages in buffer (default: 1)
bufferSize: (typeof settings.bufferSize === "number") ? Math.ceil(Math.max(1, settings.bufferSize)) : 1,
@@ -24,7 +82,7 @@ window.virtualist = window.virtualist || (function (HTMLElement, screen) { // ex
// the HTMLElement with the virtualist instance
el: settings.el,
- // the size of the viewport (default: screen.avail[Height|Width]
+ // the size of the viewport (default: screen.avail[Height|Width])
explicitSize: (typeof settings.explicitSize === "number") ? Math.ceil(Math.max(1, settings.explicitSize)) : (settings.isHorizontal ? screen.availWidth : screen.availHeight),
// specifies whether the list is virtualized horizontally or vertically
@@ -47,23 +105,67 @@ window.virtualist = window.virtualist || (function (HTMLElement, screen) { // ex
};
- }
+ //-------------------------------------------
+ // Calculate configured parameter
+ config.calculated = {
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // Public (TODO) maybe this is not need and make virtualist constructor public.
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // Specifies the edge to position list items to
+ edge: config.isHorizontal ? "left:" : "top:",
- //-------------------------------------------
- function VirtualistManager() { }
+ // the size of the rendered items
+ itemSize: Math.ceil((config.bufferSize + 1) * config.explicitSize),
+ // the lower boundary position to invalidate
+ low: -1,
+
+ // the upper boundary position to invalidate
+ high: -1
+
+ };
+
+ // the number of items to render
+ config.calculated.itemLength = Math.ceil(config.calculated.itemSize / config.size);
+
+ // the maximum index to render
+ config.calculated.maxItemIndex = (config.length - config.calculated.itemLength);
+
+
+
+ //-------------------------------------------
+ // Add scroll handling
+
+ config.scrollHandler = config.isHorizontal
+ ? function horizontalScroll(e) {
+ var html = render(config, e.target.scrollLeft);
+ if (html) { config.calculated.canvas.innerHTML = html; }
+ }
+ : function verticalScroll(e) {
+ var html = render(config, e.target.scrollTop);
+ if (html) { config.calculated.canvas.innerHTML = html; }
+ };
+ config.addEvent(config.el, "scroll", config.scrollHandler);
+
+
+
+
+ //-------------------------------------------
+ // Initialize canvas
+
+ config.el.innerHTML = "<div class=\"virtualist-canvas\" style=\""
+ .concat(config.isHorizontal ? "width:" : "height:")
+ .concat(Math.min(config.maxCanvasSize, Math.ceil(config.size * config.length)))
+ .concat("px\">")
+ .concat(render(config, 0))
+ .concat("</div>");
+ config.calculated.canvas = config.el.firstChild;
+
+ this.config = config;
+
+ }
- //-------------------------------------------
- VirtualistManager.prototype.init = function init(settings) {
- return new Virtualist(settings);
- };
- return new VirtualistManager();
+ return Virtualist;
-}(HTMLElement, screen)); // end of (function () {
+}(document, HTMLElement, screen)); // end of (function () {
Please sign in to comment.
Something went wrong with that request. Please try again.