list.js 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258
  1. (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  2. /*
  3. List.js 1.1.1
  4. By Jonny Strömberg (www.jonnystromberg.com, www.listjs.com)
  5. */
  6. (function( window, undefined ) {
  7. "use strict";
  8. var document = window.document,
  9. getByClass = require('./src/utils/get-by-class'),
  10. extend = require('./src/utils/extend'),
  11. indexOf = require('./src/utils/index-of'),
  12. events = require('./src/utils/events'),
  13. toString = require('./src/utils/to-string'),
  14. naturalSort = require('./src/utils/natural-sort'),
  15. classes = require('./src/utils/classes'),
  16. getAttribute = require('./src/utils/get-attribute'),
  17. toArray = require('./src/utils/to-array');
  18. var List = function(id, options, values) {
  19. var self = this,
  20. init,
  21. Item = require('./src/item')(self),
  22. addAsync = require('./src/add-async')(self);
  23. init = {
  24. start: function() {
  25. self.listClass = "list";
  26. self.searchClass = "search";
  27. self.sortClass = "sort";
  28. self.page = 10000;
  29. self.i = 1;
  30. self.items = [];
  31. self.visibleItems = [];
  32. self.matchingItems = [];
  33. self.searched = false;
  34. self.filtered = false;
  35. self.searchColumns = undefined;
  36. self.handlers = { 'updated': [] };
  37. self.plugins = {};
  38. self.valueNames = [];
  39. self.utils = {
  40. getByClass: getByClass,
  41. extend: extend,
  42. indexOf: indexOf,
  43. events: events,
  44. toString: toString,
  45. naturalSort: naturalSort,
  46. classes: classes,
  47. getAttribute: getAttribute,
  48. toArray: toArray
  49. };
  50. self.utils.extend(self, options);
  51. self.listContainer = (typeof(id) === 'string') ? document.getElementById(id) : id;
  52. if (!self.listContainer) { return; }
  53. self.list = getByClass(self.listContainer, self.listClass, true);
  54. self.parse = require('./src/parse')(self);
  55. self.templater = require('./src/templater')(self);
  56. self.search = require('./src/search')(self);
  57. self.filter = require('./src/filter')(self);
  58. self.sort = require('./src/sort')(self);
  59. this.handlers();
  60. this.items();
  61. self.update();
  62. this.plugins();
  63. },
  64. handlers: function() {
  65. for (var handler in self.handlers) {
  66. if (self[handler]) {
  67. self.on(handler, self[handler]);
  68. }
  69. }
  70. },
  71. items: function() {
  72. self.parse(self.list);
  73. if (values !== undefined) {
  74. self.add(values);
  75. }
  76. },
  77. plugins: function() {
  78. for (var i = 0; i < self.plugins.length; i++) {
  79. var plugin = self.plugins[i];
  80. self[plugin.name] = plugin;
  81. plugin.init(self, List);
  82. }
  83. }
  84. };
  85. /*
  86. * Re-parse the List, use if html have changed
  87. */
  88. this.reIndex = function() {
  89. self.items = [];
  90. self.visibleItems = [];
  91. self.matchingItems = [];
  92. self.searched = false;
  93. self.filtered = false;
  94. self.parse(self.list);
  95. };
  96. this.toJSON = function() {
  97. var json = [];
  98. for (var i = 0, il = self.items.length; i < il; i++) {
  99. json.push(self.items[i].values());
  100. }
  101. return json;
  102. };
  103. /*
  104. * Add object to list
  105. */
  106. this.add = function(values, callback) {
  107. if (values.length === 0) {
  108. return;
  109. }
  110. if (callback) {
  111. addAsync(values, callback);
  112. return;
  113. }
  114. var added = [],
  115. notCreate = false;
  116. if (values[0] === undefined){
  117. values = [values];
  118. }
  119. for (var i = 0, il = values.length; i < il; i++) {
  120. var item = null;
  121. notCreate = (self.items.length > self.page) ? true : false;
  122. item = new Item(values[i], undefined, notCreate);
  123. self.items.push(item);
  124. added.push(item);
  125. }
  126. self.update();
  127. return added;
  128. };
  129. this.show = function(i, page) {
  130. this.i = i;
  131. this.page = page;
  132. self.update();
  133. return self;
  134. };
  135. /* Removes object from list.
  136. * Loops through the list and removes objects where
  137. * property "valuename" === value
  138. */
  139. this.remove = function(valueName, value, options) {
  140. var found = 0;
  141. for (var i = 0, il = self.items.length; i < il; i++) {
  142. if (self.items[i].values()[valueName] == value) {
  143. self.templater.remove(self.items[i], options);
  144. self.items.splice(i,1);
  145. il--;
  146. i--;
  147. found++;
  148. }
  149. }
  150. self.update();
  151. return found;
  152. };
  153. /* Gets the objects in the list which
  154. * property "valueName" === value
  155. */
  156. this.get = function(valueName, value) {
  157. var matchedItems = [];
  158. for (var i = 0, il = self.items.length; i < il; i++) {
  159. var item = self.items[i];
  160. if (item.values()[valueName] == value) {
  161. matchedItems.push(item);
  162. }
  163. }
  164. return matchedItems;
  165. };
  166. /*
  167. * Get size of the list
  168. */
  169. this.size = function() {
  170. return self.items.length;
  171. };
  172. /*
  173. * Removes all items from the list
  174. */
  175. this.clear = function() {
  176. self.templater.clear();
  177. self.items = [];
  178. return self;
  179. };
  180. this.on = function(event, callback) {
  181. self.handlers[event].push(callback);
  182. return self;
  183. };
  184. this.off = function(event, callback) {
  185. var e = self.handlers[event];
  186. var index = indexOf(e, callback);
  187. if (index > -1) {
  188. e.splice(index, 1);
  189. }
  190. return self;
  191. };
  192. this.trigger = function(event) {
  193. var i = self.handlers[event].length;
  194. while(i--) {
  195. self.handlers[event][i](self);
  196. }
  197. return self;
  198. };
  199. this.reset = {
  200. filter: function() {
  201. var is = self.items,
  202. il = is.length;
  203. while (il--) {
  204. is[il].filtered = false;
  205. }
  206. return self;
  207. },
  208. search: function() {
  209. var is = self.items,
  210. il = is.length;
  211. while (il--) {
  212. is[il].found = false;
  213. }
  214. return self;
  215. }
  216. };
  217. this.update = function() {
  218. var is = self.items,
  219. il = is.length;
  220. self.visibleItems = [];
  221. self.matchingItems = [];
  222. self.templater.clear();
  223. for (var i = 0; i < il; i++) {
  224. if (is[i].matching() && ((self.matchingItems.length+1) >= self.i && self.visibleItems.length < self.page)) {
  225. is[i].show();
  226. self.visibleItems.push(is[i]);
  227. self.matchingItems.push(is[i]);
  228. } else if (is[i].matching()) {
  229. self.matchingItems.push(is[i]);
  230. is[i].hide();
  231. } else {
  232. is[i].hide();
  233. }
  234. }
  235. self.trigger('updated');
  236. return self;
  237. };
  238. init.start();
  239. };
  240. // AMD support
  241. if (typeof define === 'function' && define.amd) {
  242. define(function () { return List; });
  243. }
  244. module.exports = List;
  245. window.List = List;
  246. })(window);
  247. },{"./src/add-async":2,"./src/filter":3,"./src/item":4,"./src/parse":5,"./src/search":6,"./src/sort":7,"./src/templater":8,"./src/utils/classes":9,"./src/utils/events":10,"./src/utils/extend":11,"./src/utils/get-attribute":12,"./src/utils/get-by-class":13,"./src/utils/index-of":14,"./src/utils/natural-sort":15,"./src/utils/to-array":16,"./src/utils/to-string":17}],2:[function(require,module,exports){
  248. module.exports = function(list) {
  249. var addAsync = function(values, callback, items) {
  250. var valuesToAdd = values.splice(0, 50);
  251. items = items || [];
  252. items = items.concat(list.add(valuesToAdd));
  253. if (values.length > 0) {
  254. setTimeout(function() {
  255. addAsync(values, callback, items);
  256. }, 1);
  257. } else {
  258. list.update();
  259. callback(items);
  260. }
  261. };
  262. return addAsync;
  263. };
  264. },{}],3:[function(require,module,exports){
  265. module.exports = function(list) {
  266. // Add handlers
  267. list.handlers.filterStart = list.handlers.filterStart || [];
  268. list.handlers.filterComplete = list.handlers.filterComplete || [];
  269. return function(filterFunction) {
  270. list.trigger('filterStart');
  271. list.i = 1; // Reset paging
  272. list.reset.filter();
  273. if (filterFunction === undefined) {
  274. list.filtered = false;
  275. } else {
  276. list.filtered = true;
  277. var is = list.items;
  278. for (var i = 0, il = is.length; i < il; i++) {
  279. var item = is[i];
  280. if (filterFunction(item)) {
  281. item.filtered = true;
  282. } else {
  283. item.filtered = false;
  284. }
  285. }
  286. }
  287. list.update();
  288. list.trigger('filterComplete');
  289. return list.visibleItems;
  290. };
  291. };
  292. },{}],4:[function(require,module,exports){
  293. module.exports = function(list) {
  294. return function(initValues, element, notCreate) {
  295. var item = this;
  296. this._values = {};
  297. this.found = false; // Show if list.searched == true and this.found == true
  298. this.filtered = false;// Show if list.filtered == true and this.filtered == true
  299. var init = function(initValues, element, notCreate) {
  300. if (element === undefined) {
  301. if (notCreate) {
  302. item.values(initValues, notCreate);
  303. } else {
  304. item.values(initValues);
  305. }
  306. } else {
  307. item.elm = element;
  308. var values = list.templater.get(item, initValues);
  309. item.values(values);
  310. }
  311. };
  312. this.values = function(newValues, notCreate) {
  313. if (newValues !== undefined) {
  314. for(var name in newValues) {
  315. item._values[name] = newValues[name];
  316. }
  317. if (notCreate !== true) {
  318. list.templater.set(item, item.values());
  319. }
  320. } else {
  321. return item._values;
  322. }
  323. };
  324. this.show = function() {
  325. list.templater.show(item);
  326. };
  327. this.hide = function() {
  328. list.templater.hide(item);
  329. };
  330. this.matching = function() {
  331. return (
  332. (list.filtered && list.searched && item.found && item.filtered) ||
  333. (list.filtered && !list.searched && item.filtered) ||
  334. (!list.filtered && list.searched && item.found) ||
  335. (!list.filtered && !list.searched)
  336. );
  337. };
  338. this.visible = function() {
  339. return (item.elm && (item.elm.parentNode == list.list)) ? true : false;
  340. };
  341. init(initValues, element, notCreate);
  342. };
  343. };
  344. },{}],5:[function(require,module,exports){
  345. module.exports = function(list) {
  346. var Item = require('./item')(list);
  347. var getChildren = function(parent) {
  348. var nodes = parent.childNodes,
  349. items = [];
  350. for (var i = 0, il = nodes.length; i < il; i++) {
  351. // Only textnodes have a data attribute
  352. if (nodes[i].data === undefined) {
  353. items.push(nodes[i]);
  354. }
  355. }
  356. return items;
  357. };
  358. var parse = function(itemElements, valueNames) {
  359. for (var i = 0, il = itemElements.length; i < il; i++) {
  360. list.items.push(new Item(valueNames, itemElements[i]));
  361. }
  362. };
  363. var parseAsync = function(itemElements, valueNames) {
  364. var itemsToIndex = itemElements.splice(0, 50); // TODO: If < 100 items, what happens in IE etc?
  365. parse(itemsToIndex, valueNames);
  366. if (itemElements.length > 0) {
  367. setTimeout(function() {
  368. parseAsync(itemElements, valueNames);
  369. }, 1);
  370. } else {
  371. list.update();
  372. list.trigger('parseComplete');
  373. }
  374. };
  375. list.handlers.parseComplete = list.handlers.parseComplete || [];
  376. return function() {
  377. var itemsToIndex = getChildren(list.list),
  378. valueNames = list.valueNames;
  379. if (list.indexAsync) {
  380. parseAsync(itemsToIndex, valueNames);
  381. } else {
  382. parse(itemsToIndex, valueNames);
  383. }
  384. };
  385. };
  386. },{"./item":4}],6:[function(require,module,exports){
  387. module.exports = function(list) {
  388. var item,
  389. text,
  390. columns,
  391. searchString,
  392. customSearch;
  393. var prepare = {
  394. resetList: function() {
  395. list.i = 1;
  396. list.templater.clear();
  397. customSearch = undefined;
  398. },
  399. setOptions: function(args) {
  400. if (args.length == 2 && args[1] instanceof Array) {
  401. columns = args[1];
  402. } else if (args.length == 2 && typeof(args[1]) == "function") {
  403. customSearch = args[1];
  404. } else if (args.length == 3) {
  405. columns = args[1];
  406. customSearch = args[2];
  407. }
  408. },
  409. setColumns: function() {
  410. if (list.items.length === 0) return;
  411. if (columns === undefined) {
  412. columns = (list.searchColumns === undefined) ? prepare.toArray(list.items[0].values()) : list.searchColumns;
  413. }
  414. },
  415. setSearchString: function(s) {
  416. s = list.utils.toString(s).toLowerCase();
  417. s = s.replace(/[-[\]{}()*+?.,\\^$|#]/g, "\\$&"); // Escape regular expression characters
  418. searchString = s;
  419. },
  420. toArray: function(values) {
  421. var tmpColumn = [];
  422. for (var name in values) {
  423. tmpColumn.push(name);
  424. }
  425. return tmpColumn;
  426. }
  427. };
  428. var search = {
  429. list: function() {
  430. for (var k = 0, kl = list.items.length; k < kl; k++) {
  431. search.item(list.items[k]);
  432. }
  433. },
  434. item: function(item) {
  435. item.found = false;
  436. for (var j = 0, jl = columns.length; j < jl; j++) {
  437. if (search.values(item.values(), columns[j])) {
  438. item.found = true;
  439. return;
  440. }
  441. }
  442. },
  443. values: function(values, column) {
  444. if (values.hasOwnProperty(column)) {
  445. text = list.utils.toString(values[column]).toLowerCase();
  446. if ((searchString !== "") && (text.search(searchString) > -1)) {
  447. return true;
  448. }
  449. }
  450. return false;
  451. },
  452. reset: function() {
  453. list.reset.search();
  454. list.searched = false;
  455. }
  456. };
  457. var searchMethod = function(str) {
  458. list.trigger('searchStart');
  459. prepare.resetList();
  460. prepare.setSearchString(str);
  461. prepare.setOptions(arguments); // str, cols|searchFunction, searchFunction
  462. prepare.setColumns();
  463. if (searchString === "" ) {
  464. search.reset();
  465. } else {
  466. list.searched = true;
  467. if (customSearch) {
  468. customSearch(searchString, columns);
  469. } else {
  470. search.list();
  471. }
  472. }
  473. list.update();
  474. list.trigger('searchComplete');
  475. return list.visibleItems;
  476. };
  477. list.handlers.searchStart = list.handlers.searchStart || [];
  478. list.handlers.searchComplete = list.handlers.searchComplete || [];
  479. list.utils.events.bind(list.utils.getByClass(list.listContainer, list.searchClass), 'keyup', function(e) {
  480. var target = e.target || e.srcElement, // IE have srcElement
  481. alreadyCleared = (target.value === "" && !list.searched);
  482. if (!alreadyCleared) { // If oninput already have resetted the list, do nothing
  483. searchMethod(target.value);
  484. }
  485. });
  486. // Used to detect click on HTML5 clear button
  487. list.utils.events.bind(list.utils.getByClass(list.listContainer, list.searchClass), 'input', function(e) {
  488. var target = e.target || e.srcElement;
  489. if (target.value === "") {
  490. searchMethod('');
  491. }
  492. });
  493. return searchMethod;
  494. };
  495. },{}],7:[function(require,module,exports){
  496. module.exports = function(list) {
  497. list.sortFunction = list.sortFunction || function(itemA, itemB, options) {
  498. options.desc = options.order == "desc" ? true : false; // Natural sort uses this format
  499. return list.utils.naturalSort(itemA.values()[options.valueName], itemB.values()[options.valueName], options);
  500. };
  501. var buttons = {
  502. els: undefined,
  503. clear: function() {
  504. for (var i = 0, il = buttons.els.length; i < il; i++) {
  505. list.utils.classes(buttons.els[i]).remove('asc');
  506. list.utils.classes(buttons.els[i]).remove('desc');
  507. }
  508. },
  509. getOrder: function(btn) {
  510. var predefinedOrder = list.utils.getAttribute(btn, 'data-order');
  511. if (predefinedOrder == "asc" || predefinedOrder == "desc") {
  512. return predefinedOrder;
  513. } else if (list.utils.classes(btn).has('desc')) {
  514. return "asc";
  515. } else if (list.utils.classes(btn).has('asc')) {
  516. return "desc";
  517. } else {
  518. return "asc";
  519. }
  520. },
  521. getInSensitive: function(btn, options) {
  522. var insensitive = list.utils.getAttribute(btn, 'data-insensitive');
  523. if (insensitive === "false") {
  524. options.insensitive = false;
  525. } else {
  526. options.insensitive = true;
  527. }
  528. },
  529. setOrder: function(options) {
  530. for (var i = 0, il = buttons.els.length; i < il; i++) {
  531. var btn = buttons.els[i];
  532. if (list.utils.getAttribute(btn, 'data-sort') !== options.valueName) {
  533. continue;
  534. }
  535. var predefinedOrder = list.utils.getAttribute(btn, 'data-order');
  536. if (predefinedOrder == "asc" || predefinedOrder == "desc") {
  537. if (predefinedOrder == options.order) {
  538. list.utils.classes(btn).add(options.order);
  539. }
  540. } else {
  541. list.utils.classes(btn).add(options.order);
  542. }
  543. }
  544. }
  545. };
  546. var sort = function() {
  547. list.trigger('sortStart');
  548. var options = {};
  549. var target = arguments[0].currentTarget || arguments[0].srcElement || undefined;
  550. if (target) {
  551. options.valueName = list.utils.getAttribute(target, 'data-sort');
  552. buttons.getInSensitive(target, options);
  553. options.order = buttons.getOrder(target);
  554. } else {
  555. options = arguments[1] || options;
  556. options.valueName = arguments[0];
  557. options.order = options.order || "asc";
  558. options.insensitive = (typeof options.insensitive == "undefined") ? true : options.insensitive;
  559. }
  560. buttons.clear();
  561. buttons.setOrder(options);
  562. options.sortFunction = options.sortFunction || list.sortFunction;
  563. list.items.sort(function(a, b) {
  564. var mult = (options.order === 'desc') ? -1 : 1;
  565. return (options.sortFunction(a, b, options) * mult);
  566. });
  567. list.update();
  568. list.trigger('sortComplete');
  569. };
  570. // Add handlers
  571. list.handlers.sortStart = list.handlers.sortStart || [];
  572. list.handlers.sortComplete = list.handlers.sortComplete || [];
  573. buttons.els = list.utils.getByClass(list.listContainer, list.sortClass);
  574. list.utils.events.bind(buttons.els, 'click', sort);
  575. list.on('searchStart', buttons.clear);
  576. list.on('filterStart', buttons.clear);
  577. return sort;
  578. };
  579. },{}],8:[function(require,module,exports){
  580. var Templater = function(list) {
  581. var itemSource,
  582. templater = this;
  583. var init = function() {
  584. itemSource = templater.getItemSource(list.item);
  585. itemSource = templater.clearSourceItem(itemSource, list.valueNames);
  586. };
  587. this.clearSourceItem = function(el, valueNames) {
  588. for(var i = 0, il = valueNames.length; i < il; i++) {
  589. var elm;
  590. if (valueNames[i].data) {
  591. for (var j = 0, jl = valueNames[i].data.length; j < jl; j++) {
  592. el.setAttribute('data-'+valueNames[i].data[j], '');
  593. }
  594. } else if (valueNames[i].attr && valueNames[i].name) {
  595. elm = list.utils.getByClass(el, valueNames[i].name, true);
  596. if (elm) {
  597. elm.setAttribute(valueNames[i].attr, "");
  598. }
  599. } else {
  600. elm = list.utils.getByClass(el, valueNames[i], true);
  601. if (elm) {
  602. elm.innerHTML = "";
  603. }
  604. }
  605. elm = undefined;
  606. }
  607. return el;
  608. };
  609. this.getItemSource = function(item) {
  610. if (item === undefined) {
  611. var nodes = list.list.childNodes,
  612. items = [];
  613. for (var i = 0, il = nodes.length; i < il; i++) {
  614. // Only textnodes have a data attribute
  615. if (nodes[i].data === undefined) {
  616. return nodes[i].cloneNode(true);
  617. }
  618. }
  619. } else if (/^tr[\s>]/.exec(item)) {
  620. var table = document.createElement('table');
  621. table.innerHTML = item;
  622. return table.firstChild;
  623. } else if (item.indexOf("<") !== -1) {
  624. var div = document.createElement('div');
  625. div.innerHTML = item;
  626. return div.firstChild;
  627. } else {
  628. var source = document.getElementById(list.item);
  629. if (source) {
  630. return source;
  631. }
  632. }
  633. throw new Error("The list need to have at list one item on init otherwise you'll have to add a template.");
  634. };
  635. this.get = function(item, valueNames) {
  636. templater.create(item);
  637. var values = {};
  638. for(var i = 0, il = valueNames.length; i < il; i++) {
  639. var elm;
  640. if (valueNames[i].data) {
  641. for (var j = 0, jl = valueNames[i].data.length; j < jl; j++) {
  642. values[valueNames[i].data[j]] = list.utils.getAttribute(item.elm, 'data-'+valueNames[i].data[j]);
  643. }
  644. } else if (valueNames[i].attr && valueNames[i].name) {
  645. elm = list.utils.getByClass(item.elm, valueNames[i].name, true);
  646. values[valueNames[i].name] = elm ? list.utils.getAttribute(elm, valueNames[i].attr) : "";
  647. } else {
  648. elm = list.utils.getByClass(item.elm, valueNames[i], true);
  649. values[valueNames[i]] = elm ? elm.innerHTML : "";
  650. }
  651. elm = undefined;
  652. }
  653. return values;
  654. };
  655. this.set = function(item, values) {
  656. var getValueName = function(name) {
  657. for (var i = 0, il = list.valueNames.length; i < il; i++) {
  658. if (list.valueNames[i].data) {
  659. var data = list.valueNames[i].data;
  660. for (var j = 0, jl = data.length; j < jl; j++) {
  661. if (data[j] === name) {
  662. return { data: name };
  663. }
  664. }
  665. } else if (list.valueNames[i].attr && list.valueNames[i].name && list.valueNames[i].name == name) {
  666. return list.valueNames[i];
  667. } else if (list.valueNames[i] === name) {
  668. return name;
  669. }
  670. }
  671. };
  672. var setValue = function(name, value) {
  673. var elm;
  674. var valueName = getValueName(name);
  675. if (!valueName)
  676. return;
  677. if (valueName.data) {
  678. item.elm.setAttribute('data-'+valueName.data, value);
  679. } else if (valueName.attr && valueName.name) {
  680. elm = list.utils.getByClass(item.elm, valueName.name, true);
  681. if (elm) {
  682. elm.setAttribute(valueName.attr, value);
  683. }
  684. } else {
  685. elm = list.utils.getByClass(item.elm, valueName, true);
  686. if (elm) {
  687. elm.innerHTML = value;
  688. }
  689. }
  690. elm = undefined;
  691. };
  692. if (!templater.create(item)) {
  693. for(var v in values) {
  694. if (values.hasOwnProperty(v)) {
  695. setValue(v, values[v]);
  696. }
  697. }
  698. }
  699. };
  700. this.create = function(item) {
  701. if (item.elm !== undefined) {
  702. return false;
  703. }
  704. /* If item source does not exists, use the first item in list as
  705. source for new items */
  706. var newItem = itemSource.cloneNode(true);
  707. newItem.removeAttribute('id');
  708. item.elm = newItem;
  709. templater.set(item, item.values());
  710. return true;
  711. };
  712. this.remove = function(item) {
  713. if (item.elm.parentNode === list.list) {
  714. list.list.removeChild(item.elm);
  715. }
  716. };
  717. this.show = function(item) {
  718. templater.create(item);
  719. list.list.appendChild(item.elm);
  720. };
  721. this.hide = function(item) {
  722. if (item.elm !== undefined && item.elm.parentNode === list.list) {
  723. list.list.removeChild(item.elm);
  724. }
  725. };
  726. this.clear = function() {
  727. /* .innerHTML = ''; fucks up IE */
  728. if (list.list.hasChildNodes()) {
  729. while (list.list.childNodes.length >= 1)
  730. {
  731. list.list.removeChild(list.list.firstChild);
  732. }
  733. }
  734. };
  735. init();
  736. };
  737. module.exports = function(list) {
  738. return new Templater(list);
  739. };
  740. },{}],9:[function(require,module,exports){
  741. /**
  742. * Module dependencies.
  743. */
  744. var index = require('./index-of');
  745. /**
  746. * Whitespace regexp.
  747. */
  748. var re = /\s+/;
  749. /**
  750. * toString reference.
  751. */
  752. var toString = Object.prototype.toString;
  753. /**
  754. * Wrap `el` in a `ClassList`.
  755. *
  756. * @param {Element} el
  757. * @return {ClassList}
  758. * @api public
  759. */
  760. module.exports = function(el){
  761. return new ClassList(el);
  762. };
  763. /**
  764. * Initialize a new ClassList for `el`.
  765. *
  766. * @param {Element} el
  767. * @api private
  768. */
  769. function ClassList(el) {
  770. if (!el || !el.nodeType) {
  771. throw new Error('A DOM element reference is required');
  772. }
  773. this.el = el;
  774. this.list = el.classList;
  775. }
  776. /**
  777. * Add class `name` if not already present.
  778. *
  779. * @param {String} name
  780. * @return {ClassList}
  781. * @api public
  782. */
  783. ClassList.prototype.add = function(name){
  784. // classList
  785. if (this.list) {
  786. this.list.add(name);
  787. return this;
  788. }
  789. // fallback
  790. var arr = this.array();
  791. var i = index(arr, name);
  792. if (!~i) arr.push(name);
  793. this.el.className = arr.join(' ');
  794. return this;
  795. };
  796. /**
  797. * Remove class `name` when present, or
  798. * pass a regular expression to remove
  799. * any which match.
  800. *
  801. * @param {String|RegExp} name
  802. * @return {ClassList}
  803. * @api public
  804. */
  805. ClassList.prototype.remove = function(name){
  806. if ('[object RegExp]' == toString.call(name)) {
  807. return this.removeMatching(name);
  808. }
  809. // classList
  810. if (this.list) {
  811. this.list.remove(name);
  812. return this;
  813. }
  814. // fallback
  815. var arr = this.array();
  816. var i = index(arr, name);
  817. if (~i) arr.splice(i, 1);
  818. this.el.className = arr.join(' ');
  819. return this;
  820. };
  821. /**
  822. * Remove all classes matching `re`.
  823. *
  824. * @param {RegExp} re
  825. * @return {ClassList}
  826. * @api private
  827. */
  828. ClassList.prototype.removeMatching = function(re){
  829. var arr = this.array();
  830. for (var i = 0; i < arr.length; i++) {
  831. if (re.test(arr[i])) {
  832. this.remove(arr[i]);
  833. }
  834. }
  835. return this;
  836. };
  837. /**
  838. * Toggle class `name`, can force state via `force`.
  839. *
  840. * For browsers that support classList, but do not support `force` yet,
  841. * the mistake will be detected and corrected.
  842. *
  843. * @param {String} name
  844. * @param {Boolean} force
  845. * @return {ClassList}
  846. * @api public
  847. */
  848. ClassList.prototype.toggle = function(name, force){
  849. // classList
  850. if (this.list) {
  851. if ("undefined" !== typeof force) {
  852. if (force !== this.list.toggle(name, force)) {
  853. this.list.toggle(name); // toggle again to correct
  854. }
  855. } else {
  856. this.list.toggle(name);
  857. }
  858. return this;
  859. }
  860. // fallback
  861. if ("undefined" !== typeof force) {
  862. if (!force) {
  863. this.remove(name);
  864. } else {
  865. this.add(name);
  866. }
  867. } else {
  868. if (this.has(name)) {
  869. this.remove(name);
  870. } else {
  871. this.add(name);
  872. }
  873. }
  874. return this;
  875. };
  876. /**
  877. * Return an array of classes.
  878. *
  879. * @return {Array}
  880. * @api public
  881. */
  882. ClassList.prototype.array = function(){
  883. var className = this.el.getAttribute('class') || '';
  884. var str = className.replace(/^\s+|\s+$/g, '');
  885. var arr = str.split(re);
  886. if ('' === arr[0]) arr.shift();
  887. return arr;
  888. };
  889. /**
  890. * Check if class `name` is present.
  891. *
  892. * @param {String} name
  893. * @return {ClassList}
  894. * @api public
  895. */
  896. ClassList.prototype.has =
  897. ClassList.prototype.contains = function(name){
  898. return this.list ? this.list.contains(name) : !! ~index(this.array(), name);
  899. };
  900. },{"./index-of":14}],10:[function(require,module,exports){
  901. var bind = window.addEventListener ? 'addEventListener' : 'attachEvent',
  902. unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent',
  903. prefix = bind !== 'addEventListener' ? 'on' : '',
  904. toArray = require('./to-array');
  905. /**
  906. * Bind `el` event `type` to `fn`.
  907. *
  908. * @param {Element} el, NodeList, HTMLCollection or Array
  909. * @param {String} type
  910. * @param {Function} fn
  911. * @param {Boolean} capture
  912. * @api public
  913. */
  914. exports.bind = function(el, type, fn, capture){
  915. el = toArray(el);
  916. for ( var i = 0; i < el.length; i++ ) {
  917. el[i][bind](prefix + type, fn, capture || false);
  918. }
  919. };
  920. /**
  921. * Unbind `el` event `type`'s callback `fn`.
  922. *
  923. * @param {Element} el, NodeList, HTMLCollection or Array
  924. * @param {String} type
  925. * @param {Function} fn
  926. * @param {Boolean} capture
  927. * @api public
  928. */
  929. exports.unbind = function(el, type, fn, capture){
  930. el = toArray(el);
  931. for ( var i = 0; i < el.length; i++ ) {
  932. el[i][unbind](prefix + type, fn, capture || false);
  933. }
  934. };
  935. },{"./to-array":16}],11:[function(require,module,exports){
  936. /*
  937. * Source: https://github.com/segmentio/extend
  938. */
  939. module.exports = function extend (object) {
  940. // Takes an unlimited number of extenders.
  941. var args = Array.prototype.slice.call(arguments, 1);
  942. // For each extender, copy their properties on our object.
  943. for (var i = 0, source; source = args[i]; i++) {
  944. if (!source) continue;
  945. for (var property in source) {
  946. object[property] = source[property];
  947. }
  948. }
  949. return object;
  950. };
  951. },{}],12:[function(require,module,exports){
  952. /**
  953. * A cross-browser implementation of getAttribute.
  954. * Source found here: http://stackoverflow.com/a/3755343/361337 written by Vivin Paliath
  955. *
  956. * Return the value for `attr` at `element`.
  957. *
  958. * @param {Element} el
  959. * @param {String} attr
  960. * @api public
  961. */
  962. module.exports = function(el, attr) {
  963. var result = (el.getAttribute && el.getAttribute(attr)) || null;
  964. if( !result ) {
  965. var attrs = el.attributes;
  966. var length = attrs.length;
  967. for(var i = 0; i < length; i++) {
  968. if (attr[i] !== undefined) {
  969. if(attr[i].nodeName === attr) {
  970. result = attr[i].nodeValue;
  971. }
  972. }
  973. }
  974. }
  975. return result;
  976. };
  977. },{}],13:[function(require,module,exports){
  978. /**
  979. * A cross-browser implementation of getElementsByClass.
  980. * Heavily based on Dustin Diaz's function: http://dustindiaz.com/getelementsbyclass.
  981. *
  982. * Find all elements with class `className` inside `container`.
  983. * Use `single = true` to increase performance in older browsers
  984. * when only one element is needed.
  985. *
  986. * @param {String} className
  987. * @param {Element} container
  988. * @param {Boolean} single
  989. * @api public
  990. */
  991. module.exports = (function() {
  992. if (document.getElementsByClassName) {
  993. return function(container, className, single) {
  994. if (single) {
  995. return container.getElementsByClassName(className)[0];
  996. } else {
  997. return container.getElementsByClassName(className);
  998. }
  999. };
  1000. } else if (document.querySelector) {
  1001. return function(container, className, single) {
  1002. className = '.' + className;
  1003. if (single) {
  1004. return container.querySelector(className);
  1005. } else {
  1006. return container.querySelectorAll(className);
  1007. }
  1008. };
  1009. } else {
  1010. return function(container, className, single) {
  1011. var classElements = [],
  1012. tag = '*';
  1013. if (container === null) {
  1014. container = document;
  1015. }
  1016. var els = container.getElementsByTagName(tag);
  1017. var elsLen = els.length;
  1018. var pattern = new RegExp("(^|\\s)"+className+"(\\s|$)");
  1019. for (var i = 0, j = 0; i < elsLen; i++) {
  1020. if ( pattern.test(els[i].className) ) {
  1021. if (single) {
  1022. return els[i];
  1023. } else {
  1024. classElements[j] = els[i];
  1025. j++;
  1026. }
  1027. }
  1028. }
  1029. return classElements;
  1030. };
  1031. }
  1032. })();
  1033. },{}],14:[function(require,module,exports){
  1034. var indexOf = [].indexOf;
  1035. module.exports = function(arr, obj){
  1036. if (indexOf) return arr.indexOf(obj);
  1037. for (var i = 0; i < arr.length; ++i) {
  1038. if (arr[i] === obj) return i;
  1039. }
  1040. return -1;
  1041. };
  1042. },{}],15:[function(require,module,exports){
  1043. /*
  1044. * Natural Sort algorithm for Javascript - Version 0.8.1 - Released under MIT license
  1045. * Author: Jim Palmer (based on chunking idea from Dave Koelle)
  1046. */
  1047. module.exports = function(a, b, opts) {
  1048. var re = /(^([+\-]?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?(?=\D|\s|$))|^0x[\da-fA-F]+$|\d+)/g,
  1049. sre = /^\s+|\s+$/g, // trim pre-post whitespace
  1050. snre = /\s+/g, // normalize all whitespace to single ' ' character
  1051. dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,
  1052. hre = /^0x[0-9a-f]+$/i,
  1053. ore = /^0/,
  1054. options = opts || {},
  1055. i = function(s) {
  1056. return (options.insensitive && ('' + s).toLowerCase() || '' + s).replace(sre, '');
  1057. },
  1058. // convert all to strings strip whitespace
  1059. x = i(a),
  1060. y = i(b),
  1061. // chunk/tokenize
  1062. xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
  1063. yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
  1064. // numeric, hex or date detection
  1065. xD = parseInt(x.match(hre), 16) || (xN.length !== 1 && Date.parse(x)),
  1066. yD = parseInt(y.match(hre), 16) || xD && y.match(dre) && Date.parse(y) || null,
  1067. normChunk = function(s, l) {
  1068. // normalize spaces; find floats not starting with '0', string or 0 if not defined (Clint Priest)
  1069. return (!s.match(ore) || l == 1) && parseFloat(s) || s.replace(snre, ' ').replace(sre, '') || 0;
  1070. },
  1071. oFxNcL, oFyNcL;
  1072. // first try and sort Hex codes or Dates
  1073. if (yD) {
  1074. if (xD < yD) { return -1; }
  1075. else if (xD > yD) { return 1; }
  1076. }
  1077. // natural sorting through split numeric strings and default strings
  1078. for(var cLoc = 0, xNl = xN.length, yNl = yN.length, numS = Math.max(xNl, yNl); cLoc < numS; cLoc++) {
  1079. oFxNcL = normChunk(xN[cLoc] || '', xNl);
  1080. oFyNcL = normChunk(yN[cLoc] || '', yNl);
  1081. // handle numeric vs string comparison - number < string - (Kyle Adams)
  1082. if (isNaN(oFxNcL) !== isNaN(oFyNcL)) {
  1083. return isNaN(oFxNcL) ? 1 : -1;
  1084. }
  1085. // if unicode use locale comparison
  1086. if (/[^\x00-\x80]/.test(oFxNcL + oFyNcL) && oFxNcL.localeCompare) {
  1087. var comp = oFxNcL.localeCompare(oFyNcL);
  1088. return comp / Math.abs(comp);
  1089. }
  1090. if (oFxNcL < oFyNcL) { return -1; }
  1091. else if (oFxNcL > oFyNcL) { return 1; }
  1092. }
  1093. return 0;
  1094. };
  1095. },{}],16:[function(require,module,exports){
  1096. /**
  1097. * Source: https://github.com/timoxley/to-array
  1098. *
  1099. * Convert an array-like object into an `Array`.
  1100. * If `collection` is already an `Array`, then will return a clone of `collection`.
  1101. *
  1102. * @param {Array | Mixed} collection An `Array` or array-like object to convert e.g. `arguments` or `NodeList`
  1103. * @return {Array} Naive conversion of `collection` to a new `Array`.
  1104. * @api public
  1105. */
  1106. module.exports = function toArray(collection) {
  1107. if (typeof collection === 'undefined') return [];
  1108. if (collection === null) return [null];
  1109. if (collection === window) return [window];
  1110. if (typeof collection === 'string') return [collection];
  1111. if (isArray(collection)) return collection;
  1112. if (typeof collection.length != 'number') return [collection];
  1113. if (typeof collection === 'function' && collection instanceof Function) return [collection];
  1114. var arr = [];
  1115. for (var i = 0; i < collection.length; i++) {
  1116. if (Object.prototype.hasOwnProperty.call(collection, i) || i in collection) {
  1117. arr.push(collection[i]);
  1118. }
  1119. }
  1120. if (!arr.length) return [];
  1121. return arr;
  1122. };
  1123. function isArray(arr) {
  1124. return Object.prototype.toString.call(arr) === "[object Array]";
  1125. }
  1126. },{}],17:[function(require,module,exports){
  1127. module.exports = function(s) {
  1128. s = (s === undefined) ? "" : s;
  1129. s = (s === null) ? "" : s;
  1130. s = s.toString();
  1131. return s;
  1132. };
  1133. },{}]},{},[1]);