From d1a8cbf8595e971d304f1dff2fe9133eb9295b90 Mon Sep 17 00:00:00 2001 From: Amy Slagle Date: Sun, 26 Oct 2014 15:48:05 -0400 Subject: [PATCH] Version 0.5.0. Store data in template instance instead of session. All settings can be named arguments or part of settings argument. New setting to add an id to the table. Remove group argument for sharing state between tables. --- README.md | 62 ++-- .../leaderboard/.meteor/.finished-upgraders | 1 + examples/leaderboard/.meteor/platforms | 2 + examples/leaderboard/.meteor/release | 2 +- examples/leaderboard/.meteor/versions | 108 +++--- examples/leaderboard/leaderboard.js | 2 +- .../.meteor/.finished-upgraders | 1 + examples/table-features/.meteor/platforms | 2 + examples/table-features/.meteor/release | 2 +- examples/table-features/.meteor/versions | 106 +++--- lib/reactive_table.html | 32 +- lib/reactive_table.js | 350 +++++++++--------- package.js | 4 +- test/README.md | 2 - test/test_collection_argument.js | 9 + test/test_column_toggles.js | 24 +- test/test_fields.js | 86 ++--- test/test_filtering.js | 10 +- test/test_multiple_tables.js | 41 +- test/test_pagination.js | 6 +- test/test_reactivity.js | 2 +- test/test_settings.js | 113 ++++-- test/test_sorting.js | 4 +- versions.json | 40 +- 24 files changed, 524 insertions(+), 487 deletions(-) create mode 100644 examples/leaderboard/.meteor/platforms create mode 100644 examples/table-features/.meteor/platforms diff --git a/README.md b/README.md index e4a84e8..b28208e 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ If you're updating to Meteor 0.8.0, note that reactiveTable is now a template wi - [Quick Start](#quick-start) - [Customization](#customization) - [Settings](#settings) + - [rowClass Examples](#rowclass-examples) + - [Settings Object](#settings-object) - [Styling](#styling) - [Setting columns](#setting-columns) - [Setting column headers](#setting-column-headers) @@ -40,27 +42,21 @@ This package adds a template called reactiveTable. Create and subscribe to a col When the whole collection should be in the table, it's best to pass in the Meteor collection object (returned by new Meteor.Collection()). You can also pass in the cursor returned by collection.find() to show a subset of the collection, or a plain array to show data that's not in a Meteor collection. - - -## Customization - -The reactiveTable helper accepts an additional settings argument that can be used to configure the table. - - {{> reactiveTable collection=collection settings=settings}} - -Define the settings in a helper for the template that calls reactiveTable: +If you're new to Meteor, note that global variables aren't available from templates. You can add template helpers to access them: Template.myTemplate.helpers({ - settings: function () { - return { - rowsPerPage: 10, - showFilter: true, - fields: ['name', 'location', 'year'] - }; + myCollection: function () { + return myCollection; } }); +## Customization + +The reactiveTable helper accepts additional arguments that can be used to configure the table. + + {{> reactiveTable collection=collection showNavigation='never' rowsPerPage=5}} + ### Settings * `showFilter`: Boolean. Whether to display the filter box above the table. Default `true`. @@ -70,6 +66,8 @@ Define the settings in a helper for the template that calls reactiveTable: * `fields`: Object. Controls the columns; see below. * `showColumnToggles`: Boolean. Adds a button to the top right that allows the user to toggle which columns are displayed. Add `hidden` to fields to hide them unless toggled on, see below. Default `false`. * `useFontAwesome`: Boolean. Whether to use [Font Awesome](http://fortawesome.github.io/Font-Awesome/) for icons. Requires the `font-awesome` package to be installed. Default `false`. +* `class`: String. Classes to add to the table element in addition to 'reactive-table'. Default: 'table table-striped table-hover'. +* `id`: String. Unique id to add to the table element. Default: generated with [_.uniqueId](http://underscorejs.org/#uniqueId). * `rowClass`: String or function returning a class name. The row element will be passed as first parameter. #### rowClass examples @@ -98,6 +96,29 @@ as a string rowClass: 'danger', ``` +#### Settings Object + +Settings can also be grouped into a single object to pass to the table: + + {{> reactiveTable settings=settings}} + +Define the settings in a helper for the template that calls reactiveTable: + + Template.myTemplate.helpers({ + settings: function () { + return { + collection: collection, + rowsPerPage: 10, + showFilter: true, + fields: ['name', 'location', 'year'] + }; + } + }); + +You can continue to pass some settings as named arguments while grouping the others into the settings object: + + {{> reactiveTable collection=collection fields=fields settings=settings}} + ### Styling Add bootstrap or bootstrap-3 to style the table, or add your own css. The generated table will have the class 'reactive-table'. To use [Font Awesome](http://fortawesome.github.io/Font-Awesome/) for icons, also add the font-awesome package and set `useFontAwesome` to `true` in the settings. @@ -206,17 +227,6 @@ Template.posts.events({ }); ``` -## Multiple tables - -When multiple tables are used in the same application, by default they'll share pagination settings and filters. Add a different group to each table's settings to allow separate table state. - - { - fields: [...], - group: 'resources' - } - -The default group is 'reactive-table'. - ## Internationalization Internationalization support is provided using [just-i18n](https://github.com/subhog/meteor-just-i18n). diff --git a/examples/leaderboard/.meteor/.finished-upgraders b/examples/leaderboard/.meteor/.finished-upgraders index ee0ed5a..68df3d8 100644 --- a/examples/leaderboard/.meteor/.finished-upgraders +++ b/examples/leaderboard/.meteor/.finished-upgraders @@ -4,3 +4,4 @@ notices-for-0.9.0 notices-for-0.9.1 +0.9.4-platform-file diff --git a/examples/leaderboard/.meteor/platforms b/examples/leaderboard/.meteor/platforms new file mode 100644 index 0000000..efeba1b --- /dev/null +++ b/examples/leaderboard/.meteor/platforms @@ -0,0 +1,2 @@ +server +browser diff --git a/examples/leaderboard/.meteor/release b/examples/leaderboard/.meteor/release index 7b32bf7..7057f80 100644 --- a/examples/leaderboard/.meteor/release +++ b/examples/leaderboard/.meteor/release @@ -1 +1 @@ -METEOR@0.9.3 +METEOR@0.9.4 diff --git a/examples/leaderboard/.meteor/versions b/examples/leaderboard/.meteor/versions index 195fca6..b5a380d 100644 --- a/examples/leaderboard/.meteor/versions +++ b/examples/leaderboard/.meteor/versions @@ -1,56 +1,56 @@ anti:i18n@0.4.3 -application-configuration@1.0.2 -aslagle:reactive-table@0.4.10 -autopublish@1.0.0 -autoupdate@1.1.1 -base64@1.0.0 -binary-heap@1.0.0 -blaze-tools@1.0.0 -blaze@2.0.1 -boilerplate-generator@1.0.0 -callback-hook@1.0.0 -check@1.0.1 -ctl-helper@1.0.3 -ctl@1.0.1 -ddp@1.0.9 -deps@1.0.4 -ejson@1.0.3 -fastclick@1.0.0 -follower-livedata@1.0.1 -geojson-utils@1.0.0 -html-tools@1.0.1 -htmljs@1.0.1 -http@1.0.6 -id-map@1.0.0 -insecure@1.0.0 -jquery@1.0.0 -json@1.0.0 -livedata@1.0.10 -logging@1.0.3 -meteor-platform@1.1.1 -meteor@1.1.1 -minifiers@1.1.0 -minimongo@1.0.3 -mizzao:bootstrap-3@3.2.0 -mobile-status-bar@1.0.0 -mongo@1.0.6 +application-configuration@1.0.3 +aslagle:reactive-table@0.5.0 +autopublish@1.0.1 +autoupdate@1.1.2 +base64@1.0.1 +binary-heap@1.0.1 +blaze-tools@1.0.1 +blaze@2.0.2 +boilerplate-generator@1.0.1 +callback-hook@1.0.1 +check@1.0.2 +ctl-helper@1.0.4 +ctl@1.0.2 +ddp@1.0.10 +deps@1.0.5 +ejson@1.0.4 +fastclick@1.0.1 +follower-livedata@1.0.2 +geojson-utils@1.0.1 +html-tools@1.0.2 +htmljs@1.0.2 +http@1.0.7 +id-map@1.0.1 +insecure@1.0.1 +jquery@1.0.1 +json@1.0.1 +livedata@1.0.11 +logging@1.0.4 +meteor-platform@1.1.2 +meteor@1.1.2 +minifiers@1.1.1 +minimongo@1.0.4 +mizzao:bootstrap-3@3.2.0_1 +mobile-status-bar@1.0.1 +mongo@1.0.7 natestrauser:font-awesome@4.2.0 -observe-sequence@1.0.2 -ordered-dict@1.0.0 -random@1.0.0 -reactive-dict@1.0.3 -reactive-var@1.0.2 -reload@1.1.0 -retry@1.0.0 -routepolicy@1.0.1 -session@1.0.2 -spacebars-compiler@1.0.2 -spacebars@1.0.2 -standard-app-packages@1.0.2 -templating@1.0.7 -tracker@1.0.2 -ui@1.0.3 -underscore@1.0.0 -url@1.0.0 -webapp-hashing@1.0.0 -webapp@1.1.2 +observe-sequence@1.0.3 +ordered-dict@1.0.1 +random@1.0.1 +reactive-dict@1.0.4 +reactive-var@1.0.3 +reload@1.1.1 +retry@1.0.1 +routepolicy@1.0.2 +session@1.0.3 +spacebars-compiler@1.0.3 +spacebars@1.0.3 +standard-app-packages@1.0.3 +templating@1.0.8 +tracker@1.0.3 +ui@1.0.4 +underscore@1.0.1 +url@1.0.1 +webapp-hashing@1.0.1 +webapp@1.1.3 diff --git a/examples/leaderboard/leaderboard.js b/examples/leaderboard/leaderboard.js index e2b4bb7..cada7ed 100644 --- a/examples/leaderboard/leaderboard.js +++ b/examples/leaderboard/leaderboard.js @@ -13,7 +13,7 @@ if (Meteor.isClient) { fields: [ { key: 'name', label: 'Full Name' }, { key: 'name', label: 'First Name', fn: function (name) { return name.split(' ')[0]; } }, - { key: 'score', label: 'Score'} + { key: 'score', label: 'Score' } ], useFontAwesome: true }; diff --git a/examples/table-features/.meteor/.finished-upgraders b/examples/table-features/.meteor/.finished-upgraders index ee0ed5a..68df3d8 100644 --- a/examples/table-features/.meteor/.finished-upgraders +++ b/examples/table-features/.meteor/.finished-upgraders @@ -4,3 +4,4 @@ notices-for-0.9.0 notices-for-0.9.1 +0.9.4-platform-file diff --git a/examples/table-features/.meteor/platforms b/examples/table-features/.meteor/platforms new file mode 100644 index 0000000..efeba1b --- /dev/null +++ b/examples/table-features/.meteor/platforms @@ -0,0 +1,2 @@ +server +browser diff --git a/examples/table-features/.meteor/release b/examples/table-features/.meteor/release index 7b32bf7..7057f80 100644 --- a/examples/table-features/.meteor/release +++ b/examples/table-features/.meteor/release @@ -1 +1 @@ -METEOR@0.9.3 +METEOR@0.9.4 diff --git a/examples/table-features/.meteor/versions b/examples/table-features/.meteor/versions index f28f777..5c66411 100644 --- a/examples/table-features/.meteor/versions +++ b/examples/table-features/.meteor/versions @@ -1,54 +1,54 @@ anti:i18n@0.4.3 -application-configuration@1.0.2 -aslagle:reactive-table@0.4.10 -autopublish@1.0.0 -autoupdate@1.1.1 -base64@1.0.0 -binary-heap@1.0.0 -blaze-tools@1.0.0 -blaze@2.0.1 -boilerplate-generator@1.0.0 -callback-hook@1.0.0 -check@1.0.1 -ctl-helper@1.0.3 -ctl@1.0.1 -ddp@1.0.9 -deps@1.0.4 -ejson@1.0.3 -fastclick@1.0.0 -follower-livedata@1.0.1 -geojson-utils@1.0.0 -html-tools@1.0.1 -htmljs@1.0.1 -http@1.0.6 -id-map@1.0.0 -jquery@1.0.0 -json@1.0.0 -livedata@1.0.10 -logging@1.0.3 -meteor-platform@1.1.1 -meteor@1.1.1 -minifiers@1.1.0 -minimongo@1.0.3 -mizzao:bootstrap-3@3.2.0 -mobile-status-bar@1.0.0 -mongo@1.0.6 -observe-sequence@1.0.2 -ordered-dict@1.0.0 -random@1.0.0 -reactive-dict@1.0.3 -reactive-var@1.0.2 -reload@1.1.0 -retry@1.0.0 -routepolicy@1.0.1 -session@1.0.2 -spacebars-compiler@1.0.2 -spacebars@1.0.2 -standard-app-packages@1.0.2 -templating@1.0.7 -tracker@1.0.2 -ui@1.0.3 -underscore@1.0.0 -url@1.0.0 -webapp-hashing@1.0.0 -webapp@1.1.2 +application-configuration@1.0.3 +aslagle:reactive-table@0.5.0 +autopublish@1.0.1 +autoupdate@1.1.2 +base64@1.0.1 +binary-heap@1.0.1 +blaze-tools@1.0.1 +blaze@2.0.2 +boilerplate-generator@1.0.1 +callback-hook@1.0.1 +check@1.0.2 +ctl-helper@1.0.4 +ctl@1.0.2 +ddp@1.0.10 +deps@1.0.5 +ejson@1.0.4 +fastclick@1.0.1 +follower-livedata@1.0.2 +geojson-utils@1.0.1 +html-tools@1.0.2 +htmljs@1.0.2 +http@1.0.7 +id-map@1.0.1 +jquery@1.0.1 +json@1.0.1 +livedata@1.0.11 +logging@1.0.4 +meteor-platform@1.1.2 +meteor@1.1.2 +minifiers@1.1.1 +minimongo@1.0.4 +mizzao:bootstrap-3@3.2.0_1 +mobile-status-bar@1.0.1 +mongo@1.0.7 +observe-sequence@1.0.3 +ordered-dict@1.0.1 +random@1.0.1 +reactive-dict@1.0.4 +reactive-var@1.0.3 +reload@1.1.1 +retry@1.0.1 +routepolicy@1.0.2 +session@1.0.3 +spacebars-compiler@1.0.3 +spacebars@1.0.3 +standard-app-packages@1.0.3 +templating@1.0.8 +tracker@1.0.3 +ui@1.0.4 +underscore@1.0.1 +url@1.0.1 +webapp-hashing@1.0.1 +webapp@1.1.3 diff --git a/lib/reactive_table.html b/lib/reactive_table.html index 64996f0..6bafdef 100644 --- a/lib/reactive_table.html +++ b/lib/reactive_table.html @@ -1,7 +1,6 @@ diff --git a/lib/reactive_table.js b/lib/reactive_table.js index 8d04b2e..9c8f71a 100644 --- a/lib/reactive_table.js +++ b/lib/reactive_table.js @@ -1,35 +1,3 @@ -var getSessionSortKey = function (group) { - return group + '-reactive-table-sort'; -}; - -var getSessionSortDirectionKey = function (group) { - return group + '-reactive-table-sort-direction'; -}; - -var getSessionRowsPerPageKey = function (group) { - return group + '-reactive-table-rows-per-page'; -}; - -var getSessionCurrentPageKey = function (group) { - return group + '-reactive-table-current-page'; -}; - -var getSessionFilterKey = function (group) { - return group + '-reactive-table-filter'; -}; - -var getSessionShowNavigationRowsPerPageKey = function (group) { - return group + '-reactive-table-show-navigationrowsperpage'; -}; - -var getSessionShowNavigationKey = function (group) { - return group + '-reactive-table-show-navigation'; -}; - -var getSessionVisibleFieldsKey = function (group) { - return group + '-reactive-table-visible-fields'; -}; - var get = function(obj, field) { var keys = field.split('.'); var value = obj; @@ -47,10 +15,104 @@ var get = function(obj, field) { return value; }; -var generateSettings = function () { - var collection = this.collection || this; - var settings = this.settings || {}; - var group = settings.group || 'reactive-table'; + +var parseFilterString = function (filterString) { + var startQuoteRegExp = /^[\'\"]/; + var endQuoteRegExp = /[\'\"]$/; + var filters = []; + var words = filterString.split(' '); + + var inQuote = false; + var quotedWord = ''; + _.each(words, function (word) { + if (inQuote) { + if (endQuoteRegExp.test(word)) { + filters.push(quotedWord + ' ' + word.slice(0, word.length - 1)); + inQuote = false; + quotedWord = ''; + } else { + quotedWord = quotedWord + ' ' + word; + } + } else if (startQuoteRegExp.test(word)) { + if (endQuoteRegExp.test(word)) { + filters.push(word.slice(1, word.length - 1)); + } else { + inQuote = true; + quotedWord = word.slice(1, word.length); + } + } else { + filters.push(word); + } + }); + return filters; +}; + +var getFilterQuery = function (filter, fields) { + var numberRegExp = /^\d+$/; + var queryList = []; + if (filter) { + var filters = parseFilterString(filter); + _.each(filters, function (filterWord) { + var filterQueryList = []; + _.each(fields, function (field) { + var filterRegExp = new RegExp(filterWord, 'i'); + var query = {}; + query[field.key || field] = filterRegExp; + filterQueryList.push(query); + + if (numberRegExp.test(filterWord)) { + var numberQuery = {}; + numberQuery[field.key || field] = parseInt(filterWord, 10); + filterQueryList.push(numberQuery) + } + }); + if (filterQueryList.length) { + var filterQuery = {'$or': filterQueryList}; + queryList.push(filterQuery); + } + }); + } + return queryList.length ? {'$and': queryList} : {}; +}; + +var updateFilter = _.debounce(function (template, filterText) { + template.data.filter.set(filterText); + template.data.currentPage.set(0); +}, 200); + + +var getDefaultFalseSetting = function (key, templateData) { + if (!_.isUndefined(templateData[key]) && + templateData[key]) { + return true; + } + if (!_.isUndefined(templateData.settings) && + !_.isUndefined(templateData.settings[key]) && + templateData.settings[key]) { + return true; + } + return false; +}; + +var getDefaultTrueSetting = function (key, templateData) { + if (!_.isUndefined(templateData[key]) && + !templateData[key]) { + return false; + } + if (!_.isUndefined(templateData.settings) && + !_.isUndefined(templateData.settings[key]) && + !templateData.settings[key]) { + return false; + } + return true; +}; + + + +Template.reactiveTable.created = function () { + this.data.settings = this.data.settings || {}; + var collection = this.data.collection || this.data.settings.collection || this.data; + if (!(collection instanceof Meteor.Collection)) { if (_.isArray(collection)) { // collection is an array @@ -80,14 +142,18 @@ var generateSettings = function () { collection = new Meteor.Collection(null); } } + this.data.collection = collection; - var fields = settings.fields || {}; + var fields = this.data.fields || this.data.settings.fields || {}; if (_.keys(fields).length < 1 || (_.keys(fields).length === 1 && _.keys(fields)[0] === 'hash')) { fields = _.without(_.keys(collection.findOne() || {}), '_id'); } + var sortKey = 0; + var sortDirection = 1; + var normalizeField = function (field) { if (typeof field === 'string') { return {key: field, label: field}; @@ -98,15 +164,18 @@ var generateSettings = function () { var parseField = function (field, i) { if (field.sort) { - settings.sortKey = i; + sortKey = i; if (field.sort === 'desc' || field.sort === 'descending' || field.sort === -1) { - settings.sortDirectionKey = -1; + sortDirection = -1; } } return normalizeField(field); }; fields = _.map(fields, parseField); + this.data.fields = fields; + this.data.sortKey = new ReactiveVar(sortKey); + this.data.sortDirection = new ReactiveVar(sortDirection); var visibleFields = []; _.each(fields, function (field, i) { @@ -114,106 +183,40 @@ var generateSettings = function () { visibleFields.push(i); } }); + this.data.visibleFields = new ReactiveVar(visibleFields); - Session.setDefault(getSessionSortKey(group), settings.sortKey || 0); - Session.setDefault(getSessionSortDirectionKey(group), settings.sortDirectionKey || 1); - Session.setDefault(getSessionRowsPerPageKey(group), settings.rowsPerPage || 10); - Session.setDefault(getSessionCurrentPageKey(group), 0); - Session.setDefault(getSessionShowNavigationRowsPerPageKey(group), (settings.showNavigationRowsPerPage === undefined) || settings.showNavigationRowsPerPage ); - Session.setDefault(getSessionShowNavigationKey(group), settings.showNavigation || 'always'); - Session.setDefault(getSessionFilterKey(group), null); - if (visibleFields.length > 0) { - Session.setDefault(getSessionVisibleFieldsKey(group), visibleFields); - } - var showFilter = (typeof settings.showFilter === "undefined" ? true : settings.showFilter); - var rowClass = settings.rowClass || function() {return ''}; + var rowClass = this.data.rowClass || this.data.settings.rowClass || function() {return ''}; if (typeof rowClass === 'string') { var tmp = rowClass; rowClass = function(obj) { return tmp; }; } + this.data.rowClass = rowClass; - return { - group: group, - collection: collection, - settings: settings, - fields: fields, - useFontAwesome: settings.useFontAwesome, - showFilter: showFilter, - showColumnToggles: settings.showColumnToggles, - rowClass: rowClass - }; -}; + this.data.class = this.data.class || this.data.settings.class || 'table table-striped table-hover'; + this.data.id = this.data.id || this.data.settings.id || _.uniqueId('reactive-table-'); -var parseFilterString = function (filterString) { - var startQuoteRegExp = /^[\'\"]/; - var endQuoteRegExp = /[\'\"]$/; - var filters = []; - var words = filterString.split(' '); + this.data.showNavigation = this.data.showNavigation || this.data.settings.showNavigation || 'always'; + this.data.showNavigationRowsPerPage = getDefaultTrueSetting('showNavigationRowsPerPage', this.data); + this.data.rowsPerPage = new ReactiveVar(this.data.rowsPerPage || this.data.settings.rowsPerPage || 10); + this.data.currentPage = new ReactiveVar(0); - var inQuote = false; - var quotedWord = ''; - _.each(words, function (word) { - if (inQuote) { - if (endQuoteRegExp.test(word)) { - filters.push(quotedWord + ' ' + word.slice(0, word.length - 1)); - inQuote = false; - quotedWord = ''; - } else { - quotedWord = quotedWord + ' ' + word; - } - } else if (startQuoteRegExp.test(word)) { - if (endQuoteRegExp.test(word)) { - filters.push(word.slice(1, word.length - 1)); - } else { - inQuote = true; - quotedWord = word.slice(1, word.length); - } - } else { - filters.push(word); - } - }); - return filters; -}; + this.data.filter = new ReactiveVar(null); + this.data.showFilter = getDefaultTrueSetting('showFilter', this.data); -var getFilterQuery = function (group, fields) { - var numberRegExp = /^\d+$/; - var filter = Session.get(getSessionFilterKey(group)); - var queryList = []; - if (filter) { - var filters = parseFilterString(filter); - _.each(filters, function (filterWord) { - var filterQueryList = []; - _.each(fields, function (field) { - var filterRegExp = new RegExp(filterWord, 'i'); - var query = {}; - query[field.key || field] = filterRegExp; - filterQueryList.push(query); - - if (numberRegExp.test(filterWord)) { - var numberQuery = {}; - numberQuery[field.key || field] = parseInt(filterWord, 10); - filterQueryList.push(numberQuery) - } - }); - if (filterQueryList.length) { - var filterQuery = {'$or': filterQueryList}; - queryList.push(filterQuery); - } - }); - } - return queryList.length ? {'$and': queryList} : {}; + this.data.useFontAwesome = getDefaultFalseSetting('useFontAwesome', this.data); + this.data.showColumnToggles = getDefaultFalseSetting('showColumnToggles', this.data); }; Template.reactiveTable.getPageCount = function () { - var rowsPerPage = Session.get(getSessionRowsPerPageKey(this.group)); - var filterQuery = getFilterQuery(this.group, this.fields); + var rowsPerPage = this.rowsPerPage.get(); + var filterQuery = getFilterQuery(this.filter.get(), this.fields); var count = this.collection.find(filterQuery).count(); return Math.ceil(count / rowsPerPage); }; + Template.reactiveTable.helpers({ - 'generateSettings': generateSettings, 'getField': function (object) { var fn = this.fn || function (value) { return value; }; @@ -222,8 +225,8 @@ Template.reactiveTable.helpers({ return fn(value, object); }, - 'getFieldIndex': function (fields) { - return _.indexOf(fields, this); + 'getFieldIndex': function () { + return _.indexOf(Template.parentData(1).fields, this); }, 'getKey': function () { @@ -234,32 +237,35 @@ Template.reactiveTable.helpers({ return _.isString(this.label) ? this.label : this; }, - 'isSortKey': function (field, group, fields) { - return Session.equals(getSessionSortKey(group), _.indexOf(fields, field)); + 'isSortKey': function () { + var parentData = Template.parentData(1); + return parentData.sortKey.get() == _.indexOf(parentData.fields, this); }, 'isSortable': function () { return true; }, - 'isVisible': function (field, group, fields) { - return _.include(Session.get(getSessionVisibleFieldsKey(group)), _.indexOf(fields, field)); + 'isVisible': function () { + var visibleFields = Template.parentData(1).visibleFields || Template.parentData(2).visibleFields; + var fields = Template.parentData(1).fields || Template.parentData(2).fields; + return _.include(visibleFields.get(), _.indexOf(fields, this)); }, - 'isAscending' : function (group) { - var sortDirection = Session.get(getSessionSortDirectionKey(group)); + 'isAscending' : function () { + var sortDirection = Template.parentData(1).sortDirection.get(); return (sortDirection === 1); }, 'sortedRows': function () { - var sortDirection = Session.get(getSessionSortDirectionKey(this.group)); - var sortKeyIndex = Session.get(getSessionSortKey(this.group)); + var sortDirection = this.sortDirection.get(); + var sortKeyIndex = this.sortKey.get(); var sortKeyField = this.fields[sortKeyIndex] || {}; - var limit = Session.get(getSessionRowsPerPageKey(this.group)); - var currentPage = Session.get(getSessionCurrentPageKey(this.group)); + var limit = this.rowsPerPage.get(); + var currentPage = this.currentPage.get(); var skip = currentPage * limit; - var filterQuery = getFilterQuery(this.group, this.fields); + var filterQuery = getFilterQuery(this.filter.get(), this.fields); if (sortKeyField.fn && !sortKeyField.sortByValue) { var data = this.collection.find(filterQuery).fetch(); @@ -284,90 +290,76 @@ Template.reactiveTable.helpers({ }, 'filter' : function () { - return Session.get(getSessionFilterKey(this.group)) || ''; + return this.filter.get() || ''; }, 'getRowsPerPage' : function () { - return Session.get(getSessionRowsPerPageKey(this.group)); + return this.rowsPerPage.get(); }, 'getCurrentPage' : function () { - return 1 + Session.get(getSessionCurrentPageKey(this.group)); + return 1 + this.currentPage.get(); }, 'isntFirstPage' : function () { - return Session.get(getSessionCurrentPageKey(this.group)) > 0; + return this.currentPage.get() > 0; }, 'isntLastPage' : function () { - var currentPage = 1 + Session.get(getSessionCurrentPageKey(this.group)); - var rowsPerPage = Session.get(getSessionRowsPerPageKey(this.group)); - var filterQuery = getFilterQuery(this.group, this.fields); + var currentPage = 1 + this.currentPage.get(); + var rowsPerPage = this.rowsPerPage.get(); + var filterQuery = getFilterQuery(this.filter.get(), this.fields); var count = this.collection.find(filterQuery).count(); return currentPage < Math.ceil(count / rowsPerPage); }, 'showNavigation' : function () { - if (Session.get(getSessionShowNavigationKey(this.group)) === 'always') return true; - if (Session.get(getSessionShowNavigationKey(this.group)) === 'never') return false; + if (this.showNavigation === 'always') return true; + if (this.showNavigation === 'never') return false; return Template.reactiveTable.getPageCount.call(this) > 1; - }, - - 'showNavigationRowsPerPage' : function () { - return Session.get(getSessionShowNavigationRowsPerPageKey(this.group)); - }, - - 'hasClass' : function (data) { - return data.class || 'table table-striped table-hover'; } }); Template.reactiveTable.events({ 'click .reactive-table .sortable': function (event) { + var template = Template.instance(); var target = $(event.target).is('i') ? $(event.target).parent() : $(event.target); var sortIndex = parseInt(target.attr('index'), 10); - var group = target.parents('.reactive-table').attr('reactive-table-group'); - var currentSortIndex = Session.get(getSessionSortKey(group)); + var currentSortIndex = template.data.sortKey.get(); if (currentSortIndex === sortIndex) { - var sortDirection = -1 * Session.get(getSessionSortDirectionKey(group)); - Session.set(getSessionSortDirectionKey(group), sortDirection); + var sortDirection = -1 * template.data.sortDirection.get(); + template.data.sortDirection.set(sortDirection); } else { - Session.set(getSessionSortKey(group), sortIndex); + template.data.sortKey.set(sortIndex); } }, 'change .reactive-table-add-column input': function (event) { + var template = Template.instance(); var target = $(event.target); var index = parseInt(target.attr('index'), 10); - var group = target.parents('.reactive-table').attr('reactive-table-group'); - var sessionVisibleFieldsKey = getSessionVisibleFieldsKey(group); - var currentVisibleFields = Session.get(sessionVisibleFieldsKey); + var currentVisibleFields = template.data.visibleFields.get() if (_.include(currentVisibleFields, index)) { - Session.set(sessionVisibleFieldsKey, _.without(currentVisibleFields, index)); + template.data.visibleFields.set(_.without(currentVisibleFields, index)); } else { - Session.set(sessionVisibleFieldsKey, currentVisibleFields.concat(index)); + template.data.visibleFields.set(currentVisibleFields.concat(index)); } - event.stopPropagation(); - return false; }, - 'keyup .reactive-table-filter .reactive-table-input, input .reactive-table-filter .reactive-table-input': _.debounce(function (event) { + 'keyup .reactive-table-filter .reactive-table-input, input .reactive-table-filter .reactive-table-input': function (event) { + var template = Template.instance(); var filterText = $(event.target).val(); - var group = $(event.target).parents('.reactive-table-filter').attr('reactive-table-group'); - Session.set(getSessionFilterKey(group), filterText); - Session.set(getSessionCurrentPageKey(this.group), 0); - }, 200), + updateFilter(template, filterText); + }, 'change .reactive-table-navigation .rows-per-page input': function (event) { var rowsPerPage = Math.max(~~$(event.target).val(), 1); - var group = $(event.target).parents('.reactive-table-navigation').attr('reactive-table-group'); - Session.set(getSessionRowsPerPageKey(group), rowsPerPage); + Template.instance().data.rowsPerPage.set(rowsPerPage); $(event.target).val(rowsPerPage); }, 'change .reactive-table-navigation .page-number input': function (event) { var currentPage = Math.max(~~$(event.target).val(), 1); - var group = $(event.target).parents('.reactive-table-navigation').attr('reactive-table-group'); var pageCount = Template.reactiveTable.getPageCount.call(this); if (currentPage > pageCount) { currentPage = pageCount; @@ -375,21 +367,19 @@ Template.reactiveTable.events({ if (currentPage < 0) { currentPage = 1; } - Session.set(getSessionCurrentPageKey(this.group), currentPage - 1); + Template.instance().data.currentPage.set(currentPage - 1); $(event.target).val(currentPage); }, 'click .reactive-table-navigation .previous-page': function (event) { - var group = $(event.target).parents('.reactive-table-navigation').attr('reactive-table-group'); - var currentPageKey = getSessionCurrentPageKey(group); - var currentPage = Session.get(currentPageKey); - Session.set(currentPageKey, currentPage - 1); + var template = Template.instance(); + var currentPage = template.data.currentPage.get(); + template.data.currentPage.set(currentPage - 1); }, 'click .reactive-table-navigation .next-page': function (event) { - var group = $(event.target).parents('.reactive-table-navigation').attr('reactive-table-group'); - var currentPageKey = getSessionCurrentPageKey(group); - var currentPage = Session.get(currentPageKey); - Session.set(currentPageKey, currentPage + 1); + var template = Template.instance(); + var currentPage = template.data.currentPage.get(); + template.data.currentPage.set(currentPage + 1); } }); diff --git a/package.js b/package.js index 1145f4f..3c9c74a 100644 --- a/package.js +++ b/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "A reactive table designed for Meteor", - version: "0.4.10", + version: "0.5.0", name: "aslagle:reactive-table", git: "https://github.com/ecohealthalliance/reactive-table.git" }); @@ -10,6 +10,7 @@ Package.on_use(function (api) { api.use('templating', 'client'); api.use('jquery', 'client'); api.use('underscore', 'client'); + api.use('reactive-var@1.0.3', 'client'); api.use("anti:i18n@0.4.3", 'client'); api.add_files('lib/reactive_table.html', 'client'); @@ -22,6 +23,7 @@ Package.on_test(function (api) { api.use('templating', 'client'); api.use('jquery', 'client'); api.use('underscore', 'client'); + api.use('reactive-var@1.0.3', 'client'); api.use("anti:i18n@0.4.3", 'client'); api.add_files('lib/reactive_table.html', 'client'); diff --git a/test/README.md b/test/README.md index 270128a..6f60d10 100644 --- a/test/README.md +++ b/test/README.md @@ -3,5 +3,3 @@ Start the test app: meteor test-packages ./ And open http://localhost:3000 to run the tests - -Note: Due to the package's use of Session, some tests may fail when rerun without refreshing the page. diff --git a/test/test_collection_argument.js b/test/test_collection_argument.js index 663af49..8bc62ea 100644 --- a/test/test_collection_argument.js +++ b/test/test_collection_argument.js @@ -33,3 +33,12 @@ Tinytest.add('Collection Argument - collection as only argument', function (test } ); }); + +Tinytest.add('Collection Argument - in settings argument', function (test) { + testTable( + {settings: {collection: rows}}, + function () { + test.length($('.reactive-table tbody tr'), 6, "rendered table should have 6 rows"); + } + ); +}); diff --git a/test/test_column_toggles.js b/test/test_column_toggles.js index 39a3521..145ba69 100644 --- a/test/test_column_toggles.js +++ b/test/test_column_toggles.js @@ -3,8 +3,7 @@ Tinytest.add('Column Toggles - setting', function (test) { { collection: rows, settings: { - showColumnToggles: false, - group: _.uniqueId() + showColumnToggles: false } }, function () { @@ -15,10 +14,7 @@ Tinytest.add('Column Toggles - setting', function (test) { testTable( { collection: rows, - settings: { - showColumnToggles: true, - group: _.uniqueId() - } + showColumnToggles: true }, function () { test.length($('.reactive-table-add-column'), 1, "column toggle button should be visible"); @@ -37,8 +33,7 @@ Tinytest.add('Column Toggles - hidden columns', function (test) { fields: [ {key: 'name', label: 'Visible'}, {key: 'name', label: 'Hidden', hidden: true} - ], - group: _.uniqueId() + ] } }, function () { @@ -55,14 +50,11 @@ testAsyncMulti('Column Toggles - toggling', [function (test, expect) { Template.reactiveTable, { collection: rows, - settings: { - showColumnToggles: true, - fields: [ - {key: 'name', label: 'Visible'}, - {key: 'name', label: 'Hidden', hidden: true} - ], - group: _.uniqueId() - } + showColumnToggles: true, + fields: [ + {key: 'name', label: 'Visible'}, + {key: 'name', label: 'Hidden', hidden: true} + ] }, document.body ); diff --git a/test/test_fields.js b/test/test_fields.js index 9ad87eb..ffe4b2d 100644 --- a/test/test_fields.js +++ b/test/test_fields.js @@ -1,6 +1,6 @@ Tinytest.add('Fields - implicit', function (test) { testTable( - {collection: rows, settings: {group: _.uniqueId()}}, + {collection: rows}, function () { test.length($('.reactive-table th'), 2, "two columns should be rendered"); test.length($('.reactive-table th:first-child').text().trim().match(/^name/), 1, "first column should be name"); @@ -11,7 +11,7 @@ Tinytest.add('Fields - implicit', function (test) { Tinytest.add('Fields - array', function (test) { testTable( - {collection: rows, settings: {fields: ['name', 'score'], group: _.uniqueId()}}, + {collection: rows, fields: ['name', 'score']}, function () { test.length($('.reactive-table th'), 2, "two columns should be rendered"); test.length($('.reactive-table th:first-child').text().trim().match(/^name/), 1, "first column should be name"); @@ -20,7 +20,7 @@ Tinytest.add('Fields - array', function (test) { ); testTable( - {collection: rows, settings: {fields: ['score'], group: _.uniqueId()}}, + {collection: rows, settings: {fields: ['score']}}, function () { test.length($('.reactive-table th'), 1, "one columns should be rendered"); test.length($('.reactive-table th:first-child').text().trim().match(/^score/), 1, "column should be score"); @@ -36,8 +36,7 @@ Tinytest.add('Fields - labels', function (test) { fields: [ {key: 'name', label: 'Column1'}, {key: 'score', label: 'Column2'} - ], - group: _.uniqueId() + ] } }, function () { @@ -54,12 +53,9 @@ Tinytest.add('Fields - tmpl', function (test) { testTable( { collection: rows, - settings: { - fields: [ - {key: 'name', label: 'Name', tmpl: Template.testFieldsTmpl} - ], - group: _.uniqueId() - } + fields: [ + {key: 'name', label: 'Name', tmpl: Template.testFieldsTmpl} + ] }, function () { test.length($('.reactive-table tbody tr td span.test'), 6, "all rows should have use the template"); @@ -75,8 +71,7 @@ Tinytest.add('Fields - virtual column', function (test) { settings: { fields: [ {key: 'name', label: 'First Initial', fn: function (name) { return name.slice(0, 1); }} - ], - group: _.uniqueId() + ] } }, function () { @@ -90,12 +85,9 @@ Tinytest.add('Fields - virtual column sorting', function (test) { testTable( { collection: rows, - settings: { - fields: [ - {key: 'name', label: 'Letters 2&3', fn: function (name) { return name.slice(1, 3); }} - ], - group: _.uniqueId() - } + fields: [ + {key: 'name', label: 'Letters 2&3', fn: function (name) { return name.slice(1, 3); }} + ] }, function () { test.equal($('.reactive-table tbody tr:first-child td').text(), "ar", "table should be sorted by fn"); @@ -110,8 +102,7 @@ Tinytest.add('Fields - virtual column sorting', function (test) { settings: { fields: [ {key: 'name', label: 'Letters 2&3', sortByValue: true, fn: function (name) { return name.slice(1, 3); }} - ], - group: _.uniqueId() + ] } }, function () { @@ -126,18 +117,15 @@ Tinytest.add('Fields - virtual column html', function (test) { testTable( { collection: rows, - settings: { - fields: [ - { - key: 'name', - label: 'HTML', - fn: function (name) { - return Spacebars.SafeString("" + name + ""); - } + fields: [ + { + key: 'name', + label: 'HTML', + fn: function (name) { + return Spacebars.SafeString("" + name + ""); } - ], - group: _.uniqueId() - } + } + ] }, function () { test.length($('.reactive-table tbody tr span.test'), 6, "all rows should have html class"); @@ -154,8 +142,7 @@ Tinytest.add('Fields - default sort', function (test) { settings: { fields: [ {key: 'name', label: 'Name', sort: sort} - ], - group: _.uniqueId() + ] } }, function () { @@ -169,12 +156,9 @@ Tinytest.add('Fields - default sort', function (test) { testTable( { collection: rows, - settings: { - fields: [ - {key: 'name', label: 'Name', sort: 'asc'} - ], - group: _.uniqueId() - } + fields: [ + {key: 'name', label: 'Name', sort: 'asc'} + ] }, function () { test.equal($('.reactive-table tbody tr:first-child td').text(), "Ada Lovelace", "sort should be ascending"); @@ -193,8 +177,7 @@ Tinytest.add('Fields - nested key', function (test) { { collection: nestedObjectRows, settings: { - fields: [{key: 'outerObject.innerObject', label: 'Column'}], - group: _.uniqueId() + fields: [{key: 'outerObject.innerObject', label: 'Column'}] } }, function () { @@ -211,10 +194,7 @@ Tinytest.add('Fields - nested key', function (test) { testTable( { collection: nestedArrayRows, - settings: { - fields: [{key: 'outerObject.2', label: 'Column'}], - group: _.uniqueId() - } + fields: [{key: 'outerObject.2', label: 'Column'}] }, function () { test.length($('.reactive-table tbody tr'), 2, "table should have 2 rows"); @@ -232,8 +212,7 @@ Tinytest.add('Fields - hidden', function (test) { fields: [ {key: 'name', label: 'Visible', hidden: false}, {key: 'name', label: 'Hidden', hidden: true} - ], - group: _.uniqueId() + ] } }, function () { @@ -246,13 +225,10 @@ Tinytest.add('Fields - hidden', function (test) { testTable( { collection: rows, - settings: { - fields: [ - {key: 'name', label: 'Visible', hidden: function () { return false; }}, - {key: 'name', label: 'Hidden', hidden: function () { return true; }} - ], - group: _.uniqueId() - } + fields: [ + {key: 'name', label: 'Visible', hidden: function () { return false; }}, + {key: 'name', label: 'Hidden', hidden: function () { return true; }} + ] }, function () { test.length($('.reactive-table th'), 1, "one column should be visible"); diff --git a/test/test_filtering.js b/test/test_filtering.js index 7e57bf8..f7b27a6 100644 --- a/test/test_filtering.js +++ b/test/test_filtering.js @@ -1,7 +1,7 @@ testAsyncMulti('Filtering - one input', [function (test, expect) { var table = Blaze.renderWithData( Template.reactiveTable, - {collection: rows, settings: {group: _.uniqueId()}}, + {collection: rows}, document.body ); test.length($('.reactive-table tbody tr'), 6, "initial six rows"); @@ -21,7 +21,7 @@ testAsyncMulti('Filtering - one input', [function (test, expect) { testAsyncMulti('Filtering - two inputs', [function (test, expect) { var table = Blaze.renderWithData( Template.reactiveTable, - {collection: rows, settings: {group: _.uniqueId()}}, + {collection: rows}, document.body ); test.length($('.reactive-table tbody tr'), 6, "initial six rows"); @@ -40,7 +40,7 @@ testAsyncMulti('Filtering - two inputs', [function (test, expect) { testAsyncMulti('Filtering - quotes', [function (test, expect) { var table = Blaze.renderWithData( Template.reactiveTable, - {collection: rows, settings: {group: _.uniqueId()}}, + {collection: rows}, document.body ); test.length($('.reactive-table tbody tr'), 6, "initial six rows"); @@ -67,7 +67,7 @@ testAsyncMulti('Filtering - quotes', [function (test, expect) { testAsyncMulti('Filtering - numerical', [function (test, expect) { var table = Blaze.renderWithData( Template.reactiveTable, - {collection: rows, settings: {group: _.uniqueId()}}, + {collection: rows}, document.body ); test.length($('.reactive-table tbody tr'), 6, "initial six rows"); @@ -91,7 +91,7 @@ testAsyncMulti('Filtering - numbers in strings', [function (test, expect) { }); var table = Blaze.renderWithData( Template.reactiveTable, - {collection: numberStringRows, settings: {group: _.uniqueId()}}, + {collection: numberStringRows}, document.body ); test.length($('.reactive-table tbody tr'), 6, "initial six rows"); diff --git a/test/test_multiple_tables.js b/test/test_multiple_tables.js index 2d754da..f09ea48 100644 --- a/test/test_multiple_tables.js +++ b/test/test_multiple_tables.js @@ -1,9 +1,9 @@ Tinytest.add('Multiple tables - rendering', function (test) { testTable( - {collection: rows, settings: {group: _.uniqueId()}}, + {collection: rows}, function () { testTable( - {collection: collection, settings: {group: _.uniqueId()}}, + {collection: collection}, function () { test.length($('.reactive-table'), 2, "two tables should be rendered"); test.length($('.reactive-table:nth-of-type(1) tbody tr'), 6, "the first table should have 6 rows"); @@ -16,10 +16,10 @@ Tinytest.add('Multiple tables - rendering', function (test) { Tinytest.add('Multiple tables - settings', function (test) { testTable( - {collection: rows, settings: {showNavigation: true, group: _.uniqueId()}}, + {collection: rows, settings: {showNavigation: true}}, function () { testTable( - {collection: collection, settings: {showNavigation: false, group: _.uniqueId()}}, + {collection: collection, settings: {showNavigation: false}}, function () { test.length($('.reactive-table'), 2, "two tables should be rendered"); test.length($('.reactive-table-navigation'), 1, "only one table should have navigation"); @@ -29,10 +29,10 @@ Tinytest.add('Multiple tables - settings', function (test) { ); testTable( - {collection: rows, settings: {rowsPerPage: 5, group: _.uniqueId()}}, + {collection: rows, settings: {rowsPerPage: 5}}, function () { testTable( - {collection: collection, settings: {rowsPerPage: 2, group: _.uniqueId()}}, + {collection: collection, settings: {rowsPerPage: 2}}, function () { test.length($('.reactive-table'), 2, "two tables should be rendered"); test.length($('.reactive-table:nth-of-type(1) tbody tr'), 5, "the first table should have 5 rows"); @@ -46,12 +46,12 @@ Tinytest.add('Multiple tables - settings', function (test) { testAsyncMulti('Multiple tables - sorting', [function (test, expect) { var table1 = Blaze.renderWithData( Template.reactiveTable, - {collection: rows, settings: {group: _.uniqueId()}}, + {collection: rows}, document.body ); var table2 = Blaze.renderWithData( Template.reactiveTable, - {collection: rows, settings: {group: _.uniqueId()}}, + {collection: rows}, document.body ); test.equal($('.reactive-table:nth-of-type(1) tbody tr:first-child td:first-child').text(), "Ada Lovelace", "first table sorted ascending"); @@ -69,15 +69,14 @@ testAsyncMulti('Multiple tables - sorting', [function (test, expect) { }]); testAsyncMulti('Multiple tables - filtering', [function (test, expect) { - var group = _.uniqueId(); var table1 = Blaze.renderWithData( Template.reactiveTable, - {collection: rows, settings: {group: group}}, + {collection: rows}, document.body ); var table2 = Blaze.renderWithData( Template.reactiveTable, - {collection: rows, settings: {group: _.uniqueId()}}, + {collection: rows}, document.body ); test.length($('.reactive-table:nth-of-type(1) tbody tr'), 6, "first table should have 6 rows"); @@ -90,34 +89,32 @@ testAsyncMulti('Multiple tables - filtering', [function (test, expect) { Blaze.remove(table2); }); - $('.reactive-table-filter[reactive-table-group="' + group + '"] input').val("carl"); - $('.reactive-table-filter[reactive-table-group="' + group + '"] input').trigger('input'); + $($('.reactive-table-filter input')[0]).val("carl"); + $($('.reactive-table-filter input')[0]).trigger('input'); Meteor.setTimeout(expectFirstTableFiltered, 1000); }]); testAsyncMulti('Multiple tables - pagination', [function (test, expect) { - var group1 = _.uniqueId(); var table1 = Blaze.renderWithData( Template.reactiveTable, - {collection: rows, settings: {rowsPerPage: 2, group: group1}}, + {collection: rows, settings: {rowsPerPage: 2}}, document.body ); - var group2 = _.uniqueId() var table2 = Blaze.renderWithData( Template.reactiveTable, - {collection: rows, settings: {rowsPerPage: 2, group: group2}}, + {collection: rows, settings: {rowsPerPage: 2}}, document.body ); - test.equal($('.reactive-table-navigation[reactive-table-group="' + group1 + '"] .page-number input').val(), "1", "first table on page 1"); - test.equal($('.reactive-table-navigation[reactive-table-group="' + group2 + '"] .page-number input').val(), "1", "second table on page 1"); + test.equal($($('.reactive-table-navigation .page-number input')[0]).val(), "1", "first table on page 1"); + test.equal($($('.reactive-table-navigation .page-number input')[1]).val(), "1", "second table on page 1"); var expectSecondTablePageTwo = expect(function () { - test.equal($('.reactive-table-navigation[reactive-table-group="' + group1 + '"] .page-number input').val(), "1", "first table on page 1"); - test.equal($('.reactive-table-navigation[reactive-table-group="' + group2 + '"] .page-number input').val(), "2", "second table on page 2"); + test.equal($($('.reactive-table-navigation .page-number input')[0]).val(), "1", "first table on page 1"); + test.equal($($('.reactive-table-navigation .page-number input')[1]).val(), "2", "second table on page 2"); Blaze.remove(table1); Blaze.remove(table2); }); - $('.reactive-table-navigation[reactive-table-group="' + group2 + '"] .next-page').click(); + $($('.reactive-table-navigation .next-page')[1]).click(); Meteor.setTimeout(expectSecondTablePageTwo, 0); }]); diff --git a/test/test_pagination.js b/test/test_pagination.js index 3bb1f3c..621861b 100644 --- a/test/test_pagination.js +++ b/test/test_pagination.js @@ -1,6 +1,6 @@ Tinytest.add('Pagination - initial page', function (test) { testTable( - {collection: rows, settings: {rowsPerPage: 2, group: _.uniqueId()}}, + {collection: rows, settings: {rowsPerPage: 2}}, function () { test.length($('.reactive-table tbody tr'), 2, "two rows should be rendered"); test.equal($('.reactive-table tbody tr:first-child td:first-child').text(), "Ada Lovelace", "should be on the first page"); @@ -13,7 +13,7 @@ Tinytest.add('Pagination - initial page', function (test) { testAsyncMulti('Pagination - previous/next controls', [function (test, expect) { var table = Blaze.renderWithData( Template.reactiveTable, - {collection: rows, settings: {rowsPerPage: 2, group: _.uniqueId()}}, + {collection: rows, settings: {rowsPerPage: 2}}, document.body ); @@ -62,7 +62,7 @@ testAsyncMulti('Pagination - previous/next controls', [function (test, expect) { testAsyncMulti('Pagination - page input', [function (test, expect) { var table = Blaze.renderWithData( Template.reactiveTable, - {collection: rows, settings: {rowsPerPage: 2, group: _.uniqueId()}}, + {collection: rows, settings: {rowsPerPage: 2}}, document.body ); diff --git a/test/test_reactivity.js b/test/test_reactivity.js index 035aeca..4e817d1 100644 --- a/test/test_reactivity.js +++ b/test/test_reactivity.js @@ -3,7 +3,7 @@ testAsyncMulti('Reactivity - collection', [function (test, expect) { collection.insert({name: 'item 1', value: 1}); var table = Blaze.renderWithData( Template.reactiveTable, - {collection: collection, settings: {group: _.uniqueId()}}, + {collection: collection}, document.body ); test.length($('.reactive-table tbody tr'), 1, "table should initially have one row"); diff --git a/test/test_settings.js b/test/test_settings.js index c586710..680c9a6 100644 --- a/test/test_settings.js +++ b/test/test_settings.js @@ -1,77 +1,98 @@ Tinytest.add('Settings - showFilter', function (test) { testTable( - {collection: rows, group: _.uniqueId()}, + {collection: rows}, function () { test.length($('.reactive-table-filter'), 1, "filter should be visible by default"); } ); testTable( - {collection: rows, settings: {showFilter: false, group: _.uniqueId()}}, + {collection: rows, settings: {showFilter: false}}, function () { test.length($('.reactive-table-filter'), 0, "filter should be hidden"); } ); testTable( - {collection: rows, settings: {showFilter: true, group: _.uniqueId()}}, + {collection: rows, settings: {showFilter: true}}, function () { test.length($('.reactive-table-filter'), 1, "filter should be visible"); } ); + + testTable( + {collection: rows, showFilter: false}, + function () { + test.length($('.reactive-table-filter'), 0, "filter should be hidden"); + } + ); }); Tinytest.add('Settings - rowsPerPage', function (test) { testTable( - {collection: rows, settings: {rowsPerPage: 2, group: _.uniqueId()}}, + {collection: rows, settings: {rowsPerPage: 2}}, function () { test.length($('.reactive-table tbody tr'), 2, "two rows should be rendered"); } ); testTable( - {collection: rows, settings: {rowsPerPage: 1, group: _.uniqueId()}}, + {collection: rows, settings: {rowsPerPage: 1}}, function () { test.length($('.reactive-table tbody tr'), 1, "one row should be rendered"); } ); + + testTable( + {collection: rows, rowsPerPage: 2}, + function () { + test.length($('.reactive-table tbody tr'), 2, "two rows should be rendered"); + } + ); }); Tinytest.add('Settings - showNavigation', function (test) { testTable( - {collection: rows, group: _.uniqueId()}, + {collection: rows}, function () { test.length($('.reactive-table-navigation'), 1, "navigation should be visible by default"); } ); testTable( - {collection: rows, settings: {showNavigation: 'never', group: _.uniqueId()}}, + {collection: rows, settings: {showNavigation: 'never'}}, function () { test.length($('.reactive-table-navigation'), 0, "navigation should be hidden"); } ); testTable( - {collection: rows, settings: {showNavigation: 'always', group: _.uniqueId()}}, + {collection: rows, settings: {showNavigation: 'always'}}, function () { test.length($('.reactive-table-navigation'), 1, "navigation should be visible"); } ); testTable( - {collection: rows, settings: {showNavigation: 'auto', group: _.uniqueId()}}, + {collection: rows, settings: {showNavigation: 'auto'}}, function () { test.length($('.reactive-table-navigation'), 0, "navigation should be hidden"); } ); testTable( - {collection: rows, settings: {showNavigation: 'auto', rowsPerPage: 2, group: _.uniqueId()}}, + {collection: rows, settings: {showNavigation: 'auto', rowsPerPage: 2}}, function () { test.length($('.reactive-table-navigation'), 1, "navigation should be visible"); } ); + + testTable( + {collection: rows, showNavigation: 'never'}, + function () { + test.length($('.reactive-table-navigation'), 0, "navigation should be hidden"); + } + ); }); @@ -81,8 +102,7 @@ Tinytest.add('Settings - showNavigationRowsPerPage', function (test) { collection: rows, settings: { showNavigation: 'never', - showNavigationRowsPerPage: true, - group: _.uniqueId() + showNavigationRowsPerPage: true } }, function () { @@ -93,11 +113,8 @@ Tinytest.add('Settings - showNavigationRowsPerPage', function (test) { testTable( { collection: rows, - settings: { - showNavigation: 'always', - showNavigationRowsPerPage: true, - group: _.uniqueId() - } + showNavigation: 'always', + showNavigationRowsPerPage: true }, function () { test.length($('.reactive-table-navigation .rows-per-page'), 1, "rows per page should be visible"); @@ -109,8 +126,7 @@ Tinytest.add('Settings - showNavigationRowsPerPage', function (test) { collection: rows, settings: { showNavigation: 'always', - showNavigationRowsPerPage: false, - group: _.uniqueId() + showNavigationRowsPerPage: false } }, function () { @@ -122,30 +138,44 @@ Tinytest.add('Settings - showNavigationRowsPerPage', function (test) { Tinytest.add('Settings - useFontAwesome', function (test) { testTable( - {collection: rows, settings: {group: _.uniqueId()}}, + {collection: rows}, function () { test.length($('.reactive-table-filter .fa'), 0, "font awesome should be off by default"); } ); testTable( - {collection: rows, settings: {useFontAwesome: true, group: _.uniqueId()}}, + {collection: rows, settings: {useFontAwesome: true}}, function () { test.length($('.reactive-table-filter .fa'), 1, "font awesome should be on"); } ); testTable( - {collection: rows, settings: {useFontAwesome: false, group: _.uniqueId()}}, + {collection: rows, settings: {useFontAwesome: false}}, function () { test.length($('.reactive-table-filter .fa'), 0, "font awesome should be off"); } ); + + testTable( + {collection: rows, useFontAwesome: true}, + function () { + test.length($('.reactive-table-filter .fa'), 1, "font awesome should be on"); + } + ); }); Tinytest.add('Settings - rowClass', function (test) { testTable( - {collection: rows, settings: {rowClass: 'row-class', group: _.uniqueId()}}, + {collection: rows, settings: {rowClass: 'row-class'}}, + function () { + test.length($('.reactive-table tbody tr.row-class'), $('.reactive-table tbody tr').length, "all rows should have the class"); + } + ); + + testTable( + {collection: rows, rowClass: 'row-class'}, function () { test.length($('.reactive-table tbody tr.row-class'), $('.reactive-table tbody tr').length, "all rows should have the class"); } @@ -157,8 +187,7 @@ Tinytest.add('Settings - rowClass', function (test) { settings: { rowClass: function (row) { return 'row-class-' + row.score; - }, - group: _.uniqueId() + } } }, function () { @@ -170,16 +199,46 @@ Tinytest.add('Settings - rowClass', function (test) { Tinytest.add('Settings - class', function (test) { testTable( - {collection: rows, settings: {group: _.uniqueId()}}, + {collection: rows}, function () { test.length($('.reactive-table.table.table-striped.table-hover'), 1, "table should have default classes"); } ); testTable( - {collection: rows, class: 'table-class', settings: {group: _.uniqueId()}}, + {collection: rows, class: 'table-class'}, + function () { + test.length($('.reactive-table.table-class'), 1, "table should have the class"); + } + ); + + testTable( + {collection: rows, settings: {class: 'table-class'}}, function () { test.length($('.reactive-table.table-class'), 1, "table should have the class"); } ); }); + +Tinytest.add('Settings - id', function (test) { + testTable( + {collection: rows}, + function () { + test.equal($('.reactive-table').attr('id').slice(0, 15), 'reactive-table-', "table should have default id"); + } + ); + + testTable( + {collection: rows, id: 'unique-table'}, + function () { + test.length($('#unique-table.reactive-table'), 1, "table should have the id"); + } + ); + + testTable( + {collection: rows, settings: {id: 'unique-table-2'}}, + function () { + test.length($('#unique-table-2.reactive-table'), 1, "table should have the id"); + } + ); +}); diff --git a/test/test_sorting.js b/test/test_sorting.js index d8bf75f..b8d41c3 100644 --- a/test/test_sorting.js +++ b/test/test_sorting.js @@ -1,7 +1,7 @@ testAsyncMulti('Sorting - direction', [function (test, expect) { var table = Blaze.renderWithData( Template.reactiveTable, - {collection: rows, settings: {group: _.uniqueId()}}, + {collection: rows}, document.body ); test.equal($('.reactive-table tbody tr:first-child td:first-child').text(), "Ada Lovelace", "initial first row"); @@ -31,7 +31,7 @@ testAsyncMulti('Sorting - direction', [function (test, expect) { testAsyncMulti('Sorting - column', [function (test, expect) { var table = Blaze.renderWithData( Template.reactiveTable, - {collection: collection, settings: {group: _.uniqueId()}}, + {collection: collection}, document.body ); test.equal($('.reactive-table tbody tr:first-child td:first-child').text(), "Ada Lovelace", "initial first row"); diff --git a/versions.json b/versions.json index c2519f4..01d8d95 100644 --- a/versions.json +++ b/versions.json @@ -6,82 +6,82 @@ ], [ "base64", - "1.0.0" + "1.0.1" ], [ "blaze", - "2.0.1" + "2.0.2" ], [ "deps", - "1.0.4" + "1.0.5" ], [ "ejson", - "1.0.3" + "1.0.4" ], [ "geojson-utils", - "1.0.0" + "1.0.1" ], [ "htmljs", - "1.0.1" + "1.0.2" ], [ "id-map", - "1.0.0" + "1.0.1" ], [ "jquery", - "1.0.0" + "1.0.1" ], [ "json", - "1.0.0" + "1.0.1" ], [ "meteor", - "1.1.1" + "1.1.2" ], [ "minimongo", - "1.0.3" + "1.0.4" ], [ "observe-sequence", - "1.0.2" + "1.0.3" ], [ "ordered-dict", - "1.0.0" + "1.0.1" ], [ "random", - "1.0.0" + "1.0.1" ], [ "reactive-var", - "1.0.2" + "1.0.3" ], [ "templating", - "1.0.7" + "1.0.8" ], [ "tracker", - "1.0.2" + "1.0.3" ], [ "ui", - "1.0.3" + "1.0.4" ], [ "underscore", - "1.0.0" + "1.0.1" ] ], "pluginDependencies": [], - "toolVersion": "meteor-tool@1.0.33", + "toolVersion": "meteor-tool@1.0.34", "format": "1.0" } \ No newline at end of file