[Pkg-javascript-commits] [list.js] 02/06: Imported Upstream version 1.2.0~dfsg1
Alexandre Viau
aviau at moszumanska.debian.org
Thu May 19 17:01:56 UTC 2016
This is an automated email from the git hooks/post-receive script.
aviau pushed a commit to branch master
in repository list.js.
commit 9847d255e57b97d46306afb98c7b0c093b23b351
Author: aviau <alexandre at alexandreviau.net>
Date: Thu May 19 12:54:48 2016 -0400
Imported Upstream version 1.2.0~dfsg1
---
.jshintignore | 1 +
Gruntfile.js | 133 ++-
History.md | 124 ++-
LICENSE | 21 +
README.md | 28 +-
bower.json | 3 +-
component.json | 44 -
dist/list.js | 2072 +++++++++++++++++++-----------------------
index.js | 438 +++++----
package.json | 31 +-
src/add-async.js | 29 +-
src/filter.js | 46 +-
src/item.js | 108 +--
src/parse.js | 78 +-
src/search.js | 210 +++--
src/sort.js | 169 ++--
src/templater.js | 227 +++--
src/utils/classes.js | 185 ++++
src/utils/events.js | 38 +
src/utils/extend.js | 18 +
src/utils/get-attribute.js | 26 +
src/utils/get-by-class.js | 56 ++
src/utils/index-of.js | 9 +
src/utils/natural-sort.js | 48 +
src/utils/to-array.js | 33 +
src/utils/to-string.js | 6 +
test/fixtures.js | 98 +-
test/index.html | 84 +-
test/test.add-get-remove.js | 188 ++--
test/test.buttons.js | 330 +++----
test/test.create.js | 230 +++--
test/test.defaults.js | 109 ++-
test/test.filter.js | 176 ++--
test/test.item.js | 252 +++---
test/test.off.js | 62 +-
test/test.on.js | 212 ++---
test/test.parse.js | 155 +++-
test/test.re-index.js | 34 +
test/test.search-filter.js | 114 +--
test/test.search.js | 228 +++--
test/test.show.js | 386 ++++----
test/test.sort.js | 608 ++++++-------
test/test.trigger.js | 28 +-
test/usage/amd.html | 34 +
test/usage/boba.jpeg | Bin 0 -> 3271 bytes
test/usage/classic.html | 53 ++
test/usage/darth.jpeg | Bin 0 -> 2109 bytes
test/usage/leia.jpeg | Bin 0 -> 1707 bytes
test/usage/luke.jpeg | Bin 0 -> 2009 bytes
test/usage/main.js | 6 +
test/usage/require.js | 2083 +++++++++++++++++++++++++++++++++++++++++++
test/usage/rey.jpeg | Bin 0 -> 2281 bytes
test/usage/style.css | 87 ++
53 files changed, 6312 insertions(+), 3426 deletions(-)
diff --git a/.jshintignore b/.jshintignore
new file mode 100644
index 0000000..2b7b69e
--- /dev/null
+++ b/.jshintignore
@@ -0,0 +1 @@
+src/utils/extend.js
diff --git a/Gruntfile.js b/Gruntfile.js
index 4871881..3a28545 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -2,87 +2,75 @@ module.exports = function(grunt) {
"use strict";
grunt.initConfig({
- pkg: require("./package.json"),
- watch: {
- scripts: {
- files: ['{,*/}*.js', '*.js', 'test/*.html', 'test/*.js'],
- tasks: ['default'],
- options: {
- spawn: false,
- },
+ pkg: require("./package.json"),
+ watch: {
+ scripts: {
+ files: ['src/*.js', 'src/utils/*.js', '*.js', 'test/*.html', 'test/*.js'],
+ tasks: ['test'],
+ options: {
+ spawn: false,
},
},
- shell: {
- install: {
- command: 'component install --dev',
- options: {
- stderr: true
- }
- },
- build: {
- command: 'component build --dev',
- options: {
- stderr: true
- }
- },
- standalone: {
- command: 'component build --standalone List -n list.standalone'
- },
- mkdir: {
- command: 'mkdir -p dist'
- },
- move: {
- command: 'mv build/list.standalone.js dist/list.js'
- },
- remove: {
- command: 'rm -fr build components dist'
+ },
+ shell: {
+ mkdir: {
+ command: 'mkdir -p dist'
+ },
+ build: {
+ command: 'browserify index.js > dist/list.js',
+ options: {
+ stderr: true
}
},
- jshint: {
- code: {
- src: ['Gruntfile.js', '*.js', 'src/*.js'],
- options: {
- expr: true,
- multistr: false,
- globals: {
- module: true
- }
- }
- },
- tests: {
- src: ['test/(*|!mocha).js'],
- options: {
- expr: true,
- multistr: true,
- globals: {
- jQuery: true,
- module: true
- }
+ remove: {
+ command: 'rm -fr node_modules dist'
+ }
+ },
+ jshint: {
+ code: {
+ src: ['Gruntfile.js', '*.js', 'src/*.js', 'src/utils/*.js'],
+ options: {
+ expr: true,
+ multistr: false,
+ globals: {
+ module: true
}
}
},
- uglify: {
- target: {
- files: {
- 'dist/list.min.js': ['dist/list.js']
+ tests: {
+ src: ['test/(*|!mocha).js'],
+ options: {
+ expr: true,
+ multistr: true,
+ globals: {
+ jQuery: true,
+ module: true
}
}
- },
- mocha: {
- cool: {
- src: [ 'test/index.html' ],
- options: {
- run: true,
- timeout: 10000,
- bail: false,
- log: true,
- reporter: 'Nyan',
- mocha: {
- ignoreLeaks: false
- }
+ }
+ },
+ uglify: {
+ target: {
+ files: {
+ 'dist/list.min.js': ['dist/list.js']
+ }
+ }
+ },
+ mocha: {
+ cool: {
+ src: [ 'test/index.html' ],
+ options: {
+ run: true,
+ timeout: 10000,
+ bail: false,
+ log: true,
+ reporter: 'Nyan',
+ mocha: {
+ ignoreLeaks: false
}
}
}
+ }
});
grunt.loadNpmTasks("grunt-contrib-watch");
@@ -91,11 +79,10 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-mocha');
- grunt.registerTask('default', ['jshint:code', 'jshint:tests', 'shell:install', 'shell:build']);
- grunt.registerTask('dist', ['default', 'shell:standalone', 'shell:mkdir', 'shell:move', 'uglify']);
+ grunt.registerTask('default', ['jshint:code', 'jshint:tests', 'shell:mkdir', 'shell:build']);
+ grunt.registerTask('dist', ['default', 'shell:mkdir', 'shell:build', 'uglify']);
grunt.registerTask('clean', ['shell:remove']);
-
- grunt.registerTask('test', ['mocha']);
+ grunt.registerTask('test', ['dist', 'mocha']);
return grunt;
};
diff --git a/History.md b/History.md
index 83c8652..46eb380 100644
--- a/History.md
+++ b/History.md
@@ -1,43 +1,103 @@
# Changelog
+### TODO
+- Add tests for custom event handlers. 27e2d6fdeee7090eb1342a108013db898fc29b96
+- Regex in search https://github.com/javve/list.js/issues/371
+- Keep original order?
+- Automatically add item in the right place if sort is active
+- How to handle arrays?
+- Implement debouncing in search?
+- Better search https://github.com/javve/list.js/pull/312/files ?
+- Investigate sort button defaults:
+ - https://github.com/javve/list.js/issues/316
+ - https://github.com/javve/list.js/pull/301
+- Improve testability by decoupling things and make it possible to use require('') in tests
+
+### 2016-02-27: 1.2.0
+- **[Misc]** Move form Component to Browserify
+ [See commit →](https://github.com/javve/list.js/commit/58695c93849b78787d9cf78cbf9be20b01cdcc8a)
+- **[Misc]** Add tests to make sure List.js works with require.js
+ [See commit →](https://github.com/javve/list.js/commit/360098a04b87e18afd1b09e293a01a8dc113a01e)
+- **[Misc]** Update all dependencies to latest version
+ [See commit →](https://github.com/javve/list.js/commit/881991cd204a19af5ed3c62c1239c1206fa51e6c)
+- **[Breaking]** set sort order with List.js not sort function.
+ [See commit →](https://github.com/javve/list.js/commit/81d1148489c99b8503e725805c2a6ce2bde47b11)
+- **[Breaking]** set default page size to 10000 instead of 200 (because: page size is confusing for new users)
+ [See commit →](https://github.com/javve/list.js/commit/618565b203b61c34b868a9cb86eea899e75ea4b6)
+- **[Breaking]** Rename list.helpers to list.utils
+ [See commit →](https://github.com/javve/list.js/commit/58695c93849b78787d9cf78cbf9be20b01cdcc8a)
+- **[Feature]** Add support for data attributes and custom attributes ex. links and images. [See docs](http://listjs.com/).
+ [See commit →](https://github.com/javve/list.js/commit/a8e083dc0f642e90b7a3f3cc11b12f9bb353d3a0)
+- **[Feature]** Add toJSON method.
+ [See commit →](https://github.com/javve/list.js/commit/570fd10e65fcf2e0d3d959ca42137625d9fd3b7c)
+- **[Feature]** Add reIndex method that should be called if the html have been changed by something except List.js.
+ [See commit →](https://github.com/javve/list.js/commit/825b2b55d339de2bb78eb41145d56a8b27d3d888)
+- **[Feature]** Add option searchColumns to defined default columns to search in.
+ [See commit →](https://github.com/javve/list.js/commit/b8b74f21f78c17f1c1842480084ffdb58edc26cd)
+- **[Feature]** Support <tr> in options.item
+ [See commit →](https://github.com/javve/list.js/commit/9700858168811b6559983d2cb792014213b817a6)
+- **[Feature]** Make it possble to add event handlers on init `new List('listId', { searchComplete: function(list) {} })`.
+ [See commit →](https://github.com/javve/list.js/commit/b8b74f21f78c17f1c1842480084ffdb58edc26cd)
+- **[Bugfix]** Don't throw error if searching in a empty list.
+ [See commit →](https://github.com/javve/list.js/commit/d805494732922024bb99090fb6521021189861e9)
+- **[Bugfix]** Make it possible to use item.visible() on items not yet templated.
+ [See commit →](https://github.com/javve/list.js/commit/8e898b0e55a7d47a77ee27f109602bdb63183fda)
+- **[Bugfix]** Include reference to List when initializing plugins. Fix for require.js which don't have a global reference to List.
+ [See commit →](https://github.com/javve/list.js/commit/40d3c5e5f98cf3bcb9624a5717d4435a0b6f49f6)
+- **[Bugfix]** Fix index async. Fix #268
+ [See commit →](https://github.com/javve/list.js/commit/27e2d6fdeee7090eb1342a108013db898fc29b96)
+- **[Bugfix]** Fix add async
+ [See commit →](https://github.com/javve/list.js/commit/237f926d3ea0036ffb8b255dd0da42387b6a653a)
+- **[Bugfix]** Don't add empty item if empty list is initated with empty array.
+ [See commit →](https://github.com/javve/list.js/commit/607a176c12b2219fb5204a789cd44ef367a0025f)
+- **[Bugfix]** Make sort case insensitive by default for the automatic buttons
+ [See commit →](https://github.com/javve/list.js/commit/44260b862f74dccd248d08ca1f7df2b422c8f439)
+- **[Bugfix]** Clear all values from source item. Case: list.add({}) should not
+ get same values as first item in list
+ [See commit →](https://github.com/javve/list.js/commit/3a4733d52cff25ef99ee8a1326c0b54be81d64ca)
+
+
### 2014-02-03: 1.1.1
-- *[Bugfix]* Update `javve/events` version which fixes critical bugs in Safari for PC and PhantomJS (which makes the command line tests work again).
-- *[Bugfix]* Clear search when clicking in the HTML5 clear button.
-- *[Misc]* Add History.md file for changelog instead of having it at Listjs.com.
+- **[Bugfix]** Update `javve/events` version which fixes critical bugs in Safari
+ for PC and PhantomJS (which makes the command line tests work again).
+- **[Bugfix]** Clear search when clicking in the HTML5 clear button.
+- **[Misc]** Add History.md file for changelog instead of having it at Listjs.com.
### 2014-02-03: 1.1.0
-- *[Change]* The sorting API is update so it looks like this `listObj.sort('name', { order: "asc "})` and `listObj.sort('name', { order: "desc "})` instead or `listObj.sort('name', { desc: true/false })`.
-- *[Feature]* Added support for default sort function `new List('id', { sortFunction: function(itemA, itemB) { .. }})</
-- *[Feature]* Adding `data-order="asc/desc"` to a sort button makes that button only sort `asc` or `desc`, ie no to
-- *[Bugfix]* Fix `grunt watch` bug.
-- *[Bugfix]* Remove sorting when searching and filtering.
-- *[Bugfix]* Fix sorting and search when using pagiation plugin
+- **[Breaking]** The sorting API is update so it looks like this
+ `listObj.sort('name', { order: "asc "})` and `listObj.sort('name', { order: "desc "})`
+ instead or `listObj.sort('name', { desc: true/false })`.
+- **[Feature]** Added support for default sort function `new List('id', { sortFunction: function(itemA, itemB) { .. }})`
+- **[Feature]** Adding `data-order="asc/desc"` to a sort button makes that button only sort `asc` or `desc`, ie no to
+- **[Bugfix]** Fix `grunt watch` bug.
+- **[Bugfix]** Remove sorting when searching and filtering.
+- **[Bugfix]** Fix sorting and search when using pagiation plugin
### 2014-01-17: 1.0.2
-- *[Bugfix]* Fix error that broke the lib in IE8.
+- **[Bugfix]** Fix error that broke the lib in IE8.
### 2013-11-12: 1.0.0
-- *[Feature]* Add more events and enable to add them on initialization.
-- *[Feature]* Add support for Component.js, Bower, RequireJS and CommonJS
-- *[Feature]* Make it possible to remove event handlers by `.off('event', handler)`
-- *[Improvement]* Many new tests
-- *[Improvement]* Paging plugin default classes and structure now correspons to <a href="http://twitter.github.com/bootstrap/components.html#pagination">Twitter Bootstraps pagination</a>.
-- *[Improvement]* Make sorting case-insensitive (thanks @thomasklemm)
-- *[Improvement]* Add item._values for direct access to a items values. Simplifies debugging. Note: Always use item.values() when interacting with the values.
-- *[Bugfix]* `.add(items, callbak)` with `callback` set does no longer add an extra item.
-- *[Bugfix]* `templater.set()` no longer is called twice in a `templater.get()` call.
-- *[Bugfix]* Fix error when trying to sort `undefined,null,etc` values.
-- *[Bugfix]* Fix error when trying to search `undefined,null,etc` values.
-- *[Bugfix]* Fix issue #51, problems with filters/search + paging.
-- *[Misc]* Almost completely rewritten codebase and started using <a href="https://github.com/component/component">Component</a>
-- *[Misc]* Moved the website into another repo called <a href="https://github.com/javve/list-website">list-website</a>
-- *[Misc]* Add documentation for searching in specific columns.
-- *[Change]* `listObj.get('valueName', value)` does now always returns an array. Previously it return an object if only one item matched and null if no match was found.
-- *[Change]* The default sort order is now `asc` instead of `desc`.
-- *[Change]* Syntax for searching in specific columns are now `.search('val', [ 'columnName', 'columnName2' ])` instead of `.search('val', { columnName: true, columnName2: true })`.
-- *[Change]* Move plugins into seperated repos: <a href="https://github.com/javve/list.pagination.js">github.com/javve/list.pagination.js</a> and <a href="https://github.com/javve/list.fuzzysearch.js">github.com/javve/list.fuzzysearch.js</a>
-- *[Change]* Plugin initiation have changed. See <a href="/docs/plugins">getting started with plugins
+- **[Feature]** Add more events and enable to add them on initialization.
+- **[Feature]** Add support for Component.js, Bower, RequireJS and CommonJS
+- **[Feature]** Make it possible to remove event handlers by `.off('event', handler)`
+- **[Improvement]** Many new tests
+- **[Improvement]** Paging plugin default classes and structure now correspons to <a href="http://twitter.github.com/bootstrap/components.html#pagination">Twitter Bootstraps pagination</a>.
+- **[Improvement]** Make sorting case-insensitive (thanks @thomasklemm)
+- **[Improvement]** Add item.\_values for direct access to a items values. Simplifies debugging. Note: Always use item.values() when interacting with the values.
+- **[Bugfix]** `.add(items, callbak)` with `callback` set does no longer add an extra item.
+- **[Bugfix]** `templater.set()` no longer is called twice in a `templater.get()` call.
+- **[Bugfix]** Fix error when trying to sort `undefined,null,etc` values.
+- **[Bugfix]** Fix error when trying to search `undefined,null,etc` values.
+- **[Bugfix]** Fix issue #51, problems with filters/search + paging.
+- **[Misc]** Almost completely rewritten codebase and started using <a href="https://github.com/component/component">Component</a>
+- **[Misc]** Moved the website into another repo called <a href="https://github.com/javve/list-website">list-website</a>
+- **[Misc]** Add documentation for searching in specific columns.
+- **[Change]** `listObj.get('valueName', value)` does now always returns an array. Previously it return an object if only one item matched and null if no match was found.
+- **[Change]** The default sort order is now `asc` instead of `desc`.
+- **[Change]** Syntax for searching in specific columns are now `.search('val', [ 'columnName', 'columnName2' ])` instead of `.search('val', { columnName: true, columnName2: true })`.
+- **[Change]** Move plugins into seperated repos: <a href="https://github.com/javve/list.pagination.js">github.com/javve/list.pagination.js</a> and <a href="https://github.com/javve/list.fuzzysearch.js">github.com/javve/list.fuzzysearch.js</a>
+- **[Change]** Plugin initiation have changed. See <a href="/docs/plugins">getting started with plugins
### 2012-04-24: 0.2.1
@@ -58,8 +118,8 @@
### 2011-11-16: 0.1.2 release
- Sorting is now indicated by class `asc` or `desc` at sorting buttons
-- Added three new small helper functions `hasClass(element, class)`, `addClass(element, class)</
- and `removeClass(element, class)`</li>
+- Added three new small helper functions `hasClass(element, class)`, `addClass(element, class)``
+ and `removeClass(element, class)`</li>
### 2011-10-20: 0.1.1 release
- Added possibility to reverse sort the list
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..20b618d
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2011-2014 Jonny Strömberg, jonnystromberg.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/README.md b/README.md
index 5122699..9dd0a88 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,23 @@ Really simple and easy to use!
- Plugins [Read more ›](http://listjs.com/docs/plugins)
- Support for Chrome, Safari, Firefox, IE6+
+### Download / Install
+##### Via Bower
+```
+bower install list.js
+```
+##### Via Component
+```
+component install javve/list.js
+```
+##### Via CDNJS
+```
+<script src="//cdnjs.cloudflare.com/ajax/libs/list.js/1.1.1/list.min.js"></script>
+```
+##### Via Direct Download
+- [Compressed list.js](https://raw.githubusercontent.com/javve/list.js/v1.1.1/dist/list.min.js)
+- [Uncompressed list.js](https://raw.githubusercontent.com/javve/list.js/v1.1.1/dist/list.js)
+
### Demo / Examples
- [Existing list](http://listjs.com/examples/existing-list)
- [Existing list + add](http://listjs.com/examples/existing-list-add)
@@ -29,6 +46,10 @@ Really simple and easy to use!
- [Add, get, remove](http://listjs.com/examples/add-get-remove)
- [Fuzzy search](http://listjs.com/examples/fuzzy-search)
- [Pagination](http://listjs.com/examples/pagination)
+- [Search in specific column](http://codepen.io/javve/pen/GpZpow)
+- [Filter in range](http://codepen.io/javve/pen/wKGKWL)
+- [Show message filter/search results in 0 items](http://codepen.io/javve/pen/VvavzG)
+- [Only show list after search/filter](http://codepen.io/javve/pen/YyqyRg)
## Documentation
- [Getting started](http://listjs.com/docs)
@@ -45,8 +66,6 @@ Really simple and easy to use!
### Known issues
- Sorting fails with some UTF8 characters. Example: `åä`, thinking that `ä` is before `å`.
-- Tables row items can't be created with the `{ item: '<html>' }`-method.
-
## Contributors
* [javve](https://github.com/javve) / [Jonny Strömberg](http://jonnystromberg.com)
@@ -68,6 +87,7 @@ Really simple and easy to use!
* [jkeyes](https://github.com/jkeyes) / [John Keyes](http://keyes.ie/)
* [samosad](https://github.com/samosad) / Alexey Tabakman
* [Page-](https://github.com/Page-)
+* [urkle](https://github.com/urkle) / Edward Rudd
Built with [Component](https://github.com/component/component) which is created by [TJ Holowaychuk](https://github.com/visionmedia).
@@ -82,7 +102,5 @@ Built with [Component](https://github.com/component/component) which is created
## License (MIT)
-Copyright (c) 2012 Jonny Strömberg <[jonny.stromberg at gmail.com](jonny.stromberg at gmail.com)>
+Copyright (c) 2012 Jonny Strömberg <[jonny.stromberg at gmail.com](mailto:jonny.stromberg at gmail.com)>
[http://jonnystromberg.com](http://jonnystromberg.com)
-
-[![Views in the last 24 hours](https://sourcegraph.com/api/repos/github.com/javve/list.js/counters/views-24h.png)](https://sourcegraph.com/github.com/javve/list.js)
diff --git a/bower.json b/bower.json
index 62b7cd7..8794778 100644
--- a/bower.json
+++ b/bower.json
@@ -1,12 +1,11 @@
{
"name": "list.js",
"main": "dist/list.js",
- "version": "1.1.1",
"homepage": "http://listjs.com",
"authors": [
"Jonny Strömberg <jonny.stromberg at gmail.com>"
],
- "description": "Add search, sort and flexibility to plain HTML lists or tables with cross-browser native JavaScript.",
+ "description": "The perfect library for adding search, sort, filters and flexibility to tables, lists and various HTML elements. Built to be invisible and work on existing HTML",
"keywords": [
"list",
"search",
diff --git a/component.json b/component.json
deleted file mode 100644
index 8ad451f..0000000
--- a/component.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "name": "list.js",
- "repo": "javve/list.js",
- "version": "1.1.1",
- "description": "Add search, sort and flexibility to plain HTML lists or tables with cross-browser native JavaScript.",
- "keywords": [
- "list",
- "search",
- "sort",
- "table",
- "dom",
- "html",
- "ui"
- ],
- "scripts": [
- "index.js",
- "src/search.js",
- "src/sort.js",
- "src/item.js",
- "src/templater.js",
- "src/filter.js",
- "src/add-async.js",
- "src/parse.js"
- ],
- "license": "MIT",
- "dependencies": {
- "component/classes": "*",
- "segmentio/extend": "*",
- "component/indexof": "*",
- "javve/events": "*",
- "javve/get-by-class": "*",
- "javve/get-attribute": "*",
- "javve/natural-sort": "*",
- "javve/to-string": "*",
- "component/type": "*"
- },
- "development": {
- "visionmedia/mocha": "*",
- "techjacker/expect.js": "*",
- "component/jquery": "1.9.1"
- },
- "twitter": "javve",
- "remotes": []
-}
diff --git a/dist/list.js b/dist/list.js
index d8ea7ba..38ddeca 100644
--- a/dist/list.js
+++ b/dist/list.js
@@ -1,211 +1,825 @@
-;(function(){
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+/*
+List.js 1.1.1
+By Jonny Strömberg (www.jonnystromberg.com, www.listjs.com)
+*/
+(function( window, undefined ) {
+"use strict";
-/**
- * Require the given path.
- *
- * @param {String} path
- * @return {Object} exports
- * @api public
- */
+var document = window.document,
+ getByClass = require('./src/utils/get-by-class'),
+ extend = require('./src/utils/extend'),
+ indexOf = require('./src/utils/index-of'),
+ events = require('./src/utils/events'),
+ toString = require('./src/utils/to-string'),
+ naturalSort = require('./src/utils/natural-sort'),
+ classes = require('./src/utils/classes'),
+ getAttribute = require('./src/utils/get-attribute'),
+ toArray = require('./src/utils/to-array');
-function require(path, parent, orig) {
- var resolved = require.resolve(path);
-
- // lookup failed
- if (null == resolved) {
- orig = orig || path;
- parent = parent || 'root';
- var err = new Error('Failed to require "' + orig + '" from "' + parent + '"');
- err.path = orig;
- err.parent = parent;
- err.require = true;
- throw err;
- }
+var List = function(id, options, values) {
- var module = require.modules[resolved];
-
- // perform real require()
- // by invoking the module's
- // registered function
- if (!module._resolving && !module.exports) {
- var mod = {};
- mod.exports = {};
- mod.client = mod.component = true;
- module._resolving = true;
- module.call(this, mod.exports, require.relative(resolved), mod);
- delete module._resolving;
- module.exports = mod.exports;
- }
+ var self = this,
+ init,
+ Item = require('./src/item')(self),
+ addAsync = require('./src/add-async')(self);
+
+ init = {
+ start: function() {
+ self.listClass = "list";
+ self.searchClass = "search";
+ self.sortClass = "sort";
+ self.page = 10000;
+ self.i = 1;
+ self.items = [];
+ self.visibleItems = [];
+ self.matchingItems = [];
+ self.searched = false;
+ self.filtered = false;
+ self.searchColumns = undefined;
+ self.handlers = { 'updated': [] };
+ self.plugins = {};
+ self.valueNames = [];
+ self.utils = {
+ getByClass: getByClass,
+ extend: extend,
+ indexOf: indexOf,
+ events: events,
+ toString: toString,
+ naturalSort: naturalSort,
+ classes: classes,
+ getAttribute: getAttribute,
+ toArray: toArray
+ };
+
+ self.utils.extend(self, options);
+
+ self.listContainer = (typeof(id) === 'string') ? document.getElementById(id) : id;
+ if (!self.listContainer) { return; }
+ self.list = getByClass(self.listContainer, self.listClass, true);
+
+ self.parse = require('./src/parse')(self);
+ self.templater = require('./src/templater')(self);
+ self.search = require('./src/search')(self);
+ self.filter = require('./src/filter')(self);
+ self.sort = require('./src/sort')(self);
+
+ this.handlers();
+ this.items();
+ self.update();
+ this.plugins();
+ },
+ handlers: function() {
+ for (var handler in self.handlers) {
+ if (self[handler]) {
+ self.on(handler, self[handler]);
+ }
+ }
+ },
+ items: function() {
+ self.parse(self.list);
+ if (values !== undefined) {
+ self.add(values);
+ }
+ },
+ plugins: function() {
+ for (var i = 0; i < self.plugins.length; i++) {
+ var plugin = self.plugins[i];
+ self[plugin.name] = plugin;
+ plugin.init(self, List);
+ }
+ }
+ };
- return module.exports;
-}
+ /*
+ * Re-parse the List, use if html have changed
+ */
+ this.reIndex = function() {
+ self.items = [];
+ self.visibleItems = [];
+ self.matchingItems = [];
+ self.searched = false;
+ self.filtered = false;
+ self.parse(self.list);
+ };
-/**
- * Registered modules.
- */
+ this.toJSON = function() {
+ var json = [];
+ for (var i = 0, il = self.items.length; i < il; i++) {
+ json.push(self.items[i].values());
+ }
+ return json;
+ };
-require.modules = {};
-/**
- * Registered aliases.
- */
+ /*
+ * Add object to list
+ */
+ this.add = function(values, callback) {
+ if (values.length === 0) {
+ return;
+ }
+ if (callback) {
+ addAsync(values, callback);
+ return;
+ }
+ var added = [],
+ notCreate = false;
+ if (values[0] === undefined){
+ values = [values];
+ }
+ for (var i = 0, il = values.length; i < il; i++) {
+ var item = null;
+ notCreate = (self.items.length > self.page) ? true : false;
+ item = new Item(values[i], undefined, notCreate);
+ self.items.push(item);
+ added.push(item);
+ }
+ self.update();
+ return added;
+ };
-require.aliases = {};
+ this.show = function(i, page) {
+ this.i = i;
+ this.page = page;
+ self.update();
+ return self;
+ };
-/**
- * Resolve `path`.
- *
- * Lookup:
- *
- * - PATH/index.js
- * - PATH.js
- * - PATH
- *
- * @param {String} path
- * @return {String} path or null
- * @api private
- */
+ /* Removes object from list.
+ * Loops through the list and removes objects where
+ * property "valuename" === value
+ */
+ this.remove = function(valueName, value, options) {
+ var found = 0;
+ for (var i = 0, il = self.items.length; i < il; i++) {
+ if (self.items[i].values()[valueName] == value) {
+ self.templater.remove(self.items[i], options);
+ self.items.splice(i,1);
+ il--;
+ i--;
+ found++;
+ }
+ }
+ self.update();
+ return found;
+ };
-require.resolve = function(path) {
- if (path.charAt(0) === '/') path = path.slice(1);
-
- var paths = [
- path,
- path + '.js',
- path + '.json',
- path + '/index.js',
- path + '/index.json'
- ];
-
- for (var i = 0; i < paths.length; i++) {
- var path = paths[i];
- if (require.modules.hasOwnProperty(path)) return path;
- if (require.aliases.hasOwnProperty(path)) return require.aliases[path];
- }
+ /* Gets the objects in the list which
+ * property "valueName" === value
+ */
+ this.get = function(valueName, value) {
+ var matchedItems = [];
+ for (var i = 0, il = self.items.length; i < il; i++) {
+ var item = self.items[i];
+ if (item.values()[valueName] == value) {
+ matchedItems.push(item);
+ }
+ }
+ return matchedItems;
+ };
+
+ /*
+ * Get size of the list
+ */
+ this.size = function() {
+ return self.items.length;
+ };
+
+ /*
+ * Removes all items from the list
+ */
+ this.clear = function() {
+ self.templater.clear();
+ self.items = [];
+ return self;
+ };
+
+ this.on = function(event, callback) {
+ self.handlers[event].push(callback);
+ return self;
+ };
+
+ this.off = function(event, callback) {
+ var e = self.handlers[event];
+ var index = indexOf(e, callback);
+ if (index > -1) {
+ e.splice(index, 1);
+ }
+ return self;
+ };
+
+ this.trigger = function(event) {
+ var i = self.handlers[event].length;
+ while(i--) {
+ self.handlers[event][i](self);
+ }
+ return self;
+ };
+
+ this.reset = {
+ filter: function() {
+ var is = self.items,
+ il = is.length;
+ while (il--) {
+ is[il].filtered = false;
+ }
+ return self;
+ },
+ search: function() {
+ var is = self.items,
+ il = is.length;
+ while (il--) {
+ is[il].found = false;
+ }
+ return self;
+ }
+ };
+
+ this.update = function() {
+ var is = self.items,
+ il = is.length;
+
+ self.visibleItems = [];
+ self.matchingItems = [];
+ self.templater.clear();
+ for (var i = 0; i < il; i++) {
+ if (is[i].matching() && ((self.matchingItems.length+1) >= self.i && self.visibleItems.length < self.page)) {
+ is[i].show();
+ self.visibleItems.push(is[i]);
+ self.matchingItems.push(is[i]);
+ } else if (is[i].matching()) {
+ self.matchingItems.push(is[i]);
+ is[i].hide();
+ } else {
+ is[i].hide();
+ }
+ }
+ self.trigger('updated');
+ return self;
+ };
+
+ init.start();
};
-/**
- * Normalize `path` relative to the current path.
- *
- * @param {String} curr
- * @param {String} path
- * @return {String}
- * @api private
- */
-require.normalize = function(curr, path) {
- var segs = [];
+// AMD support
+if (typeof define === 'function' && define.amd) {
+ define(function () { return List; });
+}
+module.exports = List;
+window.List = List;
+
+})(window);
+
+},{"./src/add-async":2,"./src/filter":3,"./src/item":4,"./src/parse":5,"./src/search":6,"./src/sort":7,"./src/templater":8,"./src/utils/classes":9,"./src/utils/events":10,"./src/utils/extend":11,"./src/utils/get-attribute":12,"./src/utils/get-by-class":13,"./src/utils/index-of":14,"./src/utils/natural-sort":15,"./src/utils/to-array":16,"./src/utils/to-string":17}],2:[function(require,module,exports){
+module.exports = function(list) {
+ var addAsync = function(values, callback, items) {
+ var valuesToAdd = values.splice(0, 50);
+ items = items || [];
+ items = items.concat(list.add(valuesToAdd));
+ if (values.length > 0) {
+ setTimeout(function() {
+ addAsync(values, callback, items);
+ }, 1);
+ } else {
+ list.update();
+ callback(items);
+ }
+ };
+ return addAsync;
+};
- if ('.' != path.charAt(0)) return path;
+},{}],3:[function(require,module,exports){
+module.exports = function(list) {
- curr = curr.split('/');
- path = path.split('/');
+ // Add handlers
+ list.handlers.filterStart = list.handlers.filterStart || [];
+ list.handlers.filterComplete = list.handlers.filterComplete || [];
- for (var i = 0; i < path.length; ++i) {
- if ('..' == path[i]) {
- curr.pop();
- } else if ('.' != path[i] && '' != path[i]) {
- segs.push(path[i]);
+ return function(filterFunction) {
+ list.trigger('filterStart');
+ list.i = 1; // Reset paging
+ list.reset.filter();
+ if (filterFunction === undefined) {
+ list.filtered = false;
+ } else {
+ list.filtered = true;
+ var is = list.items;
+ for (var i = 0, il = is.length; i < il; i++) {
+ var item = is[i];
+ if (filterFunction(item)) {
+ item.filtered = true;
+ } else {
+ item.filtered = false;
+ }
+ }
}
- }
+ list.update();
+ list.trigger('filterComplete');
+ return list.visibleItems;
+ };
+};
+
+},{}],4:[function(require,module,exports){
+module.exports = function(list) {
+ return function(initValues, element, notCreate) {
+ var item = this;
+
+ this._values = {};
+
+ this.found = false; // Show if list.searched == true and this.found == true
+ this.filtered = false;// Show if list.filtered == true and this.filtered == true
+
+ var init = function(initValues, element, notCreate) {
+ if (element === undefined) {
+ if (notCreate) {
+ item.values(initValues, notCreate);
+ } else {
+ item.values(initValues);
+ }
+ } else {
+ item.elm = element;
+ var values = list.templater.get(item, initValues);
+ item.values(values);
+ }
+ };
+
+ this.values = function(newValues, notCreate) {
+ if (newValues !== undefined) {
+ for(var name in newValues) {
+ item._values[name] = newValues[name];
+ }
+ if (notCreate !== true) {
+ list.templater.set(item, item.values());
+ }
+ } else {
+ return item._values;
+ }
+ };
+
+ this.show = function() {
+ list.templater.show(item);
+ };
+
+ this.hide = function() {
+ list.templater.hide(item);
+ };
+
+ this.matching = function() {
+ return (
+ (list.filtered && list.searched && item.found && item.filtered) ||
+ (list.filtered && !list.searched && item.filtered) ||
+ (!list.filtered && list.searched && item.found) ||
+ (!list.filtered && !list.searched)
+ );
+ };
+
+ this.visible = function() {
+ return (item.elm && (item.elm.parentNode == list.list)) ? true : false;
+ };
- return curr.concat(segs).join('/');
+ init(initValues, element, notCreate);
+ };
};
-/**
- * Register module at `path` with callback `definition`.
- *
- * @param {String} path
- * @param {Function} definition
- * @api private
- */
+},{}],5:[function(require,module,exports){
+module.exports = function(list) {
+
+ var Item = require('./item')(list);
-require.register = function(path, definition) {
- require.modules[path] = definition;
+ var getChildren = function(parent) {
+ var nodes = parent.childNodes,
+ items = [];
+ for (var i = 0, il = nodes.length; i < il; i++) {
+ // Only textnodes have a data attribute
+ if (nodes[i].data === undefined) {
+ items.push(nodes[i]);
+ }
+ }
+ return items;
+ };
+
+ var parse = function(itemElements, valueNames) {
+ for (var i = 0, il = itemElements.length; i < il; i++) {
+ list.items.push(new Item(valueNames, itemElements[i]));
+ }
+ };
+ var parseAsync = function(itemElements, valueNames) {
+ var itemsToIndex = itemElements.splice(0, 50); // TODO: If < 100 items, what happens in IE etc?
+ parse(itemsToIndex, valueNames);
+ if (itemElements.length > 0) {
+ setTimeout(function() {
+ parseAsync(itemElements, valueNames);
+ }, 1);
+ } else {
+ list.update();
+ list.trigger('parseComplete');
+ }
+ };
+
+ list.handlers.parseComplete = list.handlers.parseComplete || [];
+
+ return function() {
+ var itemsToIndex = getChildren(list.list),
+ valueNames = list.valueNames;
+
+ if (list.indexAsync) {
+ parseAsync(itemsToIndex, valueNames);
+ } else {
+ parse(itemsToIndex, valueNames);
+ }
+ };
};
-/**
- * Alias a module definition.
- *
- * @param {String} from
- * @param {String} to
- * @api private
- */
+},{"./item":4}],6:[function(require,module,exports){
+module.exports = function(list) {
+ var item,
+ text,
+ columns,
+ searchString,
+ customSearch;
+
+ var prepare = {
+ resetList: function() {
+ list.i = 1;
+ list.templater.clear();
+ customSearch = undefined;
+ },
+ setOptions: function(args) {
+ if (args.length == 2 && args[1] instanceof Array) {
+ columns = args[1];
+ } else if (args.length == 2 && typeof(args[1]) == "function") {
+ customSearch = args[1];
+ } else if (args.length == 3) {
+ columns = args[1];
+ customSearch = args[2];
+ }
+ },
+ setColumns: function() {
+ if (list.items.length === 0) return;
+ if (columns === undefined) {
+ columns = (list.searchColumns === undefined) ? prepare.toArray(list.items[0].values()) : list.searchColumns;
+ }
+ },
+ setSearchString: function(s) {
+ s = list.utils.toString(s).toLowerCase();
+ s = s.replace(/[-[\]{}()*+?.,\\^$|#]/g, "\\$&"); // Escape regular expression characters
+ searchString = s;
+ },
+ toArray: function(values) {
+ var tmpColumn = [];
+ for (var name in values) {
+ tmpColumn.push(name);
+ }
+ return tmpColumn;
+ }
+ };
+ var search = {
+ list: function() {
+ for (var k = 0, kl = list.items.length; k < kl; k++) {
+ search.item(list.items[k]);
+ }
+ },
+ item: function(item) {
+ item.found = false;
+ for (var j = 0, jl = columns.length; j < jl; j++) {
+ if (search.values(item.values(), columns[j])) {
+ item.found = true;
+ return;
+ }
+ }
+ },
+ values: function(values, column) {
+ if (values.hasOwnProperty(column)) {
+ text = list.utils.toString(values[column]).toLowerCase();
+ if ((searchString !== "") && (text.search(searchString) > -1)) {
+ return true;
+ }
+ }
+ return false;
+ },
+ reset: function() {
+ list.reset.search();
+ list.searched = false;
+ }
+ };
-require.alias = function(from, to) {
- if (!require.modules.hasOwnProperty(from)) {
- throw new Error('Failed to alias "' + from + '", it does not exist');
- }
- require.aliases[to] = from;
+ var searchMethod = function(str) {
+ list.trigger('searchStart');
+
+ prepare.resetList();
+ prepare.setSearchString(str);
+ prepare.setOptions(arguments); // str, cols|searchFunction, searchFunction
+ prepare.setColumns();
+
+ if (searchString === "" ) {
+ search.reset();
+ } else {
+ list.searched = true;
+ if (customSearch) {
+ customSearch(searchString, columns);
+ } else {
+ search.list();
+ }
+ }
+
+ list.update();
+ list.trigger('searchComplete');
+ return list.visibleItems;
+ };
+
+ list.handlers.searchStart = list.handlers.searchStart || [];
+ list.handlers.searchComplete = list.handlers.searchComplete || [];
+
+ list.utils.events.bind(list.utils.getByClass(list.listContainer, list.searchClass), 'keyup', function(e) {
+ var target = e.target || e.srcElement, // IE have srcElement
+ alreadyCleared = (target.value === "" && !list.searched);
+ if (!alreadyCleared) { // If oninput already have resetted the list, do nothing
+ searchMethod(target.value);
+ }
+ });
+
+ // Used to detect click on HTML5 clear button
+ list.utils.events.bind(list.utils.getByClass(list.listContainer, list.searchClass), 'input', function(e) {
+ var target = e.target || e.srcElement;
+ if (target.value === "") {
+ searchMethod('');
+ }
+ });
+
+ return searchMethod;
};
-/**
- * Return a require function relative to the `parent` path.
- *
- * @param {String} parent
- * @return {Function}
- * @api private
- */
+},{}],7:[function(require,module,exports){
+module.exports = function(list) {
+ list.sortFunction = list.sortFunction || function(itemA, itemB, options) {
+ options.desc = options.order == "desc" ? true : false; // Natural sort uses this format
+ return list.utils.naturalSort(itemA.values()[options.valueName], itemB.values()[options.valueName], options);
+ };
+
+ var buttons = {
+ els: undefined,
+ clear: function() {
+ for (var i = 0, il = buttons.els.length; i < il; i++) {
+ list.utils.classes(buttons.els[i]).remove('asc');
+ list.utils.classes(buttons.els[i]).remove('desc');
+ }
+ },
+ getOrder: function(btn) {
+ var predefinedOrder = list.utils.getAttribute(btn, 'data-order');
+ if (predefinedOrder == "asc" || predefinedOrder == "desc") {
+ return predefinedOrder;
+ } else if (list.utils.classes(btn).has('desc')) {
+ return "asc";
+ } else if (list.utils.classes(btn).has('asc')) {
+ return "desc";
+ } else {
+ return "asc";
+ }
+ },
+ getInSensitive: function(btn, options) {
+ var insensitive = list.utils.getAttribute(btn, 'data-insensitive');
+ if (insensitive === "false") {
+ options.insensitive = false;
+ } else {
+ options.insensitive = true;
+ }
+ },
+ setOrder: function(options) {
+ for (var i = 0, il = buttons.els.length; i < il; i++) {
+ var btn = buttons.els[i];
+ if (list.utils.getAttribute(btn, 'data-sort') !== options.valueName) {
+ continue;
+ }
+ var predefinedOrder = list.utils.getAttribute(btn, 'data-order');
+ if (predefinedOrder == "asc" || predefinedOrder == "desc") {
+ if (predefinedOrder == options.order) {
+ list.utils.classes(btn).add(options.order);
+ }
+ } else {
+ list.utils.classes(btn).add(options.order);
+ }
+ }
+ }
+ };
+ var sort = function() {
+ list.trigger('sortStart');
+ var options = {};
+
+ var target = arguments[0].currentTarget || arguments[0].srcElement || undefined;
+
+ if (target) {
+ options.valueName = list.utils.getAttribute(target, 'data-sort');
+ buttons.getInSensitive(target, options);
+ options.order = buttons.getOrder(target);
+ } else {
+ options = arguments[1] || options;
+ options.valueName = arguments[0];
+ options.order = options.order || "asc";
+ options.insensitive = (typeof options.insensitive == "undefined") ? true : options.insensitive;
+ }
+ buttons.clear();
+ buttons.setOrder(options);
+
+ options.sortFunction = options.sortFunction || list.sortFunction;
+ list.items.sort(function(a, b) {
+ var mult = (options.order === 'desc') ? -1 : 1;
+ return (options.sortFunction(a, b, options) * mult);
+ });
+ list.update();
+ list.trigger('sortComplete');
+ };
+
+ // Add handlers
+ list.handlers.sortStart = list.handlers.sortStart || [];
+ list.handlers.sortComplete = list.handlers.sortComplete || [];
+
+ buttons.els = list.utils.getByClass(list.listContainer, list.sortClass);
+ list.utils.events.bind(buttons.els, 'click', sort);
+ list.on('searchStart', buttons.clear);
+ list.on('filterStart', buttons.clear);
+
+ return sort;
+};
-require.relative = function(parent) {
- var p = require.normalize(parent, '..');
+},{}],8:[function(require,module,exports){
+var Templater = function(list) {
+ var itemSource,
+ templater = this;
- /**
- * lastIndexOf helper.
- */
+ var init = function() {
+ itemSource = templater.getItemSource(list.item);
+ itemSource = templater.clearSourceItem(itemSource, list.valueNames);
+ };
- function lastIndexOf(arr, obj) {
- var i = arr.length;
- while (i--) {
- if (arr[i] === obj) return i;
+ this.clearSourceItem = function(el, valueNames) {
+ for(var i = 0, il = valueNames.length; i < il; i++) {
+ var elm;
+ if (valueNames[i].data) {
+ for (var j = 0, jl = valueNames[i].data.length; j < jl; j++) {
+ el.setAttribute('data-'+valueNames[i].data[j], '');
+ }
+ } else if (valueNames[i].attr && valueNames[i].name) {
+ elm = list.utils.getByClass(el, valueNames[i].name, true);
+ if (elm) {
+ elm.setAttribute(valueNames[i].attr, "");
+ }
+ } else {
+ elm = list.utils.getByClass(el, valueNames[i], true);
+ if (elm) {
+ elm.innerHTML = "";
+ }
+ }
+ elm = undefined;
}
- return -1;
- }
+ return el;
+ };
- /**
- * The relative require() itself.
- */
+ this.getItemSource = function(item) {
+ if (item === undefined) {
+ var nodes = list.list.childNodes,
+ items = [];
- function localRequire(path) {
- var resolved = localRequire.resolve(path);
- return require(resolved, parent, path);
- }
+ for (var i = 0, il = nodes.length; i < il; i++) {
+ // Only textnodes have a data attribute
+ if (nodes[i].data === undefined) {
+ return nodes[i].cloneNode(true);
+ }
+ }
+ } else if (/^tr[\s>]/.exec(item)) {
+ var table = document.createElement('table');
+ table.innerHTML = item;
+ return table.firstChild;
+ } else if (item.indexOf("<") !== -1) {
+ var div = document.createElement('div');
+ div.innerHTML = item;
+ return div.firstChild;
+ } else {
+ var source = document.getElementById(list.item);
+ if (source) {
+ return source;
+ }
+ }
+ throw new Error("The list need to have at list one item on init otherwise you'll have to add a template.");
+ };
- /**
- * Resolve relative to the parent.
- */
-
- localRequire.resolve = function(path) {
- var c = path.charAt(0);
- if ('/' == c) return path.slice(1);
- if ('.' == c) return require.normalize(p, path);
-
- // resolve deps by returning
- // the dep in the nearest "deps"
- // directory
- var segs = parent.split('/');
- var i = lastIndexOf(segs, 'deps') + 1;
- if (!i) i = 0;
- path = segs.slice(0, i + 1).join('/') + '/deps/' + path;
- return path;
+ this.get = function(item, valueNames) {
+ templater.create(item);
+ var values = {};
+ for(var i = 0, il = valueNames.length; i < il; i++) {
+ var elm;
+ if (valueNames[i].data) {
+ for (var j = 0, jl = valueNames[i].data.length; j < jl; j++) {
+ values[valueNames[i].data[j]] = list.utils.getAttribute(item.elm, 'data-'+valueNames[i].data[j]);
+ }
+ } else if (valueNames[i].attr && valueNames[i].name) {
+ elm = list.utils.getByClass(item.elm, valueNames[i].name, true);
+ values[valueNames[i].name] = elm ? list.utils.getAttribute(elm, valueNames[i].attr) : "";
+ } else {
+ elm = list.utils.getByClass(item.elm, valueNames[i], true);
+ values[valueNames[i]] = elm ? elm.innerHTML : "";
+ }
+ elm = undefined;
+ }
+ return values;
};
- /**
- * Check if module is defined at `path`.
- */
+ this.set = function(item, values) {
+ var getValueName = function(name) {
+ for (var i = 0, il = list.valueNames.length; i < il; i++) {
+ if (list.valueNames[i].data) {
+ var data = list.valueNames[i].data;
+ for (var j = 0, jl = data.length; j < jl; j++) {
+ if (data[j] === name) {
+ return { data: name };
+ }
+ }
+ } else if (list.valueNames[i].attr && list.valueNames[i].name && list.valueNames[i].name == name) {
+ return list.valueNames[i];
+ } else if (list.valueNames[i] === name) {
+ return name;
+ }
+ }
+ };
+ var setValue = function(name, value) {
+ var elm;
+ var valueName = getValueName(name);
+ if (!valueName)
+ return;
+ if (valueName.data) {
+ item.elm.setAttribute('data-'+valueName.data, value);
+ } else if (valueName.attr && valueName.name) {
+ elm = list.utils.getByClass(item.elm, valueName.name, true);
+ if (elm) {
+ elm.setAttribute(valueName.attr, value);
+ }
+ } else {
+ elm = list.utils.getByClass(item.elm, valueName, true);
+ if (elm) {
+ elm.innerHTML = value;
+ }
+ }
+ elm = undefined;
+ };
+ if (!templater.create(item)) {
+ for(var v in values) {
+ if (values.hasOwnProperty(v)) {
+ setValue(v, values[v]);
+ }
+ }
+ }
+ };
- localRequire.exists = function(path) {
- return require.modules.hasOwnProperty(localRequire.resolve(path));
+ this.create = function(item) {
+ if (item.elm !== undefined) {
+ return false;
+ }
+ /* If item source does not exists, use the first item in list as
+ source for new items */
+ var newItem = itemSource.cloneNode(true);
+ newItem.removeAttribute('id');
+ item.elm = newItem;
+ templater.set(item, item.values());
+ return true;
+ };
+ this.remove = function(item) {
+ if (item.elm.parentNode === list.list) {
+ list.list.removeChild(item.elm);
+ }
+ };
+ this.show = function(item) {
+ templater.create(item);
+ list.list.appendChild(item.elm);
+ };
+ this.hide = function(item) {
+ if (item.elm !== undefined && item.elm.parentNode === list.list) {
+ list.list.removeChild(item.elm);
+ }
+ };
+ this.clear = function() {
+ /* .innerHTML = ''; fucks up IE */
+ if (list.list.hasChildNodes()) {
+ while (list.list.childNodes.length >= 1)
+ {
+ list.list.removeChild(list.list.firstChild);
+ }
+ }
};
- return localRequire;
+ init();
};
-require.register("component-classes/index.js", function(exports, require, module){
+
+module.exports = function(list) {
+ return new Templater(list);
+};
+
+},{}],9:[function(require,module,exports){
/**
* Module dependencies.
*/
-var index = require('indexof');
+var index = require('./index-of');
/**
* Whitespace regexp.
@@ -239,7 +853,9 @@ module.exports = function(el){
*/
function ClassList(el) {
- if (!el) throw new Error('A DOM element reference is required');
+ if (!el || !el.nodeType) {
+ throw new Error('A DOM element reference is required');
+ }
this.el = el;
this.list = el.classList;
}
@@ -365,7 +981,8 @@ ClassList.prototype.toggle = function(name, force){
*/
ClassList.prototype.array = function(){
- var str = this.el.className.replace(/^\s+|\s+$/g, '');
+ var className = this.el.getAttribute('class') || '';
+ var str = className.replace(/^\s+|\s+$/g, '');
var arr = str.split(re);
if ('' === arr[0]) arr.shift();
return arr;
@@ -381,150 +998,102 @@ ClassList.prototype.array = function(){
ClassList.prototype.has =
ClassList.prototype.contains = function(name){
- return this.list
- ? this.list.contains(name)
- : !! ~index(this.array(), name);
+ return this.list ? this.list.contains(name) : !! ~index(this.array(), name);
};
-});
-require.register("segmentio-extend/index.js", function(exports, require, module){
-
-module.exports = function extend (object) {
- // Takes an unlimited number of extenders.
- var args = Array.prototype.slice.call(arguments, 1);
-
- // For each extender, copy their properties on our object.
- for (var i = 0, source; source = args[i]; i++) {
- if (!source) continue;
- for (var property in source) {
- object[property] = source[property];
- }
- }
-
- return object;
-};
-});
-require.register("component-indexof/index.js", function(exports, require, module){
-module.exports = function(arr, obj){
- if (arr.indexOf) return arr.indexOf(obj);
- for (var i = 0; i < arr.length; ++i) {
- if (arr[i] === obj) return i;
- }
- return -1;
-};
-});
-require.register("component-event/index.js", function(exports, require, module){
-var bind = window.addEventListener ? 'addEventListener' : 'attachEvent',
- unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent',
- prefix = bind !== 'addEventListener' ? 'on' : '';
+},{"./index-of":14}],10:[function(require,module,exports){
+var bind = window.addEventListener ? 'addEventListener' : 'attachEvent',
+ unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent',
+ prefix = bind !== 'addEventListener' ? 'on' : '',
+ toArray = require('./to-array');
/**
* Bind `el` event `type` to `fn`.
*
- * @param {Element} el
+ * @param {Element} el, NodeList, HTMLCollection or Array
* @param {String} type
* @param {Function} fn
* @param {Boolean} capture
- * @return {Function}
* @api public
*/
exports.bind = function(el, type, fn, capture){
- el[bind](prefix + type, fn, capture || false);
- return fn;
+ el = toArray(el);
+ for ( var i = 0; i < el.length; i++ ) {
+ el[i][bind](prefix + type, fn, capture || false);
+ }
};
/**
* Unbind `el` event `type`'s callback `fn`.
*
- * @param {Element} el
+ * @param {Element} el, NodeList, HTMLCollection or Array
* @param {String} type
* @param {Function} fn
* @param {Boolean} capture
- * @return {Function}
* @api public
*/
exports.unbind = function(el, type, fn, capture){
- el[unbind](prefix + type, fn, capture || false);
- return fn;
-};
-});
-require.register("timoxley-to-array/index.js", function(exports, require, module){
-/**
- * Convert an array-like object into an `Array`.
- * If `collection` is already an `Array`, then will return a clone of `collection`.
- *
- * @param {Array | Mixed} collection An `Array` or array-like object to convert e.g. `arguments` or `NodeList`
- * @return {Array} Naive conversion of `collection` to a new `Array`.
- * @api public
- */
-
-module.exports = function toArray(collection) {
- if (typeof collection === 'undefined') return []
- if (collection === null) return [null]
- if (collection === window) return [window]
- if (typeof collection === 'string') return [collection]
- if (isArray(collection)) return collection
- if (typeof collection.length != 'number') return [collection]
- if (typeof collection === 'function' && collection instanceof Function) return [collection]
-
- var arr = []
- for (var i = 0; i < collection.length; i++) {
- if (Object.prototype.hasOwnProperty.call(collection, i) || i in collection) {
- arr.push(collection[i])
- }
+ el = toArray(el);
+ for ( var i = 0; i < el.length; i++ ) {
+ el[i][unbind](prefix + type, fn, capture || false);
}
- if (!arr.length) return []
- return arr
-}
+};
-function isArray(arr) {
- return Object.prototype.toString.call(arr) === "[object Array]";
-}
+},{"./to-array":16}],11:[function(require,module,exports){
+/*
+ * Source: https://github.com/segmentio/extend
+ */
-});
-require.register("javve-events/index.js", function(exports, require, module){
-var events = require('event'),
- toArray = require('to-array');
+module.exports = function extend (object) {
+ // Takes an unlimited number of extenders.
+ var args = Array.prototype.slice.call(arguments, 1);
-/**
- * Bind `el` event `type` to `fn`.
- *
- * @param {Element} el, NodeList, HTMLCollection or Array
- * @param {String} type
- * @param {Function} fn
- * @param {Boolean} capture
- * @api public
- */
+ // For each extender, copy their properties on our object.
+ for (var i = 0, source; source = args[i]; i++) {
+ if (!source) continue;
+ for (var property in source) {
+ object[property] = source[property];
+ }
+ }
-exports.bind = function(el, type, fn, capture){
- el = toArray(el);
- for ( var i = 0; i < el.length; i++ ) {
- events.bind(el[i], type, fn, capture);
- }
+ return object;
};
+},{}],12:[function(require,module,exports){
/**
- * Unbind `el` event `type`'s callback `fn`.
+ * A cross-browser implementation of getAttribute.
+ * Source found here: http://stackoverflow.com/a/3755343/361337 written by Vivin Paliath
*
- * @param {Element} el, NodeList, HTMLCollection or Array
- * @param {String} type
- * @param {Function} fn
- * @param {Boolean} capture
+ * Return the value for `attr` at `element`.
+ *
+ * @param {Element} el
+ * @param {String} attr
* @api public
*/
-exports.unbind = function(el, type, fn, capture){
- el = toArray(el);
- for ( var i = 0; i < el.length; i++ ) {
- events.unbind(el[i], type, fn, capture);
+module.exports = function(el, attr) {
+ var result = (el.getAttribute && el.getAttribute(attr)) || null;
+ if( !result ) {
+ var attrs = el.attributes;
+ var length = attrs.length;
+ for(var i = 0; i < length; i++) {
+ if (attr[i] !== undefined) {
+ if(attr[i].nodeName === attr) {
+ result = attr[i].nodeValue;
+ }
+ }
+ }
}
+ return result;
};
-});
-require.register("javve-get-by-class/index.js", function(exports, require, module){
+},{}],13:[function(require,module,exports){
/**
+ * A cross-browser implementation of getElementsByClass.
+ * Heavily based on Dustin Diaz's function: http://dustindiaz.com/getelementsbyclass.
+ *
* Find all elements with class `className` inside `container`.
* Use `single = true` to increase performance in older browsers
* when only one element is needed.
@@ -557,7 +1126,7 @@ module.exports = (function() {
return function(container, className, single) {
var classElements = [],
tag = '*';
- if (container == null) {
+ if (container === null) {
container = document;
}
var els = container.getElementsByTagName(tag);
@@ -578,897 +1147,108 @@ module.exports = (function() {
}
})();
-});
-require.register("javve-get-attribute/index.js", function(exports, require, module){
-/**
- * Return the value for `attr` at `element`.
- *
- * @param {Element} el
- * @param {String} attr
- * @api public
- */
+},{}],14:[function(require,module,exports){
+var indexOf = [].indexOf;
-module.exports = function(el, attr) {
- var result = (el.getAttribute && el.getAttribute(attr)) || null;
- if( !result ) {
- var attrs = el.attributes;
- var length = attrs.length;
- for(var i = 0; i < length; i++) {
- if (attr[i] !== undefined) {
- if(attr[i].nodeName === attr) {
- result = attr[i].nodeValue;
- }
- }
- }
+module.exports = function(arr, obj){
+ if (indexOf) return arr.indexOf(obj);
+ for (var i = 0; i < arr.length; ++i) {
+ if (arr[i] === obj) return i;
}
- return result;
-}
-});
-require.register("javve-natural-sort/index.js", function(exports, require, module){
+ return -1;
+};
+
+},{}],15:[function(require,module,exports){
/*
- * Natural Sort algorithm for Javascript - Version 0.7 - Released under MIT license
+ * Natural Sort algorithm for Javascript - Version 0.8 - Released under MIT license
* Author: Jim Palmer (based on chunking idea from Dave Koelle)
*/
-
-module.exports = function(a, b, options) {
- var re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi,
- sre = /(^[ ]*|[ ]*$)/g,
- dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,
- hre = /^0x[0-9a-f]+$/i,
- ore = /^0/,
- options = options || {},
- i = function(s) { return options.insensitive && (''+s).toLowerCase() || ''+s },
- // convert all to strings strip whitespace
- x = i(a).replace(sre, '') || '',
- y = i(b).replace(sre, '') || '',
- // chunk/tokenize
- xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
- yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
- // numeric, hex or date detection
- xD = parseInt(x.match(hre)) || (xN.length != 1 && x.match(dre) && Date.parse(x)),
- yD = parseInt(y.match(hre)) || xD && y.match(dre) && Date.parse(y) || null,
- oFxNcL, oFyNcL,
- mult = options.desc ? -1 : 1;
- // first try and sort Hex codes or Dates
- if (yD)
- if ( xD < yD ) return -1 * mult;
- else if ( xD > yD ) return 1 * mult;
- // natural sorting through split numeric strings and default strings
- for(var cLoc=0, numS=Math.max(xN.length, yN.length); cLoc < numS; cLoc++) {
- // find floats not starting with '0', string or 0 if not defined (Clint Priest)
- oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0;
- oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0;
- // handle numeric vs string comparison - number < string - (Kyle Adams)
- if (isNaN(oFxNcL) !== isNaN(oFyNcL)) { return (isNaN(oFxNcL)) ? 1 : -1; }
- // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
- else if (typeof oFxNcL !== typeof oFyNcL) {
- oFxNcL += '';
- oFyNcL += '';
+module.exports = function(a, b, opts) {
+ var re = /(^([+\-]?(?:\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[\da-fA-F]+$|\d+)/g,
+ sre = /^\s+|\s+$/g, // trim pre-post whitespace
+ snre = /\s+/g, // normalize all whitespace to single ' ' character
+ dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,
+ hre = /^0x[0-9a-f]+$/i,
+ ore = /^0/,
+ options = opts || {},
+ i = function(s) { return options.insensitive && (''+s).toLowerCase() || ''+s; },
+ // convert all to strings strip whitespace
+ x = i(a) || '',
+ y = i(b) || '',
+ // chunk/tokenize
+ xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
+ yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
+ // numeric, hex or date detection
+ xD = parseInt(x.match(hre), 16) || (xN.length !== 1 && Date.parse(x)),
+ yD = parseInt(y.match(hre), 16) || xD && y.match(dre) && Date.parse(y) || null,
+ normChunk = function(s, l) {
+ // normalize spaces; find floats not starting with '0', string or 0 if not defined (Clint Priest)
+ return (!s.match(ore) || l == 1) && parseFloat(s) || s.replace(snre, ' ').replace(sre, '') || 0;
+ },
+ oFxNcL, oFyNcL;
+ // first try and sort Hex codes or Dates
+ if (yD) {
+ if ( xD < yD ) { return -1; }
+ else if ( xD > yD ) { return 1; }
}
- if (oFxNcL < oFyNcL) return -1 * mult;
- if (oFxNcL > oFyNcL) return 1 * mult;
- }
- return 0;
-};
-
-/*
-var defaultSort = getSortFunction();
-
-module.exports = function(a, b, options) {
- if (arguments.length == 1) {
- options = a;
- return getSortFunction(options);
- } else {
- return defaultSort(a,b);
- }
-}
-*/
-});
-require.register("javve-to-string/index.js", function(exports, require, module){
-module.exports = function(s) {
- s = (s === undefined) ? "" : s;
- s = (s === null) ? "" : s;
- s = s.toString();
- return s;
+ // natural sorting through split numeric strings and default strings
+ for(var cLoc=0, xNl = xN.length, yNl = yN.length, numS=Math.max(xNl, yNl); cLoc < numS; cLoc++) {
+ oFxNcL = normChunk(xN[cLoc], xNl);
+ oFyNcL = normChunk(yN[cLoc], yNl);
+ // handle numeric vs string comparison - number < string - (Kyle Adams)
+ if (isNaN(oFxNcL) !== isNaN(oFyNcL)) { return (isNaN(oFxNcL)) ? 1 : -1; }
+ // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
+ else if (typeof oFxNcL !== typeof oFyNcL) {
+ oFxNcL += '';
+ oFyNcL += '';
+ }
+ if (oFxNcL < oFyNcL) { return -1; }
+ if (oFxNcL > oFyNcL) { return 1; }
+ }
+ return 0;
};
-});
-require.register("component-type/index.js", function(exports, require, module){
-/**
- * toString ref.
- */
-
-var toString = Object.prototype.toString;
-
+},{}],16:[function(require,module,exports){
/**
- * Return the type of `val`.
+ * Source: https://github.com/timoxley/to-array
+ *
+ * Convert an array-like object into an `Array`.
+ * If `collection` is already an `Array`, then will return a clone of `collection`.
*
- * @param {Mixed} val
- * @return {String}
+ * @param {Array | Mixed} collection An `Array` or array-like object to convert e.g. `arguments` or `NodeList`
+ * @return {Array} Naive conversion of `collection` to a new `Array`.
* @api public
*/
-module.exports = function(val){
- switch (toString.call(val)) {
- case '[object Date]': return 'date';
- case '[object RegExp]': return 'regexp';
- case '[object Arguments]': return 'arguments';
- case '[object Array]': return 'array';
- case '[object Error]': return 'error';
- }
-
- if (val === null) return 'null';
- if (val === undefined) return 'undefined';
- if (val !== val) return 'nan';
- if (val && val.nodeType === 1) return 'element';
-
- return typeof val.valueOf();
-};
-
-});
-require.register("list.js/index.js", function(exports, require, module){
-/*
-ListJS with beta 1.0.0
-By Jonny Strömberg (www.jonnystromberg.com, www.listjs.com)
-*/
-(function( window, undefined ) {
-"use strict";
-
-var document = window.document,
- getByClass = require('get-by-class'),
- extend = require('extend'),
- indexOf = require('indexof');
-
-var List = function(id, options, values) {
-
- var self = this,
- init,
- Item = require('./src/item')(self),
- addAsync = require('./src/add-async')(self),
- parse = require('./src/parse')(self);
-
- init = {
- start: function() {
- self.listClass = "list";
- self.searchClass = "search";
- self.sortClass = "sort";
- self.page = 200;
- self.i = 1;
- self.items = [];
- self.visibleItems = [];
- self.matchingItems = [];
- self.searched = false;
- self.filtered = false;
- self.handlers = { 'updated': [] };
- self.plugins = {};
- self.helpers = {
- getByClass: getByClass,
- extend: extend,
- indexOf: indexOf
- };
-
- extend(self, options);
-
- self.listContainer = (typeof(id) === 'string') ? document.getElementById(id) : id;
- if (!self.listContainer) { return; }
- self.list = getByClass(self.listContainer, self.listClass, true);
-
- self.templater = require('./src/templater')(self);
- self.search = require('./src/search')(self);
- self.filter = require('./src/filter')(self);
- self.sort = require('./src/sort')(self);
-
- this.items();
- self.update();
- this.plugins();
- },
- items: function() {
- parse(self.list);
- if (values !== undefined) {
- self.add(values);
- }
- },
- plugins: function() {
- for (var i = 0; i < self.plugins.length; i++) {
- var plugin = self.plugins[i];
- self[plugin.name] = plugin;
- plugin.init(self);
- }
- }
- };
-
-
- /*
- * Add object to list
- */
- this.add = function(values, callback) {
- if (callback) {
- addAsync(values, callback);
- return;
- }
- var added = [],
- notCreate = false;
- if (values[0] === undefined){
- values = [values];
- }
- for (var i = 0, il = values.length; i < il; i++) {
- var item = null;
- if (values[i] instanceof Item) {
- item = values[i];
- item.reload();
- } else {
- notCreate = (self.items.length > self.page) ? true : false;
- item = new Item(values[i], undefined, notCreate);
- }
- self.items.push(item);
- added.push(item);
- }
- self.update();
- return added;
- };
-
- this.show = function(i, page) {
- this.i = i;
- this.page = page;
- self.update();
- return self;
- };
-
- /* Removes object from list.
- * Loops through the list and removes objects where
- * property "valuename" === value
- */
- this.remove = function(valueName, value, options) {
- var found = 0;
- for (var i = 0, il = self.items.length; i < il; i++) {
- if (self.items[i].values()[valueName] == value) {
- self.templater.remove(self.items[i], options);
- self.items.splice(i,1);
- il--;
- i--;
- found++;
- }
- }
- self.update();
- return found;
- };
-
- /* Gets the objects in the list which
- * property "valueName" === value
- */
- this.get = function(valueName, value) {
- var matchedItems = [];
- for (var i = 0, il = self.items.length; i < il; i++) {
- var item = self.items[i];
- if (item.values()[valueName] == value) {
- matchedItems.push(item);
- }
- }
- return matchedItems;
- };
-
- /*
- * Get size of the list
- */
- this.size = function() {
- return self.items.length;
- };
-
- /*
- * Removes all items from the list
- */
- this.clear = function() {
- self.templater.clear();
- self.items = [];
- return self;
- };
-
- this.on = function(event, callback) {
- self.handlers[event].push(callback);
- return self;
- };
-
- this.off = function(event, callback) {
- var e = self.handlers[event];
- var index = indexOf(e, callback);
- if (index > -1) {
- e.splice(index, 1);
- }
- return self;
- };
-
- this.trigger = function(event) {
- var i = self.handlers[event].length;
- while(i--) {
- self.handlers[event][i](self);
- }
- return self;
- };
-
- this.reset = {
- filter: function() {
- var is = self.items,
- il = is.length;
- while (il--) {
- is[il].filtered = false;
- }
- return self;
- },
- search: function() {
- var is = self.items,
- il = is.length;
- while (il--) {
- is[il].found = false;
- }
- return self;
- }
- };
-
- this.update = function() {
- var is = self.items,
- il = is.length;
-
- self.visibleItems = [];
- self.matchingItems = [];
- self.templater.clear();
- for (var i = 0; i < il; i++) {
- if (is[i].matching() && ((self.matchingItems.length+1) >= self.i && self.visibleItems.length < self.page)) {
- is[i].show();
- self.visibleItems.push(is[i]);
- self.matchingItems.push(is[i]);
- } else if (is[i].matching()) {
- self.matchingItems.push(is[i]);
- is[i].hide();
- } else {
- is[i].hide();
- }
- }
- self.trigger('updated');
- return self;
- };
-
- init.start();
-};
-
-module.exports = List;
-
-})(window);
-
-});
-require.register("list.js/src/search.js", function(exports, require, module){
-var events = require('events'),
- getByClass = require('get-by-class'),
- toString = require('to-string');
-
-module.exports = function(list) {
- var item,
- text,
- columns,
- searchString,
- customSearch;
-
- var prepare = {
- resetList: function() {
- list.i = 1;
- list.templater.clear();
- customSearch = undefined;
- },
- setOptions: function(args) {
- if (args.length == 2 && args[1] instanceof Array) {
- columns = args[1];
- } else if (args.length == 2 && typeof(args[1]) == "function") {
- customSearch = args[1];
- } else if (args.length == 3) {
- columns = args[1];
- customSearch = args[2];
- }
- },
- setColumns: function() {
- columns = (columns === undefined) ? prepare.toArray(list.items[0].values()) : columns;
- },
- setSearchString: function(s) {
- s = toString(s).toLowerCase();
- s = s.replace(/[-[\]{}()*+?.,\\^$|#]/g, "\\$&"); // Escape regular expression characters
- searchString = s;
- },
- toArray: function(values) {
- var tmpColumn = [];
- for (var name in values) {
- tmpColumn.push(name);
- }
- return tmpColumn;
- }
- };
- var search = {
- list: function() {
- for (var k = 0, kl = list.items.length; k < kl; k++) {
- search.item(list.items[k]);
- }
- },
- item: function(item) {
- item.found = false;
- for (var j = 0, jl = columns.length; j < jl; j++) {
- if (search.values(item.values(), columns[j])) {
- item.found = true;
- return;
- }
- }
- },
- values: function(values, column) {
- if (values.hasOwnProperty(column)) {
- text = toString(values[column]).toLowerCase();
- if ((searchString !== "") && (text.search(searchString) > -1)) {
- return true;
- }
- }
- return false;
- },
- reset: function() {
- list.reset.search();
- list.searched = false;
- }
- };
-
- var searchMethod = function(str) {
- list.trigger('searchStart');
-
- prepare.resetList();
- prepare.setSearchString(str);
- prepare.setOptions(arguments); // str, cols|searchFunction, searchFunction
- prepare.setColumns();
-
- if (searchString === "" ) {
- search.reset();
- } else {
- list.searched = true;
- if (customSearch) {
- customSearch(searchString, columns);
- } else {
- search.list();
- }
- }
-
- list.update();
- list.trigger('searchComplete');
- return list.visibleItems;
- };
-
- list.handlers.searchStart = list.handlers.searchStart || [];
- list.handlers.searchComplete = list.handlers.searchComplete || [];
-
- events.bind(getByClass(list.listContainer, list.searchClass), 'keyup', function(e) {
- var target = e.target || e.srcElement, // IE have srcElement
- alreadyCleared = (target.value === "" && !list.searched);
- if (!alreadyCleared) { // If oninput already have resetted the list, do nothing
- searchMethod(target.value);
- }
- });
-
- // Used to detect click on HTML5 clear button
- events.bind(getByClass(list.listContainer, list.searchClass), 'input', function(e) {
- var target = e.target || e.srcElement;
- if (target.value === "") {
- searchMethod('');
- }
- });
-
- list.helpers.toString = toString;
- return searchMethod;
-};
-
-});
-require.register("list.js/src/sort.js", function(exports, require, module){
-var naturalSort = require('natural-sort'),
- classes = require('classes'),
- events = require('events'),
- getByClass = require('get-by-class'),
- getAttribute = require('get-attribute');
-
-module.exports = function(list) {
- list.sortFunction = list.sortFunction || function(itemA, itemB, options) {
- options.desc = options.order == "desc" ? true : false; // Natural sort uses this format
- return naturalSort(itemA.values()[options.valueName], itemB.values()[options.valueName], options);
- };
-
- var buttons = {
- els: undefined,
- clear: function() {
- for (var i = 0, il = buttons.els.length; i < il; i++) {
- classes(buttons.els[i]).remove('asc');
- classes(buttons.els[i]).remove('desc');
- }
- },
- getOrder: function(btn) {
- var predefinedOrder = getAttribute(btn, 'data-order');
- if (predefinedOrder == "asc" || predefinedOrder == "desc") {
- return predefinedOrder;
- } else if (classes(btn).has('desc')) {
- return "asc";
- } else if (classes(btn).has('asc')) {
- return "desc";
- } else {
- return "asc";
- }
- },
- getInSensitive: function(btn, options) {
- var insensitive = getAttribute(btn, 'data-insensitive');
- if (insensitive === "true") {
- options.insensitive = true;
- } else {
- options.insensitive = false;
- }
- },
- setOrder: function(options) {
- for (var i = 0, il = buttons.els.length; i < il; i++) {
- var btn = buttons.els[i];
- if (getAttribute(btn, 'data-sort') !== options.valueName) {
- continue;
- }
- var predefinedOrder = getAttribute(btn, 'data-order');
- if (predefinedOrder == "asc" || predefinedOrder == "desc") {
- if (predefinedOrder == options.order) {
- classes(btn).add(options.order);
- }
- } else {
- classes(btn).add(options.order);
- }
- }
- }
- };
- var sort = function() {
- list.trigger('sortStart');
- options = {};
-
- var target = arguments[0].currentTarget || arguments[0].srcElement || undefined;
-
- if (target) {
- options.valueName = getAttribute(target, 'data-sort');
- buttons.getInSensitive(target, options);
- options.order = buttons.getOrder(target);
- } else {
- options = arguments[1] || options;
- options.valueName = arguments[0];
- options.order = options.order || "asc";
- options.insensitive = (typeof options.insensitive == "undefined") ? true : options.insensitive;
- }
- buttons.clear();
- buttons.setOrder(options);
-
- options.sortFunction = options.sortFunction || list.sortFunction;
- list.items.sort(function(a, b) {
- return options.sortFunction(a, b, options);
- });
- list.update();
- list.trigger('sortComplete');
- };
-
- // Add handlers
- list.handlers.sortStart = list.handlers.sortStart || [];
- list.handlers.sortComplete = list.handlers.sortComplete || [];
-
- buttons.els = getByClass(list.listContainer, list.sortClass);
- events.bind(buttons.els, 'click', sort);
- list.on('searchStart', buttons.clear);
- list.on('filterStart', buttons.clear);
-
- // Helpers
- list.helpers.classes = classes;
- list.helpers.naturalSort = naturalSort;
- list.helpers.events = events;
- list.helpers.getAttribute = getAttribute;
-
- return sort;
-};
-
-});
-require.register("list.js/src/item.js", function(exports, require, module){
-module.exports = function(list) {
- return function(initValues, element, notCreate) {
- var item = this;
-
- this._values = {};
-
- this.found = false; // Show if list.searched == true and this.found == true
- this.filtered = false;// Show if list.filtered == true and this.filtered == true
-
- var init = function(initValues, element, notCreate) {
- if (element === undefined) {
- if (notCreate) {
- item.values(initValues, notCreate);
- } else {
- item.values(initValues);
- }
- } else {
- item.elm = element;
- var values = list.templater.get(item, initValues);
- item.values(values);
- }
- };
- this.values = function(newValues, notCreate) {
- if (newValues !== undefined) {
- for(var name in newValues) {
- item._values[name] = newValues[name];
- }
- if (notCreate !== true) {
- list.templater.set(item, item.values());
- }
- } else {
- return item._values;
- }
- };
- this.show = function() {
- list.templater.show(item);
- };
- this.hide = function() {
- list.templater.hide(item);
- };
- this.matching = function() {
- return (
- (list.filtered && list.searched && item.found && item.filtered) ||
- (list.filtered && !list.searched && item.filtered) ||
- (!list.filtered && list.searched && item.found) ||
- (!list.filtered && !list.searched)
- );
- };
- this.visible = function() {
- return (item.elm.parentNode == list.list) ? true : false;
- };
- init(initValues, element, notCreate);
- };
-};
-
-});
-require.register("list.js/src/templater.js", function(exports, require, module){
-var getByClass = require('get-by-class');
-
-var Templater = function(list) {
- var itemSource = getItemSource(list.item),
- templater = this;
-
- function getItemSource(item) {
- if (item === undefined) {
- var nodes = list.list.childNodes,
- items = [];
-
- for (var i = 0, il = nodes.length; i < il; i++) {
- // Only textnodes have a data attribute
- if (nodes[i].data === undefined) {
- return nodes[i];
- }
- }
- return null;
- } else if (item.indexOf("<") !== -1) { // Try create html element of list, do not work for tables!!
- var div = document.createElement('div');
- div.innerHTML = item;
- return div.firstChild;
- } else {
- return document.getElementById(list.item);
- }
+module.exports = function toArray(collection) {
+ if (typeof collection === 'undefined') return [];
+ if (collection === null) return [null];
+ if (collection === window) return [window];
+ if (typeof collection === 'string') return [collection];
+ if (isArray(collection)) return collection;
+ if (typeof collection.length != 'number') return [collection];
+ if (typeof collection === 'function' && collection instanceof Function) return [collection];
+
+ var arr = [];
+ for (var i = 0; i < collection.length; i++) {
+ if (Object.prototype.hasOwnProperty.call(collection, i) || i in collection) {
+ arr.push(collection[i]);
}
-
- /* Get values from element */
- this.get = function(item, valueNames) {
- templater.create(item);
- var values = {};
- for(var i = 0, il = valueNames.length; i < il; i++) {
- var elm = getByClass(item.elm, valueNames[i], true);
- values[valueNames[i]] = elm ? elm.innerHTML : "";
- }
- return values;
- };
-
- /* Sets values at element */
- this.set = function(item, values) {
- if (!templater.create(item)) {
- for(var v in values) {
- if (values.hasOwnProperty(v)) {
- // TODO speed up if possible
- var elm = getByClass(item.elm, v, true);
- if (elm) {
- /* src attribute for image tag & text for other tags */
- if (elm.tagName === "IMG" && values[v] !== "") {
- elm.src = values[v];
- } else {
- elm.innerHTML = values[v];
- }
- }
- }
- }
- }
- };
-
- this.create = function(item) {
- if (item.elm !== undefined) {
- return false;
- }
- /* If item source does not exists, use the first item in list as
- source for new items */
- var newItem = itemSource.cloneNode(true);
- newItem.removeAttribute('id');
- item.elm = newItem;
- templater.set(item, item.values());
- return true;
- };
- this.remove = function(item) {
- list.list.removeChild(item.elm);
- };
- this.show = function(item) {
- templater.create(item);
- list.list.appendChild(item.elm);
- };
- this.hide = function(item) {
- if (item.elm !== undefined && item.elm.parentNode === list.list) {
- list.list.removeChild(item.elm);
- }
- };
- this.clear = function() {
- /* .innerHTML = ''; fucks up IE */
- if (list.list.hasChildNodes()) {
- while (list.list.childNodes.length >= 1)
- {
- list.list.removeChild(list.list.firstChild);
- }
- }
- };
-};
-
-module.exports = function(list) {
- return new Templater(list);
-};
-
-});
-require.register("list.js/src/filter.js", function(exports, require, module){
-module.exports = function(list) {
-
- // Add handlers
- list.handlers.filterStart = list.handlers.filterStart || [];
- list.handlers.filterComplete = list.handlers.filterComplete || [];
-
- return function(filterFunction) {
- list.trigger('filterStart');
- list.i = 1; // Reset paging
- list.reset.filter();
- if (filterFunction === undefined) {
- list.filtered = false;
- } else {
- list.filtered = true;
- var is = list.items;
- for (var i = 0, il = is.length; i < il; i++) {
- var item = is[i];
- if (filterFunction(item)) {
- item.filtered = true;
- } else {
- item.filtered = false;
- }
- }
- }
- list.update();
- list.trigger('filterComplete');
- return list.visibleItems;
- };
+ }
+ if (!arr.length) return [];
+ return arr;
};
-});
-require.register("list.js/src/add-async.js", function(exports, require, module){
-module.exports = function(list) {
- return function(values, callback, items) {
- var valuesToAdd = values.splice(0, 100);
- items = items || [];
- items = items.concat(list.add(valuesToAdd));
- if (values.length > 0) {
- setTimeout(function() {
- addAsync(values, callback, items);
- }, 10);
- } else {
- list.update();
- callback(items);
- }
- };
-};
-});
-require.register("list.js/src/parse.js", function(exports, require, module){
-module.exports = function(list) {
-
- var Item = require('./item')(list);
-
- var getChildren = function(parent) {
- var nodes = parent.childNodes,
- items = [];
- for (var i = 0, il = nodes.length; i < il; i++) {
- // Only textnodes have a data attribute
- if (nodes[i].data === undefined) {
- items.push(nodes[i]);
- }
- }
- return items;
- };
-
- var parse = function(itemElements, valueNames) {
- for (var i = 0, il = itemElements.length; i < il; i++) {
- list.items.push(new Item(valueNames, itemElements[i]));
- }
- };
- var parseAsync = function(itemElements, valueNames) {
- var itemsToIndex = itemElements.splice(0, 100); // TODO: If < 100 items, what happens in IE etc?
- parse(itemsToIndex, valueNames);
- if (itemElements.length > 0) {
- setTimeout(function() {
- init.items.indexAsync(itemElements, valueNames);
- }, 10);
- } else {
- list.update();
- // TODO: Add indexed callback
- }
- };
-
- return function() {
- var itemsToIndex = getChildren(list.list),
- valueNames = list.valueNames;
+function isArray(arr) {
+ return Object.prototype.toString.call(arr) === "[object Array]";
+}
- if (list.indexAsync) {
- parseAsync(itemsToIndex, valueNames);
- } else {
- parse(itemsToIndex, valueNames);
- }
- };
+},{}],17:[function(require,module,exports){
+module.exports = function(s) {
+ s = (s === undefined) ? "" : s;
+ s = (s === null) ? "" : s;
+ s = s.toString();
+ return s;
};
-});
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-require.alias("component-classes/index.js", "list.js/deps/classes/index.js");
-require.alias("component-classes/index.js", "classes/index.js");
-require.alias("component-indexof/index.js", "component-classes/deps/indexof/index.js");
-
-require.alias("segmentio-extend/index.js", "list.js/deps/extend/index.js");
-require.alias("segmentio-extend/index.js", "extend/index.js");
-
-require.alias("component-indexof/index.js", "list.js/deps/indexof/index.js");
-require.alias("component-indexof/index.js", "indexof/index.js");
-
-require.alias("javve-events/index.js", "list.js/deps/events/index.js");
-require.alias("javve-events/index.js", "events/index.js");
-require.alias("component-event/index.js", "javve-events/deps/event/index.js");
-
-require.alias("timoxley-to-array/index.js", "javve-events/deps/to-array/index.js");
-
-require.alias("javve-get-by-class/index.js", "list.js/deps/get-by-class/index.js");
-require.alias("javve-get-by-class/index.js", "get-by-class/index.js");
-
-require.alias("javve-get-attribute/index.js", "list.js/deps/get-attribute/index.js");
-require.alias("javve-get-attribute/index.js", "get-attribute/index.js");
-
-require.alias("javve-natural-sort/index.js", "list.js/deps/natural-sort/index.js");
-require.alias("javve-natural-sort/index.js", "natural-sort/index.js");
-
-require.alias("javve-to-string/index.js", "list.js/deps/to-string/index.js");
-require.alias("javve-to-string/index.js", "list.js/deps/to-string/index.js");
-require.alias("javve-to-string/index.js", "to-string/index.js");
-require.alias("javve-to-string/index.js", "javve-to-string/index.js");
-require.alias("component-type/index.js", "list.js/deps/type/index.js");
-require.alias("component-type/index.js", "type/index.js");
-if (typeof exports == "object") {
- module.exports = require("list.js");
-} else if (typeof define == "function" && define.amd) {
- define(function(){ return require("list.js"); });
-} else {
- this["List"] = require("list.js");
-}})();
\ No newline at end of file
+},{}]},{},[1]);
diff --git a/index.js b/index.js
index 05d3192..131e03c 100644
--- a/index.js
+++ b/index.js
@@ -1,226 +1,272 @@
/*
-ListJS with beta 1.0.0
+List.js 1.1.1
By Jonny Strömberg (www.jonnystromberg.com, www.listjs.com)
*/
(function( window, undefined ) {
"use strict";
var document = window.document,
- getByClass = require('get-by-class'),
- extend = require('extend'),
- indexOf = require('indexof');
+ getByClass = require('./src/utils/get-by-class'),
+ extend = require('./src/utils/extend'),
+ indexOf = require('./src/utils/index-of'),
+ events = require('./src/utils/events'),
+ toString = require('./src/utils/to-string'),
+ naturalSort = require('./src/utils/natural-sort'),
+ classes = require('./src/utils/classes'),
+ getAttribute = require('./src/utils/get-attribute'),
+ toArray = require('./src/utils/to-array');
var List = function(id, options, values) {
- var self = this,
- init,
- Item = require('./src/item')(self),
- addAsync = require('./src/add-async')(self),
- parse = require('./src/parse')(self);
-
- init = {
- start: function() {
- self.listClass = "list";
- self.searchClass = "search";
- self.sortClass = "sort";
- self.page = 200;
- self.i = 1;
- self.items = [];
- self.visibleItems = [];
- self.matchingItems = [];
- self.searched = false;
- self.filtered = false;
- self.handlers = { 'updated': [] };
- self.plugins = {};
- self.helpers = {
- getByClass: getByClass,
- extend: extend,
- indexOf: indexOf
- };
-
- extend(self, options);
-
- self.listContainer = (typeof(id) === 'string') ? document.getElementById(id) : id;
- if (!self.listContainer) { return; }
- self.list = getByClass(self.listContainer, self.listClass, true);
-
- self.templater = require('./src/templater')(self);
- self.search = require('./src/search')(self);
- self.filter = require('./src/filter')(self);
- self.sort = require('./src/sort')(self);
-
- this.items();
- self.update();
- this.plugins();
- },
- items: function() {
- parse(self.list);
- if (values !== undefined) {
- self.add(values);
- }
- },
- plugins: function() {
- for (var i = 0; i < self.plugins.length; i++) {
- var plugin = self.plugins[i];
- self[plugin.name] = plugin;
- plugin.init(self);
- }
- }
- };
+ var self = this,
+ init,
+ Item = require('./src/item')(self),
+ addAsync = require('./src/add-async')(self);
+ init = {
+ start: function() {
+ self.listClass = "list";
+ self.searchClass = "search";
+ self.sortClass = "sort";
+ self.page = 10000;
+ self.i = 1;
+ self.items = [];
+ self.visibleItems = [];
+ self.matchingItems = [];
+ self.searched = false;
+ self.filtered = false;
+ self.searchColumns = undefined;
+ self.handlers = { 'updated': [] };
+ self.plugins = {};
+ self.valueNames = [];
+ self.utils = {
+ getByClass: getByClass,
+ extend: extend,
+ indexOf: indexOf,
+ events: events,
+ toString: toString,
+ naturalSort: naturalSort,
+ classes: classes,
+ getAttribute: getAttribute,
+ toArray: toArray
+ };
- /*
- * Add object to list
- */
- this.add = function(values, callback) {
- if (callback) {
- addAsync(values, callback);
- return;
- }
- var added = [],
- notCreate = false;
- if (values[0] === undefined){
- values = [values];
- }
- for (var i = 0, il = values.length; i < il; i++) {
- var item = null;
- if (values[i] instanceof Item) {
- item = values[i];
- item.reload();
- } else {
- notCreate = (self.items.length > self.page) ? true : false;
- item = new Item(values[i], undefined, notCreate);
- }
- self.items.push(item);
- added.push(item);
+ self.utils.extend(self, options);
+
+ self.listContainer = (typeof(id) === 'string') ? document.getElementById(id) : id;
+ if (!self.listContainer) { return; }
+ self.list = getByClass(self.listContainer, self.listClass, true);
+
+ self.parse = require('./src/parse')(self);
+ self.templater = require('./src/templater')(self);
+ self.search = require('./src/search')(self);
+ self.filter = require('./src/filter')(self);
+ self.sort = require('./src/sort')(self);
+
+ this.handlers();
+ this.items();
+ self.update();
+ this.plugins();
+ },
+ handlers: function() {
+ for (var handler in self.handlers) {
+ if (self[handler]) {
+ self.on(handler, self[handler]);
}
- self.update();
- return added;
- };
+ }
+ },
+ items: function() {
+ self.parse(self.list);
+ if (values !== undefined) {
+ self.add(values);
+ }
+ },
+ plugins: function() {
+ for (var i = 0; i < self.plugins.length; i++) {
+ var plugin = self.plugins[i];
+ self[plugin.name] = plugin;
+ plugin.init(self, List);
+ }
+ }
+ };
+
+ /*
+ * Re-parse the List, use if html have changed
+ */
+ this.reIndex = function() {
+ self.items = [];
+ self.visibleItems = [];
+ self.matchingItems = [];
+ self.searched = false;
+ self.filtered = false;
+ self.parse(self.list);
+ };
+
+ this.toJSON = function() {
+ var json = [];
+ for (var i = 0, il = self.items.length; i < il; i++) {
+ json.push(self.items[i].values());
+ }
+ return json;
+ };
+
+
+ /*
+ * Add object to list
+ */
+ this.add = function(values, callback) {
+ if (values.length === 0) {
+ return;
+ }
+ if (callback) {
+ addAsync(values, callback);
+ return;
+ }
+ var added = [],
+ notCreate = false;
+ if (values[0] === undefined){
+ values = [values];
+ }
+ for (var i = 0, il = values.length; i < il; i++) {
+ var item = null;
+ notCreate = (self.items.length > self.page) ? true : false;
+ item = new Item(values[i], undefined, notCreate);
+ self.items.push(item);
+ added.push(item);
+ }
+ self.update();
+ return added;
+ };
this.show = function(i, page) {
this.i = i;
this.page = page;
self.update();
- return self;
+ return self;
};
- /* Removes object from list.
- * Loops through the list and removes objects where
- * property "valuename" === value
- */
- this.remove = function(valueName, value, options) {
- var found = 0;
- for (var i = 0, il = self.items.length; i < il; i++) {
- if (self.items[i].values()[valueName] == value) {
- self.templater.remove(self.items[i], options);
- self.items.splice(i,1);
- il--;
- i--;
- found++;
- }
- }
- self.update();
- return found;
- };
-
- /* Gets the objects in the list which
- * property "valueName" === value
- */
- this.get = function(valueName, value) {
- var matchedItems = [];
- for (var i = 0, il = self.items.length; i < il; i++) {
- var item = self.items[i];
- if (item.values()[valueName] == value) {
- matchedItems.push(item);
- }
- }
- return matchedItems;
- };
-
- /*
- * Get size of the list
- */
- this.size = function() {
- return self.items.length;
- };
-
- /*
- * Removes all items from the list
- */
- this.clear = function() {
- self.templater.clear();
- self.items = [];
- return self;
- };
-
- this.on = function(event, callback) {
- self.handlers[event].push(callback);
- return self;
- };
-
- this.off = function(event, callback) {
- var e = self.handlers[event];
- var index = indexOf(e, callback);
- if (index > -1) {
- e.splice(index, 1);
- }
- return self;
- };
+ /* Removes object from list.
+ * Loops through the list and removes objects where
+ * property "valuename" === value
+ */
+ this.remove = function(valueName, value, options) {
+ var found = 0;
+ for (var i = 0, il = self.items.length; i < il; i++) {
+ if (self.items[i].values()[valueName] == value) {
+ self.templater.remove(self.items[i], options);
+ self.items.splice(i,1);
+ il--;
+ i--;
+ found++;
+ }
+ }
+ self.update();
+ return found;
+ };
- this.trigger = function(event) {
- var i = self.handlers[event].length;
- while(i--) {
- self.handlers[event][i](self);
- }
- return self;
- };
-
- this.reset = {
- filter: function() {
- var is = self.items,
- il = is.length;
- while (il--) {
- is[il].filtered = false;
- }
- return self;
- },
- search: function() {
- var is = self.items,
- il = is.length;
- while (il--) {
- is[il].found = false;
- }
- return self;
- }
- };
+ /* Gets the objects in the list which
+ * property "valueName" === value
+ */
+ this.get = function(valueName, value) {
+ var matchedItems = [];
+ for (var i = 0, il = self.items.length; i < il; i++) {
+ var item = self.items[i];
+ if (item.values()[valueName] == value) {
+ matchedItems.push(item);
+ }
+ }
+ return matchedItems;
+ };
+
+ /*
+ * Get size of the list
+ */
+ this.size = function() {
+ return self.items.length;
+ };
+
+ /*
+ * Removes all items from the list
+ */
+ this.clear = function() {
+ self.templater.clear();
+ self.items = [];
+ return self;
+ };
+
+ this.on = function(event, callback) {
+ self.handlers[event].push(callback);
+ return self;
+ };
- this.update = function() {
- var is = self.items,
+ this.off = function(event, callback) {
+ var e = self.handlers[event];
+ var index = indexOf(e, callback);
+ if (index > -1) {
+ e.splice(index, 1);
+ }
+ return self;
+ };
+
+ this.trigger = function(event) {
+ var i = self.handlers[event].length;
+ while(i--) {
+ self.handlers[event][i](self);
+ }
+ return self;
+ };
+
+ this.reset = {
+ filter: function() {
+ var is = self.items,
+ il = is.length;
+ while (il--) {
+ is[il].filtered = false;
+ }
+ return self;
+ },
+ search: function() {
+ var is = self.items,
+ il = is.length;
+ while (il--) {
+ is[il].found = false;
+ }
+ return self;
+ }
+ };
+
+ this.update = function() {
+ var is = self.items,
il = is.length;
- self.visibleItems = [];
- self.matchingItems = [];
- self.templater.clear();
- for (var i = 0; i < il; i++) {
- if (is[i].matching() && ((self.matchingItems.length+1) >= self.i && self.visibleItems.length < self.page)) {
- is[i].show();
- self.visibleItems.push(is[i]);
- self.matchingItems.push(is[i]);
- } else if (is[i].matching()) {
- self.matchingItems.push(is[i]);
- is[i].hide();
- } else {
- is[i].hide();
- }
- }
- self.trigger('updated');
- return self;
- };
+ self.visibleItems = [];
+ self.matchingItems = [];
+ self.templater.clear();
+ for (var i = 0; i < il; i++) {
+ if (is[i].matching() && ((self.matchingItems.length+1) >= self.i && self.visibleItems.length < self.page)) {
+ is[i].show();
+ self.visibleItems.push(is[i]);
+ self.matchingItems.push(is[i]);
+ } else if (is[i].matching()) {
+ self.matchingItems.push(is[i]);
+ is[i].hide();
+ } else {
+ is[i].hide();
+ }
+ }
+ self.trigger('updated');
+ return self;
+ };
- init.start();
+ init.start();
};
+
+// AMD support
+if (typeof define === 'function' && define.amd) {
+ define(function () { return List; });
+}
module.exports = List;
+window.List = List;
})(window);
diff --git a/package.json b/package.json
index 81c4504..460cef2 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "list.js",
- "version": "1.1.1",
- "description": "Component package manager consuming git repositories",
+ "version": "1.2.0",
+ "description": "The perfect library for adding search, sort, filters and flexibility to tables, lists and various HTML elements. Built to be invisible and work on existing HTML",
"keywords": [
"list",
"search",
@@ -15,15 +15,28 @@
"repository": "git://github.com/javve/list.js.git",
"dependencies": {},
"devDependencies": {
- "grunt": "~0.4.1",
- "grunt-shell": "~0.5.0",
- "grunt-contrib-watch": "~0.5.3",
- "grunt-contrib-uglify": "~0.2.7",
- "grunt-contrib-jshint": "~0.7.1",
- "grunt-mocha": "~0.4.1"
+ "browserify": "^13.0.0",
+ "expect.js": "^0.3.1",
+ "grunt": "^0.4.5",
+ "grunt-cli": "^0.1.13",
+ "grunt-contrib-jshint": "^0.12.0",
+ "grunt-contrib-uglify": "^0.11.0",
+ "grunt-contrib-watch": "^0.6.1",
+ "grunt-mocha": "^0.4.15",
+ "grunt-shell": "^1.1.2",
+ "jquery": "^1.12.0"
},
"main": "index",
"engines": {
"node": ">= 0.10.21"
- }
+ },
+ "npmName": "list.js",
+ "npmFileMap": [
+ {
+ "basePath": "/dist/",
+ "files": [
+ "*.js"
+ ]
+ }
+ ]
}
diff --git a/src/add-async.js b/src/add-async.js
index 432333b..aa223f3 100644
--- a/src/add-async.js
+++ b/src/add-async.js
@@ -1,15 +1,16 @@
module.exports = function(list) {
- return function(values, callback, items) {
- var valuesToAdd = values.splice(0, 100);
- items = items || [];
- items = items.concat(list.add(valuesToAdd));
- if (values.length > 0) {
- setTimeout(function() {
- addAsync(values, callback, items);
- }, 10);
- } else {
- list.update();
- callback(items);
- }
- };
-};
\ No newline at end of file
+ var addAsync = function(values, callback, items) {
+ var valuesToAdd = values.splice(0, 50);
+ items = items || [];
+ items = items.concat(list.add(valuesToAdd));
+ if (values.length > 0) {
+ setTimeout(function() {
+ addAsync(values, callback, items);
+ }, 1);
+ } else {
+ list.update();
+ callback(items);
+ }
+ };
+ return addAsync;
+};
diff --git a/src/filter.js b/src/filter.js
index df6b2f0..4b14767 100644
--- a/src/filter.js
+++ b/src/filter.js
@@ -1,29 +1,29 @@
module.exports = function(list) {
- // Add handlers
- list.handlers.filterStart = list.handlers.filterStart || [];
- list.handlers.filterComplete = list.handlers.filterComplete || [];
+ // Add handlers
+ list.handlers.filterStart = list.handlers.filterStart || [];
+ list.handlers.filterComplete = list.handlers.filterComplete || [];
- return function(filterFunction) {
- list.trigger('filterStart');
- list.i = 1; // Reset paging
- list.reset.filter();
- if (filterFunction === undefined) {
- list.filtered = false;
+ return function(filterFunction) {
+ list.trigger('filterStart');
+ list.i = 1; // Reset paging
+ list.reset.filter();
+ if (filterFunction === undefined) {
+ list.filtered = false;
+ } else {
+ list.filtered = true;
+ var is = list.items;
+ for (var i = 0, il = is.length; i < il; i++) {
+ var item = is[i];
+ if (filterFunction(item)) {
+ item.filtered = true;
} else {
- list.filtered = true;
- var is = list.items;
- for (var i = 0, il = is.length; i < il; i++) {
- var item = is[i];
- if (filterFunction(item)) {
- item.filtered = true;
- } else {
- item.filtered = false;
- }
- }
+ item.filtered = false;
}
- list.update();
- list.trigger('filterComplete');
- return list.visibleItems;
- };
+ }
+ }
+ list.update();
+ list.trigger('filterComplete');
+ return list.visibleItems;
+ };
};
diff --git a/src/item.js b/src/item.js
index 307a914..f5ab9a1 100644
--- a/src/item.js
+++ b/src/item.js
@@ -1,54 +1,60 @@
module.exports = function(list) {
- return function(initValues, element, notCreate) {
- var item = this;
-
- this._values = {};
-
- this.found = false; // Show if list.searched == true and this.found == true
- this.filtered = false;// Show if list.filtered == true and this.filtered == true
-
- var init = function(initValues, element, notCreate) {
- if (element === undefined) {
- if (notCreate) {
- item.values(initValues, notCreate);
- } else {
- item.values(initValues);
- }
- } else {
- item.elm = element;
- var values = list.templater.get(item, initValues);
- item.values(values);
- }
- };
- this.values = function(newValues, notCreate) {
- if (newValues !== undefined) {
- for(var name in newValues) {
- item._values[name] = newValues[name];
- }
- if (notCreate !== true) {
- list.templater.set(item, item.values());
- }
- } else {
- return item._values;
- }
- };
- this.show = function() {
- list.templater.show(item);
- };
- this.hide = function() {
- list.templater.hide(item);
- };
- this.matching = function() {
- return (
- (list.filtered && list.searched && item.found && item.filtered) ||
- (list.filtered && !list.searched && item.filtered) ||
- (!list.filtered && list.searched && item.found) ||
- (!list.filtered && !list.searched)
- );
- };
- this.visible = function() {
- return (item.elm.parentNode == list.list) ? true : false;
- };
- init(initValues, element, notCreate);
+ return function(initValues, element, notCreate) {
+ var item = this;
+
+ this._values = {};
+
+ this.found = false; // Show if list.searched == true and this.found == true
+ this.filtered = false;// Show if list.filtered == true and this.filtered == true
+
+ var init = function(initValues, element, notCreate) {
+ if (element === undefined) {
+ if (notCreate) {
+ item.values(initValues, notCreate);
+ } else {
+ item.values(initValues);
+ }
+ } else {
+ item.elm = element;
+ var values = list.templater.get(item, initValues);
+ item.values(values);
+ }
+ };
+
+ this.values = function(newValues, notCreate) {
+ if (newValues !== undefined) {
+ for(var name in newValues) {
+ item._values[name] = newValues[name];
+ }
+ if (notCreate !== true) {
+ list.templater.set(item, item.values());
+ }
+ } else {
+ return item._values;
+ }
+ };
+
+ this.show = function() {
+ list.templater.show(item);
};
+
+ this.hide = function() {
+ list.templater.hide(item);
+ };
+
+ this.matching = function() {
+ return (
+ (list.filtered && list.searched && item.found && item.filtered) ||
+ (list.filtered && !list.searched && item.filtered) ||
+ (!list.filtered && list.searched && item.found) ||
+ (!list.filtered && !list.searched)
+ );
+ };
+
+ this.visible = function() {
+ return (item.elm && (item.elm.parentNode == list.list)) ? true : false;
+ };
+
+ init(initValues, element, notCreate);
+ };
};
diff --git a/src/parse.js b/src/parse.js
index cb39cf3..2294a47 100644
--- a/src/parse.js
+++ b/src/parse.js
@@ -1,45 +1,47 @@
module.exports = function(list) {
- var Item = require('./item')(list);
+ var Item = require('./item')(list);
- var getChildren = function(parent) {
- var nodes = parent.childNodes,
- items = [];
- for (var i = 0, il = nodes.length; i < il; i++) {
- // Only textnodes have a data attribute
- if (nodes[i].data === undefined) {
- items.push(nodes[i]);
- }
- }
- return items;
- };
+ var getChildren = function(parent) {
+ var nodes = parent.childNodes,
+ items = [];
+ for (var i = 0, il = nodes.length; i < il; i++) {
+ // Only textnodes have a data attribute
+ if (nodes[i].data === undefined) {
+ items.push(nodes[i]);
+ }
+ }
+ return items;
+ };
- var parse = function(itemElements, valueNames) {
- for (var i = 0, il = itemElements.length; i < il; i++) {
- list.items.push(new Item(valueNames, itemElements[i]));
- }
- };
- var parseAsync = function(itemElements, valueNames) {
- var itemsToIndex = itemElements.splice(0, 100); // TODO: If < 100 items, what happens in IE etc?
- parse(itemsToIndex, valueNames);
- if (itemElements.length > 0) {
- setTimeout(function() {
- init.items.indexAsync(itemElements, valueNames);
- }, 10);
- } else {
- list.update();
- // TODO: Add indexed callback
- }
- };
+ var parse = function(itemElements, valueNames) {
+ for (var i = 0, il = itemElements.length; i < il; i++) {
+ list.items.push(new Item(valueNames, itemElements[i]));
+ }
+ };
+ var parseAsync = function(itemElements, valueNames) {
+ var itemsToIndex = itemElements.splice(0, 50); // TODO: If < 100 items, what happens in IE etc?
+ parse(itemsToIndex, valueNames);
+ if (itemElements.length > 0) {
+ setTimeout(function() {
+ parseAsync(itemElements, valueNames);
+ }, 1);
+ } else {
+ list.update();
+ list.trigger('parseComplete');
+ }
+ };
- return function() {
- var itemsToIndex = getChildren(list.list),
- valueNames = list.valueNames;
+ list.handlers.parseComplete = list.handlers.parseComplete || [];
- if (list.indexAsync) {
- parseAsync(itemsToIndex, valueNames);
- } else {
- parse(itemsToIndex, valueNames);
- }
- };
+ return function() {
+ var itemsToIndex = getChildren(list.list),
+ valueNames = list.valueNames;
+
+ if (list.indexAsync) {
+ parseAsync(itemsToIndex, valueNames);
+ } else {
+ parse(itemsToIndex, valueNames);
+ }
+ };
};
diff --git a/src/search.js b/src/search.js
index f3434fa..2aeeb00 100644
--- a/src/search.js
+++ b/src/search.js
@@ -1,119 +1,117 @@
-var events = require('events'),
- getByClass = require('get-by-class'),
- toString = require('to-string');
-
module.exports = function(list) {
- var item,
- text,
- columns,
- searchString,
- customSearch;
+ var item,
+ text,
+ columns,
+ searchString,
+ customSearch;
- var prepare = {
- resetList: function() {
- list.i = 1;
- list.templater.clear();
- customSearch = undefined;
- },
- setOptions: function(args) {
- if (args.length == 2 && args[1] instanceof Array) {
- columns = args[1];
- } else if (args.length == 2 && typeof(args[1]) == "function") {
- customSearch = args[1];
- } else if (args.length == 3) {
- columns = args[1];
- customSearch = args[2];
- }
- },
- setColumns: function() {
- columns = (columns === undefined) ? prepare.toArray(list.items[0].values()) : columns;
- },
- setSearchString: function(s) {
- s = toString(s).toLowerCase();
- s = s.replace(/[-[\]{}()*+?.,\\^$|#]/g, "\\$&"); // Escape regular expression characters
- searchString = s;
- },
- toArray: function(values) {
- var tmpColumn = [];
- for (var name in values) {
- tmpColumn.push(name);
- }
- return tmpColumn;
+ var prepare = {
+ resetList: function() {
+ list.i = 1;
+ list.templater.clear();
+ customSearch = undefined;
+ },
+ setOptions: function(args) {
+ if (args.length == 2 && args[1] instanceof Array) {
+ columns = args[1];
+ } else if (args.length == 2 && typeof(args[1]) == "function") {
+ customSearch = args[1];
+ } else if (args.length == 3) {
+ columns = args[1];
+ customSearch = args[2];
+ }
+ },
+ setColumns: function() {
+ if (list.items.length === 0) return;
+ if (columns === undefined) {
+ columns = (list.searchColumns === undefined) ? prepare.toArray(list.items[0].values()) : list.searchColumns;
+ }
+ },
+ setSearchString: function(s) {
+ s = list.utils.toString(s).toLowerCase();
+ s = s.replace(/[-[\]{}()*+?.,\\^$|#]/g, "\\$&"); // Escape regular expression characters
+ searchString = s;
+ },
+ toArray: function(values) {
+ var tmpColumn = [];
+ for (var name in values) {
+ tmpColumn.push(name);
+ }
+ return tmpColumn;
+ }
+ };
+ var search = {
+ list: function() {
+ for (var k = 0, kl = list.items.length; k < kl; k++) {
+ search.item(list.items[k]);
+ }
+ },
+ item: function(item) {
+ item.found = false;
+ for (var j = 0, jl = columns.length; j < jl; j++) {
+ if (search.values(item.values(), columns[j])) {
+ item.found = true;
+ return;
}
- };
- var search = {
- list: function() {
- for (var k = 0, kl = list.items.length; k < kl; k++) {
- search.item(list.items[k]);
- }
- },
- item: function(item) {
- item.found = false;
- for (var j = 0, jl = columns.length; j < jl; j++) {
- if (search.values(item.values(), columns[j])) {
- item.found = true;
- return;
- }
- }
- },
- values: function(values, column) {
- if (values.hasOwnProperty(column)) {
- text = toString(values[column]).toLowerCase();
- if ((searchString !== "") && (text.search(searchString) > -1)) {
- return true;
- }
- }
- return false;
- },
- reset: function() {
- list.reset.search();
- list.searched = false;
+ }
+ },
+ values: function(values, column) {
+ if (values.hasOwnProperty(column)) {
+ text = list.utils.toString(values[column]).toLowerCase();
+ if ((searchString !== "") && (text.search(searchString) > -1)) {
+ return true;
}
- };
+ }
+ return false;
+ },
+ reset: function() {
+ list.reset.search();
+ list.searched = false;
+ }
+ };
- var searchMethod = function(str) {
- list.trigger('searchStart');
+ var searchMethod = function(str) {
+ list.trigger('searchStart');
- prepare.resetList();
- prepare.setSearchString(str);
- prepare.setOptions(arguments); // str, cols|searchFunction, searchFunction
- prepare.setColumns();
+ prepare.resetList();
+ prepare.setSearchString(str);
+ prepare.setOptions(arguments); // str, cols|searchFunction, searchFunction
+ prepare.setColumns();
- if (searchString === "" ) {
- search.reset();
- } else {
- list.searched = true;
- if (customSearch) {
- customSearch(searchString, columns);
- } else {
- search.list();
- }
- }
+ if (searchString === "" ) {
+ search.reset();
+ } else {
+ list.searched = true;
+ if (customSearch) {
+ customSearch(searchString, columns);
+ } else {
+ search.list();
+ }
+ }
- list.update();
- list.trigger('searchComplete');
- return list.visibleItems;
- };
+ list.update();
+ list.trigger('searchComplete');
+ return list.visibleItems;
+ };
- list.handlers.searchStart = list.handlers.searchStart || [];
- list.handlers.searchComplete = list.handlers.searchComplete || [];
+ list.handlers.searchStart = list.handlers.searchStart || [];
+ list.handlers.searchComplete = list.handlers.searchComplete || [];
- events.bind(getByClass(list.listContainer, list.searchClass), 'keyup', function(e) {
- var target = e.target || e.srcElement, // IE have srcElement
- alreadyCleared = (target.value === "" && !list.searched);
- if (!alreadyCleared) { // If oninput already have resetted the list, do nothing
- searchMethod(target.value);
- }
- });
+ list.utils.events.bind(list.utils.getByClass(list.listContainer, list.searchClass), 'keyup', function(e) {
+ var target = e.target || e.srcElement, // IE have srcElement
+ alreadyCleared = (target.value === "" && !list.searched);
+ if (!alreadyCleared) { // If oninput already have resetted the list, do nothing
+ searchMethod(target.value);
+ }
+ });
- // Used to detect click on HTML5 clear button
- events.bind(getByClass(list.listContainer, list.searchClass), 'input', function(e) {
- var target = e.target || e.srcElement;
- if (target.value === "") {
- searchMethod('');
- }
- });
+ // Used to detect click on HTML5 clear button
+ list.utils.events.bind(list.utils.getByClass(list.listContainer, list.searchClass), 'input', function(e) {
+ var target = e.target || e.srcElement;
+ if (target.value === "") {
+ searchMethod('');
+ }
+ });
- list.helpers.toString = toString;
- return searchMethod;
+ return searchMethod;
};
diff --git a/src/sort.js b/src/sort.js
index 3373012..18030f6 100644
--- a/src/sort.js
+++ b/src/sort.js
@@ -1,101 +1,90 @@
-var naturalSort = require('natural-sort'),
- classes = require('classes'),
- events = require('events'),
- getByClass = require('get-by-class'),
- getAttribute = require('get-attribute');
-
module.exports = function(list) {
- list.sortFunction = list.sortFunction || function(itemA, itemB, options) {
- options.desc = options.order == "desc" ? true : false; // Natural sort uses this format
- return naturalSort(itemA.values()[options.valueName], itemB.values()[options.valueName], options);
- };
+ list.sortFunction = list.sortFunction || function(itemA, itemB, options) {
+ options.desc = options.order == "desc" ? true : false; // Natural sort uses this format
+ return list.utils.naturalSort(itemA.values()[options.valueName], itemB.values()[options.valueName], options);
+ };
- var buttons = {
- els: undefined,
- clear: function() {
- for (var i = 0, il = buttons.els.length; i < il; i++) {
- classes(buttons.els[i]).remove('asc');
- classes(buttons.els[i]).remove('desc');
- }
- },
- getOrder: function(btn) {
- var predefinedOrder = getAttribute(btn, 'data-order');
- if (predefinedOrder == "asc" || predefinedOrder == "desc") {
- return predefinedOrder;
- } else if (classes(btn).has('desc')) {
- return "asc";
- } else if (classes(btn).has('asc')) {
- return "desc";
- } else {
- return "asc";
- }
- },
- getInSensitive: function(btn, options) {
- var insensitive = getAttribute(btn, 'data-insensitive');
- if (insensitive === "true") {
- options.insensitive = true;
- } else {
- options.insensitive = false;
- }
- },
- setOrder: function(options) {
- for (var i = 0, il = buttons.els.length; i < il; i++) {
- var btn = buttons.els[i];
- if (getAttribute(btn, 'data-sort') !== options.valueName) {
- continue;
- }
- var predefinedOrder = getAttribute(btn, 'data-order');
- if (predefinedOrder == "asc" || predefinedOrder == "desc") {
- if (predefinedOrder == options.order) {
- classes(btn).add(options.order);
- }
- } else {
- classes(btn).add(options.order);
- }
- }
+ var buttons = {
+ els: undefined,
+ clear: function() {
+ for (var i = 0, il = buttons.els.length; i < il; i++) {
+ list.utils.classes(buttons.els[i]).remove('asc');
+ list.utils.classes(buttons.els[i]).remove('desc');
+ }
+ },
+ getOrder: function(btn) {
+ var predefinedOrder = list.utils.getAttribute(btn, 'data-order');
+ if (predefinedOrder == "asc" || predefinedOrder == "desc") {
+ return predefinedOrder;
+ } else if (list.utils.classes(btn).has('desc')) {
+ return "asc";
+ } else if (list.utils.classes(btn).has('asc')) {
+ return "desc";
+ } else {
+ return "asc";
+ }
+ },
+ getInSensitive: function(btn, options) {
+ var insensitive = list.utils.getAttribute(btn, 'data-insensitive');
+ if (insensitive === "false") {
+ options.insensitive = false;
+ } else {
+ options.insensitive = true;
+ }
+ },
+ setOrder: function(options) {
+ for (var i = 0, il = buttons.els.length; i < il; i++) {
+ var btn = buttons.els[i];
+ if (list.utils.getAttribute(btn, 'data-sort') !== options.valueName) {
+ continue;
}
- };
- var sort = function() {
- list.trigger('sortStart');
- options = {};
-
- var target = arguments[0].currentTarget || arguments[0].srcElement || undefined;
-
- if (target) {
- options.valueName = getAttribute(target, 'data-sort');
- buttons.getInSensitive(target, options);
- options.order = buttons.getOrder(target);
+ var predefinedOrder = list.utils.getAttribute(btn, 'data-order');
+ if (predefinedOrder == "asc" || predefinedOrder == "desc") {
+ if (predefinedOrder == options.order) {
+ list.utils.classes(btn).add(options.order);
+ }
} else {
- options = arguments[1] || options;
- options.valueName = arguments[0];
- options.order = options.order || "asc";
- options.insensitive = (typeof options.insensitive == "undefined") ? true : options.insensitive;
+ list.utils.classes(btn).add(options.order);
}
- buttons.clear();
- buttons.setOrder(options);
+ }
+ }
+ };
+ var sort = function() {
+ list.trigger('sortStart');
+ var options = {};
+
+ var target = arguments[0].currentTarget || arguments[0].srcElement || undefined;
- options.sortFunction = options.sortFunction || list.sortFunction;
- list.items.sort(function(a, b) {
- return options.sortFunction(a, b, options);
- });
- list.update();
- list.trigger('sortComplete');
- };
+ if (target) {
+ options.valueName = list.utils.getAttribute(target, 'data-sort');
+ buttons.getInSensitive(target, options);
+ options.order = buttons.getOrder(target);
+ } else {
+ options = arguments[1] || options;
+ options.valueName = arguments[0];
+ options.order = options.order || "asc";
+ options.insensitive = (typeof options.insensitive == "undefined") ? true : options.insensitive;
+ }
+ buttons.clear();
+ buttons.setOrder(options);
- // Add handlers
- list.handlers.sortStart = list.handlers.sortStart || [];
- list.handlers.sortComplete = list.handlers.sortComplete || [];
+ options.sortFunction = options.sortFunction || list.sortFunction;
+ list.items.sort(function(a, b) {
+ var mult = (options.order === 'desc') ? -1 : 1;
+ return (options.sortFunction(a, b, options) * mult);
+ });
+ list.update();
+ list.trigger('sortComplete');
+ };
- buttons.els = getByClass(list.listContainer, list.sortClass);
- events.bind(buttons.els, 'click', sort);
- list.on('searchStart', buttons.clear);
- list.on('filterStart', buttons.clear);
+ // Add handlers
+ list.handlers.sortStart = list.handlers.sortStart || [];
+ list.handlers.sortComplete = list.handlers.sortComplete || [];
- // Helpers
- list.helpers.classes = classes;
- list.helpers.naturalSort = naturalSort;
- list.helpers.events = events;
- list.helpers.getAttribute = getAttribute;
+ buttons.els = list.utils.getByClass(list.listContainer, list.sortClass);
+ list.utils.events.bind(buttons.els, 'click', sort);
+ list.on('searchStart', buttons.clear);
+ list.on('filterStart', buttons.clear);
- return sort;
+ return sort;
};
diff --git a/src/templater.js b/src/templater.js
index 29b8d02..782fd60 100644
--- a/src/templater.js
+++ b/src/templater.js
@@ -1,96 +1,169 @@
-var getByClass = require('get-by-class');
-
var Templater = function(list) {
- var itemSource = getItemSource(list.item),
- templater = this;
+ var itemSource,
+ templater = this;
- function getItemSource(item) {
- if (item === undefined) {
- var nodes = list.list.childNodes,
- items = [];
+ var init = function() {
+ itemSource = templater.getItemSource(list.item);
+ itemSource = templater.clearSourceItem(itemSource, list.valueNames);
+ };
- for (var i = 0, il = nodes.length; i < il; i++) {
- // Only textnodes have a data attribute
- if (nodes[i].data === undefined) {
- return nodes[i];
- }
- }
- return null;
- } else if (item.indexOf("<") !== -1) { // Try create html element of list, do not work for tables!!
- var div = document.createElement('div');
- div.innerHTML = item;
- return div.firstChild;
- } else {
- return document.getElementById(list.item);
+ this.clearSourceItem = function(el, valueNames) {
+ for(var i = 0, il = valueNames.length; i < il; i++) {
+ var elm;
+ if (valueNames[i].data) {
+ for (var j = 0, jl = valueNames[i].data.length; j < jl; j++) {
+ el.setAttribute('data-'+valueNames[i].data[j], '');
+ }
+ } else if (valueNames[i].attr && valueNames[i].name) {
+ elm = list.utils.getByClass(el, valueNames[i].name, true);
+ if (elm) {
+ elm.setAttribute(valueNames[i].attr, "");
}
+ } else {
+ elm = list.utils.getByClass(el, valueNames[i], true);
+ if (elm) {
+ elm.innerHTML = "";
+ }
+ }
+ elm = undefined;
}
+ return el;
+ };
+
+ this.getItemSource = function(item) {
+ if (item === undefined) {
+ var nodes = list.list.childNodes,
+ items = [];
- /* Get values from element */
- this.get = function(item, valueNames) {
- templater.create(item);
- var values = {};
- for(var i = 0, il = valueNames.length; i < il; i++) {
- var elm = getByClass(item.elm, valueNames[i], true);
- values[valueNames[i]] = elm ? elm.innerHTML : "";
+ for (var i = 0, il = nodes.length; i < il; i++) {
+ // Only textnodes have a data attribute
+ if (nodes[i].data === undefined) {
+ return nodes[i].cloneNode(true);
}
- return values;
- };
+ }
+ } else if (/^tr[\s>]/.exec(item)) {
+ var table = document.createElement('table');
+ table.innerHTML = item;
+ return table.firstChild;
+ } else if (item.indexOf("<") !== -1) {
+ var div = document.createElement('div');
+ div.innerHTML = item;
+ return div.firstChild;
+ } else {
+ var source = document.getElementById(list.item);
+ if (source) {
+ return source;
+ }
+ }
+ throw new Error("The list need to have at list one item on init otherwise you'll have to add a template.");
+ };
- /* Sets values at element */
- this.set = function(item, values) {
- if (!templater.create(item)) {
- for(var v in values) {
- if (values.hasOwnProperty(v)) {
- // TODO speed up if possible
- var elm = getByClass(item.elm, v, true);
- if (elm) {
- /* src attribute for image tag & text for other tags */
- if (elm.tagName === "IMG" && values[v] !== "") {
- elm.src = values[v];
- } else {
- elm.innerHTML = values[v];
- }
- }
- }
- }
+ this.get = function(item, valueNames) {
+ templater.create(item);
+ var values = {};
+ for(var i = 0, il = valueNames.length; i < il; i++) {
+ var elm;
+ if (valueNames[i].data) {
+ for (var j = 0, jl = valueNames[i].data.length; j < jl; j++) {
+ values[valueNames[i].data[j]] = list.utils.getAttribute(item.elm, 'data-'+valueNames[i].data[j]);
}
- };
+ } else if (valueNames[i].attr && valueNames[i].name) {
+ elm = list.utils.getByClass(item.elm, valueNames[i].name, true);
+ values[valueNames[i].name] = elm ? list.utils.getAttribute(elm, valueNames[i].attr) : "";
+ } else {
+ elm = list.utils.getByClass(item.elm, valueNames[i], true);
+ values[valueNames[i]] = elm ? elm.innerHTML : "";
+ }
+ elm = undefined;
+ }
+ return values;
+ };
- this.create = function(item) {
- if (item.elm !== undefined) {
- return false;
+ this.set = function(item, values) {
+ var getValueName = function(name) {
+ for (var i = 0, il = list.valueNames.length; i < il; i++) {
+ if (list.valueNames[i].data) {
+ var data = list.valueNames[i].data;
+ for (var j = 0, jl = data.length; j < jl; j++) {
+ if (data[j] === name) {
+ return { data: name };
+ }
+ }
+ } else if (list.valueNames[i].attr && list.valueNames[i].name && list.valueNames[i].name == name) {
+ return list.valueNames[i];
+ } else if (list.valueNames[i] === name) {
+ return name;
}
- /* If item source does not exists, use the first item in list as
- source for new items */
- var newItem = itemSource.cloneNode(true);
- newItem.removeAttribute('id');
- item.elm = newItem;
- templater.set(item, item.values());
- return true;
- };
- this.remove = function(item) {
- list.list.removeChild(item.elm);
+ }
};
- this.show = function(item) {
- templater.create(item);
- list.list.appendChild(item.elm);
- };
- this.hide = function(item) {
- if (item.elm !== undefined && item.elm.parentNode === list.list) {
- list.list.removeChild(item.elm);
+ var setValue = function(name, value) {
+ var elm;
+ var valueName = getValueName(name);
+ if (!valueName)
+ return;
+ if (valueName.data) {
+ item.elm.setAttribute('data-'+valueName.data, value);
+ } else if (valueName.attr && valueName.name) {
+ elm = list.utils.getByClass(item.elm, valueName.name, true);
+ if (elm) {
+ elm.setAttribute(valueName.attr, value);
}
- };
- this.clear = function() {
- /* .innerHTML = ''; fucks up IE */
- if (list.list.hasChildNodes()) {
- while (list.list.childNodes.length >= 1)
- {
- list.list.removeChild(list.list.firstChild);
- }
+ } else {
+ elm = list.utils.getByClass(item.elm, valueName, true);
+ if (elm) {
+ elm.innerHTML = value;
}
+ }
+ elm = undefined;
};
+ if (!templater.create(item)) {
+ for(var v in values) {
+ if (values.hasOwnProperty(v)) {
+ setValue(v, values[v]);
+ }
+ }
+ }
+ };
+
+ this.create = function(item) {
+ if (item.elm !== undefined) {
+ return false;
+ }
+ /* If item source does not exists, use the first item in list as
+ source for new items */
+ var newItem = itemSource.cloneNode(true);
+ newItem.removeAttribute('id');
+ item.elm = newItem;
+ templater.set(item, item.values());
+ return true;
+ };
+ this.remove = function(item) {
+ if (item.elm.parentNode === list.list) {
+ list.list.removeChild(item.elm);
+ }
+ };
+ this.show = function(item) {
+ templater.create(item);
+ list.list.appendChild(item.elm);
+ };
+ this.hide = function(item) {
+ if (item.elm !== undefined && item.elm.parentNode === list.list) {
+ list.list.removeChild(item.elm);
+ }
+ };
+ this.clear = function() {
+ /* .innerHTML = ''; fucks up IE */
+ if (list.list.hasChildNodes()) {
+ while (list.list.childNodes.length >= 1)
+ {
+ list.list.removeChild(list.list.firstChild);
+ }
+ }
+ };
+
+ init();
};
module.exports = function(list) {
- return new Templater(list);
+ return new Templater(list);
};
diff --git a/src/utils/classes.js b/src/utils/classes.js
new file mode 100644
index 0000000..d7b5430
--- /dev/null
+++ b/src/utils/classes.js
@@ -0,0 +1,185 @@
+/**
+ * Module dependencies.
+ */
+
+var index = require('./index-of');
+
+/**
+ * Whitespace regexp.
+ */
+
+var re = /\s+/;
+
+/**
+ * toString reference.
+ */
+
+var toString = Object.prototype.toString;
+
+/**
+ * Wrap `el` in a `ClassList`.
+ *
+ * @param {Element} el
+ * @return {ClassList}
+ * @api public
+ */
+
+module.exports = function(el){
+ return new ClassList(el);
+};
+
+/**
+ * Initialize a new ClassList for `el`.
+ *
+ * @param {Element} el
+ * @api private
+ */
+
+function ClassList(el) {
+ if (!el || !el.nodeType) {
+ throw new Error('A DOM element reference is required');
+ }
+ this.el = el;
+ this.list = el.classList;
+}
+
+/**
+ * Add class `name` if not already present.
+ *
+ * @param {String} name
+ * @return {ClassList}
+ * @api public
+ */
+
+ClassList.prototype.add = function(name){
+ // classList
+ if (this.list) {
+ this.list.add(name);
+ return this;
+ }
+
+ // fallback
+ var arr = this.array();
+ var i = index(arr, name);
+ if (!~i) arr.push(name);
+ this.el.className = arr.join(' ');
+ return this;
+};
+
+/**
+ * Remove class `name` when present, or
+ * pass a regular expression to remove
+ * any which match.
+ *
+ * @param {String|RegExp} name
+ * @return {ClassList}
+ * @api public
+ */
+
+ClassList.prototype.remove = function(name){
+ if ('[object RegExp]' == toString.call(name)) {
+ return this.removeMatching(name);
+ }
+
+ // classList
+ if (this.list) {
+ this.list.remove(name);
+ return this;
+ }
+
+ // fallback
+ var arr = this.array();
+ var i = index(arr, name);
+ if (~i) arr.splice(i, 1);
+ this.el.className = arr.join(' ');
+ return this;
+};
+
+/**
+ * Remove all classes matching `re`.
+ *
+ * @param {RegExp} re
+ * @return {ClassList}
+ * @api private
+ */
+
+ClassList.prototype.removeMatching = function(re){
+ var arr = this.array();
+ for (var i = 0; i < arr.length; i++) {
+ if (re.test(arr[i])) {
+ this.remove(arr[i]);
+ }
+ }
+ return this;
+};
+
+/**
+ * Toggle class `name`, can force state via `force`.
+ *
+ * For browsers that support classList, but do not support `force` yet,
+ * the mistake will be detected and corrected.
+ *
+ * @param {String} name
+ * @param {Boolean} force
+ * @return {ClassList}
+ * @api public
+ */
+
+ClassList.prototype.toggle = function(name, force){
+ // classList
+ if (this.list) {
+ if ("undefined" !== typeof force) {
+ if (force !== this.list.toggle(name, force)) {
+ this.list.toggle(name); // toggle again to correct
+ }
+ } else {
+ this.list.toggle(name);
+ }
+ return this;
+ }
+
+ // fallback
+ if ("undefined" !== typeof force) {
+ if (!force) {
+ this.remove(name);
+ } else {
+ this.add(name);
+ }
+ } else {
+ if (this.has(name)) {
+ this.remove(name);
+ } else {
+ this.add(name);
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Return an array of classes.
+ *
+ * @return {Array}
+ * @api public
+ */
+
+ClassList.prototype.array = function(){
+ var className = this.el.getAttribute('class') || '';
+ var str = className.replace(/^\s+|\s+$/g, '');
+ var arr = str.split(re);
+ if ('' === arr[0]) arr.shift();
+ return arr;
+};
+
+/**
+ * Check if class `name` is present.
+ *
+ * @param {String} name
+ * @return {ClassList}
+ * @api public
+ */
+
+ClassList.prototype.has =
+ClassList.prototype.contains = function(name){
+ return this.list ? this.list.contains(name) : !! ~index(this.array(), name);
+};
diff --git a/src/utils/events.js b/src/utils/events.js
new file mode 100644
index 0000000..2169598
--- /dev/null
+++ b/src/utils/events.js
@@ -0,0 +1,38 @@
+var bind = window.addEventListener ? 'addEventListener' : 'attachEvent',
+ unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent',
+ prefix = bind !== 'addEventListener' ? 'on' : '',
+ toArray = require('./to-array');
+
+/**
+ * Bind `el` event `type` to `fn`.
+ *
+ * @param {Element} el, NodeList, HTMLCollection or Array
+ * @param {String} type
+ * @param {Function} fn
+ * @param {Boolean} capture
+ * @api public
+ */
+
+exports.bind = function(el, type, fn, capture){
+ el = toArray(el);
+ for ( var i = 0; i < el.length; i++ ) {
+ el[i][bind](prefix + type, fn, capture || false);
+ }
+};
+
+/**
+ * Unbind `el` event `type`'s callback `fn`.
+ *
+ * @param {Element} el, NodeList, HTMLCollection or Array
+ * @param {String} type
+ * @param {Function} fn
+ * @param {Boolean} capture
+ * @api public
+ */
+
+exports.unbind = function(el, type, fn, capture){
+ el = toArray(el);
+ for ( var i = 0; i < el.length; i++ ) {
+ el[i][unbind](prefix + type, fn, capture || false);
+ }
+};
diff --git a/src/utils/extend.js b/src/utils/extend.js
new file mode 100644
index 0000000..9fc6037
--- /dev/null
+++ b/src/utils/extend.js
@@ -0,0 +1,18 @@
+/*
+ * Source: https://github.com/segmentio/extend
+ */
+
+module.exports = function extend (object) {
+ // Takes an unlimited number of extenders.
+ var args = Array.prototype.slice.call(arguments, 1);
+
+ // For each extender, copy their properties on our object.
+ for (var i = 0, source; source = args[i]; i++) {
+ if (!source) continue;
+ for (var property in source) {
+ object[property] = source[property];
+ }
+ }
+
+ return object;
+};
diff --git a/src/utils/get-attribute.js b/src/utils/get-attribute.js
new file mode 100644
index 0000000..729e651
--- /dev/null
+++ b/src/utils/get-attribute.js
@@ -0,0 +1,26 @@
+/**
+ * A cross-browser implementation of getAttribute.
+ * Source found here: http://stackoverflow.com/a/3755343/361337 written by Vivin Paliath
+ *
+ * Return the value for `attr` at `element`.
+ *
+ * @param {Element} el
+ * @param {String} attr
+ * @api public
+ */
+
+module.exports = function(el, attr) {
+ var result = (el.getAttribute && el.getAttribute(attr)) || null;
+ if( !result ) {
+ var attrs = el.attributes;
+ var length = attrs.length;
+ for(var i = 0; i < length; i++) {
+ if (attr[i] !== undefined) {
+ if(attr[i].nodeName === attr) {
+ result = attr[i].nodeValue;
+ }
+ }
+ }
+ }
+ return result;
+};
diff --git a/src/utils/get-by-class.js b/src/utils/get-by-class.js
new file mode 100644
index 0000000..f475fd8
--- /dev/null
+++ b/src/utils/get-by-class.js
@@ -0,0 +1,56 @@
+/**
+ * A cross-browser implementation of getElementsByClass.
+ * Heavily based on Dustin Diaz's function: http://dustindiaz.com/getelementsbyclass.
+ *
+ * Find all elements with class `className` inside `container`.
+ * Use `single = true` to increase performance in older browsers
+ * when only one element is needed.
+ *
+ * @param {String} className
+ * @param {Element} container
+ * @param {Boolean} single
+ * @api public
+ */
+
+module.exports = (function() {
+ if (document.getElementsByClassName) {
+ return function(container, className, single) {
+ if (single) {
+ return container.getElementsByClassName(className)[0];
+ } else {
+ return container.getElementsByClassName(className);
+ }
+ };
+ } else if (document.querySelector) {
+ return function(container, className, single) {
+ className = '.' + className;
+ if (single) {
+ return container.querySelector(className);
+ } else {
+ return container.querySelectorAll(className);
+ }
+ };
+ } else {
+ return function(container, className, single) {
+ var classElements = [],
+ tag = '*';
+ if (container === null) {
+ container = document;
+ }
+ var els = container.getElementsByTagName(tag);
+ var elsLen = els.length;
+ var pattern = new RegExp("(^|\\s)"+className+"(\\s|$)");
+ for (var i = 0, j = 0; i < elsLen; i++) {
+ if ( pattern.test(els[i].className) ) {
+ if (single) {
+ return els[i];
+ } else {
+ classElements[j] = els[i];
+ j++;
+ }
+ }
+ }
+ return classElements;
+ };
+ }
+})();
diff --git a/src/utils/index-of.js b/src/utils/index-of.js
new file mode 100644
index 0000000..4c26161
--- /dev/null
+++ b/src/utils/index-of.js
@@ -0,0 +1,9 @@
+var indexOf = [].indexOf;
+
+module.exports = function(arr, obj){
+ if (indexOf) return arr.indexOf(obj);
+ for (var i = 0; i < arr.length; ++i) {
+ if (arr[i] === obj) return i;
+ }
+ return -1;
+};
diff --git a/src/utils/natural-sort.js b/src/utils/natural-sort.js
new file mode 100644
index 0000000..76c1e70
--- /dev/null
+++ b/src/utils/natural-sort.js
@@ -0,0 +1,48 @@
+/*
+ * Natural Sort algorithm for Javascript - Version 0.8 - Released under MIT license
+ * Author: Jim Palmer (based on chunking idea from Dave Koelle)
+ */
+module.exports = function(a, b, opts) {
+ var re = /(^([+\-]?(?:\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[\da-fA-F]+$|\d+)/g,
+ sre = /^\s+|\s+$/g, // trim pre-post whitespace
+ snre = /\s+/g, // normalize all whitespace to single ' ' character
+ dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,
+ hre = /^0x[0-9a-f]+$/i,
+ ore = /^0/,
+ options = opts || {},
+ i = function(s) { return options.insensitive && (''+s).toLowerCase() || ''+s; },
+ // convert all to strings strip whitespace
+ x = i(a) || '',
+ y = i(b) || '',
+ // chunk/tokenize
+ xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
+ yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
+ // numeric, hex or date detection
+ xD = parseInt(x.match(hre), 16) || (xN.length !== 1 && Date.parse(x)),
+ yD = parseInt(y.match(hre), 16) || xD && y.match(dre) && Date.parse(y) || null,
+ normChunk = function(s, l) {
+ // normalize spaces; find floats not starting with '0', string or 0 if not defined (Clint Priest)
+ return (!s.match(ore) || l == 1) && parseFloat(s) || s.replace(snre, ' ').replace(sre, '') || 0;
+ },
+ oFxNcL, oFyNcL;
+ // first try and sort Hex codes or Dates
+ if (yD) {
+ if ( xD < yD ) { return -1; }
+ else if ( xD > yD ) { return 1; }
+ }
+ // natural sorting through split numeric strings and default strings
+ for(var cLoc=0, xNl = xN.length, yNl = yN.length, numS=Math.max(xNl, yNl); cLoc < numS; cLoc++) {
+ oFxNcL = normChunk(xN[cLoc], xNl);
+ oFyNcL = normChunk(yN[cLoc], yNl);
+ // handle numeric vs string comparison - number < string - (Kyle Adams)
+ if (isNaN(oFxNcL) !== isNaN(oFyNcL)) { return (isNaN(oFxNcL)) ? 1 : -1; }
+ // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
+ else if (typeof oFxNcL !== typeof oFyNcL) {
+ oFxNcL += '';
+ oFyNcL += '';
+ }
+ if (oFxNcL < oFyNcL) { return -1; }
+ if (oFxNcL > oFyNcL) { return 1; }
+ }
+ return 0;
+};
diff --git a/src/utils/to-array.js b/src/utils/to-array.js
new file mode 100644
index 0000000..9fac261
--- /dev/null
+++ b/src/utils/to-array.js
@@ -0,0 +1,33 @@
+/**
+ * Source: https://github.com/timoxley/to-array
+ *
+ * Convert an array-like object into an `Array`.
+ * If `collection` is already an `Array`, then will return a clone of `collection`.
+ *
+ * @param {Array | Mixed} collection An `Array` or array-like object to convert e.g. `arguments` or `NodeList`
+ * @return {Array} Naive conversion of `collection` to a new `Array`.
+ * @api public
+ */
+
+module.exports = function toArray(collection) {
+ if (typeof collection === 'undefined') return [];
+ if (collection === null) return [null];
+ if (collection === window) return [window];
+ if (typeof collection === 'string') return [collection];
+ if (isArray(collection)) return collection;
+ if (typeof collection.length != 'number') return [collection];
+ if (typeof collection === 'function' && collection instanceof Function) return [collection];
+
+ var arr = [];
+ for (var i = 0; i < collection.length; i++) {
+ if (Object.prototype.hasOwnProperty.call(collection, i) || i in collection) {
+ arr.push(collection[i]);
+ }
+ }
+ if (!arr.length) return [];
+ return arr;
+};
+
+function isArray(arr) {
+ return Object.prototype.toString.call(arr) === "[object Array]";
+}
diff --git a/src/utils/to-string.js b/src/utils/to-string.js
new file mode 100644
index 0000000..cdda3bc
--- /dev/null
+++ b/src/utils/to-string.js
@@ -0,0 +1,6 @@
+module.exports = function(s) {
+ s = (s === undefined) ? "" : s;
+ s = (s === null) ? "" : s;
+ s = s.toString();
+ return s;
+};
diff --git a/test/fixtures.js b/test/fixtures.js
index 79f5190..fadfc37 100644
--- a/test/fixtures.js
+++ b/test/fixtures.js
@@ -1,56 +1,56 @@
var fixture = {
- list: function(valueNames, items) {
- var listHtml = $('<div id="list"><ul class="list"></ul></div>'),
- item = "";
+ list: function(valueNames, items) {
+ var listHtml = $('<div id="list"><ul class="list"></ul></div>'),
+ item = "";
- item = "<li>";
- for (var i = 0; i < valueNames.length; i++) {
- item += '<span class="'+valueNames[i]+'"</span>';
- }
- item += "</li>";
+ item = "<li>";
+ for (var i = 0; i < valueNames.length; i++) {
+ item += '<span class="'+valueNames[i]+'"</span>';
+ }
+ item += "</li>";
- $(document.body).append(listHtml);
+ $(document.body).append(listHtml);
- items = items || [];
+ items = items || [];
- return new List('list', {
- valueNames: valueNames,
- item: item
- }, items);
- },
- removeList: function() {
- $('#list').remove();
- },
- jonny: {
- name: "Jonny Strömberg",
- born: '1986'
- },
- martina: {
- name: "Martina Elm",
- born: '1986'
- },
- angelica: {
- name: "Angelica Abraham",
- born: '1986'
- },
- sebastian: {
- name: "Sebastian Höglund",
- born: '1989'
- },
- imma: {
- name: "Imma Grafström",
- born: '1953'
- },
- hasse: {
- name: "Hasse Strömberg",
- born: '1955'
- }
+ return new List('list', {
+ valueNames: valueNames,
+ item: item
+ }, items);
+ },
+ removeList: function() {
+ $('#list').remove();
+ },
+ jonny: {
+ name: "Jonny Strömberg",
+ born: '1986'
+ },
+ martina: {
+ name: "Martina Elm",
+ born: '1986'
+ },
+ angelica: {
+ name: "Angelica Abraham",
+ born: '1986'
+ },
+ sebastian: {
+ name: "Sebastian Höglund",
+ born: '1989'
+ },
+ imma: {
+ name: "Imma Grafström",
+ born: '1953'
+ },
+ hasse: {
+ name: "Hasse Strömberg",
+ born: '1955'
+ }
};
fixture.all = [
- fixture.jonny,
- fixture.martina,
- fixture.angelica,
- fixture.sebastian,
- fixture.imma,
- fixture.hasse
-];
\ No newline at end of file
+ fixture.jonny,
+ fixture.martina,
+ fixture.angelica,
+ fixture.sebastian,
+ fixture.imma,
+ fixture.hasse
+];
diff --git a/test/index.html b/test/index.html
index e5dfce5..89dcf54 100755
--- a/test/index.html
+++ b/test/index.html
@@ -1,56 +1,50 @@
<html>
<head>
- <meta charset="utf-8">
- <title>List.js Mocha Tests</title>
- <link rel="stylesheet" href="../build/build.css" />
- <style>
- #list,
- #parse-list,
- .list {
- margin-left:-1000px;
- }
- </style>
+ <meta charset="utf-8">
+ <title>List.js Mocha Tests</title>
+ <link rel="stylesheet" href="../node_modules/grunt-mocha/node_modules/mocha/mocha.css" />
+ <style>
+ #list,
+ #parse-list,
+ .list {
+ margin-left:-1000px;
+ }
+ </style>
</head>
<body>
- <div id="mocha"></div>
- <script src="../build/build.js"></script>
- <script src="mocha.js"></script> <!-- this specific version is needed for grunt-mocha (wtf...) -->
+ <div id="mocha"></div>
+ <script src="../node_modules/jquery/dist/jquery.js"></script>
+ <script src="../dist/list.js"></script>
+ <script src="../node_modules/expect.js/index.js"></script>
+ <script src="../node_modules/grunt-mocha/node_modules/mocha/mocha.js"></script>
- <script>
- List = require('list.js');
- $ = require('jquery');
+ <script>
+ mocha.setup('bdd');
+ </script>
- if (navigator.userAgent.indexOf('PhantomJS') < 0) {
- // This version is needed to not get "Out of stack space" error in IE
- require('mocha');
- }
+ <script src="fixtures.js"></script>
+ <script src="test.defaults.js"></script>
+ <script src="test.create.js"></script>
+ <script src="test.add-get-remove.js"></script>
+ <script src="test.item.js"></script>
+ <script src="test.filter.js"></script>
+ <script src="test.search.js"></script>
+ <script src="test.search-filter.js"></script>
+ <script src="test.show.js"></script>
+ <script src="test.on.js"></script>
+ <script src="test.off.js"></script>
+ <script src="test.trigger.js"></script>
+ <script src="test.re-index.js"></script>
- mocha.setup('bdd');
- expect = require('expect.js');
- </script>
+ <script src="test.sort.js"></script>
+ <script src="test.buttons.js"></script>
+ <script src="test.parse.js"></script>
- <script src="fixtures.js"></script>
- <script src="test.defaults.js"></script>
- <script src="test.create.js"></script>
- <script src="test.add-get-remove.js"></script>
- <script src="test.item.js"></script>
- <script src="test.filter.js"></script>
- <script src="test.search.js"></script>
- <script src="test.search-filter.js"></script>
- <script src="test.show.js"></script>
- <script src="test.on.js"></script>
- <script src="test.off.js"></script>
- <script src="test.trigger.js"></script>
-
- <script src="test.sort.js"></script>
- <script src="test.buttons.js"></script>
- <script src="test.parse.js"></script>
-
- <script>
- if (navigator.userAgent.indexOf('PhantomJS') < 0) {
- mocha.run();
- }
- </script>
+ <script>
+ if (navigator.userAgent.indexOf('PhantomJS') < 0) {
+ mocha.run();
+ }
+ </script>
</body>
</html>
diff --git a/test/test.add-get-remove.js b/test/test.add-get-remove.js
index 4840298..9d806af 100644
--- a/test/test.add-get-remove.js
+++ b/test/test.add-get-remove.js
@@ -1,97 +1,119 @@
describe('Add, get, remove', function() {
- var list;
+ var list;
- before(function() {
- list = fixture.list(['name'], [ { name: "Jonny" } ]);
- });
+ before(function() {
+ list = fixture.list(['name'], [ { name: "Jonny" } ]);
+ });
- after(function() {
- fixture.removeList();
- });
+ after(function() {
+ fixture.removeList();
+ });
+
+ afterEach(function() {
+ list.clear();
+ list.add({ name: "Jonny" });
+ });
- afterEach(function() {
- list.clear();
- list.add({ name: "Jonny" });
+ describe('Add', function() {
+ it('should add one item', function() {
+ list.add({ name: 'Jonas' });
+ expect(list.items.length).to.equal(2);
+ });
+ it('should add two items', function() {
+ list.add([
+ { name: 'Martina' },
+ { name: 'Angelica' }
+ ]);
+ expect(list.items.length).to.equal(3);
+ });
+ it('should add async items', function(done) {
+ list.add([
+{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},
+{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},
+{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},
+{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},
+{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},
+{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},
+{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},
+{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},
+{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},
+{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},
+{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},
+{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},
+{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},
+{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},
+{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'},{name:'Sven'}
+ ], function() {
+ expect(list.items.length).to.equal(91);
+ done();
+ });
});
+ it('should add async items to empty list', function(done) {
+ list.clear();
+ list.add([
+ { name: 'Sven' }
+ ], function() {
+ expect(list.items.length).to.equal(1);
+ done();
+ });
+ });
+ });
- describe('Add', function() {
- it('should add one item', function() {
- list.add({ name: 'Jonas' });
- expect(list.items.length).to.equal(2);
- });
- it('should add two items', function() {
- list.add([
- { name: 'Martina' },
- { name: 'Angelica' }
- ]);
- expect(list.items.length).to.equal(3);
- });
- it('should add async items', function(done) {
- list.add([
- { name: 'Sven' }
- ], function() {
- expect(list.items.length).to.equal(2);
- done();
- });
- });
- it('should add async items to empty list', function(done) {
- list.clear();
- list.add([
- { name: 'Sven' }
- ], function() {
- expect(list.items.length).to.equal(1);
- done();
- });
- });
+ describe('Get', function() {
+ it('should return array with one item', function() {
+ var items = list.get('name', 'Jonny');
+ expect(items[0].values().name).to.equal('Jonny');
+ });
+ it('should return empty array', function() {
+ var items = list.get('name', 'jonny');
+ expect(items.length).to.be.zero;
+ });
+ it('should return two items', function() {
+ list.add({ name: 'Jonny' });
+ var items = list.get('name', 'Jonny');
+ expect(items.length).to.equal(2);
+ expect(items[0].values().name).to.equal('Jonny');
+ expect(items[1].values().name).to.equal('Jonny');
});
+ });
- describe('Get', function() {
- it('should return array with one item', function() {
- var items = list.get('name', 'Jonny');
- expect(items[0].values().name).to.equal('Jonny');
- });
- it('should return empty array', function() {
- var items = list.get('name', 'jonny');
- expect(items.length).to.be.zero;
- });
- it('should return two items', function() {
- list.add({ name: 'Jonny' });
- var items = list.get('name', 'Jonny');
- expect(items.length).to.equal(2);
- expect(items[0].values().name).to.equal('Jonny');
- expect(items[1].values().name).to.equal('Jonny');
- });
+ describe('Remove', function() {
+ it('should remove one item', function() {
+ list.add({ name: "Jonas" });
+ expect(list.items.length).to.equal(2);
+ var count = list.remove('name', 'Jonas');
+ expect(count).to.equal(1);
+ expect(list.items.length).to.equal(1);
+ });
+ it('should not remove anything due to case sensitivity', function() {
+ var count = list.remove('name', 'jonny');
+ expect(count).to.be.equal(0);
+ expect(list.items.length).to.equal(1);
});
- describe('Remove', function() {
- it('should remove one item', function() {
- list.add({ name: "Jonas" });
- expect(list.items.length).to.equal(2);
- var count = list.remove('name', 'Jonas');
- expect(count).to.equal(1);
- expect(list.items.length).to.equal(1);
- });
- it('should not remove anything due to case sensitivity', function() {
- var count = list.remove('name', 'jonny');
- expect(count).to.be.equal(0);
- expect(list.items.length).to.equal(1);
- });
+ it('should avoid node not found error', function() {
+ var item = list.get('name', 'Jonny')[0];
+ list.list.removeChild(item.elm);
+ var count = list.remove('name', 'Jonny');
+ expect(count).to.be.equal(1);
+ expect(list.items.length).to.equal(0);
+ });
- it('should remove eight items', function() {
- list.add({ name: 'Jonny' });
- list.add({ name: 'Jonny' });
- list.add({ name: 'Sven' });
- list.add({ name: 'Jonny' });
- list.add({ name: 'Jonny' });
- list.add({ name: 'Jonny' });
- list.add({ name: 'Jonas' });
- list.add({ name: 'Jonny' });
- list.add({ name: 'Jonny' });
- expect(list.items.length).to.equal(10);
- var count = list.remove('name', 'Jonny');
- expect(count).to.equal(8);
- expect(list.items.length).to.equal(2);
- });
+ it('should remove eight items', function() {
+ list.add({ name: 'Jonny' });
+ list.add({ name: 'Jonny' });
+ list.add({ name: 'Sven' });
+ list.add({ name: 'Jonny' });
+ list.add({ name: 'Jonny' });
+ list.add({ name: 'Jonny' });
+ list.add({ name: 'Jonas' });
+ list.add({ name: 'Jonny' });
+ list.add({ name: 'Jonny' });
+ expect(list.items.length).to.equal(10);
+ var count = list.remove('name', 'Jonny');
+ expect(count).to.equal(8);
+ expect(list.items.length).to.equal(2);
});
+ });
});
diff --git a/test/test.buttons.js b/test/test.buttons.js
index 012167e..1249b0b 100644
--- a/test/test.buttons.js
+++ b/test/test.buttons.js
@@ -1,191 +1,191 @@
function fireKeyup(el) {
- if (document.createEvent) {
- var evObj;
- if (window.KeyEvent) {
- evObj = document.createEvent('KeyEvents');
- evObj.initKeyEvent('keyup', true, true, window, false, false, false, false, 13, 0);
- } else {
- evObj = document.createEvent('UIEvents');
- evObj.initUIEvent('keyup', true, true, window, 1);
- }
- el.dispatchEvent(evObj);
- } else if( document.createEventObject ) {
- el.fireEvent('onkeyup');
+ if (document.createEvent) {
+ var evObj;
+ if (window.KeyEvent) {
+ evObj = document.createEvent('KeyEvents');
+ evObj.initKeyEvent('keyup', true, true, window, false, false, false, false, 13, 0);
} else {
- // IE 5.0, seriously? :)
+ evObj = document.createEvent('UIEvents');
+ evObj.initUIEvent('keyup', true, true, window, 1);
}
+ el.dispatchEvent(evObj);
+ } else if( document.createEventObject ) {
+ el.fireEvent('onkeyup');
+ } else {
+ // IE 5.0, seriously? :)
+ }
}
// http://stackoverflow.com/questions/5658849/whats-the-equivalent-of-jquerys-trigger-method-without-jquery
function fireClick(el) {
- var evt;
- if (document.createEvent) {
- evt = document.createEvent("MouseEvents");
- evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
- }
- (evt) ? el.dispatchEvent(evt) : (el.click && el.click());
+ var evt;
+ if (document.createEvent) {
+ evt = document.createEvent("MouseEvents");
+ evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ }
+ (evt) ? el.dispatchEvent(evt) : (el.click && el.click());
}
describe('Button', function() {
- var list;
+ var list;
- beforeEach(function() {
- $('body').append($('<div id="parse-list">\
- <input class="search" />\
- <span class="sort" id="sort-name" data-sort="name">Sort name</span>\
- <span class="sort" id="sort-name-asc" data-sort="name" data-order="asc">Sort name asc</span>\
- <span class="sort" id="sort-name-desc" data-sort="name" data-order="desc">Sort name desc</span>\
- <div class="list">\
- <div><span class="name">Jonny</span><span class="born">1986</span></div>\
- <div><span class="name">Jocke</span><span class="born">1985</span></div>\
- </div>\
- </div>'));
+ beforeEach(function() {
+ $('body').append($('<div id="parse-list">\
+ <input class="search" />\
+ <span class="sort" id="sort-name" data-sort="name">Sort name</span>\
+ <span class="sort" id="sort-name-asc" data-sort="name" data-order="asc">Sort name asc</span>\
+ <span class="sort" id="sort-name-desc" data-sort="name" data-order="desc">Sort name desc</span>\
+ <div class="list">\
+ <div><span class="name">Jonny</span><span class="born">1986</span></div>\
+ <div><span class="name">Jocke</span><span class="born">1985</span></div>\
+ </div>\
+ </div>'));
- list = new List('parse-list', {
- valueNames: ['name', 'born']
- });
+ list = new List('parse-list', {
+ valueNames: ['name', 'born']
});
+ });
- afterEach(function() {
- $('#parse-list').remove();
+ afterEach(function() {
+ $('#parse-list').remove();
+ });
+
+ describe('Sort', function() {
+ it('should trigger sortStart', function(done) {
+ list.on('sortComplete', function() {
+ done();
+ });
+ fireClick($('#sort-name')[0]);
+ });
+ it('should trigger sortComplete', function(done) {
+ list.on('sortComplete', function() {
+ done();
+ });
+ fireClick($('#sort-name')[0]);
});
- describe('Sort', function() {
- it('should trigger sortStart', function(done) {
- list.on('sortComplete', function() {
- done();
- });
+ it('should switch sorting order when clicking multiple times', function(done) {
+ this.timeout(5000);
+ var sortRun = 0;
+ list.on('sortComplete', function() {
+ sortRun++;
+ if (sortRun == 1) {
+ expect($('#sort-name').hasClass('asc')).to.be(true);
+ expect($('#sort-name').hasClass('desc')).to.be(false);
+ setTimeout(function() {
fireClick($('#sort-name')[0]);
- });
- it('should trigger sortComplete', function(done) {
- list.on('sortComplete', function() {
- done();
- });
+ }, 50);
+ } else if (sortRun == 2) {
+ expect($('#sort-name').hasClass('asc')).to.be(false);
+ expect($('#sort-name').hasClass('desc')).to.be(true);
+ setTimeout(function() {
fireClick($('#sort-name')[0]);
- });
-
- it('should switch sorting order when clicking multiple times', function(done) {
- this.timeout(5000);
- var sortRun = 0;
- list.on('sortComplete', function() {
- sortRun++;
- if (sortRun == 1) {
- expect($('#sort-name').hasClass('asc')).to.be(true);
- expect($('#sort-name').hasClass('desc')).to.be(false);
- setTimeout(function() {
- fireClick($('#sort-name')[0]);
- }, 50);
- } else if (sortRun == 2) {
- expect($('#sort-name').hasClass('asc')).to.be(false);
- expect($('#sort-name').hasClass('desc')).to.be(true);
- setTimeout(function() {
- fireClick($('#sort-name')[0]);
- }, 50);
- } else if (sortRun == 3) {
- expect($('#sort-name').hasClass('asc')).to.be(true);
- expect($('#sort-name').hasClass('desc')).to.be(false);
- done();
- }
- });
- expect($('#sort-name').hasClass('asc')).to.be(false);
- expect($('#sort-name').hasClass('desc')).to.be(false);
- fireClick($('#sort-name')[0]);
- });
+ }, 50);
+ } else if (sortRun == 3) {
+ expect($('#sort-name').hasClass('asc')).to.be(true);
+ expect($('#sort-name').hasClass('desc')).to.be(false);
+ done();
+ }
+ });
+ expect($('#sort-name').hasClass('asc')).to.be(false);
+ expect($('#sort-name').hasClass('desc')).to.be(false);
+ fireClick($('#sort-name')[0]);
+ });
- it('should sort with predefined order', function(done) {
- this.timeout(10000);
- var sortRun = 0;
- list.on('sortComplete', function() {
- sortRun++;
- if (sortRun == 1) {
- expect($('#sort-name').hasClass('asc')).to.be(true);
- expect($('#sort-name').hasClass('desc')).to.be(false);
- expect($('#sort-name-asc').hasClass('asc')).to.be(true);
- expect($('#sort-name-asc').hasClass('desc')).to.be(false);
- expect($('#sort-name-desc').hasClass('asc')).to.be(false);
- expect($('#sort-name-desc').hasClass('desc')).to.be(false);
- setTimeout(function() {
- fireClick($('#sort-name-asc')[0]);
- }, 50);
- } else if (sortRun == 2) {
- expect($('#sort-name').hasClass('asc')).to.be(true);
- expect($('#sort-name').hasClass('desc')).to.be(false);
- expect($('#sort-name-asc').hasClass('asc')).to.be(true);
- expect($('#sort-name-asc').hasClass('desc')).to.be(false);
- expect($('#sort-name-desc').hasClass('asc')).to.be(false);
- expect($('#sort-name-desc').hasClass('desc')).to.be(false);
- setTimeout(function() {
- fireClick($('#sort-name-asc')[0]);
- }, 50);
- } else if (sortRun == 3) {
- expect($('#sort-name').hasClass('asc')).to.be(true);
- expect($('#sort-name').hasClass('desc')).to.be(false);
- expect($('#sort-name-asc').hasClass('asc')).to.be(true);
- expect($('#sort-name-asc').hasClass('desc')).to.be(false);
- expect($('#sort-name-desc').hasClass('asc')).to.be(false);
- expect($('#sort-name-desc').hasClass('desc')).to.be(false);
- setTimeout(function() {
- fireClick($('#sort-name-desc')[0]);
- }, 50);
- } else if (sortRun == 4) {
- expect($('#sort-name').hasClass('asc')).to.be(false);
- expect($('#sort-name').hasClass('desc')).to.be(true);
- expect($('#sort-name-asc').hasClass('asc')).to.be(false);
- expect($('#sort-name-asc').hasClass('desc')).to.be(false);
- expect($('#sort-name-desc').hasClass('asc')).to.be(false);
- expect($('#sort-name-desc').hasClass('desc')).to.be(true);
- setTimeout(function() {
- fireClick($('#sort-name-desc')[0]);
- }, 50);
- } else if (sortRun == 5) {
- expect($('#sort-name').hasClass('asc')).to.be(false);
- expect($('#sort-name').hasClass('desc')).to.be(true);
- expect($('#sort-name-asc').hasClass('asc')).to.be(false);
- expect($('#sort-name-asc').hasClass('desc')).to.be(false);
- expect($('#sort-name-desc').hasClass('asc')).to.be(false);
- expect($('#sort-name-desc').hasClass('desc')).to.be(true);
- done();
- }
- });
- expect($('#sort-name').hasClass('asc')).to.be(false);
- expect($('#sort-name').hasClass('desc')).to.be(false);
- expect($('#sort-name-asc').hasClass('asc')).to.be(false);
- expect($('#sort-name-asc').hasClass('desc')).to.be(false);
- expect($('#sort-name-desc').hasClass('asc')).to.be(false);
- expect($('#sort-name-desc').hasClass('desc')).to.be(false);
+ it('should sort with predefined order', function(done) {
+ this.timeout(10000);
+ var sortRun = 0;
+ list.on('sortComplete', function() {
+ sortRun++;
+ if (sortRun == 1) {
+ expect($('#sort-name').hasClass('asc')).to.be(true);
+ expect($('#sort-name').hasClass('desc')).to.be(false);
+ expect($('#sort-name-asc').hasClass('asc')).to.be(true);
+ expect($('#sort-name-asc').hasClass('desc')).to.be(false);
+ expect($('#sort-name-desc').hasClass('asc')).to.be(false);
+ expect($('#sort-name-desc').hasClass('desc')).to.be(false);
+ setTimeout(function() {
fireClick($('#sort-name-asc')[0]);
- });
-
- it('buttons should change class when sorting programmatically', function(done) {
- list.on('sortComplete', function() {
- expect($('#sort-name').hasClass('asc')).to.be(true);
- expect($('#sort-name').hasClass('desc')).to.be(false);
- expect($('#sort-name-asc').hasClass('asc')).to.be(true);
- expect($('#sort-name-asc').hasClass('desc')).to.be(false);
- expect($('#sort-name-desc').hasClass('asc')).to.be(false);
- expect($('#sort-name-desc').hasClass('desc')).to.be(false);
- done();
- });
- list.sort('name', { order: "asc" });
- })
+ }, 50);
+ } else if (sortRun == 2) {
+ expect($('#sort-name').hasClass('asc')).to.be(true);
+ expect($('#sort-name').hasClass('desc')).to.be(false);
+ expect($('#sort-name-asc').hasClass('asc')).to.be(true);
+ expect($('#sort-name-asc').hasClass('desc')).to.be(false);
+ expect($('#sort-name-desc').hasClass('asc')).to.be(false);
+ expect($('#sort-name-desc').hasClass('desc')).to.be(false);
+ setTimeout(function() {
+ fireClick($('#sort-name-asc')[0]);
+ }, 50);
+ } else if (sortRun == 3) {
+ expect($('#sort-name').hasClass('asc')).to.be(true);
+ expect($('#sort-name').hasClass('desc')).to.be(false);
+ expect($('#sort-name-asc').hasClass('asc')).to.be(true);
+ expect($('#sort-name-asc').hasClass('desc')).to.be(false);
+ expect($('#sort-name-desc').hasClass('asc')).to.be(false);
+ expect($('#sort-name-desc').hasClass('desc')).to.be(false);
+ setTimeout(function() {
+ fireClick($('#sort-name-desc')[0]);
+ }, 50);
+ } else if (sortRun == 4) {
+ expect($('#sort-name').hasClass('asc')).to.be(false);
+ expect($('#sort-name').hasClass('desc')).to.be(true);
+ expect($('#sort-name-asc').hasClass('asc')).to.be(false);
+ expect($('#sort-name-asc').hasClass('desc')).to.be(false);
+ expect($('#sort-name-desc').hasClass('asc')).to.be(false);
+ expect($('#sort-name-desc').hasClass('desc')).to.be(true);
+ setTimeout(function() {
+ fireClick($('#sort-name-desc')[0]);
+ }, 50);
+ } else if (sortRun == 5) {
+ expect($('#sort-name').hasClass('asc')).to.be(false);
+ expect($('#sort-name').hasClass('desc')).to.be(true);
+ expect($('#sort-name-asc').hasClass('asc')).to.be(false);
+ expect($('#sort-name-asc').hasClass('desc')).to.be(false);
+ expect($('#sort-name-desc').hasClass('asc')).to.be(false);
+ expect($('#sort-name-desc').hasClass('desc')).to.be(true);
+ done();
+ }
+ });
+ expect($('#sort-name').hasClass('asc')).to.be(false);
+ expect($('#sort-name').hasClass('desc')).to.be(false);
+ expect($('#sort-name-asc').hasClass('asc')).to.be(false);
+ expect($('#sort-name-asc').hasClass('desc')).to.be(false);
+ expect($('#sort-name-desc').hasClass('asc')).to.be(false);
+ expect($('#sort-name-desc').hasClass('desc')).to.be(false);
+ fireClick($('#sort-name-asc')[0]);
});
+ it('buttons should change class when sorting programmatically', function(done) {
+ list.on('sortComplete', function() {
+ expect($('#sort-name').hasClass('asc')).to.be(true);
+ expect($('#sort-name').hasClass('desc')).to.be(false);
+ expect($('#sort-name-asc').hasClass('asc')).to.be(true);
+ expect($('#sort-name-asc').hasClass('desc')).to.be(false);
+ expect($('#sort-name-desc').hasClass('asc')).to.be(false);
+ expect($('#sort-name-desc').hasClass('desc')).to.be(false);
+ done();
+ });
+ list.sort('name', { order: "asc" });
+ })
+ });
+
- describe('Search', function() {
- it('should trigger searchStart', function(done) {
- list.on('searchStart', function() {
- done();
- });
- $('#parse-list .search').val('jon');
- fireKeyup($('#parse-list .search')[0]);
- });
- it('should trigger searchComplete', function(done) {
- list.on('searchComplete', function() {
- done();
- });
- $('#parse-list .search').val('jon');
- fireKeyup($('#parse-list .search')[0]);
- });
+ describe('Search', function() {
+ it('should trigger searchStart', function(done) {
+ list.on('searchStart', function() {
+ done();
+ });
+ $('#parse-list .search').val('jon');
+ fireKeyup($('#parse-list .search')[0]);
+ });
+ it('should trigger searchComplete', function(done) {
+ list.on('searchComplete', function() {
+ done();
+ });
+ $('#parse-list .search').val('jon');
+ fireKeyup($('#parse-list .search')[0]);
});
+ });
});
diff --git a/test/test.create.js b/test/test.create.js
index 3d3cf37..96e2cc7 100644
--- a/test/test.create.js
+++ b/test/test.create.js
@@ -1,89 +1,189 @@
describe('Create', function() {
- describe('With HTML items', function() {
- var listEl = $('<div id="list">\
- <ul class="list">\
- <li><span class="name">Jonny</span></li>\
- </ul>\
- </div>');
+ describe('With HTML items', function() {
+ var listEl = $('<div id="list">\
+ <ul class="list">\
+ <li><span class="name">Jonny</span></li>\
+ </ul>\
+ </div>');
- $(document.body).append(listEl);
+ $(document.body).append(listEl);
- var list = new List('list', { valueNames: ['name'] });
+ var list = new List('list', { valueNames: ['name'] });
- it('should contain one item', function() {
- expect(list.items.length).to.equal(1);
- expect(listEl.find('li').size()).to.equal(1);
- });
-
- it('should contain two items', function() {
- list.add({ name: 'Jonas' });
- expect(list.items.length).to.equal(2);
- expect(listEl.find('li').size()).to.equal(2);
- });
+ it('should contain one item', function() {
+ expect(list.items.length).to.equal(1);
+ expect(listEl.find('li').size()).to.equal(1);
+ });
- listEl.remove();
+ it('should contain two items', function() {
+ list.add({ name: 'Jonas' });
+ expect(list.items.length).to.equal(2);
+ expect(listEl.find('li').size()).to.equal(2);
});
- describe('Without items and with string template', function() {
- var listEl = $('<div id="list">\
- <ul class="list"></ul>\
- </div>');
+ listEl.remove();
+ });
- $(document.body).append(listEl);
+ describe('Without items and with string template', function() {
+ var listEl = $('<div id="list">\
+ <ul class="list"></ul>\
+ </div>');
- var list = new List('list', {
- valueNames: ['name'],
- item: '<li><span class="name"></span></li>'
- }, [
- { name: 'Jonny' }
- ]);
+ $(document.body).append(listEl);
- it('should contain one item', function() {
- expect(list.items.length).to.equal(1);
- expect(listEl.find('li').size()).to.equal(1);
- });
+ var list = new List('list', {
+ valueNames: ['name'],
+ item: '<li><span class="name"></span></li>'
+ }, [
+ { name: 'Jonny' }
+ ]);
- it('should contain two items', function() {
- list.add({ name: 'Jonas' });
- expect(list.items.length).to.equal(2);
- expect(listEl.find('li').size()).to.equal(2);
- });
+ it('should contain one item', function() {
+ expect(list.items.length).to.equal(1);
+ expect(listEl.find('li').size()).to.equal(1);
+ });
- listEl.remove();
+ it('should contain two items', function() {
+ list.add({ name: 'Jonas' });
+ expect(list.items.length).to.equal(2);
+ expect(listEl.find('li').size()).to.equal(2);
});
- describe('Without items and with HTML template', function() {
- var listEl = $('<div id="list">\
- <ul class="list"></ul>\
- </div>');
+ listEl.remove();
+ });
- var templateEl = $('<li id="template-item"><span class="name"></span></li>');
+ describe('Without items and with HTML template', function() {
+ var listEl = $('<div id="list">\
+ <ul class="list"></ul>\
+ </div>');
- $(document.body).append(listEl);
- $(document.body).append(templateEl);
+ var templateEl = $('<li id="template-item"><span class="name"></span></li>');
- var list = new List('list', {
- valueNames: ['name'],
- item: 'template-item'
- }, [
- { name: 'Jonny' }
- ]);
+ $(document.body).append(listEl);
+ $(document.body).append(templateEl);
- it('should contain one item', function() {
- expect(list.items.length).to.equal(1);
- expect(listEl.find('li').size()).to.equal(1);
- });
+ var list = new List('list', {
+ valueNames: ['name'],
+ item: 'template-item'
+ }, [
+ { name: 'Jonny' }
+ ]);
- it('should contain two items', function() {
- list.add({ name: 'Jonas' });
- expect(list.items.length).to.equal(2);
- expect(listEl.find('li').size()).to.equal(2);
- });
+ it('should contain one item', function() {
+ expect(list.items.length).to.equal(1);
+ expect(listEl.find('li').size()).to.equal(1);
+ });
- listEl.remove();
- templateEl.remove();
+ it('should contain two items', function() {
+ list.add({ name: 'Jonas' });
+ expect(list.items.length).to.equal(2);
+ expect(listEl.find('li').size()).to.equal(2);
});
+ listEl.remove();
+ templateEl.remove();
+ });
+
+ describe('Asyn index with existing list', function() {
+ var listEl = $('<div id="list">\
+ <ul class="list">\
+ <li><span class="name">Jonny</span></li><li><span class="name">Sven</span></li>\
+ <li><span class="name">Anna</span></li><li><span class="name">Lisa</span></li>\
+ <li><span class="name">Egon</span></li><li><span class="name">Frida</span></li>\
+ <li><span class="name">Maj-britt</span></li><li><span class="name">Fredrik</span></li>\
+ <li><span class="name">Torbjorn</span></li><li><span class="name">Lolzor</span></li>\
+ <li><span class="name">Sandra</span></li><li><span class="name">Gottfrid</span></li>\
+ <li><span class="name">Tobias</span></li><li><span class="name">Martina</span></li>\
+ <li><span class="name">Johannes</span></li><li><span class="name">Ted</span></li>\
+ <li><span class="name">Malin</span></li><li><span class="name">Filippa</span></li>\
+ <li><span class="name">Imma</span></li><li><span class="name">Hasse</span></li>\
+ <li><span class="name">Robert</span></li><li><span class="name">Mona</span></li>\
+ <li><span class="name">Anna</span></li><li><span class="name">Lisa</span></li>\
+ <li><span class="name">Egon</span></li><li><span class="name">Frida</span></li>\
+ <li><span class="name">Maj-britt</span></li><li><span class="name">Fredrik</span></li>\
+ <li><span class="name">Torbjorn</span></li><li><span class="name">Lolzor</span></li>\
+ <li><span class="name">Sandra</span></li><li><span class="name">Gottfrid</span></li>\
+ <li><span class="name">Tobias</span></li><li><span class="name">Martina</span></li>\
+ <li><span class="name">Johannes</span></li><li><span class="name">Ted</span></li>\
+ <li><span class="name">Malin</span></li><li><span class="name">Filippa</span></li>\
+ <li><span class="name">Imma</span></li><li><span class="name">Hasse</span></li>\
+ <li><span class="name">Robert</span></li><li><span class="name">Mona</span></li>\
+ <li><span class="name">Anna</span></li><li><span class="name">Lisa</span></li>\
+ <li><span class="name">Egon</span></li><li><span class="name">Frida</span></li>\
+ <li><span class="name">Maj-britt</span></li><li><span class="name">Fredrik</span></li>\
+ <li><span class="name">Torbjorn</span></li><li><span class="name">Lolzor</span></li>\
+ <li><span class="name">Sandra</span></li><li><span class="name">Gottfrid</span></li>\
+ <li><span class="name">Tobias</span></li><li><span class="name">Martina</span></li>\
+ <li><span class="name">Johannes</span></li><li><span class="name">Ted</span></li>\
+ <li><span class="name">Malin</span></li><li><span class="name">Filippa</span></li>\
+ <li><span class="name">Imma</span></li><li><span class="name">Hasse</span></li>\
+ <li><span class="name">Robert</span></li><li><span class="name">Mona</span></li>\
+ <li><span class="name">Anna</span></li><li><span class="name">Lisa</span></li>\
+ <li><span class="name">Egon</span></li><li><span class="name">Frida</span></li>\
+ <li><span class="name">Maj-britt</span></li><li><span class="name">Fredrik</span></li>\
+ <li><span class="name">Torbjorn</span></li><li><span class="name">Lolzor</span></li>\
+ <li><span class="name">Sandra</span></li><li><span class="name">Gottfrid</span></li>\
+ <li><span class="name">Tobias</span></li><li><span class="name">Martina</span></li>\
+ <li><span class="name">Johannes</span></li><li><span class="name">Ted</span></li>\
+ <li><span class="name">Malin</span></li><li><span class="name">Filippa</span></li>\
+ <li><span class="name">Imma</span></li><li><span class="name">Hasse</span></li>\
+ <li><span class="name">Robert</span></li><li><span class="name">Mona</span></li>\
+ <li><span class="name">Anna</span></li><li><span class="name">Lisa</span></li>\
+ <li><span class="name">Egon</span></li><li><span class="name">Frida</span></li>\
+ <li><span class="name">Maj-britt</span></li><li><span class="name">Fredrik</span></li>\
+ <li><span class="name">Torbjorn</span></li><li><span class="name">Lolzor</span></li>\
+ <li><span class="name">Sandra</span></li><li><span class="name">Gottfrid</span></li>\
+ <li><span class="name">Tobias</span></li><li><span class="name">Martina</span></li>\
+ <li><span class="name">Johannes</span></li><li><span class="name">Ted</span></li>\
+ <li><span class="name">Malin</span></li><li><span class="name">Filippa</span></li>\
+ <li><span class="name">Imma</span></li><li><span class="name">Hasse</span></li>\
+ <li><span class="name">Robert</span></li><li><span class="name">Mona</span></li>\
+ <li><span class="name">Anna</span></li><li><span class="name">Lisa</span></li>\
+ <li><span class="name">Egon</span></li><li><span class="name">Frida</span></li>\
+ <li><span class="name">Maj-britt</span></li><li><span class="name">Fredrik</span></li>\
+ <li><span class="name">Torbjorn</span></li><li><span class="name">Lolzor</span></li>\
+ <li><span class="name">Sandra</span></li><li><span class="name">Gottfrid</span></li>\
+ <li><span class="name">Tobias</span></li><li><span class="name">Martina</span></li>\
+ <li><span class="name">Johannes</span></li><li><span class="name">Ted</span></li>\
+ <li><span class="name">Malin</span></li><li><span class="name">Filippa</span></li>\
+ <li><span class="name">Imma</span></li><li><span class="name">Hasse</span></li>\
+ <li><span class="name">Robert</span></li><li><span class="name">Mona</span></li>\
+ <li><span class="name">Anna</span></li><li><span class="name">Lisa</span></li>\
+ <li><span class="name">Egon</span></li><li><span class="name">Frida</span></li>\
+ <li><span class="name">Maj-britt</span></li><li><span class="name">Fredrik</span></li>\
+ <li><span class="name">Torbjorn</span></li><li><span class="name">Lolzor</span></li>\
+ <li><span class="name">Sandra</span></li><li><span class="name">Gottfrid</span></li>\
+ <li><span class="name">Tobias</span></li><li><span class="name">Martina</span></li>\
+ <li><span class="name">Johannes</span></li><li><span class="name">Ted</span></li>\
+ <li><span class="name">Malin</span></li><li><span class="name">Filippa</span></li>\
+ <li><span class="name">Imma</span></li><li><span class="name">Hasse</span></li>\
+ <li><span class="name">Robert</span></li><li><span class="name">Mona</span></li>\
+ <li><span class="name">Anna</span></li><li><span class="name">Lisa</span></li>\
+ <li><span class="name">Egon</span></li><li><span class="name">Frida</span></li>\
+ <li><span class="name">Maj-britt</span></li><li><span class="name">Fredrik</span></li>\
+ <li><span class="name">Torbjorn</span></li><li><span class="name">Lolzor</span></li>\
+ <li><span class="name">Sandra</span></li><li><span class="name">Gottfrid</span></li>\
+ <li><span class="name">Tobias</span></li><li><span class="name">Martina</span></li>\
+ <li><span class="name">Johannes</span></li><li><span class="name">Ted</span></li>\
+ <li><span class="name">Malin</span></li><li><span class="name">Filippa</span></li>\
+ <li><span class="name">Imma</span></li><li><span class="name">Hasse</span></li>\
+ <li><span class="name">Robert</span></li><li><span class="name">Mona</span></li>\
+ </ul>\
+ </div>');
+
+ it('should contain one item', function(done) {
+ $(document.body).append(listEl);
+ var list = new List('list', {
+ valueNames: ['name'],
+ indexAsync: true,
+ parseComplete: function(list) {
+ expect(listEl.find('li').size()).to.equal(162);
+ listEl.remove();
+ done();
+ }
+ });
+ });
+ });
-});
\ No newline at end of file
+});
diff --git a/test/test.defaults.js b/test/test.defaults.js
index 7908551..0f3940c 100644
--- a/test/test.defaults.js
+++ b/test/test.defaults.js
@@ -1,65 +1,64 @@
describe('Defaults', function() {
- var list;
+ var list;
- before(function() {
- list = fixture.list(['name'], [ { name: 'Jonny' }]);
- });
+ before(function() {
+ list = fixture.list(['name'], [ { name: 'Jonny' }]);
+ });
- after(function() {
- fixture.removeList();
- });
+ after(function() {
+ fixture.removeList();
+ });
- it('should have all default attributes', function() {
- expect(list.items).to.be.an('array');
- expect(list.visibleItems).to.be.an('array');
- expect(list.matchingItems).to.be.an('array');
+ it('should have all default attributes', function() {
+ expect(list.items).to.be.an('array');
+ expect(list.visibleItems).to.be.an('array');
+ expect(list.matchingItems).to.be.an('array');
- expect(list.handlers.updated).to.be.an('array');
- expect(list.handlers.searchStart).to.be.an('array');
- expect(list.handlers.searchComplete).to.be.an('array');
- expect(list.handlers.sortStart).to.be.an('array');
- expect(list.handlers.sortComplete).to.be.an('array');
- expect(list.handlers.filterStart).to.be.an('array');
- expect(list.handlers.filterComplete).to.be.an('array');
+ expect(list.handlers.updated).to.be.an('array');
+ expect(list.handlers.searchStart).to.be.an('array');
+ expect(list.handlers.searchComplete).to.be.an('array');
+ expect(list.handlers.sortStart).to.be.an('array');
+ expect(list.handlers.sortComplete).to.be.an('array');
+ expect(list.handlers.filterStart).to.be.an('array');
+ expect(list.handlers.filterComplete).to.be.an('array');
- expect(list.searched).to.be(false);
- expect(list.filtered).to.be(false);
- expect(list.i).to.equal(1);
- expect(list.page).to.equal(200);
- expect(list.listClass).to.equal('list');
- expect(list.sortClass).to.equal('sort');
- expect(list.searchClass).to.equal('search');
- expect(list.page).to.equal(200);
- });
+ expect(list.searched).to.be(false);
+ expect(list.filtered).to.be(false);
+ expect(list.i).to.equal(1);
+ expect(list.page).to.equal(10000);
+ expect(list.listClass).to.equal('list');
+ expect(list.sortClass).to.equal('sort');
+ expect(list.searchClass).to.equal('search');
+ });
- it('should have the right elements', function() {
- expect(list.list).to.equal($('.list')[0]);
- expect(list.listContainer).to.equal($('#list')[0]);
- });
+ it('should have the right elements', function() {
+ expect(list.list).to.equal($('.list')[0]);
+ expect(list.listContainer).to.equal($('#list')[0]);
+ });
- it('should have all default methods', function() {
- expect(list.add).to.be.a('function');
- expect(list.remove).to.be.a('function');
- expect(list.get).to.be.a('function');
- expect(list.sort).to.be.a('function');
- expect(list.search).to.be.a('function');
- expect(list.clear).to.be.a('function');
- expect(list.filter).to.be.a('function');
- expect(list.size).to.be.a('function');
- expect(list.show).to.be.a('function');
- expect(list.update).to.be.a('function');
- expect(list.on).to.be.a('function');
- });
+ it('should have all default methods', function() {
+ expect(list.add).to.be.a('function');
+ expect(list.remove).to.be.a('function');
+ expect(list.get).to.be.a('function');
+ expect(list.sort).to.be.a('function');
+ expect(list.search).to.be.a('function');
+ expect(list.clear).to.be.a('function');
+ expect(list.filter).to.be.a('function');
+ expect(list.size).to.be.a('function');
+ expect(list.show).to.be.a('function');
+ expect(list.update).to.be.a('function');
+ expect(list.on).to.be.a('function');
+ });
- it('should have all helper methods', function() {
- expect(list.helpers.classes).to.be.a('function');
- expect(list.helpers.getAttribute).to.be.a('function');
- expect(list.helpers.getByClass).to.be.a('function');
- expect(list.helpers.naturalSort).to.be.a('function');
- expect(list.helpers.events.bind).to.be.a('function');
- expect(list.helpers.events.unbind).to.be.a('function');
- expect(list.helpers.extend).to.be.a('function');
- expect(list.helpers.indexOf).to.be.a('function');
- expect(list.helpers.toString).to.be.a('function');
- });
+ it('should have all helper methods', function() {
+ expect(list.utils.classes).to.be.a('function');
+ expect(list.utils.getAttribute).to.be.a('function');
+ expect(list.utils.getByClass).to.be.a('function');
+ expect(list.utils.naturalSort).to.be.a('function');
+ expect(list.utils.events.bind).to.be.a('function');
+ expect(list.utils.events.unbind).to.be.a('function');
+ expect(list.utils.extend).to.be.a('function');
+ expect(list.utils.indexOf).to.be.a('function');
+ expect(list.utils.toString).to.be.a('function');
+ });
});
diff --git a/test/test.filter.js b/test/test.filter.js
index 21e693d..c6fe422 100644
--- a/test/test.filter.js
+++ b/test/test.filter.js
@@ -1,101 +1,101 @@
describe('Filter', function() {
- var list, jonny, martina, angelica, sebastian, imma, hasse;
+ var list, jonny, martina, angelica, sebastian, imma, hasse;
- before(function() {
- list = fixture.list(['name', 'born'], fixture.all);
- jonny = list.get('name', 'Jonny Strömberg')[0];
- martina = list.get('name', 'Martina Elm')[0];
- angelica = list.get('name', 'Angelica Abraham')[0];
- sebastian = list.get('name', 'Sebastian Höglund')[0];
- imma = list.get('name', 'Imma Grafström')[0];
- hasse = list.get('name', 'Hasse Strömberg')[0];
- });
+ before(function() {
+ list = fixture.list(['name', 'born'], fixture.all);
+ jonny = list.get('name', 'Jonny Strömberg')[0];
+ martina = list.get('name', 'Martina Elm')[0];
+ angelica = list.get('name', 'Angelica Abraham')[0];
+ sebastian = list.get('name', 'Sebastian Höglund')[0];
+ imma = list.get('name', 'Imma Grafström')[0];
+ hasse = list.get('name', 'Hasse Strömberg')[0];
+ });
- after(function() {
- fixture.removeList();
- });
+ after(function() {
+ fixture.removeList();
+ });
- afterEach(function() {
- list.filter();
- list.show(1, 200);
- });
+ afterEach(function() {
+ list.filter();
+ list.show(1, 200);
+ });
- describe('Basics', function() {
- it('should return everyone born after 1988', function() {
- var result = list.filter(function(item) {
- return (item.values().born > 1988);
- });
- expect(result.length).to.equal(1);
- expect(result[0]).to.eql(sebastian);
- });
- it('should return everyone born 1986', function() {
- var result = list.filter(function(item) {
- return (item.values().born == 1986);
- });
- expect(result.length).to.equal(3);
- for (var i = 0; i < result.length; i++) {
- expect(result[i].values().born).to.equal('1986');
- }
- });
+ describe('Basics', function() {
+ it('should return everyone born after 1988', function() {
+ var result = list.filter(function(item) {
+ return (item.values().born > 1988);
+ });
+ expect(result.length).to.equal(1);
+ expect(result[0]).to.eql(sebastian);
});
+ it('should return everyone born 1986', function() {
+ var result = list.filter(function(item) {
+ return (item.values().born == 1986);
+ });
+ expect(result.length).to.equal(3);
+ for (var i = 0; i < result.length; i++) {
+ expect(result[i].values().born).to.equal('1986');
+ }
+ });
+ });
- describe('Show and pages', function() {
- it('should return the visible items', function() {
- list.show(1,2);
- var result = list.filter(function(item) {
- return (item.values().born > 1985);
- });
- expect(result).to.eql(list.visibleItems);
- });
+ describe('Show and pages', function() {
+ it('should return the visible items', function() {
+ list.show(1,2);
+ var result = list.filter(function(item) {
+ return (item.values().born > 1985);
+ });
+ expect(result).to.eql(list.visibleItems);
+ });
- it('should return be 2 visible items and 3 matching', function() {
- list.show(1,2);
- var result = list.filter(function(item) {
- return (item.values().born > 1985);
- });
- expect(result.length).to.equal(2);
- expect(list.visibleItems.length).to.equal(2);
- expect(list.matchingItems.length).to.equal(4);
- });
+ it('should return be 2 visible items and 3 matching', function() {
+ list.show(1,2);
+ var result = list.filter(function(item) {
+ return (item.values().born > 1985);
+ });
+ expect(result.length).to.equal(2);
+ expect(list.visibleItems.length).to.equal(2);
+ expect(list.matchingItems.length).to.equal(4);
+ });
- describe('Specific items', function() {
- beforeEach(function() {
- list.show(1,2);
- var result = list.filter(function(item) {
- return (item.values().born > 1985);
- });
- });
- it('should match jonny', function() {
- expect(jonny.matching()).to.be(true);
- expect(jonny.filtered).to.be(true);
- expect(jonny.visible()).to.be(true);
- });
- it('should match martina', function() {
- expect(martina.matching()).to.be(true);
- expect(martina.filtered).to.be(true);
- expect(martina.visible()).to.be(true);
- });
- it('should match but not show angelica', function() {
- expect(angelica.matching()).to.be(true);
- expect(angelica.filtered).to.be(true);
- expect(angelica.visible()).to.be(false);
- });
- it('should match but not show sebastian', function() {
- expect(sebastian.matching()).to.be(true);
- expect(sebastian.filtered).to.be(true);
- expect(sebastian.visible()).to.be(false);
- });
- it('should not match imma', function() {
- expect(imma.matching()).to.be(false);
- expect(imma.filtered).to.be(false);
- expect(imma.visible()).to.be(false);
- });
- it('should not match hasse', function() {
- expect(hasse.matching()).to.be(false);
- expect(hasse.filtered).to.be(false);
- expect(hasse.visible()).to.be(false);
- });
+ describe('Specific items', function() {
+ beforeEach(function() {
+ list.show(1,2);
+ var result = list.filter(function(item) {
+ return (item.values().born > 1985);
});
+ });
+ it('should match jonny', function() {
+ expect(jonny.matching()).to.be(true);
+ expect(jonny.filtered).to.be(true);
+ expect(jonny.visible()).to.be(true);
+ });
+ it('should match martina', function() {
+ expect(martina.matching()).to.be(true);
+ expect(martina.filtered).to.be(true);
+ expect(martina.visible()).to.be(true);
+ });
+ it('should match but not show angelica', function() {
+ expect(angelica.matching()).to.be(true);
+ expect(angelica.filtered).to.be(true);
+ expect(angelica.visible()).to.be(false);
+ });
+ it('should match but not show sebastian', function() {
+ expect(sebastian.matching()).to.be(true);
+ expect(sebastian.filtered).to.be(true);
+ expect(sebastian.visible()).to.be(false);
+ });
+ it('should not match imma', function() {
+ expect(imma.matching()).to.be(false);
+ expect(imma.filtered).to.be(false);
+ expect(imma.visible()).to.be(false);
+ });
+ it('should not match hasse', function() {
+ expect(hasse.matching()).to.be(false);
+ expect(hasse.filtered).to.be(false);
+ expect(hasse.visible()).to.be(false);
+ });
});
+ });
});
diff --git a/test/test.item.js b/test/test.item.js
index b025ba0..0de3e98 100644
--- a/test/test.item.js
+++ b/test/test.item.js
@@ -1,146 +1,146 @@
describe('Item', function() {
- var list, item;
+ var list, item;
- before(function() {
- list = fixture.list(['name', 'born', 'doin'], [{
- name: "Jonny",
- born: "1986",
- doin: "Living the dream"
- }]);
- item = list.get('name', 'Jonny')[0];
- });
+ before(function() {
+ list = fixture.list(['name', 'born', 'doin'], [{
+ name: "Jonny",
+ born: "1986",
+ doin: "Living the dream"
+ }]);
+ item = list.get('name', 'Jonny')[0];
+ });
- beforeEach(function() {
- list.search();
- list.filter();
- list.show(1,200);
- });
+ beforeEach(function() {
+ list.search();
+ list.filter();
+ list.show(1,200);
+ });
- after(function() {
- fixture.removeList();
- });
+ after(function() {
+ fixture.removeList();
+ });
- describe('Defaults', function() {
- it('should have all default attributes', function() {
- expect(item.found).to.be(false);
- expect(item.filtered).to.be(false);
- });
+ describe('Defaults', function() {
+ it('should have all default attributes', function() {
+ expect(item.found).to.be(false);
+ expect(item.filtered).to.be(false);
+ });
- it('should have the right elements', function() {
- expect(item.elm).to.equal($('#list li')[0]);
- });
+ it('should have the right elements', function() {
+ expect(item.elm).to.equal($('#list li')[0]);
+ });
- it('should have all default methods', function() {
- expect(item.hide).to.be.a('function');
- expect(item.show).to.be.a('function');
- expect(item.values).to.be.a('function');
- expect(item.matching).to.be.a('function');
- expect(item.visible).to.be.a('function');
- });
+ it('should have all default methods', function() {
+ expect(item.hide).to.be.a('function');
+ expect(item.show).to.be.a('function');
+ expect(item.values).to.be.a('function');
+ expect(item.matching).to.be.a('function');
+ expect(item.visible).to.be.a('function');
});
+ });
- describe('Values()', function() {
- it('should have the right values', function() {
- expect(item.values()).to.eql({
- name: 'Jonny',
- born: '1986',
- doin: 'Living the dream'
- });
- });
- it('should be able to change one value', function() {
- expect(item.values().name).to.be.equal('Jonny');
- item.values({ name: 'Egon' });
- expect(item.values().name).to.be.equal('Egon');
- });
- it('should be able to change many value', function() {
- expect(item.values()).to.eql({
- name: 'Egon',
- born: '1986',
- doin: 'Living the dream'
- });
- item.values({
- name: 'Sven',
- born: '1801',
- doin: 'Is dead'
- });
- expect(item.values()).to.eql({
- name: 'Sven',
- born: '1801',
- doin: 'Is dead'
- });
- });
+ describe('Values()', function() {
+ it('should have the right values', function() {
+ expect(item.values()).to.eql({
+ name: 'Jonny',
+ born: '1986',
+ doin: 'Living the dream'
+ });
+ });
+ it('should be able to change one value', function() {
+ expect(item.values().name).to.be.equal('Jonny');
+ item.values({ name: 'Egon' });
+ expect(item.values().name).to.be.equal('Egon');
});
+ it('should be able to change many value', function() {
+ expect(item.values()).to.eql({
+ name: 'Egon',
+ born: '1986',
+ doin: 'Living the dream'
+ });
+ item.values({
+ name: 'Sven',
+ born: '1801',
+ doin: 'Is dead'
+ });
+ expect(item.values()).to.eql({
+ name: 'Sven',
+ born: '1801',
+ doin: 'Is dead'
+ });
+ });
+ });
- describe('Hide, show, visible', function() {
- it('should be hidden', function() {
- expect($('#list li').size()).to.equal(1);
- item.hide();
- expect(item.visible()).to.be(false);
- expect($('#list li').size()).to.equal(0);
- });
- it('should be visible', function() {
- item.hide();
- expect($('#list li').size()).to.equal(0);
- item.show();
- expect(item.visible()).to.be(true);
- expect($('#list li').size()).to.equal(1);
- });
+ describe('Hide, show, visible', function() {
+ it('should be hidden', function() {
+ expect($('#list li').size()).to.equal(1);
+ item.hide();
+ expect(item.visible()).to.be(false);
+ expect($('#list li').size()).to.equal(0);
});
+ it('should be visible', function() {
+ item.hide();
+ expect($('#list li').size()).to.equal(0);
+ item.show();
+ expect(item.visible()).to.be(true);
+ expect($('#list li').size()).to.equal(1);
+ });
+ });
- describe('Matching, found, filtered', function() {
- describe('Searching', function() {
- it('should not be visible, match, found or filtered', function() {
- list.search('Fredrik');
- expect(item.matching()).to.be(false);
- expect(item.found).to.be(false);
- expect(item.filtered).to.be(false);
- expect(item.visible()).to.be(false);
- });
- it('should be visble, match and found but not filterd', function() {
- var result = list.search('Sven');
- expect(item.matching()).to.be(true);
- expect(item.found).to.be(true);
- expect(item.filtered).to.be(false);
- expect(item.visible()).to.be(true);
- });
- it('reset: should be visible and matching but not found or filtered', function() {
- list.search();
- expect(item.matching()).to.be(true);
- expect(item.found).to.be(false);
- expect(item.filtered).to.be(false);
- expect(item.visible()).to.be(true);
- });
+ describe('Matching, found, filtered', function() {
+ describe('Searching', function() {
+ it('should not be visible, match, found or filtered', function() {
+ list.search('Fredrik');
+ expect(item.matching()).to.be(false);
+ expect(item.found).to.be(false);
+ expect(item.filtered).to.be(false);
+ expect(item.visible()).to.be(false);
+ });
+ it('should be visble, match and found but not filterd', function() {
+ var result = list.search('Sven');
+ expect(item.matching()).to.be(true);
+ expect(item.found).to.be(true);
+ expect(item.filtered).to.be(false);
+ expect(item.visible()).to.be(true);
+ });
+ it('reset: should be visible and matching but not found or filtered', function() {
+ list.search();
+ expect(item.matching()).to.be(true);
+ expect(item.found).to.be(false);
+ expect(item.filtered).to.be(false);
+ expect(item.visible()).to.be(true);
+ });
+ });
+ describe('Filtering', function() {
+ it('should not be visble, match, found or filtered', function() {
+ list.filter(function(item) {
+ return (item.values().name == "Fredrik");
});
- describe('Filtering', function() {
- it('should not be visble, match, found or filtered', function() {
- list.filter(function(item) {
- return (item.values().name == "Fredrik");
- });
- expect(item.matching()).to.be(false);
- expect(item.found).to.be(false);
- expect(item.filtered).to.be(false);
- expect(item.visible()).to.be(false);
- });
- it('should be visble, match and filtered but not found', function() {
- list.filter(function(item) {
- return (item.values().name == "Sven");
- });
- expect(item.matching()).to.be(true);
- expect(item.found).to.be(false);
- expect(item.filtered).to.be(true);
- expect(item.visible()).to.be(true);
- });
- it('reset: should be visble and match but not filtered or found', function() {
- list.filter();
- expect(item.matching()).to.be(true);
- expect(item.found).to.be(false);
- expect(item.filtered).to.be(false);
- expect(item.visible()).to.be(true);
- });
+ expect(item.matching()).to.be(false);
+ expect(item.found).to.be(false);
+ expect(item.filtered).to.be(false);
+ expect(item.visible()).to.be(false);
+ });
+ it('should be visble, match and filtered but not found', function() {
+ list.filter(function(item) {
+ return (item.values().name == "Sven");
});
+ expect(item.matching()).to.be(true);
+ expect(item.found).to.be(false);
+ expect(item.filtered).to.be(true);
+ expect(item.visible()).to.be(true);
+ });
+ it('reset: should be visble and match but not filtered or found', function() {
+ list.filter();
+ expect(item.matching()).to.be(true);
+ expect(item.found).to.be(false);
+ expect(item.filtered).to.be(false);
+ expect(item.visible()).to.be(true);
+ });
});
+ });
- fixture.removeList();
+ fixture.removeList();
});
diff --git a/test/test.off.js b/test/test.off.js
index b8bad4e..5d1449e 100644
--- a/test/test.off.js
+++ b/test/test.off.js
@@ -1,39 +1,39 @@
describe('Off', function() {
- var list;
+ var list;
- before(function() {
- list = fixture.list(['name', 'born'], fixture.all);
- });
+ before(function() {
+ list = fixture.list(['name', 'born'], fixture.all);
+ });
- after(function() {
- fixture.removeList();
- });
+ after(function() {
+ fixture.removeList();
+ });
- describe('General', function() {
- it('should be remove added handler', function(done) {
- var updated = function(list) {
- expect(list.handlers.updated.length).to.equal(1);
- list.off('updated', updated);
- expect(list.handlers.updated.length).to.equal(0);
- done();
- };
- list.on('updated', updated);
- list.search('jonny');
- });
+ describe('General', function() {
+ it('should be remove added handler', function(done) {
+ var updated = function(list) {
+ expect(list.handlers.updated.length).to.equal(1);
+ list.off('updated', updated);
+ expect(list.handlers.updated.length).to.equal(0);
+ done();
+ };
+ list.on('updated', updated);
+ list.search('jonny');
+ });
- it('should not remove unnamed handlers', function(done) {
- var searchComplete = function(list) {
- expect(list.handlers.searchComplete.length).to.equal(3);
- list.off('searchComplete', function() {});
- list.off('searchComplete', searchComplete);
- expect(list.handlers.searchComplete.length).to.equal(2);
- done();
- };
- list.on('searchComplete', function() {});
- list.on('searchComplete', searchComplete);
- list.on('searchComplete', function() {});
- list.search('jonny');
- });
+ it('should not remove unnamed handlers', function(done) {
+ var searchComplete = function(list) {
+ expect(list.handlers.searchComplete.length).to.equal(3);
+ list.off('searchComplete', function() {});
+ list.off('searchComplete', searchComplete);
+ expect(list.handlers.searchComplete.length).to.equal(2);
+ done();
+ };
+ list.on('searchComplete', function() {});
+ list.on('searchComplete', searchComplete);
+ list.on('searchComplete', function() {});
+ list.search('jonny');
});
+ });
});
diff --git a/test/test.on.js b/test/test.on.js
index b170254..faca353 100644
--- a/test/test.on.js
+++ b/test/test.on.js
@@ -1,123 +1,123 @@
describe('On', function() {
- var list;
+ var list;
- beforeEach(function() {
- list = fixture.list(['name', 'born'], fixture.all);
- });
+ beforeEach(function() {
+ list = fixture.list(['name', 'born'], fixture.all);
+ });
- afterEach(function() {
- fixture.removeList();
- });
+ afterEach(function() {
+ fixture.removeList();
+ });
- describe('Updated', function() {
- it('should be triggered after search', function(done) {
- list.on('updated', function(list) {
- done();
- });
- list.search('jonny');
- });
- it('should be triggered after sort', function(done) {
- list.on('updated', function(list) {
- done();
- });
- list.sort('name');
- });
- it('should be triggered after filter', function(done) {
- list.on('updated', function(list) {
- done();
- });
- list.filter(function() {
- return true;
- });
- });
- it('should be triggered after show', function(done) {
- list.on('updated', function(list) {
- done();
- });
- list.show(1,10);
- });
+ describe('Updated', function() {
+ it('should be triggered after search', function(done) {
+ list.on('updated', function(list) {
+ done();
+ });
+ list.search('jonny');
+ });
+ it('should be triggered after sort', function(done) {
+ list.on('updated', function(list) {
+ done();
+ });
+ list.sort('name');
+ });
+ it('should be triggered after filter', function(done) {
+ list.on('updated', function(list) {
+ done();
+ });
+ list.filter(function() {
+ return true;
+ });
+ });
+ it('should be triggered after show', function(done) {
+ list.on('updated', function(list) {
+ done();
+ });
+ list.show(1,10);
+ });
- it('should be triggered after add', function(done) {
- list.on('updated', function(list) {
- done();
- });
- list.add({ name: 'Hej' });
- });
- it('should be triggered after remove', function(done) {
- list.on('updated', function(list) {
- done();
- });
- list.remove('name', 'Jonny');
- });
+ it('should be triggered after add', function(done) {
+ list.on('updated', function(list) {
+ done();
+ });
+ list.add({ name: 'Hej' });
+ });
+ it('should be triggered after remove', function(done) {
+ list.on('updated', function(list) {
+ done();
+ });
+ list.remove('name', 'Jonny');
});
+ });
- describe('Multiple handlers', function() {
- it('should be trigger both handlers', function(done) {
- var done1 = false,
- done2 = false,
- isDone = function() {
- if (done1 && done2) {
- done();
- }
- };
+ describe('Multiple handlers', function() {
+ it('should be trigger both handlers', function(done) {
+ var done1 = false,
+ done2 = false,
+ isDone = function() {
+ if (done1 && done2) {
+ done();
+ }
+ };
- list.on('updated', function(list) {
- done1 = true;
- isDone();
- });
- list.on('updated', function(list) {
- done2 = true;
- isDone();
- });
- list.search('jonny');
- });
+ list.on('updated', function(list) {
+ done1 = true;
+ isDone();
+ });
+ list.on('updated', function(list) {
+ done2 = true;
+ isDone();
+ });
+ list.search('jonny');
});
+ });
- describe('Search', function() {
- it('should be triggered before and after search', function(done) {
- var done1 = false;
- list.on('searchStart', function(list) {
- done1 = true;
- });
- list.on('searchComplete', function(list) {
- if (done1) {
- done();
- }
- });
- list.search('jonny');
- });
+ describe('Search', function() {
+ it('should be triggered before and after search', function(done) {
+ var done1 = false;
+ list.on('searchStart', function(list) {
+ done1 = true;
+ });
+ list.on('searchComplete', function(list) {
+ if (done1) {
+ done();
+ }
+ });
+ list.search('jonny');
});
+ });
- describe('Sort', function() {
- it('should be triggered before and after sort', function(done) {
- var done1 = false;
- list.on('sortStart', function(list) {
- done1 = true;
- });
- list.on('sortComplete', function(list) {
- if (done1) {
- done();
- }
- });
- list.sort('name');
- });
+ describe('Sort', function() {
+ it('should be triggered before and after sort', function(done) {
+ var done1 = false;
+ list.on('sortStart', function(list) {
+ done1 = true;
+ });
+ list.on('sortComplete', function(list) {
+ if (done1) {
+ done();
+ }
+ });
+ list.sort('name');
});
+ });
- describe('Filter', function() {
- it('should be triggered before and after filter', function(done) {
- var done1 = false;
- list.on('filterStart', function(list) {
- done1 = true;
- });
- list.on('filterComplete', function(list) {
- if (done1) {
- done();
- }
- });
- list.filter(function() {
- return true;
- });
- });
+ describe('Filter', function() {
+ it('should be triggered before and after filter', function(done) {
+ var done1 = false;
+ list.on('filterStart', function(list) {
+ done1 = true;
+ });
+ list.on('filterComplete', function(list) {
+ if (done1) {
+ done();
+ }
+ });
+ list.filter(function() {
+ return true;
+ });
});
+ });
});
diff --git a/test/test.parse.js b/test/test.parse.js
index 463099f..117107d 100644
--- a/test/test.parse.js
+++ b/test/test.parse.js
@@ -1,48 +1,119 @@
describe('Parse', function() {
+ describe('Parse class', function() {
var list;
+ beforeEach(function() {
+ $('body').append($('<div id="parse-list">\
+ <div class="list">\
+ <div><span class="name">Jonny</span><span class="born">1986</span></div>\
+ <div><span class="name">Jocke</span><span class="born">1985</span></div>\
+ </div>\
+ </div>'));
- before(function() {
- $('body').append($('<div id="parse-list">\
- <div class="list">\
- <div><span class="name">Jonny</span><span class="born">1986</span></div>\
- <div><span class="name">Jocke</span><span class="born">1985</span></div>\
- </div>\
- </div>'));
-
- list = new List('parse-list', {
- valueNames: ['name', 'born']
- });
- });
-
- after(function() {
- $('#parse-list').remove();
- });
-
- describe('Parse', function() {
- it('should have two items', function() {
- expect(list.items.length).to.equal(2);
- expect(list.items[0].values().name).to.equal("Jonny");
- expect(list.items[1].values().name).to.equal("Jocke");
- });
- it('should add item to parsed list', function() {
- list.add({ name: "Sven", born: 1950 });
- expect(list.items.length).to.equal(3);
- expect(list.items[0].values().name).to.equal("Jonny");
- expect(list.items[1].values().name).to.equal("Jocke");
- expect(list.items[2].values().name).to.equal("Sven");
- expect(list.items[0].values().born).to.equal("1986");
- expect(list.items[2].values().born).to.equal(1950);
- var el = $($('#parse-list').find('.list div')[2]);
- expect(el.find('span').size()).to.equal(2);
- expect(el.find('span.name').text()).to.equal('Sven');
- expect(el.find('span.born').text()).to.equal('1950');
- });
- it('should parsed value always be string while added could be number', function() {
- expect(list.items[0].values().born).to.equal("1986");
- expect(list.items[0].values().born).not.to.equal(1986);
- expect(list.items[2].values().born).not.to.equal("1950");
- expect(list.items[2].values().born).to.equal(1950);
- });
+ list = new List('parse-list', {
+ valueNames: ['name', 'born']
+ });
});
+
+ afterEach(function() {
+ $('#parse-list').remove();
+ });
+
+ it('should have two items', function() {
+ expect(list.items.length).to.equal(2);
+ expect(list.items[0].values().name).to.equal("Jonny");
+ expect(list.items[1].values().name).to.equal("Jocke");
+ });
+ it('should add item to parsed list', function() {
+ list.add({ name: "Sven", born: 1950 });
+ expect(list.items.length).to.equal(3);
+ expect(list.items[0].values().name).to.equal("Jonny");
+ expect(list.items[1].values().name).to.equal("Jocke");
+ expect(list.items[2].values().name).to.equal("Sven");
+ expect(list.items[0].values().born).to.equal("1986");
+ expect(list.items[2].values().born).to.equal(1950);
+ var el = $($('#parse-list').find('.list div')[2]);
+ expect(el.find('span').size()).to.equal(2);
+ expect(el.find('span.name').text()).to.equal('Sven');
+ expect(el.find('span.born').text()).to.equal('1950');
+ });
+ it('should parsed value always be string while added could be number', function() {
+ list.add({ name: "Sven", born: 1950 });
+ expect(list.items[0].values().born).to.equal("1986");
+ expect(list.items[0].values().born).not.to.equal(1986);
+ expect(list.items[2].values().born).not.to.equal("1950");
+ expect(list.items[2].values().born).to.equal(1950);
+ });
+ });
+
+ describe('Parse data', function() {
+
+ var list;
+
+ beforeEach(function() {
+ $('body').append($('<div id="parse-list">\
+ <div class="list">\
+ <div data-id="1">\
+ <a href="http://lol.com" class="link name">Jonny</a>\
+ <span class="born timestamp" data-timestamp="54321">1986</span>\
+ <img class="image" src="jonny.jpg">\
+ <input class="foo" value="Bar">\
+ </div>\
+ <div data-id="2">\
+ <a href="http://lol.com" class="link name">Jocke</a>\
+ <span class="born timestamp" data-timestamp="12345">1985</span>\
+ <img class="image" src="jocke.png">\
+ <input class="foo child" value="Car">\
+ </div>\
+ </div>\
+ </div>'));
+
+ list = new List('parse-list', {
+ valueNames: [
+ 'name',
+ 'born',
+ { data: [ 'id' ] },
+ { attr: 'src', name: 'image'},
+ { attr: 'href', name: 'link'},
+ { attr: 'value', name: 'foo'},
+ { attr: 'data-timestamp', name: 'timestamp' }
+ ]
+ });
+ });
+
+ afterEach(function() {
+ $('#parse-list').remove();
+ });
+
+ it('should get values from class, data, src, value and child els data-attribute', function() {
+ expect(list.items.length).to.equal(2);
+ var jonny = list.items[0].values()
+ expect(jonny.name).to.equal("Jonny");
+ expect(jonny.born).to.equal("1986");
+ expect(jonny.id).to.equal("1");
+ expect(jonny.image).to.equal("jonny.jpg");
+ expect(jonny.timestamp).to.equal("54321");
+ expect(jonny.foo).to.equal("Bar");
+ });
+ it('should add item to list with class, data and src', function() {
+ list.add({ name: "Sven", born: 1950, id: 4, image: 'sven.gif', link: 'localhost', timestamp: '1337', foo: 'hej' });
+ expect(list.items.length).to.equal(3);
+ var sven = list.items[2].values();
+ expect(sven.name).to.equal("Sven");
+ expect(sven.born).to.equal(1950);
+ expect(sven.id).to.equal(4);
+ expect(sven.image).to.equal("sven.gif");
+ expect(sven.link).to.equal("localhost");
+ expect(sven.timestamp).to.equal("1337");
+ expect(sven.foo).to.equal("hej");
+ var el = $($('#parse-list').find('.list div')[2]);
+ expect(el.data('id')).to.equal(4);
+ expect(el.find('.name').text()).to.equal('Sven');
+ expect(el.find('.born').text()).to.equal('1950');
+ expect(el.find('.image').attr('src')).to.equal('sven.gif');
+ expect(el.find('.link').attr('href')).to.equal('localhost');
+ expect(el.find('.timestamp').data('timestamp')).to.equal(1337);
+ expect(el.find('.foo').val()).to.equal('hej');
+ });
+ });
});
diff --git a/test/test.re-index.js b/test/test.re-index.js
new file mode 100644
index 0000000..ad04f85
--- /dev/null
+++ b/test/test.re-index.js
@@ -0,0 +1,34 @@
+describe('ReIndex', function() {
+
+ var list, jonny, martina, angelica, sebastian, imma, hasse;
+
+ before(function() {
+ list = fixture.list(['name', 'born'], fixture.all);
+ });
+
+ after(function() {
+ fixture.removeList();
+ });
+
+ afterEach(function() {
+ list.show(1, 200);
+ });
+ it('should return everyone born after 1988', function() {
+ expect(list.toJSON()).to.eql([
+ { name: "Jonny Strömberg", born: '1986' },
+ { name: "Martina Elm", born: '1986' },
+ { name: "Angelica Abraham", born: '1986' },
+ { name: "Sebastian Höglund", born: '1989' },
+ { name: "Imma Grafström", born: '1953' },
+ { name: "Hasse Strömberg", born: '1955' }
+ ]);
+ var newHtml = '<li><span class="name">Sven</span><span class="born">2013</span>';
+ newHtml = newHtml + '<li><span class="name">Anna</span><span class="born">3043</span>'
+ $(list.list).html(newHtml);
+ list.reIndex();
+ expect(list.toJSON()).to.eql([
+ { name: "Sven", born: '2013' },
+ { name: "Anna", born: '3043' }
+ ]);
+ });
+});
diff --git a/test/test.search-filter.js b/test/test.search-filter.js
index c0643e3..3b9af3e 100644
--- a/test/test.search-filter.js
+++ b/test/test.search-filter.js
@@ -1,66 +1,66 @@
describe('Search and filter', function() {
- var list, jonny, martina, angelica, sebastian, imma, hasse;
+ var list, jonny, martina, angelica, sebastian, imma, hasse;
- before(function() {
- list = fixture.list(['name', 'born'], fixture.all);
+ before(function() {
+ list = fixture.list(['name', 'born'], fixture.all);
- jonny = list.get('name', 'Jonny Strömberg')[0];
- martina = list.get('name', 'Martina Elm')[0];
- angelica = list.get('name', 'Angelica Abraham')[0];
- sebastian = list.get('name', 'Sebastian Höglund')[0];
- imma = list.get('name', 'Imma Grafström')[0];
- hasse = list.get('name', 'Hasse Strömberg')[0];
- });
+ jonny = list.get('name', 'Jonny Strömberg')[0];
+ martina = list.get('name', 'Martina Elm')[0];
+ angelica = list.get('name', 'Angelica Abraham')[0];
+ sebastian = list.get('name', 'Sebastian Höglund')[0];
+ imma = list.get('name', 'Imma Grafström')[0];
+ hasse = list.get('name', 'Hasse Strömberg')[0];
+ });
- after(function() {
- fixture.removeList();
- });
+ after(function() {
+ fixture.removeList();
+ });
- afterEach(function() {
- list.search();
- list.filter();
- });
+ afterEach(function() {
+ list.search();
+ list.filter();
+ });
- describe('Search with filter', function() {
- it('should find everyone born 1986', function() {
- list.filter(function(item) {
- return (item.values().born == '1986');
- });
- expect(list.matchingItems.length).to.equal(3);
- expect(jonny.matching()).to.be(true);
- expect(martina.matching()).to.be(true);
- expect(angelica.matching()).to.be(true);
- expect(sebastian.matching()).to.be(false);
- expect(imma.matching()).to.be(false);
- expect(hasse.matching()).to.be(false);
- });
- it('should find everyone born 1986 and containes "ö"', function() {
- list.filter(function(item) {
- return (item.values().born == '1986');
- });
- list.search('ö');
- expect(list.matchingItems.length).to.equal(1);
- expect(jonny.matching()).to.be(true);
- expect(martina.matching()).to.be(false);
- expect(angelica.matching()).to.be(false);
- expect(sebastian.matching()).to.be(false);
- expect(imma.matching()).to.be(false);
- expect(hasse.matching()).to.be(false);
- });
- it('should find everyone with a "ö"', function() {
- list.filter(function(item) {
- return (item.values().born == '1986');
- });
- list.search('ö');
- list.filter();
- expect(list.matchingItems.length).to.equal(4);
- expect(jonny.matching()).to.be(true);
- expect(martina.matching()).to.be(false);
- expect(angelica.matching()).to.be(false);
- expect(sebastian.matching()).to.be(true);
- expect(imma.matching()).to.be(true);
- expect(hasse.matching()).to.be(true);
- });
+ describe('Search with filter', function() {
+ it('should find everyone born 1986', function() {
+ list.filter(function(item) {
+ return (item.values().born == '1986');
+ });
+ expect(list.matchingItems.length).to.equal(3);
+ expect(jonny.matching()).to.be(true);
+ expect(martina.matching()).to.be(true);
+ expect(angelica.matching()).to.be(true);
+ expect(sebastian.matching()).to.be(false);
+ expect(imma.matching()).to.be(false);
+ expect(hasse.matching()).to.be(false);
+ });
+ it('should find everyone born 1986 and containes "ö"', function() {
+ list.filter(function(item) {
+ return (item.values().born == '1986');
+ });
+ list.search('ö');
+ expect(list.matchingItems.length).to.equal(1);
+ expect(jonny.matching()).to.be(true);
+ expect(martina.matching()).to.be(false);
+ expect(angelica.matching()).to.be(false);
+ expect(sebastian.matching()).to.be(false);
+ expect(imma.matching()).to.be(false);
+ expect(hasse.matching()).to.be(false);
+ });
+ it('should find everyone with a "ö"', function() {
+ list.filter(function(item) {
+ return (item.values().born == '1986');
+ });
+ list.search('ö');
+ list.filter();
+ expect(list.matchingItems.length).to.equal(4);
+ expect(jonny.matching()).to.be(true);
+ expect(martina.matching()).to.be(false);
+ expect(angelica.matching()).to.be(false);
+ expect(sebastian.matching()).to.be(true);
+ expect(imma.matching()).to.be(true);
+ expect(hasse.matching()).to.be(true);
});
+ });
});
diff --git a/test/test.search.js b/test/test.search.js
index 69426e9..c98fc53 100644
--- a/test/test.search.js
+++ b/test/test.search.js
@@ -1,114 +1,148 @@
describe('Search', function() {
- var list, jonny, martina, angelica, sebastian, imma, hasse;
+ var list, jonny, martina, angelica, sebastian, imma, hasse;
- beforeEach(function() {
- list = fixture.list(['name', 'born'], fixture.all);
+ beforeEach(function() {
+ list = fixture.list(['name', 'born'], fixture.all);
- jonny = list.get('name', 'Jonny Strömberg')[0];
- martina = list.get('name', 'Martina Elm')[0];
- angelica = list.get('name', 'Angelica Abraham')[0];
- sebastian = list.get('name', 'Sebastian Höglund')[0];
- imma = list.get('name', 'Imma Grafström')[0];
- hasse = list.get('name', 'Hasse Strömberg')[0];
+ jonny = list.get('name', 'Jonny Strömberg')[0];
+ martina = list.get('name', 'Martina Elm')[0];
+ angelica = list.get('name', 'Angelica Abraham')[0];
+ sebastian = list.get('name', 'Sebastian Höglund')[0];
+ imma = list.get('name', 'Imma Grafström')[0];
+ hasse = list.get('name', 'Hasse Strömberg')[0];
+ });
+
+ afterEach(function() {
+ fixture.removeList();
+ });
+
+ describe('Case-sensitive', function() {
+ it('should not be case-sensitive', function() {
+ var result = list.search('jonny');
+ expect(result.length).to.equal(1);
+ expect(result[0]).to.eql(jonny);
});
+ });
- afterEach(function() {
- fixture.removeList();
+ describe('Number of results', function() {
+ it('should find jonny, martina, angelice', function() {
+ var result = list.search('1986');
+ expect(result.length).to.equal(3); // 3!!
+ expect(jonny.matching()).to.be(true);
+ expect(martina.matching()).to.be(true);
+ expect(angelica.matching()).to.be(true);
+ expect(sebastian.matching()).to.be(false);
+ expect(imma.matching()).to.be(false);
+ expect(hasse.matching()).to.be(false);
+ });
+ it('should find all with utf-8 char ö', function() {
+ var result = list.search('ö');
+ expect(result.length).to.equal(4); // 4!!
+ expect(jonny.matching()).to.be(true);
+ expect(martina.matching()).to.be(false);
+ expect(angelica.matching()).to.be(false);
+ expect(sebastian.matching()).to.be(true);
+ expect(imma.matching()).to.be(true);
+ expect(hasse.matching()).to.be(true);
});
+ it('should not break with weird searches', function() {
+ expect(list.search).withArgs(undefined).to.not.throwException();
+ expect(list.search).withArgs(null).to.not.throwException();
+ expect(list.search).withArgs(0).to.not.throwException();
+ expect(list.search).withArgs(function() {}).to.not.throwException();
+ expect(list.search).withArgs({ foo: "bar" }).to.not.throwException();
+ });
+ it('should not break with weird values', function() {
+ jonny.values({ name: undefined });
+ martina.values({ name: null });
+ angelica.values({ name: 0 });
+ sebastian.values({ name: function() {} });
+ imma.values({ name: { foo: "bar" } });
- describe('Case-sensitive', function() {
- it('should not be case-sensitive', function() {
- var result = list.search('jonny');
- expect(result.length).to.equal(1);
- expect(result[0]).to.eql(jonny);
- });
+ expect(list.search).withArgs("jonny").to.not.throwException();
+ expect(list.search).withArgs(undefined).to.not.throwException();
+ expect(list.search).withArgs(null).to.not.throwException();
+ expect(list.search).withArgs(0).to.not.throwException();
+ expect(list.search).withArgs(function() {}).to.not.throwException();
+ expect(list.search).withArgs({ foo: "bar" }).to.not.throwException();
});
+ });
- describe('Number of results', function() {
- it('should find jonny, martina, angelice', function() {
- var result = list.search('1986');
- expect(result.length).to.equal(3); // 3!!
- expect(jonny.matching()).to.be(true);
- expect(martina.matching()).to.be(true);
- expect(angelica.matching()).to.be(true);
- expect(sebastian.matching()).to.be(false);
- expect(imma.matching()).to.be(false);
- expect(hasse.matching()).to.be(false);
- });
- it('should find all with utf-8 char ö', function() {
- var result = list.search('ö');
- expect(result.length).to.equal(4); // 4!!
- expect(jonny.matching()).to.be(true);
- expect(martina.matching()).to.be(false);
- expect(angelica.matching()).to.be(false);
- expect(sebastian.matching()).to.be(true);
- expect(imma.matching()).to.be(true);
- expect(hasse.matching()).to.be(true);
- });
- it('should not break with weird searches', function() {
- expect(list.search).withArgs(undefined).to.not.throwException();
- expect(list.search).withArgs(null).to.not.throwException();
- expect(list.search).withArgs(0).to.not.throwException();
- expect(list.search).withArgs(function() {}).to.not.throwException();
- expect(list.search).withArgs({ foo: "bar" }).to.not.throwException();
- });
- it('should not break with weird values', function() {
- jonny.values({ name: undefined });
- martina.values({ name: null });
- angelica.values({ name: 0 });
- sebastian.values({ name: function() {} });
- imma.values({ name: { foo: "bar" } });
- expect(list.search).withArgs("jonny").to.not.throwException();
- expect(list.search).withArgs(undefined).to.not.throwException();
- expect(list.search).withArgs(null).to.not.throwException();
- expect(list.search).withArgs(0).to.not.throwException();
- expect(list.search).withArgs(function() {}).to.not.throwException();
- expect(list.search).withArgs({ foo: "bar" }).to.not.throwException();
- });
+ describe('Default search columns', function() {
+ it('should find in the default match column', function() {
+ list.searchColumns = ['name'];
+ var result = list.search('jonny');
+ expect(result.length).to.equal(1);
+ expect(result[0]).to.eql(jonny);
+ });
+ it('should not find in the default match column', function() {
+ list.searchColumns = ['born'];
+ var result = list.search('jonny');
+ expect(result.length).to.equal(0);
});
+ });
+
- describe('Specfic columns', function() {
- it('should find match in column', function() {
- var result = list.search('jonny', [ 'name' ]);
- expect(result.length).to.equal(1);
- expect(result[0]).to.eql(jonny);
- });
- it('should not find match in column', function() {
- var result = list.search('jonny', [ 'born' ]);
- expect(result.length).to.equal(0);
- });
- it('should find match in column', function() {
- var result = list.search('jonny', [ 'name' ]);
- expect(result.length).to.equal(1);
- expect(result[0]).to.eql(jonny);
- });
- it('should not find match in column', function() {
- var result = list.search('jonny', [ 'born' ]);
- expect(result.length).to.equal(0);
- });
- it('should work with columns that does not exist', function() {
- var result = list.search('jonny', [ 'pet' ]);
- expect(result.length).to.equal(0);
- });
+ describe('Specfic columns', function() {
+ it('should find match in column', function() {
+ var result = list.search('jonny', [ 'name' ]);
+ expect(result.length).to.equal(1);
+ expect(result[0]).to.eql(jonny);
});
+ it('should not find match in column', function() {
+ var result = list.search('jonny', [ 'born' ]);
+ expect(result.length).to.equal(0);
+ });
+ it('should find match in column', function() {
+ var result = list.search('jonny', [ 'name' ]);
+ expect(result.length).to.equal(1);
+ expect(result[0]).to.eql(jonny);
+ });
+ it('should not find match in column', function() {
+ var result = list.search('jonny', [ 'born' ]);
+ expect(result.length).to.equal(0);
+ });
+ it('should work with columns that does not exist', function() {
+ var result = list.search('jonny', [ 'pet' ]);
+ expect(result.length).to.equal(0);
+ });
+ });
- describe('Custom search function', function() {
- var customSearchFunction = function(searchString, columns) {
- for (var k = 0, kl = list.items.length; k < kl; k++) {
- if (list.items[k].values().born > 1985) {
- list.items[k].found = true;
- }
- }
- };
- it('should use custom function in third argument', function() {
- var result = list.search('jonny', [ 'name' ], customSearchFunction);
- expect(result.length).to.equal(4);
- });
- it('should use custom function in second argument', function() {
- var result = list.search('jonny', customSearchFunction);
- expect(result.length).to.equal(4);
- });
+ describe('Custom search function', function() {
+ var customSearchFunction = function(searchString, columns) {
+ for (var k = 0, kl = list.items.length; k < kl; k++) {
+ if (list.items[k].values().born > 1985) {
+ list.items[k].found = true;
+ }
+ }
+ };
+ it('should use custom function in third argument', function() {
+ var result = list.search('jonny', [ 'name' ], customSearchFunction);
+ expect(result.length).to.equal(4);
+ });
+ it('should use custom function in second argument', function() {
+ var result = list.search('jonny', customSearchFunction);
+ expect(result.length).to.equal(4);
});
+ });
+ //
+ // describe('Special characters', function() {
+ // it('should escape and handle special characters', function() {
+ // list.add([
+ // { name: 'Jonny&Jabba' },
+ // { name: '<Leia' },
+ // { name: '>Luke' },
+ // { name: '"Chewie"' },
+ // { name: "'Ewok'" }
+ // ]);
+ // var result = list.search('Leia');
+ // console.log(result);
+ // expect(result.length).to.equal(1);
+ // var result = list.search('<');
+ // console.log(result);
+ // expect(result.length).to.equal(1);
+ // });
+ // });
});
diff --git a/test/test.show.js b/test/test.show.js
index 23261ca..eb42ddb 100644
--- a/test/test.show.js
+++ b/test/test.show.js
@@ -1,208 +1,208 @@
describe('Show', function() {
- var list, a, b, c, d, e, f;
+ var list, a, b, c, d, e, f;
- before(function() {
- list = fixture.list(['id'], [
- { id: "1", id2: "a" },
- { id: "2", id2: "a" },
- { id: "3", id2: "b" },
- { id: "4", id2: "b" },
- { id: "5", id2: "bc" },
- { id: "6", id2: "bc" }
- ]);
- a = list.get('id', '1')[0];
- b = list.get('id', '2')[0];
- c = list.get('id', '3')[0];
- d = list.get('id', '4')[0];
- e = list.get('id', '5')[0];
- f = list.get('id', '6')[0];
- });
+ before(function() {
+ list = fixture.list(['id', 'id2'], [
+ { id: "1", id2: "a" },
+ { id: "2", id2: "a" },
+ { id: "3", id2: "b" },
+ { id: "4", id2: "b" },
+ { id: "5", id2: "bc" },
+ { id: "6", id2: "bc" }
+ ]);
+ a = list.get('id', '1')[0];
+ b = list.get('id', '2')[0];
+ c = list.get('id', '3')[0];
+ d = list.get('id', '4')[0];
+ e = list.get('id', '5')[0];
+ f = list.get('id', '6')[0];
+ });
+
+ after(function() {
+ fixture.removeList();
+ });
+
+ afterEach(function() {
+ list.filter();
+ list.show(1, 200);
+ });
- after(function() {
- fixture.removeList();
+ describe('Basics', function() {
+ it('should be 1, 2', function() {
+ list.show(1,2);
+ expect(list.visibleItems.length).to.equal(2);
+ expect(a.visible()).to.be(true);
+ expect(b.visible()).to.be(true);
+ expect(c.visible()).to.be(false);
+ expect(d.visible()).to.be(false);
+ expect(e.visible()).to.be(false);
+ expect(f.visible()).to.be(false);
+ });
+ it('should show item 6', function() {
+ list.show(6,2);
+ expect(list.visibleItems.length).to.equal(1);
+ expect(a.visible()).to.be(false);
+ expect(b.visible()).to.be(false);
+ expect(c.visible()).to.be(false);
+ expect(d.visible()).to.be(false);
+ expect(e.visible()).to.be(false);
+ expect(f.visible()).to.be(true);
+ });
+ it('should show item 1, 2, 3, 4, 5, 6', function() {
+ list.show(1,200);
+ expect(list.visibleItems.length).to.equal(6);
+ expect(a.visible()).to.be(true);
+ expect(b.visible()).to.be(true);
+ expect(c.visible()).to.be(true);
+ expect(d.visible()).to.be(true);
+ expect(e.visible()).to.be(true);
+ expect(f.visible()).to.be(true);
});
+ it('should show item 3, 4, 5', function() {
+ list.show(3,3);
+ expect(list.visibleItems.length).to.equal(3);
+ expect(a.visible()).to.be(false);
+ expect(b.visible()).to.be(false);
+ expect(c.visible()).to.be(true);
+ expect(d.visible()).to.be(true);
+ expect(e.visible()).to.be(true);
+ expect(f.visible()).to.be(false);
+ });
+ it('should show item 5, 6', function() {
+ list.show(5,3);
+ expect(list.visibleItems.length).to.equal(2);
+ expect(a.visible()).to.be(false);
+ expect(b.visible()).to.be(false);
+ expect(c.visible()).to.be(false);
+ expect(d.visible()).to.be(false);
+ expect(e.visible()).to.be(true);
+ expect(f.visible()).to.be(true);
+ });
+ });
+ describe('Search', function() {
afterEach(function() {
- list.filter();
- list.show(1, 200);
+ list.search();
});
-
- describe('Basics', function() {
- it('should be 1, 2', function() {
- list.show(1,2);
- expect(list.visibleItems.length).to.equal(2);
- expect(a.visible()).to.be(true);
- expect(b.visible()).to.be(true);
- expect(c.visible()).to.be(false);
- expect(d.visible()).to.be(false);
- expect(e.visible()).to.be(false);
- expect(f.visible()).to.be(false);
- });
- it('should show item 6', function() {
- list.show(6,2);
- expect(list.visibleItems.length).to.equal(1);
- expect(a.visible()).to.be(false);
- expect(b.visible()).to.be(false);
- expect(c.visible()).to.be(false);
- expect(d.visible()).to.be(false);
- expect(e.visible()).to.be(false);
- expect(f.visible()).to.be(true);
- });
- it('should show item 1, 2, 3, 4, 5, 6', function() {
- list.show(1,200);
- expect(list.visibleItems.length).to.equal(6);
- expect(a.visible()).to.be(true);
- expect(b.visible()).to.be(true);
- expect(c.visible()).to.be(true);
- expect(d.visible()).to.be(true);
- expect(e.visible()).to.be(true);
- expect(f.visible()).to.be(true);
- });
- it('should show item 3, 4, 5', function() {
- list.show(3,3);
- expect(list.visibleItems.length).to.equal(3);
- expect(a.visible()).to.be(false);
- expect(b.visible()).to.be(false);
- expect(c.visible()).to.be(true);
- expect(d.visible()).to.be(true);
- expect(e.visible()).to.be(true);
- expect(f.visible()).to.be(false);
- });
- it('should show item 5, 6', function() {
- list.show(5,3);
- expect(list.visibleItems.length).to.equal(2);
- expect(a.visible()).to.be(false);
- expect(b.visible()).to.be(false);
- expect(c.visible()).to.be(false);
- expect(d.visible()).to.be(false);
- expect(e.visible()).to.be(true);
- expect(f.visible()).to.be(true);
- });
+ it('should show 3, 4', function() {
+ list.search('b');
+ list.show(1,2);
+ expect(list.visibleItems.length).to.equal(2);
+ expect(a.visible()).to.be(false);
+ expect(b.visible()).to.be(false);
+ expect(c.visible()).to.be(true);
+ expect(d.visible()).to.be(true);
+ expect(e.visible()).to.be(false);
+ expect(f.visible()).to.be(false);
});
-
- describe('Search', function() {
- afterEach(function() {
- list.search();
- });
- it('should show 3, 4', function() {
- list.search('b');
- list.show(1,2);
- expect(list.visibleItems.length).to.equal(2);
- expect(a.visible()).to.be(false);
- expect(b.visible()).to.be(false);
- expect(c.visible()).to.be(true);
- expect(d.visible()).to.be(true);
- expect(e.visible()).to.be(false);
- expect(f.visible()).to.be(false);
- });
- it('should show item 3,4,5,6', function() {
- list.search('b');
- list.show(1,4);
- expect(list.visibleItems.length).to.equal(4);
- expect(a.visible()).to.be(false);
- expect(b.visible()).to.be(false);
- expect(c.visible()).to.be(true);
- expect(d.visible()).to.be(true);
- expect(e.visible()).to.be(true);
- expect(f.visible()).to.be(true);
- });
- it('should not show any items but match two', function() {
- list.search('a');
- list.show(3,2);
- expect(list.visibleItems.length).to.equal(0);
- expect(list.matchingItems.length).to.equal(2);
- expect(a.visible()).to.be(false);
- expect(b.visible()).to.be(false);
- expect(c.visible()).to.be(false);
- expect(d.visible()).to.be(false);
- expect(e.visible()).to.be(false);
- expect(f.visible()).to.be(false);
- });
+ it('should show item 3,4,5,6', function() {
+ list.search('b');
+ list.show(1,4);
+ expect(list.visibleItems.length).to.equal(4);
+ expect(a.visible()).to.be(false);
+ expect(b.visible()).to.be(false);
+ expect(c.visible()).to.be(true);
+ expect(d.visible()).to.be(true);
+ expect(e.visible()).to.be(true);
+ expect(f.visible()).to.be(true);
});
+ it('should not show any items but match two', function() {
+ list.search('a');
+ list.show(3,2);
+ expect(list.visibleItems.length).to.equal(0);
+ expect(list.matchingItems.length).to.equal(2);
+ expect(a.visible()).to.be(false);
+ expect(b.visible()).to.be(false);
+ expect(c.visible()).to.be(false);
+ expect(d.visible()).to.be(false);
+ expect(e.visible()).to.be(false);
+ expect(f.visible()).to.be(false);
+ });
+ });
- describe('Filter', function() {
- afterEach(function() {
- list.filter();
- });
- it('should show 3, 4', function() {
- list.filter(function(item) {
- return (item.values().id2 == 'b');
- });
- list.show(1,2);
- expect(list.visibleItems.length).to.equal(2);
- expect(list.matchingItems.length).to.equal(2);
- expect(a.visible()).to.be(false);
- expect(b.visible()).to.be(false);
- expect(c.visible()).to.be(true);
- expect(d.visible()).to.be(true);
- expect(e.visible()).to.be(false);
- expect(f.visible()).to.be(false);
- });
- it('should show item 3,4,5,6', function() {
- list.filter(function(item) {
- return (item.values().id2 == 'bc');
- });
- list.show(1,4);
- expect(list.visibleItems.length).to.equal(2);
- expect(list.matchingItems.length).to.equal(2);
- expect(a.visible()).to.be(false);
- expect(b.visible()).to.be(false);
- expect(c.visible()).to.be(false);
- expect(d.visible()).to.be(false);
- expect(e.visible()).to.be(true);
- expect(f.visible()).to.be(true);
- });
- it('should not show any items but match two', function() {
- list.filter(function(item) {
- return (item.values().id2 == 'b');
- });
- list.show(3,2);
- expect(list.visibleItems.length).to.equal(0);
- expect(list.matchingItems.length).to.equal(2);
- expect(a.visible()).to.be(false);
- expect(b.visible()).to.be(false);
- expect(c.visible()).to.be(false);
- expect(d.visible()).to.be(false);
- expect(e.visible()).to.be(false);
- expect(f.visible()).to.be(false);
- });
+ describe('Filter', function() {
+ afterEach(function() {
+ list.filter();
+ });
+ it('should show 3, 4', function() {
+ list.filter(function(item) {
+ return (item.values().id2 == 'b');
+ });
+ list.show(1,2);
+ expect(list.visibleItems.length).to.equal(2);
+ expect(list.matchingItems.length).to.equal(2);
+ expect(a.visible()).to.be(false);
+ expect(b.visible()).to.be(false);
+ expect(c.visible()).to.be(true);
+ expect(d.visible()).to.be(true);
+ expect(e.visible()).to.be(false);
+ expect(f.visible()).to.be(false);
+ });
+ it('should show item 3,4,5,6', function() {
+ list.filter(function(item) {
+ return (item.values().id2 == 'bc');
+ });
+ list.show(1,4);
+ expect(list.visibleItems.length).to.equal(2);
+ expect(list.matchingItems.length).to.equal(2);
+ expect(a.visible()).to.be(false);
+ expect(b.visible()).to.be(false);
+ expect(c.visible()).to.be(false);
+ expect(d.visible()).to.be(false);
+ expect(e.visible()).to.be(true);
+ expect(f.visible()).to.be(true);
});
+ it('should not show any items but match two', function() {
+ list.filter(function(item) {
+ return (item.values().id2 == 'b');
+ });
+ list.show(3,2);
+ expect(list.visibleItems.length).to.equal(0);
+ expect(list.matchingItems.length).to.equal(2);
+ expect(a.visible()).to.be(false);
+ expect(b.visible()).to.be(false);
+ expect(c.visible()).to.be(false);
+ expect(d.visible()).to.be(false);
+ expect(e.visible()).to.be(false);
+ expect(f.visible()).to.be(false);
+ });
+ });
- describe('Filter and search', function() {
- afterEach(function() {
- list.filter();
- });
- it('should show 4, 5', function() {
- list.show(1,2);
- list.filter(function(item) {
- return (item.values().id > '3');
- });
- list.search('b');
- expect(list.visibleItems.length).to.equal(2);
- expect(list.matchingItems.length).to.equal(3);
- expect(a.visible()).to.be(false);
- expect(b.visible()).to.be(false);
- expect(c.visible()).to.be(false);
- expect(d.visible()).to.be(true);
- expect(e.visible()).to.be(true);
- expect(f.visible()).to.be(false);
- });
- it('should show 5, 6', function() {
- list.show(1,2);
- list.filter(function(item) {
- return (item.values().id > '3');
- });
- list.search('b');
- list.show(2,2);
- expect(list.visibleItems.length).to.equal(2);
- expect(list.matchingItems.length).to.equal(3);
- expect(a.visible()).to.be(false);
- expect(b.visible()).to.be(false);
- expect(c.visible()).to.be(false);
- expect(d.visible()).to.be(false);
- expect(e.visible()).to.be(true);
- expect(f.visible()).to.be(true);
- });
+ describe('Filter and search', function() {
+ afterEach(function() {
+ list.filter();
+ });
+ it('should show 4, 5', function() {
+ list.show(1,2);
+ list.filter(function(item) {
+ return (item.values().id > '3');
+ });
+ list.search('b');
+ expect(list.visibleItems.length).to.equal(2);
+ expect(list.matchingItems.length).to.equal(3);
+ expect(a.visible()).to.be(false);
+ expect(b.visible()).to.be(false);
+ expect(c.visible()).to.be(false);
+ expect(d.visible()).to.be(true);
+ expect(e.visible()).to.be(true);
+ expect(f.visible()).to.be(false);
+ });
+ it('should show 5, 6', function() {
+ list.show(1,2);
+ list.filter(function(item) {
+ return (item.values().id > '3');
+ });
+ list.search('b');
+ list.show(2,2);
+ expect(list.visibleItems.length).to.equal(2);
+ expect(list.matchingItems.length).to.equal(3);
+ expect(a.visible()).to.be(false);
+ expect(b.visible()).to.be(false);
+ expect(c.visible()).to.be(false);
+ expect(d.visible()).to.be(false);
+ expect(e.visible()).to.be(true);
+ expect(f.visible()).to.be(true);
});
+ });
});
diff --git a/test/test.sort.js b/test/test.sort.js
index 8450b7e..0e9ca9c 100644
--- a/test/test.sort.js
+++ b/test/test.sort.js
@@ -1,320 +1,320 @@
describe('Sort', function() {
- var list, i1, i2, i3, i4, i5, i6;
+ var list, i1, i2, i3, i4, i5, i6;
- beforeEach(function() {
- list = fixture.list(['id'], [
- { id: "1", val: "" },
- { id: "2", val: "" },
- { id: "3", val: "" },
- { id: "4", val: "" },
- { id: "5", val: "" },
- { id: "6", val: "" }
- ]);
- i1 = list.get('id', '1')[0];
- i2 = list.get('id', '2')[0];
- i3 = list.get('id', '3')[0];
- i4 = list.get('id', '4')[0];
- i5 = list.get('id', '5')[0];
- i6 = list.get('id', '6')[0];
- });
+ beforeEach(function() {
+ list = fixture.list(['id'], [
+ { id: "1", val: "" },
+ { id: "2", val: "" },
+ { id: "3", val: "" },
+ { id: "4", val: "" },
+ { id: "5", val: "" },
+ { id: "6", val: "" }
+ ]);
+ i1 = list.get('id', '1')[0];
+ i2 = list.get('id', '2')[0];
+ i3 = list.get('id', '3')[0];
+ i4 = list.get('id', '4')[0];
+ i5 = list.get('id', '5')[0];
+ i6 = list.get('id', '6')[0];
+ });
- afterEach(function() {
- fixture.removeList();
- });
+ afterEach(function() {
+ fixture.removeList();
+ });
- describe('Basics', function() {
- it('should sort letters asc', function() {
- i1.values({ val: "b" });
- i2.values({ val: "a" });
- i3.values({ val: "c" });
- i4.values({ val: "z" });
- i5.values({ val: "s" });
- i6.values({ val: "y" });
- list.sort('val');
- expect(list.items[0].values().val).to.be.equal("a");
- expect(list.items[1].values().val).to.be.equal("b");
- expect(list.items[2].values().val).to.be.equal("c");
- expect(list.items[3].values().val).to.be.equal("s");
- expect(list.items[4].values().val).to.be.equal("y");
- expect(list.items[5].values().val).to.be.equal("z");
- });
- it('should sort letters desc', function() {
- i1.values({ val: "b" });
- i2.values({ val: "a" });
- i3.values({ val: "c" });
- i4.values({ val: "z" });
- i5.values({ val: "s" });
- i6.values({ val: "y" });
- list.sort('val', { order: "desc" });
- expect(list.items[0].values().val).to.be.equal("z");
- expect(list.items[1].values().val).to.be.equal("y");
- expect(list.items[2].values().val).to.be.equal("s");
- expect(list.items[3].values().val).to.be.equal("c");
- expect(list.items[4].values().val).to.be.equal("b");
- expect(list.items[5].values().val).to.be.equal("a");
- });
- it('should fail to sort åäö desc (becomes äåö)', function() {
- i1.values({ val: "a" });
- i2.values({ val: "å" });
- i3.values({ val: "ä" });
- i4.values({ val: "ö" });
- i5.values({ val: "o" });
- i6.values({ val: "s" });
- list.sort('val');
- expect(list.items[0].values().val).to.be.equal("a");
- expect(list.items[1].values().val).to.be.equal("o");
- expect(list.items[2].values().val).to.be.equal("s");
- expect(list.items[3].values().val).to.be.equal("ä");
- expect(list.items[4].values().val).to.be.equal("å");
- expect(list.items[5].values().val).to.be.equal("ö");
- });
- it('should fail to sort åäö asc (becomes öåä)', function() {
- i1.values({ val: "a" });
- i2.values({ val: "å" });
- i3.values({ val: "ä" });
- i4.values({ val: "ö" });
- i5.values({ val: "o" });
- i6.values({ val: "s" });
- list.sort('val', { order: "desc" });
- expect(list.items[0].values().val).to.be.equal("ö");
- expect(list.items[1].values().val).to.be.equal("å");
- expect(list.items[2].values().val).to.be.equal("ä");
- expect(list.items[3].values().val).to.be.equal("s");
- expect(list.items[4].values().val).to.be.equal("o");
- expect(list.items[5].values().val).to.be.equal("a");
- });
- it('should handle case-insensitive by default', function() {
- i1.values({ val: "e" });
- i2.values({ val: "b" });
- i4.values({ val: "F" });
- i3.values({ val: "D" });
- i5.values({ val: "A" });
- i6.values({ val: "C" });
- list.sort('val');
- expect(list.items[0].values().val).to.be.equal("A");
- expect(list.items[1].values().val).to.be.equal("b");
- expect(list.items[2].values().val).to.be.equal("C");
- expect(list.items[3].values().val).to.be.equal("D");
- expect(list.items[4].values().val).to.be.equal("e");
- expect(list.items[5].values().val).to.be.equal("F");
- });
- it('should disable insensitive', function() {
- i1.values({ val: "e" });
- i2.values({ val: "b" });
- i4.values({ val: "F" });
- i3.values({ val: "D" });
- i5.values({ val: "A" });
- i6.values({ val: "C" });
- list.sort('val', { insensitive: false });
- expect(list.items[0].values().val).to.be.equal("A");
- expect(list.items[1].values().val).to.be.equal("C");
- expect(list.items[2].values().val).to.be.equal("D");
- expect(list.items[3].values().val).to.be.equal("F");
- expect(list.items[4].values().val).to.be.equal("b");
- expect(list.items[5].values().val).to.be.equal("e");
- });
- it('should sort dates', function() {
- i1.values({ val: "10/12/2008" });
- i2.values({ val: "10/11/2008" });
- i3.values({ val: "10/11/2007" });
- i4.values({ val: "10/12/2009" });
- i5.values({ val: "4/01/2007" });
- i6.values({ val: "10/12/2006" });
- list.sort('val', { order: "asc" });
- expect(list.items[0].values().val).to.be.equal("10/12/2006");
- expect(list.items[1].values().val).to.be.equal("4/01/2007");
- expect(list.items[2].values().val).to.be.equal("10/11/2007");
- expect(list.items[3].values().val).to.be.equal("10/11/2008");
- expect(list.items[4].values().val).to.be.equal("10/12/2008");
- expect(list.items[5].values().val).to.be.equal("10/12/2009");
- });
- it('should sort file names', function() {
- i1.values({ val: "car.mov" });
- i2.values({ val: "01alpha.sgi" });
- i3.values({ val: "001alpha.sgi" });
- i4.values({ val: "my.string_41299.tif" });
- i5.values({ val: "0003.zip" });
- i6.values({ val: "0002.asp" });
- list.sort('val', { order: "asc" });
- expect(list.items[0].values().val).to.be.equal("0002.asp");
- expect(list.items[1].values().val).to.be.equal("0003.zip");
- expect(list.items[2].values().val).to.be.equal("001alpha.sgi");
- expect(list.items[3].values().val).to.be.equal("01alpha.sgi");
- expect(list.items[4].values().val).to.be.equal("car.mov");
- expect(list.items[5].values().val).to.be.equal("my.string_41299.tif");
- });
- it('should sort floates', function() {
- i1.values({ val: "10.0401" });
- i2.values({ val: "10.022" });
- i3.values({ val: "10.021999" });
- i4.values({ val: "11.231" });
- i5.values({ val: "0003.123" });
- i6.values({ val: "09.2123" });
- list.sort('val', { order: "asc" });
- expect(list.items[0].values().val).to.be.equal("0003.123");
- expect(list.items[1].values().val).to.be.equal("09.2123");
- expect(list.items[2].values().val).to.be.equal("10.021999");
- expect(list.items[3].values().val).to.be.equal("10.022");
- expect(list.items[4].values().val).to.be.equal("10.0401");
- expect(list.items[5].values().val).to.be.equal("11.231");
- });
- it('should sort IP addresses', function() {
- i1.values({ val: "192.168.1.1" });
- i2.values({ val: "192.168.0.100" });
- i3.values({ val: "192.168.0.1" });
- i4.values({ val: "192.168.1.3" });
- i5.values({ val: "127.0.0.1" });
- i6.values({ val: "192.168.1.2" });
- list.sort('val', { order: "asc" });
- expect(list.items[0].values().val).to.be.equal("127.0.0.1");
- expect(list.items[1].values().val).to.be.equal("192.168.0.1");
- expect(list.items[2].values().val).to.be.equal("192.168.0.100");
- expect(list.items[3].values().val).to.be.equal("192.168.1.1");
- expect(list.items[4].values().val).to.be.equal("192.168.1.2");
- expect(list.items[5].values().val).to.be.equal("192.168.1.3");
- });
- it('should not break with weird values', function() {
- i1.values({ val: undefined });
- i2.values({ val: null });
- i3.values({ val: 0 });
- i4.values({ val: function() {} });
- i5.values({ val: { foo: "bar" } });
+ describe('Basics', function() {
+ it('should sort letters asc', function() {
+ i1.values({ val: "b" });
+ i2.values({ val: "a" });
+ i3.values({ val: "c" });
+ i4.values({ val: "z" });
+ i5.values({ val: "s" });
+ i6.values({ val: "y" });
+ list.sort('val');
+ expect(list.items[0].values().val).to.be.equal("a");
+ expect(list.items[1].values().val).to.be.equal("b");
+ expect(list.items[2].values().val).to.be.equal("c");
+ expect(list.items[3].values().val).to.be.equal("s");
+ expect(list.items[4].values().val).to.be.equal("y");
+ expect(list.items[5].values().val).to.be.equal("z");
+ });
+ it('should sort letters desc', function() {
+ i1.values({ val: "b" });
+ i2.values({ val: "a" });
+ i3.values({ val: "c" });
+ i4.values({ val: "z" });
+ i5.values({ val: "s" });
+ i6.values({ val: "y" });
+ list.sort('val', { order: "desc" });
+ expect(list.items[0].values().val).to.be.equal("z");
+ expect(list.items[1].values().val).to.be.equal("y");
+ expect(list.items[2].values().val).to.be.equal("s");
+ expect(list.items[3].values().val).to.be.equal("c");
+ expect(list.items[4].values().val).to.be.equal("b");
+ expect(list.items[5].values().val).to.be.equal("a");
+ });
+ it('should fail to sort åäö desc (becomes äåö)', function() {
+ i1.values({ val: "a" });
+ i2.values({ val: "å" });
+ i3.values({ val: "ä" });
+ i4.values({ val: "ö" });
+ i5.values({ val: "o" });
+ i6.values({ val: "s" });
+ list.sort('val');
+ expect(list.items[0].values().val).to.be.equal("a");
+ expect(list.items[1].values().val).to.be.equal("o");
+ expect(list.items[2].values().val).to.be.equal("s");
+ expect(list.items[3].values().val).to.be.equal("ä");
+ expect(list.items[4].values().val).to.be.equal("å");
+ expect(list.items[5].values().val).to.be.equal("ö");
+ });
+ it('should fail to sort åäö asc (becomes öåä)', function() {
+ i1.values({ val: "a" });
+ i2.values({ val: "å" });
+ i3.values({ val: "ä" });
+ i4.values({ val: "ö" });
+ i5.values({ val: "o" });
+ i6.values({ val: "s" });
+ list.sort('val', { order: "desc" });
+ expect(list.items[0].values().val).to.be.equal("ö");
+ expect(list.items[1].values().val).to.be.equal("å");
+ expect(list.items[2].values().val).to.be.equal("ä");
+ expect(list.items[3].values().val).to.be.equal("s");
+ expect(list.items[4].values().val).to.be.equal("o");
+ expect(list.items[5].values().val).to.be.equal("a");
+ });
+ it('should handle case-insensitive by default', function() {
+ i1.values({ val: "e" });
+ i2.values({ val: "b" });
+ i4.values({ val: "F" });
+ i3.values({ val: "D" });
+ i5.values({ val: "A" });
+ i6.values({ val: "C" });
+ list.sort('val');
+ expect(list.items[0].values().val).to.be.equal("A");
+ expect(list.items[1].values().val).to.be.equal("b");
+ expect(list.items[2].values().val).to.be.equal("C");
+ expect(list.items[3].values().val).to.be.equal("D");
+ expect(list.items[4].values().val).to.be.equal("e");
+ expect(list.items[5].values().val).to.be.equal("F");
+ });
+ it('should disable insensitive', function() {
+ i1.values({ val: "e" });
+ i2.values({ val: "b" });
+ i4.values({ val: "F" });
+ i3.values({ val: "D" });
+ i5.values({ val: "A" });
+ i6.values({ val: "C" });
+ list.sort('val', { insensitive: false });
+ expect(list.items[0].values().val).to.be.equal("A");
+ expect(list.items[1].values().val).to.be.equal("C");
+ expect(list.items[2].values().val).to.be.equal("D");
+ expect(list.items[3].values().val).to.be.equal("F");
+ expect(list.items[4].values().val).to.be.equal("b");
+ expect(list.items[5].values().val).to.be.equal("e");
+ });
+ it('should sort dates', function() {
+ i1.values({ val: "10/12/2008" });
+ i2.values({ val: "10/11/2008" });
+ i3.values({ val: "10/11/2007" });
+ i4.values({ val: "10/12/2009" });
+ i5.values({ val: "4/01/2007" });
+ i6.values({ val: "10/12/2006" });
+ list.sort('val', { order: "asc" });
+ expect(list.items[0].values().val).to.be.equal("10/12/2006");
+ expect(list.items[1].values().val).to.be.equal("4/01/2007");
+ expect(list.items[2].values().val).to.be.equal("10/11/2007");
+ expect(list.items[3].values().val).to.be.equal("10/11/2008");
+ expect(list.items[4].values().val).to.be.equal("10/12/2008");
+ expect(list.items[5].values().val).to.be.equal("10/12/2009");
+ });
+ it('should sort file names', function() {
+ i1.values({ val: "car.mov" });
+ i2.values({ val: "01alpha.sgi" });
+ i3.values({ val: "001alpha.sgi" });
+ i4.values({ val: "my.string_41299.tif" });
+ i5.values({ val: "0003.zip" });
+ i6.values({ val: "0002.asp" });
+ list.sort('val', { order: "asc" });
+ expect(list.items[0].values().val).to.be.equal("0002.asp");
+ expect(list.items[1].values().val).to.be.equal("0003.zip");
+ expect(list.items[2].values().val).to.be.equal("001alpha.sgi");
+ expect(list.items[3].values().val).to.be.equal("01alpha.sgi");
+ expect(list.items[4].values().val).to.be.equal("car.mov");
+ expect(list.items[5].values().val).to.be.equal("my.string_41299.tif");
+ });
+ it('should sort floates', function() {
+ i1.values({ val: "10.0401" });
+ i2.values({ val: "10.022" });
+ i3.values({ val: "10.021999" });
+ i4.values({ val: "11.231" });
+ i5.values({ val: "0003.123" });
+ i6.values({ val: "09.2123" });
+ list.sort('val', { order: "asc" });
+ expect(list.items[0].values().val).to.be.equal("0003.123");
+ expect(list.items[1].values().val).to.be.equal("09.2123");
+ expect(list.items[2].values().val).to.be.equal("10.021999");
+ expect(list.items[3].values().val).to.be.equal("10.022");
+ expect(list.items[4].values().val).to.be.equal("10.0401");
+ expect(list.items[5].values().val).to.be.equal("11.231");
+ });
+ it('should sort IP addresses', function() {
+ i1.values({ val: "192.168.1.1" });
+ i2.values({ val: "192.168.0.100" });
+ i3.values({ val: "192.168.0.1" });
+ i4.values({ val: "192.168.1.3" });
+ i5.values({ val: "127.0.0.1" });
+ i6.values({ val: "192.168.1.2" });
+ list.sort('val', { order: "asc" });
+ expect(list.items[0].values().val).to.be.equal("127.0.0.1");
+ expect(list.items[1].values().val).to.be.equal("192.168.0.1");
+ expect(list.items[2].values().val).to.be.equal("192.168.0.100");
+ expect(list.items[3].values().val).to.be.equal("192.168.1.1");
+ expect(list.items[4].values().val).to.be.equal("192.168.1.2");
+ expect(list.items[5].values().val).to.be.equal("192.168.1.3");
+ });
+ it('should not break with weird values', function() {
+ i1.values({ val: undefined });
+ i2.values({ val: null });
+ i3.values({ val: 0 });
+ i4.values({ val: function() {} });
+ i5.values({ val: { foo: "bar" } });
- expect(list.sort).withArgs('val').to.not.throwException();
- expect(list.sort).withArgs('val').to.not.throwException();
- expect(list.sort).withArgs('val').to.not.throwException();
- expect(list.sort).withArgs('val').to.not.throwException();
- expect(list.sort).withArgs('val').to.not.throwException();
- expect(list.sort).withArgs('val').to.not.throwException();
- });
- /*
- it('should show how random values are sorted', function() {
- list.add({ id: '7', val: "" });
- list.add({ id: '8', val: "" });
- list.add({ id: '9', val: "" });
- list.add({ id: '10', val: "" });
- list.add({ id: '11', val: "" });
- list.add({ id: '12', val: "" });
+ expect(list.sort).withArgs('val').to.not.throwException();
+ expect(list.sort).withArgs('val').to.not.throwException();
+ expect(list.sort).withArgs('val').to.not.throwException();
+ expect(list.sort).withArgs('val').to.not.throwException();
+ expect(list.sort).withArgs('val').to.not.throwException();
+ expect(list.sort).withArgs('val').to.not.throwException();
+ });
+ /*
+ it('should show how random values are sorted', function() {
+ list.add({ id: '7', val: "" });
+ list.add({ id: '8', val: "" });
+ list.add({ id: '9', val: "" });
+ list.add({ id: '10', val: "" });
+ list.add({ id: '11', val: "" });
+ list.add({ id: '12', val: "" });
- var i7 = list.get('id', '7')[0],
- i8 = list.get('id', '8')[0],
- i9 = list.get('id', '9')[0],
- i10 = list.get('id', '10')[0],
- i11 = list.get('id', '11')[0],
- i12 = list.get('id', '12')[0];
+ var i7 = list.get('id', '7')[0],
+ i8 = list.get('id', '8')[0],
+ i9 = list.get('id', '9')[0],
+ i10 = list.get('id', '10')[0],
+ i11 = list.get('id', '11')[0],
+ i12 = list.get('id', '12')[0];
- i1.values({ val: undefined });
- i2.values({ val: "" });
- i3.values({ val: null });
- i4.values({ val: "a" });
- i5.values({ val: "0" });
- i6.values({ val: true });
- i7.values({ val: 0 });
- i8.values({ val: "z" });
- i9.values({ val: "!" });
- i10.values({ val: "?" });
- i11.values({ val: 100 });
- i12.values({ val: false });
+ i1.values({ val: undefined });
+ i2.values({ val: "" });
+ i3.values({ val: null });
+ i4.values({ val: "a" });
+ i5.values({ val: "0" });
+ i6.values({ val: true });
+ i7.values({ val: 0 });
+ i8.values({ val: "z" });
+ i9.values({ val: "!" });
+ i10.values({ val: "?" });
+ i11.values({ val: 100 });
+ i12.values({ val: false });
- list.sort('val', { order: "asc" });
- list.sort('val', { order: "desc" });
- list.sort('val', { order: "asc" });
+ list.sort('val', { order: "asc" });
+ list.sort('val', { order: "desc" });
+ list.sort('val', { order: "asc" });
- expect(list.items[0].values().val).to.be.equal("");
- expect(list.items[1].values().val).to.be.equal("0");
- expect(list.items[2].values().val).to.be.equal(0);
- expect(list.items[3].values().val).to.be.equal(100);
- expect(list.items[4].values().val).to.be.equal("!");
- expect(list.items[5].values().val).to.be.equal("?");
- expect(list.items[6].values().val).to.be.equal("a");
- expect(list.items[7].values().val).to.be.equal(false);
- expect(list.items[8].values().val).to.be.equal(null);
- expect(list.items[9].values().val).to.be.equal(true);
- expect(list.items[10].values().val).to.be.equal(undefined);
- expect(list.items[11].values().val).to.be.equal("z");
- });
+ expect(list.items[0].values().val).to.be.equal("");
+ expect(list.items[1].values().val).to.be.equal("0");
+ expect(list.items[2].values().val).to.be.equal(0);
+ expect(list.items[3].values().val).to.be.equal(100);
+ expect(list.items[4].values().val).to.be.equal("!");
+ expect(list.items[5].values().val).to.be.equal("?");
+ expect(list.items[6].values().val).to.be.equal("a");
+ expect(list.items[7].values().val).to.be.equal(false);
+ expect(list.items[8].values().val).to.be.equal(null);
+ expect(list.items[9].values().val).to.be.equal(true);
+ expect(list.items[10].values().val).to.be.equal(undefined);
+ expect(list.items[11].values().val).to.be.equal("z");
+ });
- it('should handle space and zero the same for desc and asc (random)', function() {
- list.clear();
- list.add({ val: "" });
- list.add({ val: "0" });
- list.add({ val: 0 });
+ it('should handle space and zero the same for desc and asc (random)', function() {
+ list.clear();
+ list.add({ val: "" });
+ list.add({ val: "0" });
+ list.add({ val: 0 });
- list.sort('val', { order: "asc" });
- expect(list.items[0].values().val).to.be.equal("");
- expect(list.items[1].values().val).to.be.equal("0");
- expect(list.items[2].values().val).to.be.equal(0);
- list.sort('val', { order: "desc" });
- expect(list.items[0].values().val).to.be.equal("");
- expect(list.items[1].values().val).to.be.equal("0");
- expect(list.items[2].values().val).to.be.equal(0);
- list.sort('val', { order: "asc" });
- expect(list.items[0].values().val).to.be.equal("");
- expect(list.items[1].values().val).to.be.equal("0");
- expect(list.items[2].values().val).to.be.equal(0);
- });
- */
+ list.sort('val', { order: "asc" });
+ expect(list.items[0].values().val).to.be.equal("");
+ expect(list.items[1].values().val).to.be.equal("0");
+ expect(list.items[2].values().val).to.be.equal(0);
+ list.sort('val', { order: "desc" });
+ expect(list.items[0].values().val).to.be.equal("");
+ expect(list.items[1].values().val).to.be.equal("0");
+ expect(list.items[2].values().val).to.be.equal(0);
+ list.sort('val', { order: "asc" });
+ expect(list.items[0].values().val).to.be.equal("");
+ expect(list.items[1].values().val).to.be.equal("0");
+ expect(list.items[2].values().val).to.be.equal(0);
});
+ */
+ });
- describe('Custom sort function', function() {
- it('should use custom sort option', function() {
- i1.values({ val: "<input value='b' />" });
- i2.values({ val: "<input value='a' />" });
- i3.values({ val: "<input value='c' />" });
- i4.values({ val: "<input value='z' />" });
- i5.values({ val: "<input value='s' />" });
- i6.values({ val: "<input value='y' />" });
- list.sort('val', {
- sortFunction: function(itemA, itemB, options) {
- options.desc = false;
- return list.helpers.naturalSort($(itemA.values()[options.valueName]).val(), $(itemB.values()[options.valueName]).val(), options);
- }
- });
- expect(list.items[0].values().val).to.be.equal("<input value='a' />");
- expect(list.items[1].values().val).to.be.equal("<input value='b' />");
- expect(list.items[2].values().val).to.be.equal("<input value='c' />");
- expect(list.items[3].values().val).to.be.equal("<input value='s' />");
- expect(list.items[4].values().val).to.be.equal("<input value='y' />");
- expect(list.items[5].values().val).to.be.equal("<input value='z' />");
- });
- it('should use default custom sort function', function() {
- list.sortFunction = function(itemA, itemB, options) {
- options.desc = false;
- return list.helpers.naturalSort($(itemA.values()[options.valueName]).val(), $(itemB.values()[options.valueName]).val(), options);
- };
- i1.values({ val: "<input value='b' />" });
- i2.values({ val: "<input value='a' />" });
- i3.values({ val: "<input value='c' />" });
- i4.values({ val: "<input value='z' />" });
- i5.values({ val: "<input value='s' />" });
- i6.values({ val: "<input value='y' />" });
- list.sort('val');
- expect(list.items[0].values().val).to.be.equal("<input value='a' />");
- expect(list.items[1].values().val).to.be.equal("<input value='b' />");
- expect(list.items[2].values().val).to.be.equal("<input value='c' />");
- expect(list.items[3].values().val).to.be.equal("<input value='s' />");
- expect(list.items[4].values().val).to.be.equal("<input value='y' />");
- expect(list.items[5].values().val).to.be.equal("<input value='z' />");
- });
- it('should use default custom sort function with options', function() {
- list.sortFunction = function(itemA, itemB, options) {
- options.desc = true;
- return list.helpers.naturalSort($(itemA.values()[options.valueName]).val(), $(itemB.values()[options.valueName]).val(), options);
- };
- i1.values({ val: "<input value='b' />" });
- i2.values({ val: "<input value='a' />" });
- i3.values({ val: "<input value='c' />" });
- i4.values({ val: "<input value='z' />" });
- i5.values({ val: "<input value='s' />" });
- i6.values({ val: "<input value='y' />" });
- list.sort('val', { order: "desc"});
- expect(list.items[0].values().val).to.be.equal("<input value='z' />");
- expect(list.items[1].values().val).to.be.equal("<input value='y' />");
- expect(list.items[2].values().val).to.be.equal("<input value='s' />");
- expect(list.items[3].values().val).to.be.equal("<input value='c' />");
- expect(list.items[4].values().val).to.be.equal("<input value='b' />");
- expect(list.items[5].values().val).to.be.equal("<input value='a' />");
- });
+ describe('Custom sort function', function() {
+ it('should use custom sort option', function() {
+ i1.values({ val: "<input value='b' />" });
+ i2.values({ val: "<input value='a' />" });
+ i3.values({ val: "<input value='c' />" });
+ i4.values({ val: "<input value='z' />" });
+ i5.values({ val: "<input value='s' />" });
+ i6.values({ val: "<input value='y' />" });
+ list.sort('val', {
+ sortFunction: function(itemA, itemB, options) {
+ options.desc = false;
+ return list.utils.naturalSort($(itemA.values()[options.valueName]).val(), $(itemB.values()[options.valueName]).val(), options);
+ }
+ });
+ expect(list.items[0].values().val).to.be.equal("<input value='a' />");
+ expect(list.items[1].values().val).to.be.equal("<input value='b' />");
+ expect(list.items[2].values().val).to.be.equal("<input value='c' />");
+ expect(list.items[3].values().val).to.be.equal("<input value='s' />");
+ expect(list.items[4].values().val).to.be.equal("<input value='y' />");
+ expect(list.items[5].values().val).to.be.equal("<input value='z' />");
+ });
+ it('should use default custom sort function', function() {
+ list.sortFunction = function(itemA, itemB, options) {
+ options.desc = false;
+ return list.utils.naturalSort($(itemA.values()[options.valueName]).val(), $(itemB.values()[options.valueName]).val(), options);
+ };
+ i1.values({ val: "<input value='b' />" });
+ i2.values({ val: "<input value='a' />" });
+ i3.values({ val: "<input value='c' />" });
+ i4.values({ val: "<input value='z' />" });
+ i5.values({ val: "<input value='s' />" });
+ i6.values({ val: "<input value='y' />" });
+ list.sort('val');
+ expect(list.items[0].values().val).to.be.equal("<input value='a' />");
+ expect(list.items[1].values().val).to.be.equal("<input value='b' />");
+ expect(list.items[2].values().val).to.be.equal("<input value='c' />");
+ expect(list.items[3].values().val).to.be.equal("<input value='s' />");
+ expect(list.items[4].values().val).to.be.equal("<input value='y' />");
+ expect(list.items[5].values().val).to.be.equal("<input value='z' />");
+ });
+ it('should use default custom sort function with options', function() {
+ list.sortFunction = function(itemA, itemB, options) {
+ options.desc = true;
+ return list.utils.naturalSort($(itemA.values()[options.valueName]).val(), $(itemB.values()[options.valueName]).val(), options);
+ };
+ i1.values({ val: "<input value='b' />" });
+ i2.values({ val: "<input value='a' />" });
+ i3.values({ val: "<input value='c' />" });
+ i4.values({ val: "<input value='z' />" });
+ i5.values({ val: "<input value='s' />" });
+ i6.values({ val: "<input value='y' />" });
+ list.sort('val', { order: "desc"});
+ expect(list.items[0].values().val).to.be.equal("<input value='z' />");
+ expect(list.items[1].values().val).to.be.equal("<input value='y' />");
+ expect(list.items[2].values().val).to.be.equal("<input value='s' />");
+ expect(list.items[3].values().val).to.be.equal("<input value='c' />");
+ expect(list.items[4].values().val).to.be.equal("<input value='b' />");
+ expect(list.items[5].values().val).to.be.equal("<input value='a' />");
});
+ });
});
diff --git a/test/test.trigger.js b/test/test.trigger.js
index c51ecff..12ad889 100644
--- a/test/test.trigger.js
+++ b/test/test.trigger.js
@@ -1,21 +1,21 @@
describe('Trigger', function() {
- var list;
+ var list;
- before(function() {
- list = fixture.list(['name', 'born'], fixture.all);
- });
+ before(function() {
+ list = fixture.list(['name', 'born'], fixture.all);
+ });
- after(function() {
- fixture.removeList();
- });
+ after(function() {
+ fixture.removeList();
+ });
- describe('General', function() {
- it('should be triggered by searchComplete', function(done) {
- list.on('searchComplete', function() {
- done();
- });
- list.trigger('searchComplete');
- });
+ describe('General', function() {
+ it('should be triggered by searchComplete', function(done) {
+ list.on('searchComplete', function() {
+ done();
+ });
+ list.trigger('searchComplete');
});
+ });
});
\ No newline at end of file
diff --git a/test/usage/amd.html b/test/usage/amd.html
new file mode 100644
index 0000000..32fccbb
--- /dev/null
+++ b/test/usage/amd.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script data-main="main" src="require.js"></script>
+ <link rel="stylesheet" href="style.css" />
+</head>
+<body>
+
+ <div id="users">
+ <input class="search" placeholder="Search" />
+ <button class="sort" data-sort="name">
+ Sort by name
+ </button>
+ <ul class="list">
+ <li>
+ <h3 class="name">Jonny Stromberg</h3>
+ <p class="born">1986</p>
+ </li>
+ <li>
+ <h3 class="name">Jonas Arnklint</h3>
+ <p class="born">1985</p>
+ </li>
+ <li>
+ <h3 class="name">Martina Elm</h3>
+ <p class="born">1986</p>
+ </li>
+ <li>
+ <h3 class="name">Gustaf Lindqvist</h3>
+ <p class="born">1983</p>
+ </li>
+ </ul>
+ </div>
+</body>
+</html>
diff --git a/test/usage/boba.jpeg b/test/usage/boba.jpeg
new file mode 100644
index 0000000..3003f7b
Binary files /dev/null and b/test/usage/boba.jpeg differ
diff --git a/test/usage/classic.html b/test/usage/classic.html
new file mode 100644
index 0000000..aa3fb0c
--- /dev/null
+++ b/test/usage/classic.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="../../dist/list.js"></script>
+ <link rel="stylesheet" href="style.css" />
+</head>
+<body>
+
+ <div id="users">
+ <input class="search" placeholder="Search" />
+ <button class="sort" data-sort="name">
+ Sort by name
+ </button>
+ <ul class="list">
+ <li data-id="1">
+ <a href="https://twitter.com/javve" class="link name">Jonny Stromberg</a>
+ <p class="born timestamp" data-timestamp="12345">1986</p>
+ <img class="image" src="luke.jpeg">
+ </li>
+ <li data-id="2">
+ <a href="https://twitter.com/arnklint" class="link name">Jonas Arnklint</a>
+ <p class="born timestamp" data-timestamp="23456">1985</p>
+ <img class="image" src="darth.jpeg">
+ </li>
+ <li data-id="3">
+ <a href="https://twitter.com/martinaelm" class="link name">Martina Elm</a>
+ <p class="born timestamp" data-timestamp="34567">1986</p>
+ <img class="image" src="rey.jpeg">
+ </li>
+ <li data-id="4">
+ <a href="https://twitter.com/GLindqvist" class="link name">Gustaf Lindqvist</a>
+ <p class="born timestamp" data-timestamp="45678">1983</p>
+ <img class="image" src="boba.jpeg">
+ </li>
+ </ul>
+ </div>
+
+ <script>
+ var options = {
+ valueNames: [
+ 'name',
+ 'born',
+ { data: ['id'] },
+ { attr: 'src', name: 'image' },
+ { attr: 'href', name: 'link' },
+ { attr: 'data-timestamp', name: 'timestamp' }
+ ]
+ };
+ var userList = new List('users', options);
+ userList.add({ name: 'Leia', born: '1954', image: 'leia.jpeg', id: 5, timestamp: '67893' });
+ </script>
+</body>
+</html>
diff --git a/test/usage/darth.jpeg b/test/usage/darth.jpeg
new file mode 100644
index 0000000..f4ff609
Binary files /dev/null and b/test/usage/darth.jpeg differ
diff --git a/test/usage/leia.jpeg b/test/usage/leia.jpeg
new file mode 100644
index 0000000..20d07cb
Binary files /dev/null and b/test/usage/leia.jpeg differ
diff --git a/test/usage/luke.jpeg b/test/usage/luke.jpeg
new file mode 100644
index 0000000..4eaaba6
Binary files /dev/null and b/test/usage/luke.jpeg differ
diff --git a/test/usage/main.js b/test/usage/main.js
new file mode 100644
index 0000000..63cc377
--- /dev/null
+++ b/test/usage/main.js
@@ -0,0 +1,6 @@
+require(['../../dist/list', '../../dist/list.min'], function(List, ListMin) {
+ var options = {
+ valueNames: [ 'name', 'born' ]
+ };
+ var userList = new List('users', options);
+});
diff --git a/test/usage/require.js b/test/usage/require.js
new file mode 100644
index 0000000..babfa9a
--- /dev/null
+++ b/test/usage/require.js
@@ -0,0 +1,2083 @@
+/** vim: et:ts=4:sw=4:sts=4
+ * @license RequireJS 2.1.17 Copyright (c) 2010-2015, The Dojo Foundation All Rights Reserved.
+ * Available via the MIT or new BSD license.
+ * see: http://github.com/jrburke/requirejs for details
+ */
+//Not using strict: uneven strict support in browsers, #392, and causes
+//problems with requirejs.exec()/transpiler plugins that may not be strict.
+/*jslint regexp: true, nomen: true, sloppy: true */
+/*global window, navigator, document, importScripts, setTimeout, opera */
+
+var requirejs, require, define;
+(function (global) {
+ var req, s, head, baseElement, dataMain, src,
+ interactiveScript, currentlyAddingScript, mainScript, subPath,
+ version = '2.1.17',
+ commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
+ cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
+ jsSuffixRegExp = /\.js$/,
+ currDirRegExp = /^\.\//,
+ op = Object.prototype,
+ ostring = op.toString,
+ hasOwn = op.hasOwnProperty,
+ ap = Array.prototype,
+ apsp = ap.splice,
+ isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document),
+ isWebWorker = !isBrowser && typeof importScripts !== 'undefined',
+ //PS3 indicates loaded and complete, but need to wait for complete
+ //specifically. Sequence is 'loading', 'loaded', execution,
+ // then 'complete'. The UA check is unfortunate, but not sure how
+ //to feature test w/o causing perf issues.
+ readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ?
+ /^complete$/ : /^(complete|loaded)$/,
+ defContextName = '_',
+ //Oh the tragedy, detecting opera. See the usage of isOpera for reason.
+ isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]',
+ contexts = {},
+ cfg = {},
+ globalDefQueue = [],
+ useInteractive = false;
+
+ function isFunction(it) {
+ return ostring.call(it) === '[object Function]';
+ }
+
+ function isArray(it) {
+ return ostring.call(it) === '[object Array]';
+ }
+
+ /**
+ * Helper function for iterating over an array. If the func returns
+ * a true value, it will break out of the loop.
+ */
+ function each(ary, func) {
+ if (ary) {
+ var i;
+ for (i = 0; i < ary.length; i += 1) {
+ if (ary[i] && func(ary[i], i, ary)) {
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Helper function for iterating over an array backwards. If the func
+ * returns a true value, it will break out of the loop.
+ */
+ function eachReverse(ary, func) {
+ if (ary) {
+ var i;
+ for (i = ary.length - 1; i > -1; i -= 1) {
+ if (ary[i] && func(ary[i], i, ary)) {
+ break;
+ }
+ }
+ }
+ }
+
+ function hasProp(obj, prop) {
+ return hasOwn.call(obj, prop);
+ }
+
+ function getOwn(obj, prop) {
+ return hasProp(obj, prop) && obj[prop];
+ }
+
+ /**
+ * Cycles over properties in an object and calls a function for each
+ * property value. If the function returns a truthy value, then the
+ * iteration is stopped.
+ */
+ function eachProp(obj, func) {
+ var prop;
+ for (prop in obj) {
+ if (hasProp(obj, prop)) {
+ if (func(obj[prop], prop)) {
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Simple function to mix in properties from source into target,
+ * but only if target does not already have a property of the same name.
+ */
+ function mixin(target, source, force, deepStringMixin) {
+ if (source) {
+ eachProp(source, function (value, prop) {
+ if (force || !hasProp(target, prop)) {
+ if (deepStringMixin && typeof value === 'object' && value &&
+ !isArray(value) && !isFunction(value) &&
+ !(value instanceof RegExp)) {
+
+ if (!target[prop]) {
+ target[prop] = {};
+ }
+ mixin(target[prop], value, force, deepStringMixin);
+ } else {
+ target[prop] = value;
+ }
+ }
+ });
+ }
+ return target;
+ }
+
+ //Similar to Function.prototype.bind, but the 'this' object is specified
+ //first, since it is easier to read/figure out what 'this' will be.
+ function bind(obj, fn) {
+ return function () {
+ return fn.apply(obj, arguments);
+ };
+ }
+
+ function scripts() {
+ return document.getElementsByTagName('script');
+ }
+
+ function defaultOnError(err) {
+ throw err;
+ }
+
+ //Allow getting a global that is expressed in
+ //dot notation, like 'a.b.c'.
+ function getGlobal(value) {
+ if (!value) {
+ return value;
+ }
+ var g = global;
+ each(value.split('.'), function (part) {
+ g = g[part];
+ });
+ return g;
+ }
+
+ /**
+ * Constructs an error with a pointer to an URL with more information.
+ * @param {String} id the error ID that maps to an ID on a web page.
+ * @param {String} message human readable error.
+ * @param {Error} [err] the original error, if there is one.
+ *
+ * @returns {Error}
+ */
+ function makeError(id, msg, err, requireModules) {
+ var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id);
+ e.requireType = id;
+ e.requireModules = requireModules;
+ if (err) {
+ e.originalError = err;
+ }
+ return e;
+ }
+
+ if (typeof define !== 'undefined') {
+ //If a define is already in play via another AMD loader,
+ //do not overwrite.
+ return;
+ }
+
+ if (typeof requirejs !== 'undefined') {
+ if (isFunction(requirejs)) {
+ //Do not overwrite an existing requirejs instance.
+ return;
+ }
+ cfg = requirejs;
+ requirejs = undefined;
+ }
+
+ //Allow for a require config object
+ if (typeof require !== 'undefined' && !isFunction(require)) {
+ //assume it is a config object.
+ cfg = require;
+ require = undefined;
+ }
+
+ function newContext(contextName) {
+ var inCheckLoaded, Module, context, handlers,
+ checkLoadedTimeoutId,
+ config = {
+ //Defaults. Do not set a default for map
+ //config to speed up normalize(), which
+ //will run faster if there is no default.
+ waitSeconds: 7,
+ baseUrl: './',
+ paths: {},
+ bundles: {},
+ pkgs: {},
+ shim: {},
+ config: {}
+ },
+ registry = {},
+ //registry of just enabled modules, to speed
+ //cycle breaking code when lots of modules
+ //are registered, but not activated.
+ enabledRegistry = {},
+ undefEvents = {},
+ defQueue = [],
+ defined = {},
+ urlFetched = {},
+ bundlesMap = {},
+ requireCounter = 1,
+ unnormalizedCounter = 1;
+
+ /**
+ * Trims the . and .. from an array of path segments.
+ * It will keep a leading path segment if a .. will become
+ * the first path segment, to help with module name lookups,
+ * which act like paths, but can be remapped. But the end result,
+ * all paths that use this function should look normalized.
+ * NOTE: this method MODIFIES the input array.
+ * @param {Array} ary the array of path segments.
+ */
+ function trimDots(ary) {
+ var i, part;
+ for (i = 0; i < ary.length; i++) {
+ part = ary[i];
+ if (part === '.') {
+ ary.splice(i, 1);
+ i -= 1;
+ } else if (part === '..') {
+ // If at the start, or previous value is still ..,
+ // keep them so that when converted to a path it may
+ // still work when converted to a path, even though
+ // as an ID it is less than ideal. In larger point
+ // releases, may be better to just kick out an error.
+ if (i === 0 || (i === 1 && ary[2] === '..') || ary[i - 1] === '..') {
+ continue;
+ } else if (i > 0) {
+ ary.splice(i - 1, 2);
+ i -= 2;
+ }
+ }
+ }
+ }
+
+ /**
+ * Given a relative module name, like ./something, normalize it to
+ * a real name that can be mapped to a path.
+ * @param {String} name the relative name
+ * @param {String} baseName a real name that the name arg is relative
+ * to.
+ * @param {Boolean} applyMap apply the map config to the value. Should
+ * only be done if this normalization is for a dependency ID.
+ * @returns {String} normalized name
+ */
+ function normalize(name, baseName, applyMap) {
+ var pkgMain, mapValue, nameParts, i, j, nameSegment, lastIndex,
+ foundMap, foundI, foundStarMap, starI, normalizedBaseParts,
+ baseParts = (baseName && baseName.split('/')),
+ map = config.map,
+ starMap = map && map['*'];
+
+ //Adjust any relative paths.
+ if (name) {
+ name = name.split('/');
+ lastIndex = name.length - 1;
+
+ // If wanting node ID compatibility, strip .js from end
+ // of IDs. Have to do this here, and not in nameToUrl
+ // because node allows either .js or non .js to map
+ // to same file.
+ if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
+ name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
+ }
+
+ // Starts with a '.' so need the baseName
+ if (name[0].charAt(0) === '.' && baseParts) {
+ //Convert baseName to array, and lop off the last part,
+ //so that . matches that 'directory' and not name of the baseName's
+ //module. For instance, baseName of 'one/two/three', maps to
+ //'one/two/three.js', but we want the directory, 'one/two' for
+ //this normalization.
+ normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
+ name = normalizedBaseParts.concat(name);
+ }
+
+ trimDots(name);
+ name = name.join('/');
+ }
+
+ //Apply map config if available.
+ if (applyMap && map && (baseParts || starMap)) {
+ nameParts = name.split('/');
+
+ outerLoop: for (i = nameParts.length; i > 0; i -= 1) {
+ nameSegment = nameParts.slice(0, i).join('/');
+
+ if (baseParts) {
+ //Find the longest baseName segment match in the config.
+ //So, do joins on the biggest to smallest lengths of baseParts.
+ for (j = baseParts.length; j > 0; j -= 1) {
+ mapValue = getOwn(map, baseParts.slice(0, j).join('/'));
+
+ //baseName segment has config, find if it has one for
+ //this name.
+ if (mapValue) {
+ mapValue = getOwn(mapValue, nameSegment);
+ if (mapValue) {
+ //Match, update name to the new value.
+ foundMap = mapValue;
+ foundI = i;
+ break outerLoop;
+ }
+ }
+ }
+ }
+
+ //Check for a star map match, but just hold on to it,
+ //if there is a shorter segment match later in a matching
+ //config, then favor over this star map.
+ if (!foundStarMap && starMap && getOwn(starMap, nameSegment)) {
+ foundStarMap = getOwn(starMap, nameSegment);
+ starI = i;
+ }
+ }
+
+ if (!foundMap && foundStarMap) {
+ foundMap = foundStarMap;
+ foundI = starI;
+ }
+
+ if (foundMap) {
+ nameParts.splice(0, foundI, foundMap);
+ name = nameParts.join('/');
+ }
+ }
+
+ // If the name points to a package's name, use
+ // the package main instead.
+ pkgMain = getOwn(config.pkgs, name);
+
+ return pkgMain ? pkgMain : name;
+ }
+
+ function removeScript(name) {
+ if (isBrowser) {
+ each(scripts(), function (scriptNode) {
+ if (scriptNode.getAttribute('data-requiremodule') === name &&
+ scriptNode.getAttribute('data-requirecontext') === context.contextName) {
+ scriptNode.parentNode.removeChild(scriptNode);
+ return true;
+ }
+ });
+ }
+ }
+
+ function hasPathFallback(id) {
+ var pathConfig = getOwn(config.paths, id);
+ if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) {
+ //Pop off the first array value, since it failed, and
+ //retry
+ pathConfig.shift();
+ context.require.undef(id);
+
+ //Custom require that does not do map translation, since
+ //ID is "absolute", already mapped/resolved.
+ context.makeRequire(null, {
+ skipMap: true
+ })([id]);
+
+ return true;
+ }
+ }
+
+ //Turns a plugin!resource to [plugin, resource]
+ //with the plugin being undefined if the name
+ //did not have a plugin prefix.
+ function splitPrefix(name) {
+ var prefix,
+ index = name ? name.indexOf('!') : -1;
+ if (index > -1) {
+ prefix = name.substring(0, index);
+ name = name.substring(index + 1, name.length);
+ }
+ return [prefix, name];
+ }
+
+ /**
+ * Creates a module mapping that includes plugin prefix, module
+ * name, and path. If parentModuleMap is provided it will
+ * also normalize the name via require.normalize()
+ *
+ * @param {String} name the module name
+ * @param {String} [parentModuleMap] parent module map
+ * for the module name, used to resolve relative names.
+ * @param {Boolean} isNormalized: is the ID already normalized.
+ * This is true if this call is done for a define() module ID.
+ * @param {Boolean} applyMap: apply the map config to the ID.
+ * Should only be true if this map is for a dependency.
+ *
+ * @returns {Object}
+ */
+ function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) {
+ var url, pluginModule, suffix, nameParts,
+ prefix = null,
+ parentName = parentModuleMap ? parentModuleMap.name : null,
+ originalName = name,
+ isDefine = true,
+ normalizedName = '';
+
+ //If no name, then it means it is a require call, generate an
+ //internal name.
+ if (!name) {
+ isDefine = false;
+ name = '_ at r' + (requireCounter += 1);
+ }
+
+ nameParts = splitPrefix(name);
+ prefix = nameParts[0];
+ name = nameParts[1];
+
+ if (prefix) {
+ prefix = normalize(prefix, parentName, applyMap);
+ pluginModule = getOwn(defined, prefix);
+ }
+
+ //Account for relative paths if there is a base name.
+ if (name) {
+ if (prefix) {
+ if (pluginModule && pluginModule.normalize) {
+ //Plugin is loaded, use its normalize method.
+ normalizedName = pluginModule.normalize(name, function (name) {
+ return normalize(name, parentName, applyMap);
+ });
+ } else {
+ // If nested plugin references, then do not try to
+ // normalize, as it will not normalize correctly. This
+ // places a restriction on resourceIds, and the longer
+ // term solution is not to normalize until plugins are
+ // loaded and all normalizations to allow for async
+ // loading of a loader plugin. But for now, fixes the
+ // common uses. Details in #1131
+ normalizedName = name.indexOf('!') === -1 ?
+ normalize(name, parentName, applyMap) :
+ name;
+ }
+ } else {
+ //A regular module.
+ normalizedName = normalize(name, parentName, applyMap);
+
+ //Normalized name may be a plugin ID due to map config
+ //application in normalize. The map config values must
+ //already be normalized, so do not need to redo that part.
+ nameParts = splitPrefix(normalizedName);
+ prefix = nameParts[0];
+ normalizedName = nameParts[1];
+ isNormalized = true;
+
+ url = context.nameToUrl(normalizedName);
+ }
+ }
+
+ //If the id is a plugin id that cannot be determined if it needs
+ //normalization, stamp it with a unique ID so two matching relative
+ //ids that may conflict can be separate.
+ suffix = prefix && !pluginModule && !isNormalized ?
+ '_unnormalized' + (unnormalizedCounter += 1) :
+ '';
+
+ return {
+ prefix: prefix,
+ name: normalizedName,
+ parentMap: parentModuleMap,
+ unnormalized: !!suffix,
+ url: url,
+ originalName: originalName,
+ isDefine: isDefine,
+ id: (prefix ?
+ prefix + '!' + normalizedName :
+ normalizedName) + suffix
+ };
+ }
+
+ function getModule(depMap) {
+ var id = depMap.id,
+ mod = getOwn(registry, id);
+
+ if (!mod) {
+ mod = registry[id] = new context.Module(depMap);
+ }
+
+ return mod;
+ }
+
+ function on(depMap, name, fn) {
+ var id = depMap.id,
+ mod = getOwn(registry, id);
+
+ if (hasProp(defined, id) &&
+ (!mod || mod.defineEmitComplete)) {
+ if (name === 'defined') {
+ fn(defined[id]);
+ }
+ } else {
+ mod = getModule(depMap);
+ if (mod.error && name === 'error') {
+ fn(mod.error);
+ } else {
+ mod.on(name, fn);
+ }
+ }
+ }
+
+ function onError(err, errback) {
+ var ids = err.requireModules,
+ notified = false;
+
+ if (errback) {
+ errback(err);
+ } else {
+ each(ids, function (id) {
+ var mod = getOwn(registry, id);
+ if (mod) {
+ //Set error on module, so it skips timeout checks.
+ mod.error = err;
+ if (mod.events.error) {
+ notified = true;
+ mod.emit('error', err);
+ }
+ }
+ });
+
+ if (!notified) {
+ req.onError(err);
+ }
+ }
+ }
+
+ /**
+ * Internal method to transfer globalQueue items to this context's
+ * defQueue.
+ */
+ function takeGlobalQueue() {
+ //Push all the globalDefQueue items into the context's defQueue
+ if (globalDefQueue.length) {
+ //Array splice in the values since the context code has a
+ //local var ref to defQueue, so cannot just reassign the one
+ //on context.
+ apsp.apply(defQueue,
+ [defQueue.length, 0].concat(globalDefQueue));
+ globalDefQueue = [];
+ }
+ }
+
+ handlers = {
+ 'require': function (mod) {
+ if (mod.require) {
+ return mod.require;
+ } else {
+ return (mod.require = context.makeRequire(mod.map));
+ }
+ },
+ 'exports': function (mod) {
+ mod.usingExports = true;
+ if (mod.map.isDefine) {
+ if (mod.exports) {
+ return (defined[mod.map.id] = mod.exports);
+ } else {
+ return (mod.exports = defined[mod.map.id] = {});
+ }
+ }
+ },
+ 'module': function (mod) {
+ if (mod.module) {
+ return mod.module;
+ } else {
+ return (mod.module = {
+ id: mod.map.id,
+ uri: mod.map.url,
+ config: function () {
+ return getOwn(config.config, mod.map.id) || {};
+ },
+ exports: mod.exports || (mod.exports = {})
+ });
+ }
+ }
+ };
+
+ function cleanRegistry(id) {
+ //Clean up machinery used for waiting modules.
+ delete registry[id];
+ delete enabledRegistry[id];
+ }
+
+ function breakCycle(mod, traced, processed) {
+ var id = mod.map.id;
+
+ if (mod.error) {
+ mod.emit('error', mod.error);
+ } else {
+ traced[id] = true;
+ each(mod.depMaps, function (depMap, i) {
+ var depId = depMap.id,
+ dep = getOwn(registry, depId);
+
+ //Only force things that have not completed
+ //being defined, so still in the registry,
+ //and only if it has not been matched up
+ //in the module already.
+ if (dep && !mod.depMatched[i] && !processed[depId]) {
+ if (getOwn(traced, depId)) {
+ mod.defineDep(i, defined[depId]);
+ mod.check(); //pass false?
+ } else {
+ breakCycle(dep, traced, processed);
+ }
+ }
+ });
+ processed[id] = true;
+ }
+ }
+
+ function checkLoaded() {
+ var err, usingPathFallback,
+ waitInterval = config.waitSeconds * 1000,
+ //It is possible to disable the wait interval by using waitSeconds of 0.
+ expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),
+ noLoads = [],
+ reqCalls = [],
+ stillLoading = false,
+ needCycleCheck = true;
+
+ //Do not bother if this call was a result of a cycle break.
+ if (inCheckLoaded) {
+ return;
+ }
+
+ inCheckLoaded = true;
+
+ //Figure out the state of all the modules.
+ eachProp(enabledRegistry, function (mod) {
+ var map = mod.map,
+ modId = map.id;
+
+ //Skip things that are not enabled or in error state.
+ if (!mod.enabled) {
+ return;
+ }
+
+ if (!map.isDefine) {
+ reqCalls.push(mod);
+ }
+
+ if (!mod.error) {
+ //If the module should be executed, and it has not
+ //been inited and time is up, remember it.
+ if (!mod.inited && expired) {
+ if (hasPathFallback(modId)) {
+ usingPathFallback = true;
+ stillLoading = true;
+ } else {
+ noLoads.push(modId);
+ removeScript(modId);
+ }
+ } else if (!mod.inited && mod.fetched && map.isDefine) {
+ stillLoading = true;
+ if (!map.prefix) {
+ //No reason to keep looking for unfinished
+ //loading. If the only stillLoading is a
+ //plugin resource though, keep going,
+ //because it may be that a plugin resource
+ //is waiting on a non-plugin cycle.
+ return (needCycleCheck = false);
+ }
+ }
+ }
+ });
+
+ if (expired && noLoads.length) {
+ //If wait time expired, throw error of unloaded modules.
+ err = makeError('timeout', 'Load timeout for modules: ' + noLoads, null, noLoads);
+ err.contextName = context.contextName;
+ return onError(err);
+ }
+
+ //Not expired, check for a cycle.
+ if (needCycleCheck) {
+ each(reqCalls, function (mod) {
+ breakCycle(mod, {}, {});
+ });
+ }
+
+ //If still waiting on loads, and the waiting load is something
+ //other than a plugin resource, or there are still outstanding
+ //scripts, then just try back later.
+ if ((!expired || usingPathFallback) && stillLoading) {
+ //Something is still waiting to load. Wait for it, but only
+ //if a timeout is not already in effect.
+ if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) {
+ checkLoadedTimeoutId = setTimeout(function () {
+ checkLoadedTimeoutId = 0;
+ checkLoaded();
+ }, 50);
+ }
+ }
+
+ inCheckLoaded = false;
+ }
+
+ Module = function (map) {
+ this.events = getOwn(undefEvents, map.id) || {};
+ this.map = map;
+ this.shim = getOwn(config.shim, map.id);
+ this.depExports = [];
+ this.depMaps = [];
+ this.depMatched = [];
+ this.pluginMaps = {};
+ this.depCount = 0;
+
+ /* this.exports this.factory
+ this.depMaps = [],
+ this.enabled, this.fetched
+ */
+ };
+
+ Module.prototype = {
+ init: function (depMaps, factory, errback, options) {
+ options = options || {};
+
+ //Do not do more inits if already done. Can happen if there
+ //are multiple define calls for the same module. That is not
+ //a normal, common case, but it is also not unexpected.
+ if (this.inited) {
+ return;
+ }
+
+ this.factory = factory;
+
+ if (errback) {
+ //Register for errors on this module.
+ this.on('error', errback);
+ } else if (this.events.error) {
+ //If no errback already, but there are error listeners
+ //on this module, set up an errback to pass to the deps.
+ errback = bind(this, function (err) {
+ this.emit('error', err);
+ });
+ }
+
+ //Do a copy of the dependency array, so that
+ //source inputs are not modified. For example
+ //"shim" deps are passed in here directly, and
+ //doing a direct modification of the depMaps array
+ //would affect that config.
+ this.depMaps = depMaps && depMaps.slice(0);
+
+ this.errback = errback;
+
+ //Indicate this module has be initialized
+ this.inited = true;
+
+ this.ignore = options.ignore;
+
+ //Could have option to init this module in enabled mode,
+ //or could have been previously marked as enabled. However,
+ //the dependencies are not known until init is called. So
+ //if enabled previously, now trigger dependencies as enabled.
+ if (options.enabled || this.enabled) {
+ //Enable this module and dependencies.
+ //Will call this.check()
+ this.enable();
+ } else {
+ this.check();
+ }
+ },
+
+ defineDep: function (i, depExports) {
+ //Because of cycles, defined callback for a given
+ //export can be called more than once.
+ if (!this.depMatched[i]) {
+ this.depMatched[i] = true;
+ this.depCount -= 1;
+ this.depExports[i] = depExports;
+ }
+ },
+
+ fetch: function () {
+ if (this.fetched) {
+ return;
+ }
+ this.fetched = true;
+
+ context.startTime = (new Date()).getTime();
+
+ var map = this.map;
+
+ //If the manager is for a plugin managed resource,
+ //ask the plugin to load it now.
+ if (this.shim) {
+ context.makeRequire(this.map, {
+ enableBuildCallback: true
+ })(this.shim.deps || [], bind(this, function () {
+ return map.prefix ? this.callPlugin() : this.load();
+ }));
+ } else {
+ //Regular dependency.
+ return map.prefix ? this.callPlugin() : this.load();
+ }
+ },
+
+ load: function () {
+ var url = this.map.url;
+
+ //Regular dependency.
+ if (!urlFetched[url]) {
+ urlFetched[url] = true;
+ context.load(this.map.id, url);
+ }
+ },
+
+ /**
+ * Checks if the module is ready to define itself, and if so,
+ * define it.
+ */
+ check: function () {
+ if (!this.enabled || this.enabling) {
+ return;
+ }
+
+ var err, cjsModule,
+ id = this.map.id,
+ depExports = this.depExports,
+ exports = this.exports,
+ factory = this.factory;
+
+ if (!this.inited) {
+ this.fetch();
+ } else if (this.error) {
+ this.emit('error', this.error);
+ } else if (!this.defining) {
+ //The factory could trigger another require call
+ //that would result in checking this module to
+ //define itself again. If already in the process
+ //of doing that, skip this work.
+ this.defining = true;
+
+ if (this.depCount < 1 && !this.defined) {
+ if (isFunction(factory)) {
+ //If there is an error listener, favor passing
+ //to that instead of throwing an error. However,
+ //only do it for define()'d modules. require
+ //errbacks should not be called for failures in
+ //their callbacks (#699). However if a global
+ //onError is set, use that.
+ if ((this.events.error && this.map.isDefine) ||
+ req.onError !== defaultOnError) {
+ try {
+ exports = context.execCb(id, factory, depExports, exports);
+ } catch (e) {
+ err = e;
+ }
+ } else {
+ exports = context.execCb(id, factory, depExports, exports);
+ }
+
+ // Favor return value over exports. If node/cjs in play,
+ // then will not have a return value anyway. Favor
+ // module.exports assignment over exports object.
+ if (this.map.isDefine && exports === undefined) {
+ cjsModule = this.module;
+ if (cjsModule) {
+ exports = cjsModule.exports;
+ } else if (this.usingExports) {
+ //exports already set the defined value.
+ exports = this.exports;
+ }
+ }
+
+ if (err) {
+ err.requireMap = this.map;
+ err.requireModules = this.map.isDefine ? [this.map.id] : null;
+ err.requireType = this.map.isDefine ? 'define' : 'require';
+ return onError((this.error = err));
+ }
+
+ } else {
+ //Just a literal value
+ exports = factory;
+ }
+
+ this.exports = exports;
+
+ if (this.map.isDefine && !this.ignore) {
+ defined[id] = exports;
+
+ if (req.onResourceLoad) {
+ req.onResourceLoad(context, this.map, this.depMaps);
+ }
+ }
+
+ //Clean up
+ cleanRegistry(id);
+
+ this.defined = true;
+ }
+
+ //Finished the define stage. Allow calling check again
+ //to allow define notifications below in the case of a
+ //cycle.
+ this.defining = false;
+
+ if (this.defined && !this.defineEmitted) {
+ this.defineEmitted = true;
+ this.emit('defined', this.exports);
+ this.defineEmitComplete = true;
+ }
+
+ }
+ },
+
+ callPlugin: function () {
+ var map = this.map,
+ id = map.id,
+ //Map already normalized the prefix.
+ pluginMap = makeModuleMap(map.prefix);
+
+ //Mark this as a dependency for this plugin, so it
+ //can be traced for cycles.
+ this.depMaps.push(pluginMap);
+
+ on(pluginMap, 'defined', bind(this, function (plugin) {
+ var load, normalizedMap, normalizedMod,
+ bundleId = getOwn(bundlesMap, this.map.id),
+ name = this.map.name,
+ parentName = this.map.parentMap ? this.map.parentMap.name : null,
+ localRequire = context.makeRequire(map.parentMap, {
+ enableBuildCallback: true
+ });
+
+ //If current map is not normalized, wait for that
+ //normalized name to load instead of continuing.
+ if (this.map.unnormalized) {
+ //Normalize the ID if the plugin allows it.
+ if (plugin.normalize) {
+ name = plugin.normalize(name, function (name) {
+ return normalize(name, parentName, true);
+ }) || '';
+ }
+
+ //prefix and name should already be normalized, no need
+ //for applying map config again either.
+ normalizedMap = makeModuleMap(map.prefix + '!' + name,
+ this.map.parentMap);
+ on(normalizedMap,
+ 'defined', bind(this, function (value) {
+ this.init([], function () { return value; }, null, {
+ enabled: true,
+ ignore: true
+ });
+ }));
+
+ normalizedMod = getOwn(registry, normalizedMap.id);
+ if (normalizedMod) {
+ //Mark this as a dependency for this plugin, so it
+ //can be traced for cycles.
+ this.depMaps.push(normalizedMap);
+
+ if (this.events.error) {
+ normalizedMod.on('error', bind(this, function (err) {
+ this.emit('error', err);
+ }));
+ }
+ normalizedMod.enable();
+ }
+
+ return;
+ }
+
+ //If a paths config, then just load that file instead to
+ //resolve the plugin, as it is built into that paths layer.
+ if (bundleId) {
+ this.map.url = context.nameToUrl(bundleId);
+ this.load();
+ return;
+ }
+
+ load = bind(this, function (value) {
+ this.init([], function () { return value; }, null, {
+ enabled: true
+ });
+ });
+
+ load.error = bind(this, function (err) {
+ this.inited = true;
+ this.error = err;
+ err.requireModules = [id];
+
+ //Remove temp unnormalized modules for this module,
+ //since they will never be resolved otherwise now.
+ eachProp(registry, function (mod) {
+ if (mod.map.id.indexOf(id + '_unnormalized') === 0) {
+ cleanRegistry(mod.map.id);
+ }
+ });
+
+ onError(err);
+ });
+
+ //Allow plugins to load other code without having to know the
+ //context or how to 'complete' the load.
+ load.fromText = bind(this, function (text, textAlt) {
+ /*jslint evil: true */
+ var moduleName = map.name,
+ moduleMap = makeModuleMap(moduleName),
+ hasInteractive = useInteractive;
+
+ //As of 2.1.0, support just passing the text, to reinforce
+ //fromText only being called once per resource. Still
+ //support old style of passing moduleName but discard
+ //that moduleName in favor of the internal ref.
+ if (textAlt) {
+ text = textAlt;
+ }
+
+ //Turn off interactive script matching for IE for any define
+ //calls in the text, then turn it back on at the end.
+ if (hasInteractive) {
+ useInteractive = false;
+ }
+
+ //Prime the system by creating a module instance for
+ //it.
+ getModule(moduleMap);
+
+ //Transfer any config to this other module.
+ if (hasProp(config.config, id)) {
+ config.config[moduleName] = config.config[id];
+ }
+
+ try {
+ req.exec(text);
+ } catch (e) {
+ return onError(makeError('fromtexteval',
+ 'fromText eval for ' + id +
+ ' failed: ' + e,
+ e,
+ [id]));
+ }
+
+ if (hasInteractive) {
+ useInteractive = true;
+ }
+
+ //Mark this as a dependency for the plugin
+ //resource
+ this.depMaps.push(moduleMap);
+
+ //Support anonymous modules.
+ context.completeLoad(moduleName);
+
+ //Bind the value of that module to the value for this
+ //resource ID.
+ localRequire([moduleName], load);
+ });
+
+ //Use parentName here since the plugin's name is not reliable,
+ //could be some weird string with no path that actually wants to
+ //reference the parentName's path.
+ plugin.load(map.name, localRequire, load, config);
+ }));
+
+ context.enable(pluginMap, this);
+ this.pluginMaps[pluginMap.id] = pluginMap;
+ },
+
+ enable: function () {
+ enabledRegistry[this.map.id] = this;
+ this.enabled = true;
+
+ //Set flag mentioning that the module is enabling,
+ //so that immediate calls to the defined callbacks
+ //for dependencies do not trigger inadvertent load
+ //with the depCount still being zero.
+ this.enabling = true;
+
+ //Enable each dependency
+ each(this.depMaps, bind(this, function (depMap, i) {
+ var id, mod, handler;
+
+ if (typeof depMap === 'string') {
+ //Dependency needs to be converted to a depMap
+ //and wired up to this module.
+ depMap = makeModuleMap(depMap,
+ (this.map.isDefine ? this.map : this.map.parentMap),
+ false,
+ !this.skipMap);
+ this.depMaps[i] = depMap;
+
+ handler = getOwn(handlers, depMap.id);
+
+ if (handler) {
+ this.depExports[i] = handler(this);
+ return;
+ }
+
+ this.depCount += 1;
+
+ on(depMap, 'defined', bind(this, function (depExports) {
+ this.defineDep(i, depExports);
+ this.check();
+ }));
+
+ if (this.errback) {
+ on(depMap, 'error', bind(this, this.errback));
+ } else if (this.events.error) {
+ // No direct errback on this module, but something
+ // else is listening for errors, so be sure to
+ // propagate the error correctly.
+ on(depMap, 'error', bind(this, function(err) {
+ this.emit('error', err);
+ }));
+ }
+ }
+
+ id = depMap.id;
+ mod = registry[id];
+
+ //Skip special modules like 'require', 'exports', 'module'
+ //Also, don't call enable if it is already enabled,
+ //important in circular dependency cases.
+ if (!hasProp(handlers, id) && mod && !mod.enabled) {
+ context.enable(depMap, this);
+ }
+ }));
+
+ //Enable each plugin that is used in
+ //a dependency
+ eachProp(this.pluginMaps, bind(this, function (pluginMap) {
+ var mod = getOwn(registry, pluginMap.id);
+ if (mod && !mod.enabled) {
+ context.enable(pluginMap, this);
+ }
+ }));
+
+ this.enabling = false;
+
+ this.check();
+ },
+
+ on: function (name, cb) {
+ var cbs = this.events[name];
+ if (!cbs) {
+ cbs = this.events[name] = [];
+ }
+ cbs.push(cb);
+ },
+
+ emit: function (name, evt) {
+ each(this.events[name], function (cb) {
+ cb(evt);
+ });
+ if (name === 'error') {
+ //Now that the error handler was triggered, remove
+ //the listeners, since this broken Module instance
+ //can stay around for a while in the registry.
+ delete this.events[name];
+ }
+ }
+ };
+
+ function callGetModule(args) {
+ //Skip modules already defined.
+ if (!hasProp(defined, args[0])) {
+ getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);
+ }
+ }
+
+ function removeListener(node, func, name, ieName) {
+ //Favor detachEvent because of IE9
+ //issue, see attachEvent/addEventListener comment elsewhere
+ //in this file.
+ if (node.detachEvent && !isOpera) {
+ //Probably IE. If not it will throw an error, which will be
+ //useful to know.
+ if (ieName) {
+ node.detachEvent(ieName, func);
+ }
+ } else {
+ node.removeEventListener(name, func, false);
+ }
+ }
+
+ /**
+ * Given an event from a script node, get the requirejs info from it,
+ * and then removes the event listeners on the node.
+ * @param {Event} evt
+ * @returns {Object}
+ */
+ function getScriptData(evt) {
+ //Using currentTarget instead of target for Firefox 2.0's sake. Not
+ //all old browsers will be supported, but this one was easy enough
+ //to support and still makes sense.
+ var node = evt.currentTarget || evt.srcElement;
+
+ //Remove the listeners once here.
+ removeListener(node, context.onScriptLoad, 'load', 'onreadystatechange');
+ removeListener(node, context.onScriptError, 'error');
+
+ return {
+ node: node,
+ id: node && node.getAttribute('data-requiremodule')
+ };
+ }
+
+ function intakeDefines() {
+ var args;
+
+ //Any defined modules in the global queue, intake them now.
+ takeGlobalQueue();
+
+ //Make sure any remaining defQueue items get properly processed.
+ while (defQueue.length) {
+ args = defQueue.shift();
+ if (args[0] === null) {
+ return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1]));
+ } else {
+ //args are id, deps, factory. Should be normalized by the
+ //define() function.
+ callGetModule(args);
+ }
+ }
+ }
+
+ context = {
+ config: config,
+ contextName: contextName,
+ registry: registry,
+ defined: defined,
+ urlFetched: urlFetched,
+ defQueue: defQueue,
+ Module: Module,
+ makeModuleMap: makeModuleMap,
+ nextTick: req.nextTick,
+ onError: onError,
+
+ /**
+ * Set a configuration for the context.
+ * @param {Object} cfg config object to integrate.
+ */
+ configure: function (cfg) {
+ //Make sure the baseUrl ends in a slash.
+ if (cfg.baseUrl) {
+ if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') {
+ cfg.baseUrl += '/';
+ }
+ }
+
+ //Save off the paths since they require special processing,
+ //they are additive.
+ var shim = config.shim,
+ objs = {
+ paths: true,
+ bundles: true,
+ config: true,
+ map: true
+ };
+
+ eachProp(cfg, function (value, prop) {
+ if (objs[prop]) {
+ if (!config[prop]) {
+ config[prop] = {};
+ }
+ mixin(config[prop], value, true, true);
+ } else {
+ config[prop] = value;
+ }
+ });
+
+ //Reverse map the bundles
+ if (cfg.bundles) {
+ eachProp(cfg.bundles, function (value, prop) {
+ each(value, function (v) {
+ if (v !== prop) {
+ bundlesMap[v] = prop;
+ }
+ });
+ });
+ }
+
+ //Merge shim
+ if (cfg.shim) {
+ eachProp(cfg.shim, function (value, id) {
+ //Normalize the structure
+ if (isArray(value)) {
+ value = {
+ deps: value
+ };
+ }
+ if ((value.exports || value.init) && !value.exportsFn) {
+ value.exportsFn = context.makeShimExports(value);
+ }
+ shim[id] = value;
+ });
+ config.shim = shim;
+ }
+
+ //Adjust packages if necessary.
+ if (cfg.packages) {
+ each(cfg.packages, function (pkgObj) {
+ var location, name;
+
+ pkgObj = typeof pkgObj === 'string' ? { name: pkgObj } : pkgObj;
+
+ name = pkgObj.name;
+ location = pkgObj.location;
+ if (location) {
+ config.paths[name] = pkgObj.location;
+ }
+
+ //Save pointer to main module ID for pkg name.
+ //Remove leading dot in main, so main paths are normalized,
+ //and remove any trailing .js, since different package
+ //envs have different conventions: some use a module name,
+ //some use a file name.
+ config.pkgs[name] = pkgObj.name + '/' + (pkgObj.main || 'main')
+ .replace(currDirRegExp, '')
+ .replace(jsSuffixRegExp, '');
+ });
+ }
+
+ //If there are any "waiting to execute" modules in the registry,
+ //update the maps for them, since their info, like URLs to load,
+ //may have changed.
+ eachProp(registry, function (mod, id) {
+ //If module already has init called, since it is too
+ //late to modify them, and ignore unnormalized ones
+ //since they are transient.
+ if (!mod.inited && !mod.map.unnormalized) {
+ mod.map = makeModuleMap(id);
+ }
+ });
+
+ //If a deps array or a config callback is specified, then call
+ //require with those args. This is useful when require is defined as a
+ //config object before require.js is loaded.
+ if (cfg.deps || cfg.callback) {
+ context.require(cfg.deps || [], cfg.callback);
+ }
+ },
+
+ makeShimExports: function (value) {
+ function fn() {
+ var ret;
+ if (value.init) {
+ ret = value.init.apply(global, arguments);
+ }
+ return ret || (value.exports && getGlobal(value.exports));
+ }
+ return fn;
+ },
+
+ makeRequire: function (relMap, options) {
+ options = options || {};
+
+ function localRequire(deps, callback, errback) {
+ var id, map, requireMod;
+
+ if (options.enableBuildCallback && callback && isFunction(callback)) {
+ callback.__requireJsBuild = true;
+ }
+
+ if (typeof deps === 'string') {
+ if (isFunction(callback)) {
+ //Invalid call
+ return onError(makeError('requireargs', 'Invalid require call'), errback);
+ }
+
+ //If require|exports|module are requested, get the
+ //value for them from the special handlers. Caveat:
+ //this only works while module is being defined.
+ if (relMap && hasProp(handlers, deps)) {
+ return handlers[deps](registry[relMap.id]);
+ }
+
+ //Synchronous access to one module. If require.get is
+ //available (as in the Node adapter), prefer that.
+ if (req.get) {
+ return req.get(context, deps, relMap, localRequire);
+ }
+
+ //Normalize module name, if it contains . or ..
+ map = makeModuleMap(deps, relMap, false, true);
+ id = map.id;
+
+ if (!hasProp(defined, id)) {
+ return onError(makeError('notloaded', 'Module name "' +
+ id +
+ '" has not been loaded yet for context: ' +
+ contextName +
+ (relMap ? '' : '. Use require([])')));
+ }
+ return defined[id];
+ }
+
+ //Grab defines waiting in the global queue.
+ intakeDefines();
+
+ //Mark all the dependencies as needing to be loaded.
+ context.nextTick(function () {
+ //Some defines could have been added since the
+ //require call, collect them.
+ intakeDefines();
+
+ requireMod = getModule(makeModuleMap(null, relMap));
+
+ //Store if map config should be applied to this require
+ //call for dependencies.
+ requireMod.skipMap = options.skipMap;
+
+ requireMod.init(deps, callback, errback, {
+ enabled: true
+ });
+
+ checkLoaded();
+ });
+
+ return localRequire;
+ }
+
+ mixin(localRequire, {
+ isBrowser: isBrowser,
+
+ /**
+ * Converts a module name + .extension into an URL path.
+ * *Requires* the use of a module name. It does not support using
+ * plain URLs like nameToUrl.
+ */
+ toUrl: function (moduleNamePlusExt) {
+ var ext,
+ index = moduleNamePlusExt.lastIndexOf('.'),
+ segment = moduleNamePlusExt.split('/')[0],
+ isRelative = segment === '.' || segment === '..';
+
+ //Have a file extension alias, and it is not the
+ //dots from a relative path.
+ if (index !== -1 && (!isRelative || index > 1)) {
+ ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
+ moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
+ }
+
+ return context.nameToUrl(normalize(moduleNamePlusExt,
+ relMap && relMap.id, true), ext, true);
+ },
+
+ defined: function (id) {
+ return hasProp(defined, makeModuleMap(id, relMap, false, true).id);
+ },
+
+ specified: function (id) {
+ id = makeModuleMap(id, relMap, false, true).id;
+ return hasProp(defined, id) || hasProp(registry, id);
+ }
+ });
+
+ //Only allow undef on top level require calls
+ if (!relMap) {
+ localRequire.undef = function (id) {
+ //Bind any waiting define() calls to this context,
+ //fix for #408
+ takeGlobalQueue();
+
+ var map = makeModuleMap(id, relMap, true),
+ mod = getOwn(registry, id);
+
+ removeScript(id);
+
+ delete defined[id];
+ delete urlFetched[map.url];
+ delete undefEvents[id];
+
+ //Clean queued defines too. Go backwards
+ //in array so that the splices do not
+ //mess up the iteration.
+ eachReverse(defQueue, function(args, i) {
+ if(args[0] === id) {
+ defQueue.splice(i, 1);
+ }
+ });
+
+ if (mod) {
+ //Hold on to listeners in case the
+ //module will be attempted to be reloaded
+ //using a different config.
+ if (mod.events.defined) {
+ undefEvents[id] = mod.events;
+ }
+
+ cleanRegistry(id);
+ }
+ };
+ }
+
+ return localRequire;
+ },
+
+ /**
+ * Called to enable a module if it is still in the registry
+ * awaiting enablement. A second arg, parent, the parent module,
+ * is passed in for context, when this method is overridden by
+ * the optimizer. Not shown here to keep code compact.
+ */
+ enable: function (depMap) {
+ var mod = getOwn(registry, depMap.id);
+ if (mod) {
+ getModule(depMap).enable();
+ }
+ },
+
+ /**
+ * Internal method used by environment adapters to complete a load event.
+ * A load event could be a script load or just a load pass from a synchronous
+ * load call.
+ * @param {String} moduleName the name of the module to potentially complete.
+ */
+ completeLoad: function (moduleName) {
+ var found, args, mod,
+ shim = getOwn(config.shim, moduleName) || {},
+ shExports = shim.exports;
+
+ takeGlobalQueue();
+
+ while (defQueue.length) {
+ args = defQueue.shift();
+ if (args[0] === null) {
+ args[0] = moduleName;
+ //If already found an anonymous module and bound it
+ //to this name, then this is some other anon module
+ //waiting for its completeLoad to fire.
+ if (found) {
+ break;
+ }
+ found = true;
+ } else if (args[0] === moduleName) {
+ //Found matching define call for this script!
+ found = true;
+ }
+
+ callGetModule(args);
+ }
+
+ //Do this after the cycle of callGetModule in case the result
+ //of those calls/init calls changes the registry.
+ mod = getOwn(registry, moduleName);
+
+ if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) {
+ if (config.enforceDefine && (!shExports || !getGlobal(shExports))) {
+ if (hasPathFallback(moduleName)) {
+ return;
+ } else {
+ return onError(makeError('nodefine',
+ 'No define call for ' + moduleName,
+ null,
+ [moduleName]));
+ }
+ } else {
+ //A script that does not call define(), so just simulate
+ //the call for it.
+ callGetModule([moduleName, (shim.deps || []), shim.exportsFn]);
+ }
+ }
+
+ checkLoaded();
+ },
+
+ /**
+ * Converts a module name to a file path. Supports cases where
+ * moduleName may actually be just an URL.
+ * Note that it **does not** call normalize on the moduleName,
+ * it is assumed to have already been normalized. This is an
+ * internal API, not a public one. Use toUrl for the public API.
+ */
+ nameToUrl: function (moduleName, ext, skipExt) {
+ var paths, syms, i, parentModule, url,
+ parentPath, bundleId,
+ pkgMain = getOwn(config.pkgs, moduleName);
+
+ if (pkgMain) {
+ moduleName = pkgMain;
+ }
+
+ bundleId = getOwn(bundlesMap, moduleName);
+
+ if (bundleId) {
+ return context.nameToUrl(bundleId, ext, skipExt);
+ }
+
+ //If a colon is in the URL, it indicates a protocol is used and it is just
+ //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?)
+ //or ends with .js, then assume the user meant to use an url and not a module id.
+ //The slash is important for protocol-less URLs as well as full paths.
+ if (req.jsExtRegExp.test(moduleName)) {
+ //Just a plain path, not module name lookup, so just return it.
+ //Add extension if it is included. This is a bit wonky, only non-.js things pass
+ //an extension, this method probably needs to be reworked.
+ url = moduleName + (ext || '');
+ } else {
+ //A module that needs to be converted to a path.
+ paths = config.paths;
+
+ syms = moduleName.split('/');
+ //For each module name segment, see if there is a path
+ //registered for it. Start with most specific name
+ //and work up from it.
+ for (i = syms.length; i > 0; i -= 1) {
+ parentModule = syms.slice(0, i).join('/');
+
+ parentPath = getOwn(paths, parentModule);
+ if (parentPath) {
+ //If an array, it means there are a few choices,
+ //Choose the one that is desired
+ if (isArray(parentPath)) {
+ parentPath = parentPath[0];
+ }
+ syms.splice(0, i, parentPath);
+ break;
+ }
+ }
+
+ //Join the path parts together, then figure out if baseUrl is needed.
+ url = syms.join('/');
+ url += (ext || (/^data\:|\?/.test(url) || skipExt ? '' : '.js'));
+ url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url;
+ }
+
+ return config.urlArgs ? url +
+ ((url.indexOf('?') === -1 ? '?' : '&') +
+ config.urlArgs) : url;
+ },
+
+ //Delegates to req.load. Broken out as a separate function to
+ //allow overriding in the optimizer.
+ load: function (id, url) {
+ req.load(context, id, url);
+ },
+
+ /**
+ * Executes a module callback function. Broken out as a separate function
+ * solely to allow the build system to sequence the files in the built
+ * layer in the right sequence.
+ *
+ * @private
+ */
+ execCb: function (name, callback, args, exports) {
+ return callback.apply(exports, args);
+ },
+
+ /**
+ * callback for script loads, used to check status of loading.
+ *
+ * @param {Event} evt the event from the browser for the script
+ * that was loaded.
+ */
+ onScriptLoad: function (evt) {
+ //Using currentTarget instead of target for Firefox 2.0's sake. Not
+ //all old browsers will be supported, but this one was easy enough
+ //to support and still makes sense.
+ if (evt.type === 'load' ||
+ (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) {
+ //Reset interactive script so a script node is not held onto for
+ //to long.
+ interactiveScript = null;
+
+ //Pull out the name of the module and the context.
+ var data = getScriptData(evt);
+ context.completeLoad(data.id);
+ }
+ },
+
+ /**
+ * Callback for script errors.
+ */
+ onScriptError: function (evt) {
+ var data = getScriptData(evt);
+ if (!hasPathFallback(data.id)) {
+ return onError(makeError('scripterror', 'Script error for: ' + data.id, evt, [data.id]));
+ }
+ }
+ };
+
+ context.require = context.makeRequire();
+ return context;
+ }
+
+ /**
+ * Main entry point.
+ *
+ * If the only argument to require is a string, then the module that
+ * is represented by that string is fetched for the appropriate context.
+ *
+ * If the first argument is an array, then it will be treated as an array
+ * of dependency string names to fetch. An optional function callback can
+ * be specified to execute when all of those dependencies are available.
+ *
+ * Make a local req variable to help Caja compliance (it assumes things
+ * on a require that are not standardized), and to give a short
+ * name for minification/local scope use.
+ */
+ req = requirejs = function (deps, callback, errback, optional) {
+
+ //Find the right context, use default
+ var context, config,
+ contextName = defContextName;
+
+ // Determine if have config object in the call.
+ if (!isArray(deps) && typeof deps !== 'string') {
+ // deps is a config object
+ config = deps;
+ if (isArray(callback)) {
+ // Adjust args if there are dependencies
+ deps = callback;
+ callback = errback;
+ errback = optional;
+ } else {
+ deps = [];
+ }
+ }
+
+ if (config && config.context) {
+ contextName = config.context;
+ }
+
+ context = getOwn(contexts, contextName);
+ if (!context) {
+ context = contexts[contextName] = req.s.newContext(contextName);
+ }
+
+ if (config) {
+ context.configure(config);
+ }
+
+ return context.require(deps, callback, errback);
+ };
+
+ /**
+ * Support require.config() to make it easier to cooperate with other
+ * AMD loaders on globally agreed names.
+ */
+ req.config = function (config) {
+ return req(config);
+ };
+
+ /**
+ * Execute something after the current tick
+ * of the event loop. Override for other envs
+ * that have a better solution than setTimeout.
+ * @param {Function} fn function to execute later.
+ */
+ req.nextTick = typeof setTimeout !== 'undefined' ? function (fn) {
+ setTimeout(fn, 4);
+ } : function (fn) { fn(); };
+
+ /**
+ * Export require as a global, but only if it does not already exist.
+ */
+ if (!require) {
+ require = req;
+ }
+
+ req.version = version;
+
+ //Used to filter out dependencies that are already paths.
+ req.jsExtRegExp = /^\/|:|\?|\.js$/;
+ req.isBrowser = isBrowser;
+ s = req.s = {
+ contexts: contexts,
+ newContext: newContext
+ };
+
+ //Create default context.
+ req({});
+
+ //Exports some context-sensitive methods on global require.
+ each([
+ 'toUrl',
+ 'undef',
+ 'defined',
+ 'specified'
+ ], function (prop) {
+ //Reference from contexts instead of early binding to default context,
+ //so that during builds, the latest instance of the default context
+ //with its config gets used.
+ req[prop] = function () {
+ var ctx = contexts[defContextName];
+ return ctx.require[prop].apply(ctx, arguments);
+ };
+ });
+
+ if (isBrowser) {
+ head = s.head = document.getElementsByTagName('head')[0];
+ //If BASE tag is in play, using appendChild is a problem for IE6.
+ //When that browser dies, this can be removed. Details in this jQuery bug:
+ //http://dev.jquery.com/ticket/2709
+ baseElement = document.getElementsByTagName('base')[0];
+ if (baseElement) {
+ head = s.head = baseElement.parentNode;
+ }
+ }
+
+ /**
+ * Any errors that require explicitly generates will be passed to this
+ * function. Intercept/override it if you want custom error handling.
+ * @param {Error} err the error object.
+ */
+ req.onError = defaultOnError;
+
+ /**
+ * Creates the node for the load command. Only used in browser envs.
+ */
+ req.createNode = function (config, moduleName, url) {
+ var node = config.xhtml ?
+ document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
+ document.createElement('script');
+ node.type = config.scriptType || 'text/javascript';
+ node.charset = 'utf-8';
+ node.async = true;
+ return node;
+ };
+
+ /**
+ * Does the request to load a module for the browser case.
+ * Make this a separate function to allow other environments
+ * to override it.
+ *
+ * @param {Object} context the require context to find state.
+ * @param {String} moduleName the name of the module.
+ * @param {Object} url the URL to the module.
+ */
+ req.load = function (context, moduleName, url) {
+ var config = (context && context.config) || {},
+ node;
+ if (isBrowser) {
+ //In the browser so use a script tag
+ node = req.createNode(config, moduleName, url);
+
+ node.setAttribute('data-requirecontext', context.contextName);
+ node.setAttribute('data-requiremodule', moduleName);
+
+ //Set up load listener. Test attachEvent first because IE9 has
+ //a subtle issue in its addEventListener and script onload firings
+ //that do not match the behavior of all other browsers with
+ //addEventListener support, which fire the onload event for a
+ //script right after the script execution. See:
+ //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution
+ //UNFORTUNATELY Opera implements attachEvent but does not follow the script
+ //script execution mode.
+ if (node.attachEvent &&
+ //Check if node.attachEvent is artificially added by custom script or
+ //natively supported by browser
+ //read https://github.com/jrburke/requirejs/issues/187
+ //if we can NOT find [native code] then it must NOT natively supported.
+ //in IE8, node.attachEvent does not have toString()
+ //Note the test for "[native code" with no closing brace, see:
+ //https://github.com/jrburke/requirejs/issues/273
+ !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) &&
+ !isOpera) {
+ //Probably IE. IE (at least 6-8) do not fire
+ //script onload right after executing the script, so
+ //we cannot tie the anonymous define call to a name.
+ //However, IE reports the script as being in 'interactive'
+ //readyState at the time of the define call.
+ useInteractive = true;
+
+ node.attachEvent('onreadystatechange', context.onScriptLoad);
+ //It would be great to add an error handler here to catch
+ //404s in IE9+. However, onreadystatechange will fire before
+ //the error handler, so that does not help. If addEventListener
+ //is used, then IE will fire error before load, but we cannot
+ //use that pathway given the connect.microsoft.com issue
+ //mentioned above about not doing the 'script execute,
+ //then fire the script load event listener before execute
+ //next script' that other browsers do.
+ //Best hope: IE10 fixes the issues,
+ //and then destroys all installs of IE 6-9.
+ //node.attachEvent('onerror', context.onScriptError);
+ } else {
+ node.addEventListener('load', context.onScriptLoad, false);
+ node.addEventListener('error', context.onScriptError, false);
+ }
+ node.src = url;
+
+ //For some cache cases in IE 6-8, the script executes before the end
+ //of the appendChild execution, so to tie an anonymous define
+ //call to the module name (which is stored on the node), hold on
+ //to a reference to this node, but clear after the DOM insertion.
+ currentlyAddingScript = node;
+ if (baseElement) {
+ head.insertBefore(node, baseElement);
+ } else {
+ head.appendChild(node);
+ }
+ currentlyAddingScript = null;
+
+ return node;
+ } else if (isWebWorker) {
+ try {
+ //In a web worker, use importScripts. This is not a very
+ //efficient use of importScripts, importScripts will block until
+ //its script is downloaded and evaluated. However, if web workers
+ //are in play, the expectation that a build has been done so that
+ //only one script needs to be loaded anyway. This may need to be
+ //reevaluated if other use cases become common.
+ importScripts(url);
+
+ //Account for anonymous modules
+ context.completeLoad(moduleName);
+ } catch (e) {
+ context.onError(makeError('importscripts',
+ 'importScripts failed for ' +
+ moduleName + ' at ' + url,
+ e,
+ [moduleName]));
+ }
+ }
+ };
+
+ function getInteractiveScript() {
+ if (interactiveScript && interactiveScript.readyState === 'interactive') {
+ return interactiveScript;
+ }
+
+ eachReverse(scripts(), function (script) {
+ if (script.readyState === 'interactive') {
+ return (interactiveScript = script);
+ }
+ });
+ return interactiveScript;
+ }
+
+ //Look for a data-main script attribute, which could also adjust the baseUrl.
+ if (isBrowser && !cfg.skipDataMain) {
+ //Figure out baseUrl. Get it from the script tag with require.js in it.
+ eachReverse(scripts(), function (script) {
+ //Set the 'head' where we can append children by
+ //using the script's parent.
+ if (!head) {
+ head = script.parentNode;
+ }
+
+ //Look for a data-main attribute to set main script for the page
+ //to load. If it is there, the path to data main becomes the
+ //baseUrl, if it is not already set.
+ dataMain = script.getAttribute('data-main');
+ if (dataMain) {
+ //Preserve dataMain in case it is a path (i.e. contains '?')
+ mainScript = dataMain;
+
+ //Set final baseUrl if there is not already an explicit one.
+ if (!cfg.baseUrl) {
+ //Pull off the directory of data-main for use as the
+ //baseUrl.
+ src = mainScript.split('/');
+ mainScript = src.pop();
+ subPath = src.length ? src.join('/') + '/' : './';
+
+ cfg.baseUrl = subPath;
+ }
+
+ //Strip off any trailing .js since mainScript is now
+ //like a module name.
+ mainScript = mainScript.replace(jsSuffixRegExp, '');
+
+ //If mainScript is still a path, fall back to dataMain
+ if (req.jsExtRegExp.test(mainScript)) {
+ mainScript = dataMain;
+ }
+
+ //Put the data-main script in the files to load.
+ cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript];
+
+ return true;
+ }
+ });
+ }
+
+ /**
+ * The function that handles definitions of modules. Differs from
+ * require() in that a string for the module should be the first argument,
+ * and the function to execute after dependencies are loaded should
+ * return a value to define the module corresponding to the first argument's
+ * name.
+ */
+ define = function (name, deps, callback) {
+ var node, context;
+
+ //Allow for anonymous modules
+ if (typeof name !== 'string') {
+ //Adjust args appropriately
+ callback = deps;
+ deps = name;
+ name = null;
+ }
+
+ //This module may not have dependencies
+ if (!isArray(deps)) {
+ callback = deps;
+ deps = null;
+ }
+
+ //If no name, and callback is a function, then figure out if it a
+ //CommonJS thing with dependencies.
+ if (!deps && isFunction(callback)) {
+ deps = [];
+ //Remove comments from the callback string,
+ //look for require calls, and pull them into the dependencies,
+ //but only if there are function args.
+ if (callback.length) {
+ callback
+ .toString()
+ .replace(commentRegExp, '')
+ .replace(cjsRequireRegExp, function (match, dep) {
+ deps.push(dep);
+ });
+
+ //May be a CommonJS thing even without require calls, but still
+ //could use exports, and module. Avoid doing exports and module
+ //work though if it just needs require.
+ //REQUIRES the function to expect the CommonJS variables in the
+ //order listed below.
+ deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps);
+ }
+ }
+
+ //If in IE 6-8 and hit an anonymous define() call, do the interactive
+ //work.
+ if (useInteractive) {
+ node = currentlyAddingScript || getInteractiveScript();
+ if (node) {
+ if (!name) {
+ name = node.getAttribute('data-requiremodule');
+ }
+ context = contexts[node.getAttribute('data-requirecontext')];
+ }
+ }
+
+ //Always save off evaluating the def call until the script onload handler.
+ //This allows multiple modules to be in a file without prematurely
+ //tracing dependencies, and allows for anonymous module support,
+ //where the module name is not known until the script onload event
+ //occurs. If no context, use the global queue, and get it processed
+ //in the onscript load callback.
+ (context ? context.defQueue : globalDefQueue).push([name, deps, callback]);
+ };
+
+ define.amd = {
+ jQuery: true
+ };
+
+
+ /**
+ * Executes the text. Normally just uses eval, but can be modified
+ * to use a better, environment-specific call. Only used for transpiling
+ * loader plugins, not for plain JS modules.
+ * @param {String} text the text to execute/evaluate.
+ */
+ req.exec = function (text) {
+ /*jslint evil: true */
+ return eval(text);
+ };
+
+ //Set up with config info.
+ req(cfg);
+}(this));
diff --git a/test/usage/rey.jpeg b/test/usage/rey.jpeg
new file mode 100644
index 0000000..a399b78
Binary files /dev/null and b/test/usage/rey.jpeg differ
diff --git a/test/usage/style.css b/test/usage/style.css
new file mode 100644
index 0000000..4c744c5
--- /dev/null
+++ b/test/usage/style.css
@@ -0,0 +1,87 @@
+ .list {
+ font-family:sans-serif;
+ margin:0;
+ padding:20px 0 0;
+ }
+ .list > li {
+ display:block;
+ background-color: #eee;
+ padding:10px;
+ box-shadow: inset 0 1px 0 #fff;
+ }
+ .avatar {
+ max-width: 150px;
+ }
+ img {
+ max-width: 100%;
+ }
+ h3 {
+ font-size: 16px;
+ margin:0 0 0.3rem;
+ font-weight: normal;
+ font-weight:bold;
+ }
+ p {
+ margin:0;
+ }
+
+ input {
+ border:solid 1px #ccc;
+ border-radius: 5px;
+ padding:7px 14px;
+ margin-bottom:10px
+ }
+ input:focus {
+ outline:none;
+ border-color:#aaa;
+ }
+ .sort {
+ padding:8px 30px;
+ border-radius: 6px;
+ border:none;
+ display:inline-block;
+ color:#fff;
+ text-decoration: none;
+ background-color: #28a8e0;
+ height:30px;
+ }
+ .sort:hover {
+ text-decoration: none;
+ background-color:#1b8aba;
+ }
+ .sort:focus {
+ outline:none;
+ }
+ .sort:after {
+ width: 0;
+ height: 0;
+ border-left: 5px solid transparent;
+ border-right: 5px solid transparent;
+ border-bottom: 5px solid transparent;
+ content:"";
+ position: relative;
+ top:-10px;
+ right:-5px;
+ }
+ .sort.asc:after {
+ width: 0;
+ height: 0;
+ border-left: 5px solid transparent;
+ border-right: 5px solid transparent;
+ border-top: 5px solid #fff;
+ content:"";
+ position: relative;
+ top:13px;
+ right:-5px;
+ }
+ .sort.desc:after {
+ width: 0;
+ height: 0;
+ border-left: 5px solid transparent;
+ border-right: 5px solid transparent;
+ border-bottom: 5px solid #fff;
+ content:"";
+ position: relative;
+ top:-10px;
+ right:-5px;
+ }
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/list.js.git
More information about the Pkg-javascript-commits
mailing list