UNPKG

metro4

Version:

The front-end framework for Build responsive, mobile-first projects on the web with the first front-end component library in Metro Style

864 lines (688 loc) 26.1 kB
var List = { init: function( options, elem ) { this.options = $.extend( {}, this.options, options ); this.elem = elem; this.element = $(elem); this.currentPage = 1; this.pagesCount = 1; this.filterString = ""; this.data = null; this.activity = null; this.busy = false; this.filters = []; this.wrapperInfo = null; this.wrapperSearch = null; this.wrapperRows = null; this.wrapperPagination = null; this.filterIndex = null; this.filtersIndexes = []; this.sort = { dir: "asc", colIndex: 0 }; this.header = null; this.items = []; this._setOptionsFromDOM(); this._create(); return this; }, options: { thousandSeparator: ",", decimalSeparator: ",", sortTarget: "li", sortClass: null, sortDir: "asc", sortInitial: false, filterClass: null, filter: null, filterString: "", filters: null, source: null, showItemsSteps: false, showSearch: false, showListInfo: false, showPagination: false, showAllPages: false, showActivity: true, muteList: true, items: -1, itemsSteps: "all, 10,25,50,100", itemsAllTitle: "Show all", listItemsCountTitle: "Show entries:", listSearchTitle: "Search:", listInfoTitle: "Showing $1 to $2 of $3 entries", paginationPrevTitle: "Prev", paginationNextTitle: "Next", activityType: "cycle", activityStyle: "color", activityTimeout: 100, searchWrapper: null, rowsWrapper: null, infoWrapper: null, paginationWrapper: null, clsComponent: "", clsList: "", clsListItem: "", clsListTop: "", clsItemsCount: "", clsSearch: "", clsListBottom: "", clsListInfo: "", clsListPagination: "", clsPagination: "", onDraw: Metro.noop, onDrawItem: Metro.noop, onSortStart: Metro.noop, onSortStop: Metro.noop, onSortItemSwitch: Metro.noop, onSearch: Metro.noop, onRowsCountChange: Metro.noop, onDataLoad: Metro.noop, onDataLoaded: Metro.noop, onFilterItemAccepted: Metro.noop, onFilterItemDeclined: Metro.noop, onListCreate: Metro.noop }, _setOptionsFromDOM: function(){ var element = this.element, o = this.options; $.each(element.data(), function(key, value){ if (key in o) { try { o[key] = JSON.parse(value); } catch (e) { o[key] = value; } } }); }, _create: function(){ var that = this, element = this.element, o = this.options; if (o.source !== null) { Utils.exec(o.onDataLoad, [o.source], element[0]); $.get(o.source, function(data){ that._build(data); Utils.exec(o.onDataLoaded, [o.source, data], element[0]); }).fail(function( jqXHR, textStatus, errorThrown) { console.log(textStatus); console.log(jqXHR); console.log(errorThrown); }); } else { that._build(); } }, _build: function(data){ var element = this.element, o = this.options; if (Utils.isValue(data)) { this._createItemsFromJSON(data); } else { this._createItemsFromHTML() } this._createStructure(); this._createEvents(); Utils.exec(o.onListCreate, [element], element[0]); }, _createItemsFromHTML: function(){ var that = this, element = this.element, o = this.options; this.items = []; $.each(element.children(o.sortTarget), function(){ that.items.push(this); }); }, _createItemsFromJSON: function(source){ var that = this; this.items = []; if (Utils.isValue(source.header)) { that.header = source.header; } if (Utils.isValue(source.data)) { $.each(source.data, function(){ var row = this; var li = document.createElement("li"); var inner = Utils.isValue(that.header.template) ? that.header.template : ""; $.each(row, function(k, v){ inner = inner.replace("$"+k, v); }); li.innerHTML = inner; that.items.push(li); }); } }, _createTopBlock: function (){ var that = this, element = this.element, o = this.options; var top_block = $("<div>").addClass("list-top").addClass(o.clsListTop).insertBefore(element); var search_block, search_input, rows_block, rows_select; search_block = Utils.isValue(this.wrapperSearch) ? this.wrapperSearch : $("<div>").addClass("list-search-block").addClass(o.clsSearch).appendTo(top_block); search_input = $("<input>").attr("type", "text").appendTo(search_block); search_input.input({ prepend: o.listSearchTitle }); if (o.showSearch !== true) { search_block.hide(); } rows_block = Utils.isValue(this.wrapperRows) ? this.wrapperRows : $("<div>").addClass("list-rows-block").addClass(o.clsItemsCount).appendTo(top_block); rows_select = $("<select>").appendTo(rows_block); $.each(Utils.strToArray(o.itemsSteps), function () { var option = $("<option>").attr("value", this === "all" ? -1 : this).text(this === "all" ? o.itemsAllTitle : this).appendTo(rows_select); if (parseInt(this) === parseInt(o.items)) { option.attr("selected", "selected"); } }); rows_select.select({ filter: false, prepend: o.listItemsCountTitle, onChange: function (val) { if (parseInt(val) === parseInt(o.items)) { return; } o.items = parseInt(val); that.currentPage = 1; that._draw(); Utils.exec(o.onRowsCountChange, [val], element[0]) } }); if (o.showItemsSteps !== true) { rows_block.hide(); } return top_block; }, _createBottomBlock: function (){ var element = this.element, o = this.options; var bottom_block = $("<div>").addClass("list-bottom").addClass(o.clsListBottom).insertAfter(element); var info, pagination; info = $("<div>").addClass("list-info").addClass(o.clsListInfo).appendTo(bottom_block); if (o.showListInfo !== true) { info.hide(); } pagination = $("<div>").addClass("list-pagination").addClass(o.clsListPagination).appendTo(bottom_block); if (o.showPagination !== true) { pagination.hide(); } return bottom_block; }, _createStructure: function(){ var that = this, element = this.element, o = this.options; var list_component; var w_search = $(o.searchWrapper), w_info = $(o.infoWrapper), w_rows = $(o.rowsWrapper), w_paging = $(o.paginationWrapper); if (w_search.length > 0) {this.wrapperSearch = w_search;} if (w_info.length > 0) {this.wrapperInfo = w_info;} if (w_rows.length > 0) {this.wrapperRows = w_rows;} if (w_paging.length > 0) {this.wrapperPagination = w_paging;} if (!element.parent().hasClass("list-component")) { list_component = $("<div>").addClass("list-component").insertBefore(element); element.appendTo(list_component); } else { list_component = element.parent(); } list_component.addClass(o.clsComponent); this.activity = $("<div>").addClass("list-progress").appendTo(list_component); $("<div>").activity({ type: o.activityType, style: o.activityStyle }).appendTo(this.activity); if (o.showActivity !== true) { this.activity.css({ visibility: "hidden" }) } // element.html("").addClass(o.clsList); element.addClass(o.clsList); this._createTopBlock(); this._createBottomBlock(); if (Utils.isValue(o.filterString)) { this.filterString = o.filterString; } var filter_func; if (Utils.isValue(o.filter)) { filter_func = Utils.isFunc(o.filter); if (filter_func === false) { filter_func = Utils.func(o.filter); } that.filterIndex = that.addFilter(filter_func); } if (Utils.isValue(o.filters)) { $.each(Utils.strToArray(o.filters), function(){ filter_func = Utils.isFunc(this); if (filter_func !== false) { that.filtersIndexes.push(that.addFilter(filter_func)); } }); } this.currentPage = 1; this.sorting(o.sortClass, o.sortDir, true); }, _createEvents: function(){ var that = this, element = this.element; var component = element.parent(); var search = component.find(".list-search-block input"); var customSearch; search.on(Metro.events.inputchange, function(){ that.filterString = this.value.trim().toLowerCase(); if (that.filterString[that.filterString.length - 1] === ":") { return ; } that.currentPage = 1; that._draw(); }); if (Utils.isValue(this.wrapperSearch)) { customSearch = this.wrapperSearch.find("input"); if (customSearch.length > 0) { customSearch.on(Metro.events.inputchange, function(){ that.filterString = this.value.trim().toLowerCase(); if (that.filterString[that.filterString.length - 1] === ":") { return ; } that.currentPage = 1; that._draw(); }); } } function pageLinkClick(l){ var link = $(l); var item = link.parent(); if (item.hasClass("active")) { return ; } if (item.hasClass("service")) { if (link.data("page") === "prev") { that.currentPage--; if (that.currentPage === 0) { that.currentPage = 1; } } else { that.currentPage++; if (that.currentPage > that.pagesCount) { that.currentPage = that.pagesCount; } } } else { that.currentPage = link.data("page"); } that._draw(); } component.on(Metro.events.click, ".pagination .page-link", function(){ pageLinkClick(this) }); if (Utils.isValue(this.wrapperPagination)) { this.wrapperPagination.on(Metro.events.click, ".pagination .page-link", function(){ pageLinkClick(this) }); } }, _info: function(start, stop, length){ var element = this.element, o = this.options; var component = element.parent(); var info = Utils.isValue(this.wrapperInfo) ? this.wrapperInfo : component.find(".list-info"); var text; if (info.length === 0) { return ; } if (stop > length) { stop = length; } if (this.items.length === 0) { start = stop = length = 0; } text = o.listInfoTitle; text = text.replace("$1", start); text = text.replace("$2", stop); text = text.replace("$3", length); info.html(text); }, _paging: function(length){ var that = this, element = this.element, o = this.options; var component = element.parent(); var pagination_wrapper = Utils.isValue(this.wrapperPagination) ? this.wrapperPagination : component.find(".list-pagination"); var i, prev, next; var shortDistance = 5; var pagination; pagination_wrapper.html(""); pagination = $("<ul>").addClass("pagination").addClass(o.clsPagination).appendTo(pagination_wrapper); if (this.items.length === 0) { return ; } this.pagesCount = Math.ceil(length / o.items); var add_item = function(item_title, item_type, data){ var li, a; li = $("<li>").addClass("page-item").addClass(item_type); a = $("<a>").addClass("page-link").html(item_title); a.data("page", data); a.appendTo(li); return li; }; prev = add_item(o.paginationPrevTitle, "service prev-page", "prev"); pagination.append(prev); pagination.append(add_item(1, that.currentPage === 1 ? "active" : "", 1)); if (o.showAllPages === true || this.pagesCount <= 7) { for (i = 2; i < this.pagesCount; i++) { pagination.append(add_item(i, i === that.currentPage ? "active" : "", i)); } } else { if (that.currentPage < shortDistance) { for (i = 2; i <= shortDistance; i++) { pagination.append(add_item(i, i === that.currentPage ? "active" : "", i)); } if (this.pagesCount > shortDistance) { pagination.append(add_item("...", "no-link", null)); } } else if (that.currentPage <= that.pagesCount && that.currentPage > that.pagesCount - shortDistance + 1) { if (this.pagesCount > shortDistance) { pagination.append(add_item("...", "no-link", null)); } for (i = that.pagesCount - shortDistance + 1; i < that.pagesCount; i++) { pagination.append(add_item(i, i === that.currentPage ? "active" : "", i)); } } else { pagination.append(add_item("...", "no-link", null)); pagination.append(add_item(that.currentPage - 1, "", that.currentPage - 1)); pagination.append(add_item(that.currentPage, "active", that.currentPage)); pagination.append(add_item(that.currentPage + 1, "", that.currentPage + 1)); pagination.append(add_item("...", "no-link", null)); } } if (that.pagesCount > 1 || that.currentPage < that.pagesCount) pagination.append(add_item(that.pagesCount, that.currentPage === that.pagesCount ? "active" : "", that.pagesCount)); next = add_item(o.paginationNextTitle, "service next-page", "next"); pagination.append(next); if (this.currentPage === 1) { prev.addClass("disabled"); } if (this.currentPage === this.pagesCount) { next.addClass("disabled"); } }, _filter: function(){ var that = this, element = this.element, o = this.options, items, i, data, inset, c1, result; if (Utils.isValue(this.filterString) || this.filters.length > 0) { items = this.items.filter(function(item){ data = ""; if (Utils.isValue(o.filterClass)) { inset = item.getElementsByClassName(o.filterClass); if (inset.length > 0) for (i = 0; i < inset.length; i++) { data += inset[i].textContent; } } else { data = item.textContent; } c1 = data.replace(/[\n\r]+|[\s]{2,}/g, ' ').trim().toLowerCase(); result = Utils.isValue(that.filterString) ? c1.indexOf(that.filterString) > -1 : true; if (result === true && that.filters.length > 0) { for (i = 0; i < that.filters.length; i++) { if (Utils.exec(that.filters[i], [item]) !== true) { result = false; break; } } } if (result) { Utils.exec(o.onFilterItemAccepted, [item], element[0]); } else { Utils.exec(o.onFilterItemDeclined, [item], element[0]); } return result; }); Utils.exec(o.onSearch, [that.filterString, items], element[0]) } else { items = this.items; } return items; }, _draw: function(cb){ var element = this.element, o = this.options; var i; var start = o.items === -1 ? 0 : o.items * (this.currentPage - 1), stop = o.items === -1 ? this.items.length - 1 : start + o.items - 1; var items; items = this._filter(); element.children(o.sortTarget).remove(); for (i = start; i <= stop; i++) { if (Utils.isValue(items[i])) { $(items[i]).addClass(o.clsListItem).appendTo(element); } Utils.exec(o.onDrawItem, [items[i]], element[0]); } this._info(start + 1, stop + 1, items.length); this._paging(items.length); this.activity.hide(); Utils.exec(o.onDraw, [element], element[0]); if (cb !== undefined) { Utils.exec(cb, [element], element[0]) } }, _getItemContent: function(item){ var o = this.options, $item = $(item); var i, inset, data; var format, formatMask = Utils.isValue($item.data("formatMask")) ? $item.data("formatMask") : null; if (Utils.isValue(o.sortClass)) { data = ""; inset = $(item).find("."+o.sortClass); if (inset.length > 0) for (i = 0; i < inset.length; i++) { data += inset[i].textContent; } format = inset.length > 0 ? inset[0].getAttribute("data-format") : ""; } else { data = item.textContent; format = item.getAttribute("data-format"); } data = (""+data).toLowerCase().replace(/[\n\r]+|[\s]{2,}/g, ' ').trim(); if (Utils.isValue(format)) { if (['number', 'int', 'integer', 'float', 'money'].indexOf(format) !== -1 && (o.thousandSeparator !== "," || o.decimalSeparator !== "." )) { data = Utils.parseNumber(data, o.thousandSeparator, o.decimalSeparator); } switch (format) { case "date": data = Utils.isValue(formatMask) ? data.toDate(formatMask) : new Date(data); break; case "number": data = Number(data); break; case "int": case "integer": data = parseInt(data); break; case "float": data = parseFloat(data); break; case "money": data = Utils.parseMoney(data); break; case "card": data = Utils.parseCard(data); break; case "phone": data = Utils.parsePhone(data); break; } } return data; }, deleteItem: function(value){ var i, deleteIndexes = [], item; var is_func = Utils.isFunc(value); for (i = 0; i < this.items.length; i++) { item = this.items[i]; if (is_func) { if (Utils.exec(value, [item])) { deleteIndexes.push(i); } } else { if (item.textContent.contains(value)) { deleteIndexes.push(i); } } } this.items = Utils.arrayDeleteByMultipleKeys(this.items, deleteIndexes); return this; }, draw: function(){ return this._draw(); }, sorting: function(source, dir, redraw){ var that = this, element = this.element, o = this.options; if (Utils.isValue(source)) { o.sortClass = source; } if (Utils.isValue(dir) && ["asc", "desc"].indexOf(dir) > -1) { o.sortDir= dir; } Utils.exec(o.onSortStart, [this.items], element[0]); this.items.sort(function(a, b){ var c1 = that._getItemContent(a); var c2 = that._getItemContent(b); var result = 0; if (c1 < c2) { result = o.sortDir === "asc" ? -1 : 1; } if (c1 > c2) { result = o.sortDir === "asc" ? 1 : -1; } if (result !== 0) { Utils.exec(o.onSortItemSwitch, [a, b, result], element[0]); } return result; }); Utils.exec(o.onSortStop, [this.items], element[0]); if (redraw === true) { this._draw(); } return this; }, filter: function(val){ this.filterString = val.trim().toLowerCase(); this.currentPage = 1; this._draw(); }, loadData: function(source){ var that = this, element = this.element, o = this.options; if (Utils.isValue(source) !== true) { return ; } o.source = source; Utils.exec(o.onDataLoad, [o.source], element[0]); $.get(o.source, function(data){ Utils.exec(o.onDataLoaded, [o.source, data], element[0]); that._createItemsFromJSON(data); element.html(""); if (Utils.isValue(o.filterString)) { that.filterString = o.filterString; } var filter_func; if (Utils.isValue(o.filter)) { filter_func = Utils.isFunc(o.filter); if (filter_func === false) { filter_func = Utils.func(o.filter); } that.filterIndex = that.addFilter(filter_func); } if (Utils.isValue(o.filters)) { $.each(Utils.strToArray(o.filters), function(){ filter_func = Utils.isFunc(this); if (filter_func !== false) { that.filtersIndexes.push(that.addFilter(filter_func)); } }); } that.currentPage = 1; that.sorting(o.sortClass, o.sortDir, true); }).fail(function( jqXHR, textStatus, errorThrown) { console.log(textStatus); console.log(jqXHR); console.log(errorThrown); }); }, next: function(){ if (this.items.length === 0) return ; this.currentPage++; if (this.currentPage > this.pagesCount) { this.currentPage = this.pagesCount; return ; } this._draw(); }, prev: function(){ if (this.items.length === 0) return ; this.currentPage--; if (this.currentPage === 0) { this.currentPage = 1; return ; } this._draw(); }, first: function(){ if (this.items.length === 0) return ; this.currentPage = 1; this._draw(); }, last: function(){ if (this.items.length === 0) return ; this.currentPage = this.pagesCount; this._draw(); }, page: function(num){ if (num <= 0) { num = 1; } if (num > this.pagesCount) { num = this.pagesCount; } this.currentPage = num; this._draw(); }, addFilter: function(f, redraw){ var func = Utils.isFunc(f); if (func === false) { return ; } this.filters.push(func); if (redraw === true) { this.currentPage = 1; this.draw(); } return this.filters.length - 1; }, removeFilter: function(key, redraw){ Utils.arrayDeleteByKey(this.filters, key); if (redraw === true) { this.currentPage = 1; this.draw(); } return this; }, removeFilters: function(redraw){ this.filters = []; if (redraw === true) { this.currentPage = 1; this.draw(); } }, getFilters: function(){ return this.filters; }, getFilterIndex: function(){ return this.filterIndex; }, getFiltersIndexes: function(){ return this.filtersIndexes; }, changeAttribute: function(attributeName){ var that = this, element = this.element, o = this.options; var changeSortDir = function(){ var dir = element.attr("data-sort-dir"); if (!Utils.isValue(dir)) { return ; } o.sortDir = dir; that.sorting(o.sortClass, o.sortDir, true); }; var changeSortClass = function(){ var target = element.attr("data-sort-source"); if (!Utils.isValue(target)) { return ; } o.sortClass = target; that.sorting(o.sortClass, o.sortDir, true); }; var changeFilterString = function(){ var filter = element.attr("data-filter-string"); if (!Utils.isValue(target)) { return ; } o.filterString = filter; that.filter(o.filterString); }; switch (attributeName) { case "data-sort-dir": changeSortDir(); break; case "data-sort-source": changeSortClass(); break; case "data-filter-string": changeFilterString(); break; } }, destroy: function(){} }; Metro.plugin('list', List);