diff --git a/dev/dev.html b/dev/dev.html index 871a7a565..ffd8b7a54 100644 --- a/dev/dev.html +++ b/dev/dev.html @@ -39,18 +39,21 @@ }); })(); require(['jquery', '../data', 'fuelux/all'], function($, data){ - //REPEATER - var delays = ['300', '600', '900', '1200']; - var $myRepeater = $('#myRepeater'); + // simulate network latency + var loadDelays = ['300', '600', '900', '1200']; + // list view setup var list = function(options, callback){ + + // build dataSource based with options var resp = { count: data.repeater.listData.length, items: [], page: options.pageIndex }; - var i, l; + // get start and end limits for JSON + var i, l; resp.pages = Math.ceil(resp.count/(options.pageSize || 50)); i = options.pageIndex * (options.pageSize || 50); @@ -59,12 +62,12 @@ resp.start = i + 1; resp.end = l; + // setup columns for list view resp.columns = [ { label: 'Common Name', property: 'commonName', - sortable: true, - className: 'rover' + sortable: true }, { label: 'Latin Name', @@ -74,8 +77,7 @@ { label: 'Appearance', property: 'appearance', - sortable: true, - className: 'blub' + sortable: true }, { label: 'Sound', @@ -84,7 +86,9 @@ } ]; + // add sample items to datasource for(i; i @@ -184,11 +208,14 @@
+ + +
diff --git a/js/repeater-list.js b/js/repeater-list.js index 0927049e4..2a58bdc20 100755 --- a/js/repeater-list.js +++ b/js/repeater-list.js @@ -34,7 +34,7 @@ $.fn.repeater.Constructor.prototype.list_highlightColumn = function(index, force){ var tbody = this.$canvas.find('.repeater-list tbody'); - if(this.options.list_highlightSortedColumn || force){ + if(this.viewOptions.list_highlightSortedColumn || force){ tbody.find('td.sorted').removeClass('sorted'); tbody.find('tr').each(function(){ var col = $(this).find('td:nth-child(' + (index + 1) + ')'); @@ -70,7 +70,7 @@ }; $.fn.repeater.Constructor.prototype.list_setSelectedItems = function(items, force){ - var selectable = this.options.list_selectable; + var selectable = this.viewOptions.list_selectable; var self = this; var data, i, $item, l; @@ -145,9 +145,9 @@ }); //EXTENSION DEFINITION - $.fn.repeater.views.list = { + $.fn.repeater.viewTypes.list = { cleared: function(helpers, callback){ - if(this.options.list_columnSyncing){ + if(this.viewOptions.list_columnSyncing){ this.list_sizeHeadings(); } callback(); @@ -167,7 +167,7 @@ callback(); }, selected: function(helpers, callback){ - var infScroll = this.options.list_infiniteScroll; + var infScroll = this.viewOptions.list_infiniteScroll; var opts; this.list_firstRender = true; @@ -181,7 +181,7 @@ callback(); }, resize: function(helpers, callback){ - if(this.options.list_columnSyncing){ + if(this.viewOptions.list_columnSyncing){ this.list_sizeHeadings(); } callback(); @@ -189,7 +189,7 @@ renderer: { //RENDERING REPEATER-LIST, REPEATER-LIST-WRAPPER, AND TABLE complete: function(helpers, callback){ var $sorted; - if(this.options.list_columnSyncing){ + if(this.viewOptions.list_columnSyncing){ this.list_sizeHeadings(); this.list_positionHeadings(); } @@ -208,7 +208,7 @@ }else{ $item = $('
'); $item.find('.repeater-list-wrapper').on('scroll.fu.repeaterList', function(){ - if(self.options.list_columnSyncing){ + if(self.viewOptions.list_columnSyncing){ self.list_positionHeadings(); } }); @@ -222,7 +222,7 @@ var self = this; var i, l, newWidth, taken; - if(!this.options.list_columnSizing || this.list_columnsSame){ + if(!this.viewOptions.list_columnSizing || this.list_columnsSame){ callback(); }else{ i = 0; @@ -327,7 +327,7 @@ $spans.removeClass(chevUp).addClass(chevDown); self.list_sortDirection = 'desc'; }else{ - if(!self.options.list_sortClearing){ + if(!self.viewOptions.list_sortClearing){ $spans.removeClass(chevDown).addClass(chevUp); self.list_sortDirection = 'asc'; }else{ @@ -382,7 +382,7 @@ if(helpers.data.items.length<1){ obj.skipNested = true; $empty = $(''); - $empty.find('td').append(this.options.list_noItemsHTML); + $empty.find('td').append(this.viewOptions.list_noItemsHTML); $item.append($empty); } @@ -398,8 +398,8 @@ if(helpers.item!==undefined){ obj.item = helpers.item; } - if(this.options.list_rowRendered){ - this.options.list_rowRendered(obj, function(){ + if(this.viewOptions.list_rowRendered){ + this.viewOptions.list_rowRendered(obj, function(){ callback(); }); }else{ @@ -410,7 +410,7 @@ var $item = $(''); var self = this; - if(this.options.list_selectable){ + if(this.viewOptions.list_selectable){ $item.addClass('selectable'); $item.attr('tabindex', 0); // allow items to be tabbed to / focused on $item.data('item_data', helpers.subset[helpers.index]); @@ -421,7 +421,7 @@ $row.find('.repeater-list-check').remove(); self.$element.trigger('deselected.fu.repeaterList', $row); }else{ - if(self.options.list_selectable!=='multi'){ + if(self.viewOptions.list_selectable!=='multi'){ self.$canvas.find('.repeater-list-check').remove(); self.$canvas.find('.repeater-list tbody tr.selected').each(function(){ $(this).removeClass('selected'); @@ -457,8 +457,8 @@ if(helpers.item!==undefined){ obj.item = helpers.item; } - if(this.options.list_columnRendered){ - this.options.list_columnRendered(obj, function(){ + if(this.viewOptions.list_columnRendered){ + this.viewOptions.list_columnRendered(obj, function(){ callback(); }); }else{ diff --git a/js/repeater-thumbnail.js b/js/repeater-thumbnail.js index 2d2d9307c..de9f19b4f 100755 --- a/js/repeater-thumbnail.js +++ b/js/repeater-thumbnail.js @@ -40,7 +40,7 @@ }; $.fn.repeater.Constructor.prototype.thumbnail_setSelectedItems = function(items, force){ - var selectable = this.options.thumbnail_selectable; + var selectable = this.viewOptions.thumbnail_selectable; var self = this; var i, $item, l; @@ -94,9 +94,9 @@ }); //EXTENSION DEFINITION - $.fn.repeater.views.thumbnail = { + $.fn.repeater.viewTypes.thumbnail = { selected: function(helpers, callback){ - var infScroll = this.options.thumbnail_infiniteScroll; + var infScroll = this.viewOptions.thumbnail_infiniteScroll; var opts; if(infScroll){ opts = (typeof infScroll === 'object') ? infScroll : {}; @@ -118,7 +118,7 @@ if(helpers.data.items.length<1){ obj.skipNested = true; $empty = $('
'); - $empty.append(this.options.thumbnail_noItemsHTML); + $empty.append(this.viewOptions.thumbnail_noItemsHTML); $item.append($empty); }else{ $item.find('.empty:first').remove(); @@ -132,7 +132,7 @@ container: helpers.container, itemData: helpers.subset[helpers.index] }; - var selectable = this.options.thumbnail_selectable; + var selectable = this.viewOptions.thumbnail_selectable; var selected = 'selected'; var self = this; var $item; @@ -159,8 +159,8 @@ }); } } - if(this.options.thumbnail_itemRendered){ - this.options.thumbnail_itemRendered(obj, function(){ + if(this.viewOptions.thumbnail_itemRendered){ + this.viewOptions.thumbnail_itemRendered(obj, function(){ callback(); }); }else{ @@ -191,7 +191,7 @@ } return str; }; - callback({ item: template(this.options.thumbnail_template) }); + callback({ item: template(this.viewOptions.thumbnail_template) }); }, repeat: 'data.items' } diff --git a/js/repeater.js b/js/repeater.js index 6c95e1072..43a076c26 100755 --- a/js/repeater.js +++ b/js/repeater.js @@ -62,7 +62,8 @@ this.options = $.extend({}, $.fn.repeater.defaults, options); this.pageIncrement = 0; // store direction navigated this.resizeTimeout = {}; - this.staticHeight = (this.options.staticHeight===-1) ? this.$element.attr('data-staticheight') : this.options.staticHeight; + this.viewOptions = {}; + this.viewType = null; this.$filters.selectlist(); this.$pageSize.selectlist(); @@ -114,8 +115,9 @@ $btn = this.$views.find('label.active input'); currentView = ($btn.length>0) ? $btn.val() : 'list'; } + this.setViewOptions(currentView); - this.initViews(function(){ + this.initViewTypes(function(){ self.resize(); self.$element.trigger('resized.fu.repeater'); self.render({ changeView: currentView }); @@ -208,7 +210,7 @@ opts.search = val; } - viewDataOpts = $.fn.repeater.views[this.currentView] || {}; + viewDataOpts = $.fn.repeater.viewTypes[this.viewType] || {}; viewDataOpts = viewDataOpts.dataOptions; if(viewDataOpts){ viewDataOpts.call(this, opts, function(obj){ @@ -281,22 +283,22 @@ } }, - initViews: function(callback){ - var views = []; - var i, viewsLength; + initViewTypes: function(callback){ + var viewTypes = []; + var i, viewTypesLength; var init = function(index){ var next = function(){ index++; - if(index0){ + viewTypesLength = viewTypes.length; + if(viewTypesLength>0){ init(0); }else{ callback(); @@ -353,7 +355,7 @@ this.$primaryPaging.removeClass(act); this.$secondaryPaging.removeClass(act); - if(pages<=this.options.dropPagingCap){ + if(pages<=this.viewOptions.dropPagingCap){ this.$primaryPaging.addClass(act); dropMenu = this.$primaryPaging.find('.dropdown-menu'); dropMenu.empty(); @@ -418,7 +420,7 @@ render: function(options){ var self = this; var viewChanged = false; - var viewObj = $.fn.repeater.views[self.currentView] || {}; + var viewTypeObj = $.fn.repeater.viewTypes[self.viewType] || {}; var prevView; var start = function(){ @@ -427,8 +429,8 @@ self.$loader.show().loader('play'); } self.getDataOptions(options, function(opts){ - self.options.dataSource(opts, function(data){ - var renderer = viewObj.renderer; + self.viewOptions.dataSource(opts, function(data){ + var renderer = viewTypeObj.renderer; if(self.infiniteScrollingEnabled){ self.infiniteScrollingCallback({}); }else{ @@ -453,8 +455,8 @@ options.preserve = (options.preserve!==undefined) ? options.preserve : !viewChanged; self.clear(options); - if(!viewChanged && viewObj.cleared){ - viewObj.cleared.call(self, {}, function(){ + if(!viewChanged && viewTypeObj.cleared){ + viewTypeObj.cleared.call(self, {}, function(){ next(); }); }else{ @@ -468,7 +470,10 @@ if(options.changeView && this.currentView!==options.changeView){ prevView = this.currentView; this.currentView = options.changeView; + this.viewType = this.currentView.split('.')[0]; + this.setViewOptions(this.currentView); this.$element.attr('data-currentview', this.currentView); + this.$element.attr('data-viewtype', this.viewType); viewChanged = true; this.$element.trigger('viewChanged.fu.repeater', this.currentView); @@ -476,9 +481,9 @@ if(this.infiniteScrollingEnabled){ self.infiniteScrolling(false); } - viewObj = $.fn.repeater.views[self.currentView] || {}; - if(viewObj.selected){ - viewObj.selected.call(this, { prevView: prevView }, function(){ + viewTypeObj = $.fn.repeater.viewTypes[self.viewType] || {}; + if(viewTypeObj.selected){ + viewTypeObj.selected.call(this, { prevView: prevView }, function(){ start(); }); }else{ @@ -490,10 +495,14 @@ }, resize: function(){ - var staticHeight = this.staticHeight; - var viewObj = $.fn.repeater.views[this.currentView] || {}; + var staticHeight = (this.viewOptions.staticHeight===-1) ? this.$element.attr('data-staticheight') : this.viewOptions.staticHeight; + var viewTypeObj = {}; var height, viewportMargins; + if(this.viewType){ + viewTypeObj = $.fn.repeater.viewTypes[this.viewType] || {}; + } + if(staticHeight!==undefined){ this.$canvas.addClass('scrolling'); viewportMargins = { @@ -510,8 +519,8 @@ this.$canvas.removeClass('scrolling'); } - if(viewObj.resize){ - viewObj.resize.call(this, { + if(viewTypeObj.resize){ + viewTypeObj.resize.call(this, { height: this.$element.outerHeight(), width: this.$element.outerWidth() }, function(){}); @@ -637,6 +646,19 @@ loopSubset(0); }, + setViewOptions: function(curView){ + var opts = {}; + var viewName = curView.split('.')[1]; + + if(viewName && this.options.views){ + opts = this.options.views[viewName] || this.options.views[curView] || {}; + }else{ + opts = {}; + } + + this.viewOptions = $.extend({}, this.options, opts); + }, + viewChanged: function(e){ var $selected = $(e.target); var val = $selected.val(); @@ -666,7 +688,8 @@ dataSource: function(options, callback){}, defaultView: -1, //should be a string value. -1 means it will grab the active view from the view controls dropPagingCap: 10, - staticHeight: -1 //normally true or false. -1 means it will look for data-staticheight on the element + staticHeight: -1, //normally true or false. -1 means it will look for data-staticheight on the element + views: null //can be set to an object to configure multiple views of the same type }; //views object contains keyed list of view plugins, each an object with following optional parameters: @@ -696,7 +719,8 @@ //item: str or jQuery object, (only there if rendered function returned item) //subset: {}, (only there if repeat was set. subset of data being repeated on) //} - $.fn.repeater.views = {}; + + $.fn.repeater.viewTypes = {}; $.fn.repeater.Constructor = Repeater; diff --git a/less/repeater-list.less b/less/repeater-list.less index 58b9f95f6..4649e863f 100755 --- a/less/repeater-list.less +++ b/less/repeater-list.less @@ -1,4 +1,4 @@ -.repeater[data-currentview="list"] { +.repeater[data-viewtype="list"] { .repeater-canvas.scrolling { overflow: visible; diff --git a/test/fuelux-browser-globals.js b/test/fuelux-browser-globals.js index cb319b929..335067961 100644 --- a/test/fuelux-browser-globals.js +++ b/test/fuelux-browser-globals.js @@ -83,11 +83,11 @@ }); test('repeater list should be defined on jQuery object', function () { - ok($.fn.repeater.views.list, 'repeater list view is defined'); + ok($.fn.repeater.viewTypes.list, 'repeater list view is defined'); }); test('repeater thumbnail should be defined on jQuery object', function () { - ok($.fn.repeater.views.thumbnail, 'repeater thumbnail view is defined'); + ok($.fn.repeater.viewTypes.thumbnail, 'repeater thumbnail view is defined'); }); test('scheduler should be defined on the jQuery object', function () { diff --git a/test/repeater-list-test.js b/test/repeater-list-test.js index bb95deced..0ac8a679f 100644 --- a/test/repeater-list-test.js +++ b/test/repeater-list-test.js @@ -76,7 +76,7 @@ define(function(require){ }); test('should be defined on jquery object', function () { - ok($.fn.repeater.views.list, 'repeater-list view plugin is defined'); + ok($.fn.repeater.viewTypes.list, 'repeater-list view plugin is defined'); }); test('should render correctly', function () { diff --git a/test/repeater-test.js b/test/repeater-test.js index 8be936e9b..9361c57e1 100644 --- a/test/repeater-test.js +++ b/test/repeater-test.js @@ -17,16 +17,16 @@ define(function(require){ this.$markup = $(html); this.$markup.find('.repeater-views').append('' + '' + ''); }, teardown: function(){ - delete $.fn.repeater.views.test1; + delete $.fn.repeater.viewTypes.test1; } }); @@ -173,9 +173,9 @@ define(function(require){ $repeater.repeater({ dataSource: function(options, callback){ if(hasCalledDS){ - equal(options.view, 'test2', 'correct view value passed to dataSource upon selecting different view'); + equal(options.view, 'test2.view2', 'correct view value passed to dataSource upon selecting different view'); }else{ - equal(options.view, 'test1', 'correct view value passed to dataSource initially'); + equal(options.view, 'test1.view1', 'correct view value passed to dataSource initially'); hasCalledDS = true; callback({}); $views.find('label:last input').trigger('change'); @@ -190,7 +190,7 @@ define(function(require){ var $repeater = $(this.$markup); var repeated = false; var skipped = false; - $.fn.repeater.views.test1 = { + $.fn.repeater.viewTypes.test1 = { initialize: function(helpers, callback){ equal(ran, 0, 'initialize function correctly ran first'); equal(typeof helpers, 'object', 'initialize function provided helpers object'); @@ -278,6 +278,27 @@ define(function(require){ }); }); + test('views config option should function as expected', function(){ + var $repeater = $(this.$markup); + var $views = $repeater.find('.repeater-views'); + $repeater.repeater({ + views: { + view1: { + dataSource: function(options, callback){ + equal(options.view, 'test1.view1', 'view-specific configuration honored'); + } + }, + 'test2.view2': { + dataSource: function(options, callback){ + equal(options.view, 'test1.view1', 'view-specific configuration honored'); + callback({}); + $views.find('label:last input').trigger('change'); + } + } + } + }); + }); + asyncTest('should destroy control', function(){ var $repeater = $(this.$markup); diff --git a/test/repeater-thumbnail-test.js b/test/repeater-thumbnail-test.js index 57328370d..581f75c19 100644 --- a/test/repeater-thumbnail-test.js +++ b/test/repeater-thumbnail-test.js @@ -49,7 +49,7 @@ define(function(require){ }); test('should be defined on jquery object', function () { - ok($.fn.repeater.views.thumbnail, 'repeater-thumbnail view plugin is defined'); + ok($.fn.repeater.viewTypes.thumbnail, 'repeater-thumbnail view plugin is defined'); }); test('should render correctly', function(){