repeater.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. /*
  2. * Fuel UX Repeater
  3. * https://github.com/ExactTarget/fuelux
  4. *
  5. * Copyright (c) 2014 ExactTarget
  6. * Licensed under the BSD New license.
  7. */
  8. // -- BEGIN UMD WRAPPER PREFACE --
  9. // For more information on UMD visit:
  10. // https://github.com/umdjs/umd/blob/master/jqueryPlugin.js
  11. (function (factory) {
  12. if (typeof define === 'function' && define.amd) {
  13. // if AMD loader is available, register as an anonymous module.
  14. define(['jquery', 'fuelux/combobox', 'fuelux/infinite-scroll', 'fuelux/search', 'fuelux/selectlist'], factory);
  15. } else {
  16. // OR use browser globals if AMD is not present
  17. factory(jQuery);
  18. }
  19. }(function ($) {
  20. // -- END UMD WRAPPER PREFACE --
  21. // -- BEGIN MODULE CODE HERE --
  22. var old = $.fn.repeater;
  23. // REPEATER CONSTRUCTOR AND PROTOTYPE
  24. var Repeater = function (element, options) {
  25. var self = this;
  26. var $btn, currentView;
  27. this.$element = $(element);
  28. this.$canvas = this.$element.find('.repeater-canvas');
  29. this.$count = this.$element.find('.repeater-count');
  30. this.$end = this.$element.find('.repeater-end');
  31. this.$filters = this.$element.find('.repeater-filters');
  32. this.$loader = this.$element.find('.repeater-loader');
  33. this.$pageSize = this.$element.find('.repeater-itemization .selectlist');
  34. this.$nextBtn = this.$element.find('.repeater-next');
  35. this.$pages = this.$element.find('.repeater-pages');
  36. this.$prevBtn = this.$element.find('.repeater-prev');
  37. this.$primaryPaging = this.$element.find('.repeater-primaryPaging');
  38. this.$search = this.$element.find('.repeater-search').find('.search');
  39. this.$secondaryPaging = this.$element.find('.repeater-secondaryPaging');
  40. this.$start = this.$element.find('.repeater-start');
  41. this.$viewport = this.$element.find('.repeater-viewport');
  42. this.$views = this.$element.find('.repeater-views');
  43. this.currentPage = 0;
  44. this.currentView = null;
  45. this.infiniteScrollingCallback = function () {};
  46. this.infiniteScrollingCont = null;
  47. this.infiniteScrollingEnabled = false;
  48. this.infiniteScrollingEnd = null;
  49. this.infiniteScrollingOptions = {};
  50. this.lastPageInput = 0;
  51. this.options = $.extend({}, $.fn.repeater.defaults, options);
  52. this.pageIncrement = 0;// store direction navigated
  53. this.resizeTimeout = {};
  54. this.stamp = new Date().getTime() + (Math.floor(Math.random() * 100) + 1);
  55. this.storedDataSourceOpts = null;
  56. this.viewOptions = {};
  57. this.viewType = null;
  58. this.$filters.selectlist();
  59. this.$pageSize.selectlist();
  60. this.$primaryPaging.find('.combobox').combobox();
  61. this.$search.search();
  62. this.$filters.on('changed.fu.selectlist', function (e, value) {
  63. self.$element.trigger('filtered.fu.repeater', value);
  64. self.render({
  65. clearInfinite: true,
  66. pageIncrement: null
  67. });
  68. });
  69. this.$nextBtn.on('click.fu.repeater', $.proxy(this.next, this));
  70. this.$pageSize.on('changed.fu.selectlist', function (e, value) {
  71. self.$element.trigger('pageSizeChanged.fu.repeater', value);
  72. self.render({
  73. pageIncrement: null
  74. });
  75. });
  76. this.$prevBtn.on('click.fu.repeater', $.proxy(this.previous, this));
  77. this.$primaryPaging.find('.combobox').on('changed.fu.combobox', function (evt, data) {
  78. self.$element.trigger('pageChanged.fu.repeater', [data.text, data]);
  79. self.pageInputChange(data.text);
  80. });
  81. this.$search.on('searched.fu.search cleared.fu.search', function (e, value) {
  82. self.$element.trigger('searchChanged.fu.repeater', value);
  83. self.render({
  84. clearInfinite: true,
  85. pageIncrement: null
  86. });
  87. });
  88. this.$secondaryPaging.on('blur.fu.repeater', function (e) {
  89. self.pageInputChange(self.$secondaryPaging.val());
  90. });
  91. this.$secondaryPaging.on('keyup', function (e) {
  92. if (e.keyCode === 13) {
  93. self.pageInputChange(self.$secondaryPaging.val());
  94. }
  95. });
  96. this.$views.find('input').on('change.fu.repeater', $.proxy(this.viewChanged, this));
  97. // ID needed since event is bound to instance
  98. $(window).on('resize.fu.repeater.' + this.stamp, function (event) {
  99. clearTimeout(self.resizeTimeout);
  100. self.resizeTimeout = setTimeout(function () {
  101. self.resize();
  102. self.$element.trigger('resized.fu.repeater');
  103. }, 75);
  104. });
  105. this.$loader.loader();
  106. this.$loader.loader('pause');
  107. if (this.options.defaultView !== -1) {
  108. currentView = this.options.defaultView;
  109. } else {
  110. $btn = this.$views.find('label.active input');
  111. currentView = ($btn.length > 0) ? $btn.val() : 'list';
  112. }
  113. this.setViewOptions(currentView);
  114. this.initViewTypes(function () {
  115. self.resize();
  116. self.$element.trigger('resized.fu.repeater');
  117. self.render({
  118. changeView: currentView
  119. });
  120. });
  121. };
  122. Repeater.prototype = {
  123. constructor: Repeater,
  124. clear: function (options) {
  125. var viewChanged, viewTypeObj;
  126. function scan (cont) {
  127. var keep = [];
  128. cont.children().each(function () {
  129. var item = $(this);
  130. var pres = item.attr('data-preserve');
  131. if (pres === 'deep') {
  132. item.detach();
  133. keep.push(item);
  134. } else if (pres === 'shallow') {
  135. scan(item);
  136. item.detach();
  137. keep.push(item);
  138. }
  139. });
  140. cont.empty();
  141. cont.append(keep);
  142. }
  143. options = options || {};
  144. if (!options.preserve) {
  145. //Just trash everything because preserve is false
  146. this.$canvas.empty();
  147. } else if (!this.infiniteScrollingEnabled || options.clearInfinite) {
  148. //Preserve clear only if infiniteScrolling is disabled or if specifically told to do so
  149. scan(this.$canvas);
  150. } //Otherwise don't clear because infiniteScrolling is enabled
  151. //If viewChanged and current viewTypeObj has a cleared function, call it
  152. viewChanged = (options.viewChanged !== undefined) ? options.viewChanged : false;
  153. viewTypeObj = $.fn.repeater.viewTypes[this.viewType] || {};
  154. if (!viewChanged && viewTypeObj.cleared) {
  155. viewTypeObj.cleared.call(this, {
  156. options: options
  157. });
  158. }
  159. },
  160. clearPreservedDataSourceOptions: function () {
  161. this.storedDataSourceOpts = null;
  162. },
  163. destroy: function () {
  164. var markup;
  165. // set input value attrbute in markup
  166. this.$element.find('input').each(function () {
  167. $(this).attr('value', $(this).val());
  168. });
  169. // empty elements to return to original markup
  170. this.$canvas.empty();
  171. markup = this.$element[0].outerHTML;
  172. // destroy components and remove leftover
  173. this.$element.find('.combobox').combobox('destroy');
  174. this.$element.find('.selectlist').selectlist('destroy');
  175. this.$element.find('.search').search('destroy');
  176. if (this.infiniteScrollingEnabled) {
  177. $(this.infiniteScrollingCont).infinitescroll('destroy');
  178. }
  179. this.$element.remove();
  180. // any external events
  181. $(window).off('resize.fu.repeater.' + this.stamp);
  182. return markup;
  183. },
  184. getDataOptions: function (options) {
  185. var dataSourceOptions = {};
  186. var opts = {};
  187. var val, viewDataOpts;
  188. options = options || {};
  189. opts.filter = (this.$filters.length > 0) ? this.$filters.selectlist('selectedItem') : {
  190. text: 'All',
  191. value: 'all'
  192. };
  193. opts.view = this.currentView;
  194. if (!this.infiniteScrollingEnabled) {
  195. opts.pageSize = (this.$pageSize.length > 0) ? parseInt(this.$pageSize.selectlist('selectedItem').value, 10) : 25;
  196. }
  197. if (options.pageIncrement !== undefined) {
  198. if (options.pageIncrement === null) {
  199. this.currentPage = 0;
  200. } else {
  201. this.currentPage += options.pageIncrement;
  202. }
  203. }
  204. opts.pageIndex = this.currentPage;
  205. val = (this.$search.length > 0) ? this.$search.find('input').val() : '';
  206. if (val !== '') {
  207. opts.search = val;
  208. }
  209. if (options.dataSourceOptions) {
  210. dataSourceOptions = options.dataSourceOptions;
  211. if (options.preserveDataSourceOptions) {
  212. this.storedDataSourceOpts = (this.storedDataSourceOpts) ? $.extend(this.storedDataSourceOpts, dataSourceOptions) : dataSourceOptions;
  213. }
  214. }
  215. if (this.storedDataSourceOpts) {
  216. dataSourceOptions = $.extend(this.storedDataSourceOpts, dataSourceOptions);
  217. }
  218. viewDataOpts = $.fn.repeater.viewTypes[this.viewType] || {};
  219. viewDataOpts = viewDataOpts.dataOptions;
  220. if (viewDataOpts) {
  221. viewDataOpts = viewDataOpts.call(this, opts);
  222. opts = $.extend(viewDataOpts, dataSourceOptions);
  223. } else {
  224. opts = $.extend(opts, dataSourceOptions);
  225. }
  226. return opts;
  227. },
  228. infiniteScrolling: function (enable, options) {
  229. var itemization = this.$element.find('.repeater-itemization');
  230. var pagination = this.$element.find('.repeater-pagination');
  231. var cont, data;
  232. options = options || {};
  233. if (enable) {
  234. this.infiniteScrollingEnabled = true;
  235. this.infiniteScrollingEnd = options.end;
  236. delete options.dataSource;
  237. delete options.end;
  238. this.infiniteScrollingOptions = options;
  239. itemization.hide();
  240. pagination.hide();
  241. } else {
  242. cont = this.infiniteScrollingCont;
  243. data = cont.data();
  244. delete data.infinitescroll;
  245. cont.off('scroll');
  246. cont.removeClass('infinitescroll');
  247. this.infiniteScrollingCont = null;
  248. this.infiniteScrollingEnabled = false;
  249. this.infiniteScrollingEnd = null;
  250. this.infiniteScrollingOptions = {};
  251. itemization.show();
  252. pagination.show();
  253. }
  254. },
  255. infiniteScrollPaging: function (data, options) {
  256. var end = (this.infiniteScrollingEnd !== true) ? this.infiniteScrollingEnd : undefined;
  257. var page = data.page;
  258. var pages = data.pages;
  259. this.currentPage = (page !== undefined) ? page : NaN;
  260. if ((this.currentPage + 1) >= pages) {
  261. this.infiniteScrollingCont.infinitescroll('end', end);
  262. }
  263. },
  264. initInfiniteScrolling: function () {
  265. var cont = this.$canvas.find('[data-infinite="true"]:first');
  266. var opts, self;
  267. cont = (cont.length < 1) ? this.$canvas : cont;
  268. if (cont.data('fu.infinitescroll')) {
  269. cont.infinitescroll('enable');
  270. } else {
  271. self = this;
  272. opts = $.extend({}, this.infiniteScrollingOptions);
  273. opts.dataSource = function (helpers, callback) {
  274. self.infiniteScrollingCallback = callback;
  275. self.render({
  276. pageIncrement: 1
  277. });
  278. };
  279. cont.infinitescroll(opts);
  280. this.infiniteScrollingCont = cont;
  281. }
  282. },
  283. initViewTypes: function (callback) {
  284. var self = this;
  285. var viewTypes = [];
  286. var i, viewTypesLength;
  287. function init (index) {
  288. function next () {
  289. index++;
  290. if (index < viewTypesLength) {
  291. init(index);
  292. } else {
  293. callback();
  294. }
  295. }
  296. if (viewTypes[index].initialize) {
  297. viewTypes[index].initialize.call(self, {}, function () {
  298. next();
  299. });
  300. } else {
  301. next();
  302. }
  303. }
  304. for (i in $.fn.repeater.viewTypes) {
  305. viewTypes.push($.fn.repeater.viewTypes[i]);
  306. }
  307. viewTypesLength = viewTypes.length;
  308. if (viewTypesLength > 0) {
  309. init(0);
  310. } else {
  311. callback();
  312. }
  313. },
  314. itemization: function (data) {
  315. this.$count.html(data.count || '');
  316. this.$end.html(data.end || '');
  317. this.$start.html(data.start || '');
  318. },
  319. next: function (e) {
  320. var d = 'disabled';
  321. this.$nextBtn.attr(d, d);
  322. this.$prevBtn.attr(d, d);
  323. this.pageIncrement = 1;
  324. this.$element.trigger('nextClicked.fu.repeater');
  325. this.render({
  326. pageIncrement: this.pageIncrement
  327. });
  328. },
  329. pageInputChange: function (val) {
  330. var pageInc;
  331. if (val !== this.lastPageInput) {
  332. this.lastPageInput = val;
  333. val = parseInt(val, 10) - 1;
  334. pageInc = val - this.currentPage;
  335. this.$element.trigger('pageChanged.fu.repeater', val);
  336. this.render({
  337. pageIncrement: pageInc
  338. });
  339. }
  340. },
  341. pagination: function (data) {
  342. var act = 'active';
  343. var dsbl = 'disabled';
  344. var page = data.page;
  345. var pages = data.pages;
  346. var dropMenu, i, l;
  347. this.currentPage = (page !== undefined) ? page : NaN;
  348. this.$primaryPaging.removeClass(act);
  349. this.$secondaryPaging.removeClass(act);
  350. if (pages <= this.viewOptions.dropPagingCap) {
  351. this.$primaryPaging.addClass(act);
  352. dropMenu = this.$primaryPaging.find('.dropdown-menu');
  353. dropMenu.empty();
  354. for (i = 0; i < pages; i++) {
  355. l = i + 1;
  356. dropMenu.append('<li data-value="' + l + '"><a href="#">' + l + '</a></li>');
  357. }
  358. this.$primaryPaging.find('input.form-control').val(this.currentPage + 1);
  359. } else {
  360. this.$secondaryPaging.addClass(act);
  361. this.$secondaryPaging.val(this.currentPage + 1);
  362. }
  363. this.lastPageInput = this.currentPage + 1 + '';
  364. this.$pages.html(pages);
  365. // this is not the last page
  366. if ((this.currentPage + 1) < pages) {
  367. this.$nextBtn.removeAttr(dsbl);
  368. } else {
  369. this.$nextBtn.attr(dsbl, dsbl);
  370. }
  371. // this is not the first page
  372. if ((this.currentPage - 1) >= 0) {
  373. this.$prevBtn.removeAttr(dsbl);
  374. } else {
  375. this.$prevBtn.attr(dsbl, dsbl);
  376. }
  377. // return focus to next/previous buttons after navigating
  378. if (this.pageIncrement !== 0) {
  379. if (this.pageIncrement > 0) {
  380. if (this.$nextBtn.is(':disabled')) {
  381. // if you can't focus, go the other way
  382. this.$prevBtn.focus();
  383. } else {
  384. this.$nextBtn.focus();
  385. }
  386. } else {
  387. if (this.$prevBtn.is(':disabled')) {
  388. // if you can't focus, go the other way
  389. this.$nextBtn.focus();
  390. } else {
  391. this.$prevBtn.focus();
  392. }
  393. }
  394. }
  395. },
  396. previous: function () {
  397. var d = 'disabled';
  398. this.$nextBtn.attr(d, d);
  399. this.$prevBtn.attr(d, d);
  400. this.pageIncrement = -1;
  401. this.$element.trigger('previousClicked.fu.repeater');
  402. this.render({
  403. pageIncrement: this.pageIncrement
  404. });
  405. },
  406. render: function (options) {
  407. var self = this;
  408. var viewChanged = false;
  409. var viewTypeObj = $.fn.repeater.viewTypes[this.viewType] || {};
  410. var dataOptions, prevView;
  411. options = options || {};
  412. if (options.changeView && (this.currentView !== options.changeView)) {
  413. prevView = this.currentView;
  414. this.currentView = options.changeView;
  415. this.viewType = this.currentView.split('.')[0];
  416. this.setViewOptions(this.currentView);
  417. this.$element.attr('data-currentview', this.currentView);
  418. this.$element.attr('data-viewtype', this.viewType);
  419. viewChanged = true;
  420. options.viewChanged = viewChanged;
  421. this.$element.trigger('viewChanged.fu.repeater', this.currentView);
  422. if (this.infiniteScrollingEnabled) {
  423. self.infiniteScrolling(false);
  424. }
  425. viewTypeObj = $.fn.repeater.viewTypes[this.viewType] || {};
  426. if (viewTypeObj.selected) {
  427. viewTypeObj.selected.call(this, {
  428. prevView: prevView
  429. });
  430. }
  431. }
  432. options.preserve = (options.preserve !== undefined) ? options.preserve : !viewChanged;
  433. this.clear(options);
  434. if (!this.infiniteScrollingEnabled || (this.infiniteScrollingEnabled && viewChanged)) {
  435. this.$loader.show().loader('play');
  436. }
  437. dataOptions = this.getDataOptions(options);
  438. this.viewOptions.dataSource(dataOptions, function (data) {
  439. if (self.infiniteScrollingEnabled) {
  440. self.infiniteScrollingCallback({});
  441. } else {
  442. self.itemization(data);
  443. self.pagination(data);
  444. }
  445. self.runRenderer(viewTypeObj, data, function () {
  446. if (self.infiniteScrollingEnabled) {
  447. if (viewChanged || options.clearInfinite) {
  448. self.initInfiniteScrolling();
  449. }
  450. self.infiniteScrollPaging(data, options);
  451. }
  452. self.$loader.hide().loader('pause');
  453. self.$element.trigger('rendered.fu.repeater', {
  454. data: data,
  455. options: dataOptions,
  456. renderOptions: options
  457. });
  458. //for maintaining support of 'loaded' event
  459. self.$element.trigger('loaded.fu.repeater', dataOptions);
  460. });
  461. });
  462. },
  463. resize: function () {
  464. var staticHeight = (this.viewOptions.staticHeight === -1) ? this.$element.attr('data-staticheight') : this.viewOptions.staticHeight;
  465. var viewTypeObj = {};
  466. var height, viewportMargins;
  467. if (this.viewType) {
  468. viewTypeObj = $.fn.repeater.viewTypes[this.viewType] || {};
  469. }
  470. if (staticHeight !== undefined && staticHeight !== false && staticHeight !== 'false') {
  471. this.$canvas.addClass('scrolling');
  472. viewportMargins = {
  473. bottom: this.$viewport.css('margin-bottom'),
  474. top: this.$viewport.css('margin-top')
  475. };
  476. height = ((staticHeight === 'true' || staticHeight === true) ? this.$element.height() : parseInt(staticHeight, 10)) -
  477. this.$element.find('.repeater-header').outerHeight() -
  478. this.$element.find('.repeater-footer').outerHeight() -
  479. ((viewportMargins.bottom === 'auto') ? 0 : parseInt(viewportMargins.bottom, 10)) -
  480. ((viewportMargins.top === 'auto') ? 0 : parseInt(viewportMargins.top, 10));
  481. this.$viewport.outerHeight(height);
  482. } else {
  483. this.$canvas.removeClass('scrolling');
  484. }
  485. if (viewTypeObj.resize) {
  486. viewTypeObj.resize.call(this, {
  487. height: this.$element.outerHeight(),
  488. width: this.$element.outerWidth()
  489. });
  490. }
  491. },
  492. runRenderer: function (viewTypeObj, data, callback) {
  493. var $container, i, l, response, repeat, subset;
  494. function addItem ($parent, resp) {
  495. var action;
  496. if (resp) {
  497. action = (resp.action) ? resp.action : 'append';
  498. if (action !== 'none' && resp.item !== undefined) {
  499. $parent = (resp.container !== undefined) ? $(resp.container) : $parent;
  500. $parent[action](resp.item);
  501. }
  502. }
  503. }
  504. if (!viewTypeObj.render) {
  505. if (viewTypeObj.before) {
  506. response = viewTypeObj.before.call(this, {
  507. container: this.$canvas,
  508. data: data
  509. });
  510. addItem(this.$canvas, response);
  511. }
  512. $container = this.$canvas.find('[data-container="true"]:last');
  513. $container = ($container.length > 0) ? $container : this.$canvas;
  514. if (viewTypeObj.renderItem) {
  515. repeat = viewTypeObj.repeat || 'data.items';
  516. repeat = repeat.split('.');
  517. if (repeat[0] === 'data' || repeat[0] === 'this') {
  518. subset = (repeat[0] === 'this') ? this : data;
  519. repeat.shift();
  520. } else {
  521. repeat = [];
  522. subset = [];
  523. if (window.console && window.console.warn) {
  524. window.console.warn('WARNING: Repeater plugin "repeat" value must start with either "data" or "this"');
  525. }
  526. }
  527. for (i = 0, l = repeat.length; i < l; i++) {
  528. if (subset[repeat[i]] !== undefined){
  529. subset = subset[repeat[i]];
  530. } else {
  531. subset = [];
  532. if (window.console && window.console.warn) {
  533. window.console.warn('WARNING: Repeater unable to find property to iterate renderItem on.');
  534. }
  535. break;
  536. }
  537. }
  538. for (i = 0, l = subset.length; i < l; i++) {
  539. response = viewTypeObj.renderItem.call(this, {
  540. container: $container,
  541. data: data,
  542. index: i,
  543. subset: subset
  544. });
  545. addItem($container, response);
  546. }
  547. }
  548. if (viewTypeObj.after) {
  549. response = viewTypeObj.after.call(this, {
  550. container: this.$canvas,
  551. data: data
  552. });
  553. addItem(this.$canvas, response);
  554. }
  555. callback();
  556. } else {
  557. viewTypeObj.render.call(this, {
  558. container: this.$canvas,
  559. data: data
  560. }, function(){
  561. callback();
  562. });
  563. }
  564. },
  565. setViewOptions: function (curView) {
  566. var opts = {};
  567. var viewName = curView.split('.')[1];
  568. if (viewName && this.options.views) {
  569. opts = this.options.views[viewName] || this.options.views[curView] || {};
  570. } else {
  571. opts = {};
  572. }
  573. this.viewOptions = $.extend({}, this.options, opts);
  574. },
  575. viewChanged: function (e) {
  576. var $selected = $(e.target);
  577. var val = $selected.val();
  578. this.render({
  579. changeView: val,
  580. pageIncrement: null
  581. });
  582. }
  583. };
  584. // REPEATER PLUGIN DEFINITION
  585. $.fn.repeater = function (option) {
  586. var args = Array.prototype.slice.call(arguments, 1);
  587. var methodReturn;
  588. var $set = this.each(function () {
  589. var $this = $(this);
  590. var data = $this.data('fu.repeater');
  591. var options = typeof option === 'object' && option;
  592. if (!data) {
  593. $this.data('fu.repeater', (data = new Repeater(this, options)));
  594. }
  595. if (typeof option === 'string') {
  596. methodReturn = data[option].apply(data, args);
  597. }
  598. });
  599. return (methodReturn === undefined) ? $set : methodReturn;
  600. };
  601. $.fn.repeater.defaults = {
  602. dataSource: function (options, callback) {},
  603. defaultView: -1, //should be a string value. -1 means it will grab the active view from the view controls
  604. dropPagingCap: 10,
  605. staticHeight: -1, //normally true or false. -1 means it will look for data-staticheight on the element
  606. views: null //can be set to an object to configure multiple views of the same type
  607. };
  608. $.fn.repeater.viewTypes = {};
  609. $.fn.repeater.Constructor = Repeater;
  610. $.fn.repeater.noConflict = function () {
  611. $.fn.repeater = old;
  612. return this;
  613. };
  614. // -- BEGIN UMD WRAPPER AFTERWORD --
  615. }));
  616. // -- END UMD WRAPPER AFTERWORD --