diff --git a/view/js/bootgrid/jquery.bootgrid.js b/view/js/bootgrid/jquery.bootgrid.js
index f221932c66..ef2cf152d8 100644
--- a/view/js/bootgrid/jquery.bootgrid.js
+++ b/view/js/bootgrid/jquery.bootgrid.js
@@ -1,2044 +1,2044 @@
-/*!
- * jQuery Bootgrid v1.3.1 - 09/11/2015
- * Copyright (c) 2014-2015 Rafael Staib (http://www.jquery-bootgrid.com)
- * Licensed under MIT http://www.opensource.org/licenses/MIT
- */
-;(function ($, window, undefined)
-{
- /*jshint validthis: true */
- "use strict";
-
- // GRID INTERNAL FIELDS
- // ====================
-
- var namespace = ".rs.jquery.bootgrid";
-
- // GRID INTERNAL FUNCTIONS
- // =====================
-
- function appendRow(row)
- {
- var that = this;
-
- function exists(item)
- {
- return that.identifier && item[that.identifier] === row[that.identifier];
- }
-
- if (!this.rows.contains(exists))
- {
- this.rows.push(row);
- return true;
- }
-
- return false;
- }
-
- function findFooterAndHeaderItems(selector)
- {
- var footer = (this.footer) ? this.footer.find(selector) : $(),
- header = (this.header) ? this.header.find(selector) : $();
- return $.merge(footer, header);
- }
-
- function getParams(context)
- {
- return (context) ? $.extend({}, this.cachedParams, { ctx: context }) :
- this.cachedParams;
- }
-
- function getRequest()
- {
- var request = {
- current: this.current,
- rowCount: this.rowCount,
- sort: this.sortDictionary,
- searchPhrase: this.searchPhrase
- },
- post = this.options.post;
-
- post = ($.isFunction(post)) ? post() : post;
- return this.options.requestHandler($.extend(true, request, post));
- }
-
- function getCssSelector(css)
- {
- return "." + $.trim(css).replace(/\s+/gm, ".");
- }
-
- function getUrl()
- {
- var url = this.options.url;
- return ($.isFunction(url)) ? url() : url;
- }
-
- function init()
- {
- this.element.trigger("initialize" + namespace);
-
- loadColumns.call(this); // Loads columns from HTML thead tag
- this.selection = this.options.selection && this.identifier != null;
- loadRows.call(this); // Loads rows from HTML tbody tag if ajax is false
- prepareTable.call(this);
- renderTableHeader.call(this);
- renderSearchField.call(this);
- renderActions.call(this);
- loadData.call(this);
-
- this.element.trigger("initialized" + namespace);
- }
-
- function highlightAppendedRows(rows)
- {
- if (this.options.highlightRows)
- {
- // todo: implement
- }
- }
-
- function isVisible(column)
- {
- return column.visible;
- }
-
- function loadColumns()
- {
- var that = this,
- firstHeadRow = this.element.find("thead > tr").first(),
- sorted = false;
-
- /*jshint -W018*/
- firstHeadRow.children().each(function ()
- {
- var $this = $(this),
- data = $this.data(),
- column = {
- id: data.columnId,
- identifier: that.identifier == null && data.identifier || false,
- converter: that.options.converters[data.converter || data.type] || that.options.converters["string"],
- text: $this.text(),
- align: data.align || "left",
- headerAlign: data.headerAlign || "left",
- cssClass: data.cssClass || "",
- headerCssClass: data.headerCssClass || "",
- formatter: that.options.formatters[data.formatter] || null,
- order: (!sorted && (data.order === "asc" || data.order === "desc")) ? data.order : null,
- searchable: !(data.searchable === false), // default: true
- sortable: !(data.sortable === false), // default: true
- visible: !(data.visible === false), // default: true
- visibleInSelection: !(data.visibleInSelection === false), // default: true
- width: ($.isNumeric(data.width)) ? data.width + "px" :
- (typeof(data.width) === "string") ? data.width : null
- };
- that.columns.push(column);
- if (column.order != null)
- {
- that.sortDictionary[column.id] = column.order;
- }
-
- // Prevents multiple identifiers
- if (column.identifier)
- {
- that.identifier = column.id;
- that.converter = column.converter;
- }
-
- // ensures that only the first order will be applied in case of multi sorting is disabled
- if (!that.options.multiSort && column.order !== null)
- {
- sorted = true;
- }
- });
- /*jshint +W018*/
- }
-
- /*
- response = {
- current: 1,
- rowCount: 10,
- rows: [{}, {}],
- sort: [{ "columnId": "asc" }],
- total: 101
- }
- */
-
- function loadData()
- {
- var that = this;
-
- this.element._bgBusyAria(true).trigger("load" + namespace);
- showLoading.call(this);
-
- function containsPhrase(row)
- {
- var column,
- searchPattern = new RegExp(that.searchPhrase, (that.options.caseSensitive) ? "g" : "gi");
-
- for (var i = 0; i < that.columns.length; i++)
- {
- column = that.columns[i];
- if (column.searchable && column.visible &&
- column.converter.to(row[column.id]).search(searchPattern) > -1)
- {
- return true;
- }
- }
-
- return false;
- }
-
- function update(rows, total)
- {
- that.currentRows = rows;
- setTotals.call(that, total);
-
- if (!that.options.keepSelection)
- {
- that.selectedRows = [];
- }
-
- renderRows.call(that, rows);
- renderInfos.call(that);
- renderPagination.call(that);
-
- that.element._bgBusyAria(false).trigger("loaded" + namespace);
- }
-
- if (this.options.ajax)
- {
- var request = getRequest.call(this),
- url = getUrl.call(this);
-
- if (url == null || typeof url !== "string" || url.length === 0)
- {
- throw new Error("Url setting must be a none empty string or a function that returns one.");
- }
-
- // aborts the previous ajax request if not already finished or failed
- if (this.xqr)
- {
- this.xqr.abort();
- }
-
- var settings = {
- url: url,
- data: request,
- success: function(response)
- {
- that.xqr = null;
-
- if (typeof (response) === "string")
- {
- response = $.parseJSON(response);
- }
-
- response = that.options.responseHandler(response);
-
- that.current = response.current;
- update(response.rows, response.total);
- },
- error: function (jqXHR, textStatus, errorThrown)
- {
- that.xqr = null;
-
- if (textStatus !== "abort")
- {
- renderNoResultsRow.call(that); // overrides loading mask
- that.element._bgBusyAria(false).trigger("loaded" + namespace);
- }
- }
- };
- settings = $.extend(this.options.ajaxSettings, settings);
-
- this.xqr = $.ajax(settings);
- }
- else
- {
- var rows = (this.searchPhrase.length > 0) ? this.rows.where(containsPhrase) : this.rows,
- total = rows.length;
- if (this.rowCount !== -1)
- {
- rows = rows.page(this.current, this.rowCount);
- }
-
- // todo: improve the following comment
- // setTimeout decouples the initialization so that adding event handlers happens before
- window.setTimeout(function () { update(rows, total); }, 10);
- }
- }
-
- function loadRows()
- {
- if (!this.options.ajax)
- {
- var that = this,
- rows = this.element.find("tbody > tr");
-
- rows.each(function ()
- {
- var $this = $(this),
- cells = $this.children("td"),
- row = {};
-
- $.each(that.columns, function (i, column)
- {
- row[column.id] = column.converter.from(cells.eq(i).text());
- });
-
- appendRow.call(that, row);
- });
-
- setTotals.call(this, this.rows.length);
- sortRows.call(this);
- }
- }
-
- function setTotals(total)
- {
- this.total = total;
- this.totalPages = (this.rowCount === -1) ? 1 :
- Math.ceil(this.total / this.rowCount);
- }
-
- function prepareTable()
- {
- var tpl = this.options.templates,
- wrapper = (this.element.parent().hasClass(this.options.css.responsiveTable)) ?
- this.element.parent() : this.element;
-
- this.element.addClass(this.options.css.table);
-
- // checks whether there is an tbody element; otherwise creates one
- if (this.element.children("tbody").length === 0)
- {
- this.element.append(tpl.body);
- }
-
- if (this.options.navigation & 1)
- {
- this.header = $(tpl.header.resolve(getParams.call(this, { id: this.element._bgId() + "-header" })));
- wrapper.before(this.header);
- }
-
- if (this.options.navigation & 2)
- {
- this.footer = $(tpl.footer.resolve(getParams.call(this, { id: this.element._bgId() + "-footer" })));
- wrapper.after(this.footer);
- }
- }
-
- function renderActions()
- {
- if (this.options.navigation !== 0)
- {
- var css = this.options.css,
- selector = getCssSelector(css.actions),
- actionItems = findFooterAndHeaderItems.call(this, selector);
-
- if (actionItems.length > 0)
- {
- var that = this,
- tpl = this.options.templates,
- actions = $(tpl.actions.resolve(getParams.call(this)));
-
- // Refresh Button
- if (this.options.ajax)
- {
- var refreshIcon = tpl.icon.resolve(getParams.call(this, { iconCss: css.iconRefresh })),
- refresh = $(tpl.actionButton.resolve(getParams.call(this,
- { content: refreshIcon, text: this.options.labels.refresh })))
- .on("click" + namespace, function (e)
- {
- // todo: prevent multiple fast clicks (fast click detection)
- e.stopPropagation();
- that.current = 1;
- loadData.call(that);
- });
- actions.append(refresh);
- }
-
- // Row count selection
- renderRowCountSelection.call(this, actions);
-
- // Column selection
- renderColumnSelection.call(this, actions);
-
- replacePlaceHolder.call(this, actionItems, actions);
- }
- }
- }
-
- function renderColumnSelection(actions)
- {
- if (this.options.columnSelection && this.columns.length > 1)
- {
- var that = this,
- css = this.options.css,
- tpl = this.options.templates,
- icon = tpl.icon.resolve(getParams.call(this, { iconCss: css.iconColumns })),
- dropDown = $(tpl.actionDropDown.resolve(getParams.call(this, { content: icon }))),
- selector = getCssSelector(css.dropDownItem),
- checkboxSelector = getCssSelector(css.dropDownItemCheckbox),
- itemsSelector = getCssSelector(css.dropDownMenuItems);
-
- $.each(this.columns, function (i, column)
- {
- if (column.visibleInSelection)
- {
- var item = $(tpl.actionDropDownCheckboxItem.resolve(getParams.call(that,
- { name: column.id, label: column.text, checked: column.visible })))
- .on("click" + namespace, selector, function (e)
- {
- e.stopPropagation();
-
- var $this = $(this),
- checkbox = $this.find(checkboxSelector);
- if (!checkbox.prop("disabled"))
- {
- column.visible = checkbox.prop("checked");
- var enable = that.columns.where(isVisible).length > 1;
- $this.parents(itemsSelector).find(selector + ":has(" + checkboxSelector + ":checked)")
- ._bgEnableAria(enable).find(checkboxSelector)._bgEnableField(enable);
-
- that.element.find("tbody").empty(); // Fixes an column visualization bug
- renderTableHeader.call(that);
- loadData.call(that);
- }
- });
- dropDown.find(getCssSelector(css.dropDownMenuItems)).append(item);
- }
- });
- actions.append(dropDown);
- }
- }
-
- function renderInfos()
- {
- if (this.options.navigation !== 0)
- {
- var selector = getCssSelector(this.options.css.infos),
- infoItems = findFooterAndHeaderItems.call(this, selector);
-
- if (infoItems.length > 0)
- {
- var end = (this.current * this.rowCount),
- infos = $(this.options.templates.infos.resolve(getParams.call(this, {
- end: (this.total === 0 || end === -1 || end > this.total) ? this.total : end,
- start: (this.total === 0) ? 0 : (end - this.rowCount + 1),
- total: this.total
- })));
-
- replacePlaceHolder.call(this, infoItems, infos);
- }
- }
- }
-
- function renderNoResultsRow()
- {
- var tbody = this.element.children("tbody").first(),
- tpl = this.options.templates,
- count = this.columns.where(isVisible).length;
-
- if (this.selection)
- {
- count = count + 1;
- }
- tbody.html(tpl.noResults.resolve(getParams.call(this, { columns: count })));
- }
-
- function renderPagination()
- {
- if (this.options.navigation !== 0)
- {
- var selector = getCssSelector(this.options.css.pagination),
- paginationItems = findFooterAndHeaderItems.call(this, selector)._bgShowAria(this.rowCount !== -1);
-
- if (this.rowCount !== -1 && paginationItems.length > 0)
- {
- var tpl = this.options.templates,
- current = this.current,
- totalPages = this.totalPages,
- pagination = $(tpl.pagination.resolve(getParams.call(this))),
- offsetRight = totalPages - current,
- offsetLeft = (this.options.padding - current) * -1,
- startWith = ((offsetRight >= this.options.padding) ?
- Math.max(offsetLeft, 1) :
- Math.max((offsetLeft - this.options.padding + offsetRight), 1)),
- maxCount = this.options.padding * 2 + 1,
- count = (totalPages >= maxCount) ? maxCount : totalPages;
-
- renderPaginationItem.call(this, pagination, "first", "«", "first")
- ._bgEnableAria(current > 1);
- renderPaginationItem.call(this, pagination, "prev", "<", "prev")
- ._bgEnableAria(current > 1);
-
- for (var i = 0; i < count; i++)
- {
- var pos = i + startWith;
- renderPaginationItem.call(this, pagination, pos, pos, "page-" + pos)
- ._bgEnableAria()._bgSelectAria(pos === current);
- }
-
- if (count === 0)
- {
- renderPaginationItem.call(this, pagination, 1, 1, "page-" + 1)
- ._bgEnableAria(false)._bgSelectAria();
- }
-
- renderPaginationItem.call(this, pagination, "next", ">", "next")
- ._bgEnableAria(totalPages > current);
- renderPaginationItem.call(this, pagination, "last", "»", "last")
- ._bgEnableAria(totalPages > current);
-
- replacePlaceHolder.call(this, paginationItems, pagination);
- }
- }
- }
-
- function renderPaginationItem(list, page, text, markerCss)
- {
- var that = this,
- tpl = this.options.templates,
- css = this.options.css,
- values = getParams.call(this, { css: markerCss, text: text, page: page }),
- item = $(tpl.paginationItem.resolve(values))
- .on("click" + namespace, getCssSelector(css.paginationButton), function (e)
- {
- e.stopPropagation();
- e.preventDefault();
-
- var $this = $(this),
- parent = $this.parent();
- if (!parent.hasClass("active") && !parent.hasClass("disabled"))
- {
- var commandList = {
- first: 1,
- prev: that.current - 1,
- next: that.current + 1,
- last: that.totalPages
- };
- var command = $this.data("page");
- that.current = commandList[command] || command;
- loadData.call(that);
- }
- $this.trigger("blur");
- });
-
- list.append(item);
- return item;
- }
-
- function renderRowCountSelection(actions)
- {
- var that = this,
- rowCountList = this.options.rowCount;
-
- function getText(value)
- {
- return (value === -1) ? that.options.labels.all : value;
- }
-
- if ($.isArray(rowCountList))
- {
- var css = this.options.css,
- tpl = this.options.templates,
- dropDown = $(tpl.actionDropDown.resolve(getParams.call(this, { content: getText(this.rowCount) }))),
- menuSelector = getCssSelector(css.dropDownMenu),
- menuTextSelector = getCssSelector(css.dropDownMenuText),
- menuItemsSelector = getCssSelector(css.dropDownMenuItems),
- menuItemSelector = getCssSelector(css.dropDownItemButton);
-
- $.each(rowCountList, function (index, value)
- {
- var item = $(tpl.actionDropDownItem.resolve(getParams.call(that,
- { text: getText(value), action: value })))
- ._bgSelectAria(value === that.rowCount)
- .on("click" + namespace, menuItemSelector, function (e)
- {
- e.preventDefault();
-
- var $this = $(this),
- newRowCount = $this.data("action");
- if (newRowCount !== that.rowCount)
- {
- // todo: sophisticated solution needed for calculating which page is selected
- that.current = 1; // that.rowCount === -1 ---> All
- that.rowCount = newRowCount;
- $this.parents(menuItemsSelector).children().each(function ()
- {
- var $item = $(this),
- currentRowCount = $item.find(menuItemSelector).data("action");
- $item._bgSelectAria(currentRowCount === newRowCount);
- });
- $this.parents(menuSelector).find(menuTextSelector).text(getText(newRowCount));
- loadData.call(that);
- }
- });
- dropDown.find(menuItemsSelector).append(item);
- });
- actions.append(dropDown);
- }
- }
-
- function renderRows(rows)
- {
- if (rows.length > 0)
- {
- var that = this,
- css = this.options.css,
- tpl = this.options.templates,
- tbody = this.element.children("tbody").first(),
- allRowsSelected = true,
- html = "";
-
- $.each(rows, function (index, row)
- {
- var cells = "",
- rowAttr = " data-row-id=\"" + ((that.identifier == null) ? index : row[that.identifier]) + "\"",
- rowCss = "";
-
- if (that.selection)
- {
- var selected = ($.inArray(row[that.identifier], that.selectedRows) !== -1),
- selectBox = tpl.select.resolve(getParams.call(that,
- { type: "checkbox", value: row[that.identifier], checked: selected }));
- cells += tpl.cell.resolve(getParams.call(that, { content: selectBox, css: css.selectCell }));
- allRowsSelected = (allRowsSelected && selected);
- if (selected)
- {
- rowCss += css.selected;
- rowAttr += " aria-selected=\"true\"";
- }
- }
-
- var status = row.status != null && that.options.statusMapping[row.status];
- if (status)
- {
- rowCss += status;
- }
-
- $.each(that.columns, function (j, column)
- {
- if (column.visible)
- {
- var value = ($.isFunction(column.formatter)) ?
- column.formatter.call(that, column, row) :
- column.converter.to(row[column.id]),
- cssClass = (column.cssClass.length > 0) ? " " + column.cssClass : "";
- cells += tpl.cell.resolve(getParams.call(that, {
- content: (value == null || value === "") ? " " : value,
- css: ((column.align === "right") ? css.right : (column.align === "center") ?
- css.center : css.left) + cssClass,
- style: (column.width == null) ? "" : "width:" + column.width + ";" }));
- }
- });
-
- if (rowCss.length > 0)
- {
- rowAttr += " class=\"" + rowCss + "\"";
- }
- html += tpl.row.resolve(getParams.call(that, { attr: rowAttr, cells: cells }));
- });
-
- // sets or clears multi selectbox state
- that.element.find("thead " + getCssSelector(that.options.css.selectBox))
- .prop("checked", allRowsSelected);
-
- tbody.html(html);
-
- registerRowEvents.call(this, tbody);
- }
- else
- {
- renderNoResultsRow.call(this);
- }
- }
-
- function registerRowEvents(tbody)
- {
- var that = this,
- selectBoxSelector = getCssSelector(this.options.css.selectBox);
-
- if (this.selection)
- {
- tbody.off("click" + namespace, selectBoxSelector)
- .on("click" + namespace, selectBoxSelector, function(e)
- {
- e.stopPropagation();
-
- var $this = $(this),
- id = that.converter.from($this.val());
-
- if ($this.prop("checked"))
- {
- that.select([id]);
- }
- else
- {
- that.deselect([id]);
- }
- });
- }
-
- tbody.off("click" + namespace, "> tr")
- .on("click" + namespace, "> tr", function(e)
- {
- e.stopPropagation();
-
- var $this = $(this),
- id = (that.identifier == null) ? $this.data("row-id") :
- that.converter.from($this.data("row-id") + ""),
- row = (that.identifier == null) ? that.currentRows[id] :
- that.currentRows.first(function (item) { return item[that.identifier] === id; });
-
- if (that.selection && that.options.rowSelect)
- {
- if ($this.hasClass(that.options.css.selected))
- {
- that.deselect([id]);
- }
- else
- {
- that.select([id]);
- }
- }
-
- that.element.trigger("click" + namespace, [that.columns, row]);
- });
- }
-
- function renderSearchField()
- {
- if (this.options.navigation !== 0)
- {
- var css = this.options.css,
- selector = getCssSelector(css.search),
- searchItems = findFooterAndHeaderItems.call(this, selector);
-
- if (searchItems.length > 0)
- {
- var that = this,
- tpl = this.options.templates,
- timer = null, // fast keyup detection
- currentValue = "",
- searchFieldSelector = getCssSelector(css.searchField),
- search = $(tpl.search.resolve(getParams.call(this))),
- searchField = (search.is(searchFieldSelector)) ? search :
- search.find(searchFieldSelector);
-
- searchField.on("keyup" + namespace, function (e)
- {
- e.stopPropagation();
- var newValue = $(this).val();
- if (currentValue !== newValue || (e.which === 13 && newValue !== ""))
- {
- currentValue = newValue;
- if (e.which === 13 || newValue.length === 0 || newValue.length >= that.options.searchSettings.characters)
- {
- window.clearTimeout(timer);
- timer = window.setTimeout(function ()
- {
- executeSearch.call(that, newValue);
- }, that.options.searchSettings.delay);
- }
- }
- });
-
- replacePlaceHolder.call(this, searchItems, search);
- }
- }
- }
-
- function executeSearch(phrase)
- {
- if (this.searchPhrase !== phrase)
- {
- this.current = 1;
- this.searchPhrase = phrase;
- loadData.call(this);
- }
- }
-
- function renderTableHeader()
- {
- var that = this,
- headerRow = this.element.find("thead > tr"),
- css = this.options.css,
- tpl = this.options.templates,
- html = "",
- sorting = this.options.sorting;
-
- if (this.selection)
- {
- var selectBox = (this.options.multiSelect) ?
- tpl.select.resolve(getParams.call(that, { type: "checkbox", value: "all" })) : "";
- html += tpl.rawHeaderCell.resolve(getParams.call(that, { content: selectBox,
- css: css.selectCell }));
- }
-
- $.each(this.columns, function (index, column)
- {
- if (column.visible)
- {
- var sortOrder = that.sortDictionary[column.id],
- iconCss = ((sorting && sortOrder && sortOrder === "asc") ? css.iconUp :
- (sorting && sortOrder && sortOrder === "desc") ? css.iconDown : ""),
- icon = tpl.icon.resolve(getParams.call(that, { iconCss: iconCss })),
- align = column.headerAlign,
- cssClass = (column.headerCssClass.length > 0) ? " " + column.headerCssClass : "";
- html += tpl.headerCell.resolve(getParams.call(that, {
- column: column, icon: icon, sortable: sorting && column.sortable && css.sortable || "",
- css: ((align === "right") ? css.right : (align === "center") ?
- css.center : css.left) + cssClass,
- style: (column.width == null) ? "" : "width:" + column.width + ";" }));
- }
- });
-
- headerRow.html(html);
-
- if (sorting)
- {
- var sortingSelector = getCssSelector(css.sortable);
- headerRow.off("click" + namespace, sortingSelector)
- .on("click" + namespace, sortingSelector, function (e)
- {
- e.preventDefault();
-
- setTableHeaderSortDirection.call(that, $(this));
- sortRows.call(that);
- loadData.call(that);
- });
- }
-
- // todo: create a own function for that piece of code
- if (this.selection && this.options.multiSelect)
- {
- var selectBoxSelector = getCssSelector(css.selectBox);
- headerRow.off("click" + namespace, selectBoxSelector)
- .on("click" + namespace, selectBoxSelector, function(e)
- {
- e.stopPropagation();
-
- if ($(this).prop("checked"))
- {
- that.select();
- }
- else
- {
- that.deselect();
- }
- });
- }
- }
-
- function setTableHeaderSortDirection(element)
- {
- var css = this.options.css,
- iconSelector = getCssSelector(css.icon),
- columnId = element.data("column-id") || element.parents("th").first().data("column-id"),
- sortOrder = this.sortDictionary[columnId],
- icon = element.find(iconSelector);
-
- if (!this.options.multiSort)
- {
- element.parents("tr").first().find(iconSelector).removeClass(css.iconDown + " " + css.iconUp);
- this.sortDictionary = {};
- }
-
- if (sortOrder && sortOrder === "asc")
- {
- this.sortDictionary[columnId] = "desc";
- icon.removeClass(css.iconUp).addClass(css.iconDown);
- }
- else if (sortOrder && sortOrder === "desc")
- {
- if (this.options.multiSort)
- {
- var newSort = {};
- for (var key in this.sortDictionary)
- {
- if (key !== columnId)
- {
- newSort[key] = this.sortDictionary[key];
- }
- }
- this.sortDictionary = newSort;
- icon.removeClass(css.iconDown);
- }
- else
- {
- this.sortDictionary[columnId] = "asc";
- icon.removeClass(css.iconDown).addClass(css.iconUp);
- }
- }
- else
- {
- this.sortDictionary[columnId] = "asc";
- icon.addClass(css.iconUp);
- }
- }
-
- function replacePlaceHolder(placeholder, element)
- {
- placeholder.each(function (index, item)
- {
- // todo: check how append is implemented. Perhaps cloning here is superfluous.
- $(item).before(element.clone(true)).remove();
- });
- }
-
- function showLoading()
- {
- var that = this;
-
- window.setTimeout(function()
- {
- if (that.element._bgAria("busy") === "true")
- {
- var tpl = that.options.templates,
- thead = that.element.children("thead").first(),
- tbody = that.element.children("tbody").first(),
- firstCell = tbody.find("tr > td").first(),
- padding = (that.element.height() - thead.height()) - (firstCell.height() + 20),
- count = that.columns.where(isVisible).length;
-
- if (that.selection)
- {
- count = count + 1;
- }
- tbody.html(tpl.loading.resolve(getParams.call(that, { columns: count })));
- if (that.rowCount !== -1 && padding > 0)
- {
- tbody.find("tr > td").css("padding", "20px 0 " + padding + "px");
- }
- }
- }, 250);
- }
-
- function sortRows()
- {
- var sortArray = [];
-
- function sort(x, y, current)
- {
- current = current || 0;
- var next = current + 1,
- item = sortArray[current];
-
- function sortOrder(value)
- {
- return (item.order === "asc") ? value : value * -1;
- }
-
- return (x[item.id] > y[item.id]) ? sortOrder(1) :
- (x[item.id] < y[item.id]) ? sortOrder(-1) :
- (sortArray.length > next) ? sort(x, y, next) : 0;
- }
-
- if (!this.options.ajax)
- {
- var that = this;
-
- for (var key in this.sortDictionary)
- {
- if (this.options.multiSort || sortArray.length === 0)
- {
- sortArray.push({
- id: key,
- order: this.sortDictionary[key]
- });
- }
- }
-
- if (sortArray.length > 0)
- {
- this.rows.sort(sort);
- }
- }
- }
-
- // GRID PUBLIC CLASS DEFINITION
- // ====================
-
- /**
- * Represents the jQuery Bootgrid plugin.
- *
- * @class Grid
- * @constructor
- * @param element {Object} The corresponding DOM element.
- * @param options {Object} The options to override default settings.
- * @chainable
- **/
- var Grid = function(element, options)
- {
- this.element = $(element);
- this.origin = this.element.clone();
- this.options = $.extend(true, {}, Grid.defaults, this.element.data(), options);
- // overrides rowCount explicitly because deep copy ($.extend) leads to strange behaviour
- var rowCount = this.options.rowCount = this.element.data().rowCount || options.rowCount || this.options.rowCount;
- this.columns = [];
- this.current = 1;
- this.currentRows = [];
- this.identifier = null; // The first column ID that is marked as identifier
- this.selection = false;
- this.converter = null; // The converter for the column that is marked as identifier
- this.rowCount = ($.isArray(rowCount)) ? rowCount[0] : rowCount;
- this.rows = [];
- this.searchPhrase = "";
- this.selectedRows = [];
- this.sortDictionary = {};
- this.total = 0;
- this.totalPages = 0;
- this.cachedParams = {
- lbl: this.options.labels,
- css: this.options.css,
- ctx: {}
- };
- this.header = null;
- this.footer = null;
- this.xqr = null;
-
- // todo: implement cache
- };
-
- /**
- * An object that represents the default settings.
- *
- * @static
- * @class defaults
- * @for Grid
- * @example
- * // Global approach
- * $.bootgrid.defaults.selection = true;
- * @example
- * // Initialization approach
- * $("#bootgrid").bootgrid({ selection = true });
- **/
- Grid.defaults = {
- navigation: 3, // it's a flag: 0 = none, 1 = top, 2 = bottom, 3 = both (top and bottom)
- padding: 2, // page padding (pagination)
- columnSelection: true,
- rowCount: [10, 25, 50, -1], // rows per page int or array of int (-1 represents "All")
-
- /**
- * Enables row selection (to enable multi selection see also `multiSelect`). Default value is `false`.
- *
- * @property selection
- * @type Boolean
- * @default false
- * @for defaults
- * @since 1.0.0
- **/
- selection: false,
-
- /**
- * Enables multi selection (`selection` must be set to `true` as well). Default value is `false`.
- *
- * @property multiSelect
- * @type Boolean
- * @default false
- * @for defaults
- * @since 1.0.0
- **/
- multiSelect: false,
-
- /**
- * Enables entire row click selection (`selection` must be set to `true` as well). Default value is `false`.
- *
- * @property rowSelect
- * @type Boolean
- * @default false
- * @for defaults
- * @since 1.1.0
- **/
- rowSelect: false,
-
- /**
- * Defines whether the row selection is saved internally on filtering, paging and sorting
- * (even if the selected rows are not visible).
- *
- * @property keepSelection
- * @type Boolean
- * @default false
- * @for defaults
- * @since 1.1.0
- **/
- keepSelection: false,
-
- highlightRows: false, // highlights new rows (find the page of the first new row)
- sorting: true,
- multiSort: false,
-
- /**
- * General search settings to configure the search field behaviour.
- *
- * @property searchSettings
- * @type Object
- * @for defaults
- * @since 1.2.0
- **/
- searchSettings: {
- /**
- * The time in milliseconds to wait before search gets executed.
- *
- * @property delay
- * @type Number
- * @default 250
- * @for searchSettings
- **/
- delay: 250,
-
- /**
- * The characters to type before the search gets executed.
- *
- * @property characters
- * @type Number
- * @default 1
- * @for searchSettings
- **/
- characters: 1
- },
-
- /**
- * Defines whether the data shall be loaded via an asynchronous HTTP (Ajax) request.
- *
- * @property ajax
- * @type Boolean
- * @default false
- * @for defaults
- **/
- ajax: false,
-
- /**
- * Ajax request settings that shall be used for server-side communication.
- * All setting except data, error, success and url can be overridden.
- * For the full list of settings go to http://api.jquery.com/jQuery.ajax/.
- *
- * @property ajaxSettings
- * @type Object
- * @for defaults
- * @since 1.2.0
- **/
- ajaxSettings: {
- /**
- * Specifies the HTTP method which shall be used when sending data to the server.
- * Go to http://api.jquery.com/jQuery.ajax/ for more details.
- * This setting is overriden for backward compatibility.
- *
- * @property method
- * @type String
- * @default "POST"
- * @for ajaxSettings
- **/
- method: "POST"
- },
-
- /**
- * Enriches the request object with additional properties. Either a `PlainObject` or a `Function`
- * that returns a `PlainObject` can be passed. Default value is `{}`.
- *
- * @property post
- * @type Object|Function
- * @default function (request) { return request; }
- * @for defaults
- * @deprecated Use instead `requestHandler`
- **/
- post: {}, // or use function () { return {}; } (reserved properties are "current", "rowCount", "sort" and "searchPhrase")
-
- /**
- * Sets the data URL to a data service (e.g. a REST service). Either a `String` or a `Function`
- * that returns a `String` can be passed. Default value is `""`.
- *
- * @property url
- * @type String|Function
- * @default ""
- * @for defaults
- **/
- url: "", // or use function () { return ""; }
-
- /**
- * Defines whether the search is case sensitive or insensitive.
- *
- * @property caseSensitive
- * @type Boolean
- * @default true
- * @for defaults
- * @since 1.1.0
- **/
- caseSensitive: true,
-
- // note: The following properties should not be used via data-api attributes
-
- /**
- * Transforms the JSON request object in what ever is needed on the server-side implementation.
- *
- * @property requestHandler
- * @type Function
- * @default function (request) { return request; }
- * @for defaults
- * @since 1.1.0
- **/
- requestHandler: function (request) { return request; },
-
- /**
- * Transforms the response object into the expected JSON response object.
- *
- * @property responseHandler
- * @type Function
- * @default function (response) { return response; }
- * @for defaults
- * @since 1.1.0
- **/
- responseHandler: function (response) { return response; },
-
- /**
- * A list of converters.
- *
- * @property converters
- * @type Object
- * @for defaults
- * @since 1.0.0
- **/
- converters: {
- numeric: {
- from: function (value) { return +value; }, // converts from string to numeric
- to: function (value) { return value + ""; } // converts from numeric to string
- },
- string: {
- // default converter
- from: function (value) { return value; },
- to: function (value) { return value; }
- }
- },
-
- /**
- * Contains all css classes.
- *
- * @property css
- * @type Object
- * @for defaults
- **/
- css: {
- actions: "actions btn-group", // must be a unique class name or constellation of class names within the header and footer
- center: "text-center",
- columnHeaderAnchor: "column-header-anchor", // must be a unique class name or constellation of class names within the column header cell
- columnHeaderText: "text",
- dropDownItem: "dropdown-item", // must be a unique class name or constellation of class names within the actionDropDown,
- dropDownItemButton: "dropdown-item-button", // must be a unique class name or constellation of class names within the actionDropDown
- dropDownItemCheckbox: "dropdown-item-checkbox", // must be a unique class name or constellation of class names within the actionDropDown
- dropDownMenu: "dropdown btn-group", // must be a unique class name or constellation of class names within the actionDropDown
- dropDownMenuItems: "dropdown-menu pull-right", // must be a unique class name or constellation of class names within the actionDropDown
- dropDownMenuText: "dropdown-text", // must be a unique class name or constellation of class names within the actionDropDown
- footer: "bootgrid-footer",
- header: "bootgrid-header",
- icon: "icon glyphicon",
- iconColumns: "glyphicon-th-list",
- iconDown: "glyphicon-chevron-down",
- iconRefresh: "glyphicon-refresh",
- iconSearch: "glyphicon-search",
- iconUp: "glyphicon-chevron-up",
- infos: "infos", // must be a unique class name or constellation of class names within the header and footer,
- left: "text-left",
- pagination: "pagination", // must be a unique class name or constellation of class names within the header and footer
- paginationButton: "button", // must be a unique class name or constellation of class names within the pagination
-
- /**
- * CSS class to select the parent div which activates responsive mode.
- *
- * @property responsiveTable
- * @type String
- * @default "table-responsive"
- * @for css
- * @since 1.1.0
- **/
- responsiveTable: "table-responsive",
-
- right: "text-right",
- search: "search form-group", // must be a unique class name or constellation of class names within the header and footer
- searchField: "search-field form-control",
- selectBox: "select-box", // must be a unique class name or constellation of class names within the entire table
- selectCell: "select-cell", // must be a unique class name or constellation of class names within the entire table
-
- /**
- * CSS class to highlight selected rows.
- *
- * @property selected
- * @type String
- * @default "active"
- * @for css
- * @since 1.1.0
- **/
- selected: "active",
-
- sortable: "sortable",
- table: "bootgrid-table table"
- },
-
- /**
- * A dictionary of formatters.
- *
- * @property formatters
- * @type Object
- * @for defaults
- * @since 1.0.0
- **/
- formatters: {},
-
- /**
- * Contains all labels.
- *
- * @property labels
- * @type Object
- * @for defaults
- **/
- labels: {
- all: "All",
- infos: "Showing {{ctx.start}} to {{ctx.end}} of {{ctx.total}} entries",
- loading: "Loading...",
- noResults: "No results found!",
- refresh: "Refresh",
- search: "Search"
- },
-
- /**
- * Specifies the mapping between status and contextual classes to color rows.
- *
- * @property statusMapping
- * @type Object
- * @for defaults
- * @since 1.2.0
- **/
- statusMapping: {
- /**
- * Specifies a successful or positive action.
- *
- * @property 0
- * @type String
- * @for statusMapping
- **/
- 0: "success",
-
- /**
- * Specifies a neutral informative change or action.
- *
- * @property 1
- * @type String
- * @for statusMapping
- **/
- 1: "info",
-
- /**
- * Specifies a warning that might need attention.
- *
- * @property 2
- * @type String
- * @for statusMapping
- **/
- 2: "warning",
-
- /**
- * Specifies a dangerous or potentially negative action.
- *
- * @property 3
- * @type String
- * @for statusMapping
- **/
- 3: "danger"
- },
-
- /**
- * Contains all templates.
- *
- * @property templates
- * @type Object
- * @for defaults
- **/
- templates: {
- actionButton: "",
- actionDropDown: "
",
- actionDropDownItem: "{{ctx.text}}",
- actionDropDownCheckboxItem: "",
- actions: "",
- body: "",
- cell: "{{ctx.content}} | ",
- footer: "",
- header: "",
- headerCell: "{{ctx.column.text}}{{ctx.icon}} | ",
- icon: "",
- infos: "{{lbl.infos}}
",
- loading: "{{lbl.loading}} |
",
- noResults: "{{lbl.noResults}} |
",
- pagination: "",
- paginationItem: "",
- rawHeaderCell: "{{ctx.content}} | ", // Used for the multi select box
- row: "{{ctx.cells}}
",
- search: "",
- select: ""
- }
- };
-
- /**
- * Appends rows.
- *
- * @method append
- * @param rows {Array} An array of rows to append
- * @chainable
- **/
- Grid.prototype.append = function(rows)
- {
- if (this.options.ajax)
- {
- // todo: implement ajax PUT
- }
- else
- {
- var appendedRows = [];
- for (var i = 0; i < rows.length; i++)
- {
- if (appendRow.call(this, rows[i]))
- {
- appendedRows.push(rows[i]);
- }
- }
- sortRows.call(this);
- highlightAppendedRows.call(this, appendedRows);
- loadData.call(this);
- this.element.trigger("appended" + namespace, [appendedRows]);
- }
-
- return this;
- };
-
- /**
- * Removes all rows.
- *
- * @method clear
- * @chainable
- **/
- Grid.prototype.clear = function()
- {
- if (this.options.ajax)
- {
- // todo: implement ajax POST
- }
- else
- {
- var removedRows = $.extend([], this.rows);
- this.rows = [];
- this.current = 1;
- this.total = 0;
- loadData.call(this);
- this.element.trigger("cleared" + namespace, [removedRows]);
- }
-
- return this;
- };
-
- /**
- * Removes the control functionality completely and transforms the current state to the initial HTML structure.
- *
- * @method destroy
- * @chainable
- **/
- Grid.prototype.destroy = function()
- {
- // todo: this method has to be optimized (the complete initial state must be restored)
- $(window).off(namespace);
- if (this.options.navigation & 1)
- {
- this.header.remove();
- }
- if (this.options.navigation & 2)
- {
- this.footer.remove();
- }
- this.element.before(this.origin).remove();
-
- return this;
- };
-
- /**
- * Resets the state and reloads rows.
- *
- * @method reload
- * @chainable
- **/
- Grid.prototype.reload = function()
- {
- if(!this.current){
- this.current = 1; // reset
- }
- loadData.call(this);
-
- return this;
- };
-
- /**
- * Removes rows by ids. Removes selected rows if no ids are provided.
- *
- * @method remove
- * @param [rowsIds] {Array} An array of rows ids to remove
- * @chainable
- **/
- Grid.prototype.remove = function(rowIds)
- {
- if (this.identifier != null)
- {
- var that = this;
-
- if (this.options.ajax)
- {
- // todo: implement ajax DELETE
- }
- else
- {
- rowIds = rowIds || this.selectedRows;
- var id,
- removedRows = [];
-
- for (var i = 0; i < rowIds.length; i++)
- {
- id = rowIds[i];
-
- for (var j = 0; j < this.rows.length; j++)
- {
- if (this.rows[j][this.identifier] === id)
- {
- removedRows.push(this.rows[j]);
- this.rows.splice(j, 1);
- break;
- }
- }
- }
-
- this.current = 1; // reset
- loadData.call(this);
- this.element.trigger("removed" + namespace, [removedRows]);
- }
- }
-
- return this;
- };
-
- /**
- * Searches in all rows for a specific phrase (but only in visible cells).
- * The search filter will be reseted, if no argument is provided.
- *
- * @method search
- * @param [phrase] {String} The phrase to search for
- * @chainable
- **/
- Grid.prototype.search = function(phrase)
- {
- phrase = phrase || "";
-
- if (this.searchPhrase !== phrase)
- {
- var selector = getCssSelector(this.options.css.searchField),
- searchFields = findFooterAndHeaderItems.call(this, selector);
- searchFields.val(phrase);
- }
-
- executeSearch.call(this, phrase);
-
-
- return this;
- };
-
- /**
- * Selects rows by ids. Selects all visible rows if no ids are provided.
- * In server-side scenarios only visible rows are selectable.
- *
- * @method select
- * @param [rowsIds] {Array} An array of rows ids to select
- * @chainable
- **/
- Grid.prototype.select = function(rowIds)
- {
- if (this.selection)
- {
- rowIds = rowIds || this.currentRows.propValues(this.identifier);
-
- var id, i,
- selectedRows = [];
-
- while (rowIds.length > 0 && !(!this.options.multiSelect && selectedRows.length === 1))
- {
- id = rowIds.pop();
- if ($.inArray(id, this.selectedRows) === -1)
- {
- for (i = 0; i < this.currentRows.length; i++)
- {
- if (this.currentRows[i][this.identifier] === id)
- {
- selectedRows.push(this.currentRows[i]);
- this.selectedRows.push(id);
- break;
- }
- }
- }
- }
-
- if (selectedRows.length > 0)
- {
- var selectBoxSelector = getCssSelector(this.options.css.selectBox),
- selectMultiSelectBox = this.selectedRows.length >= this.currentRows.length;
-
- i = 0;
- while (!this.options.keepSelection && selectMultiSelectBox && i < this.currentRows.length)
- {
- selectMultiSelectBox = ($.inArray(this.currentRows[i++][this.identifier], this.selectedRows) !== -1);
- }
- this.element.find("thead " + selectBoxSelector).prop("checked", selectMultiSelectBox);
-
- if (!this.options.multiSelect)
- {
- this.element.find("tbody > tr " + selectBoxSelector + ":checked")
- .trigger("click" + namespace);
- }
-
- for (i = 0; i < this.selectedRows.length; i++)
- {
- this.element.find("tbody > tr[data-row-id=\"" + this.selectedRows[i] + "\"]")
- .addClass(this.options.css.selected)._bgAria("selected", "true")
- .find(selectBoxSelector).prop("checked", true);
- }
-
- this.element.trigger("selected" + namespace, [selectedRows]);
- }
- }
-
- return this;
- };
-
- /**
- * Deselects rows by ids. Deselects all visible rows if no ids are provided.
- * In server-side scenarios only visible rows are deselectable.
- *
- * @method deselect
- * @param [rowsIds] {Array} An array of rows ids to deselect
- * @chainable
- **/
- Grid.prototype.deselect = function(rowIds)
- {
- if (this.selection)
- {
- rowIds = rowIds || this.currentRows.propValues(this.identifier);
-
- var id, i, pos,
- deselectedRows = [];
-
- while (rowIds.length > 0)
- {
- id = rowIds.pop();
- pos = $.inArray(id, this.selectedRows);
- if (pos !== -1)
- {
- for (i = 0; i < this.currentRows.length; i++)
- {
- if (this.currentRows[i][this.identifier] === id)
- {
- deselectedRows.push(this.currentRows[i]);
- this.selectedRows.splice(pos, 1);
- break;
- }
- }
- }
- }
-
- if (deselectedRows.length > 0)
- {
- var selectBoxSelector = getCssSelector(this.options.css.selectBox);
-
- this.element.find("thead " + selectBoxSelector).prop("checked", false);
- for (i = 0; i < deselectedRows.length; i++)
- {
- this.element.find("tbody > tr[data-row-id=\"" + deselectedRows[i][this.identifier] + "\"]")
- .removeClass(this.options.css.selected)._bgAria("selected", "false")
- .find(selectBoxSelector).prop("checked", false);
- }
-
- this.element.trigger("deselected" + namespace, [deselectedRows]);
- }
- }
-
- return this;
- };
-
- /**
- * Sorts the rows by a given sort descriptor dictionary.
- * The sort filter will be reseted, if no argument is provided.
- *
- * @method sort
- * @param [dictionary] {Object} A sort descriptor dictionary that contains the sort information
- * @chainable
- **/
- Grid.prototype.sort = function(dictionary)
- {
- var values = (dictionary) ? $.extend({}, dictionary) : {};
-
- if (values === this.sortDictionary)
- {
- return this;
- }
-
- this.sortDictionary = values;
- renderTableHeader.call(this);
- sortRows.call(this);
- loadData.call(this);
-
- return this;
- };
-
- /**
- * Gets a list of the column settings.
- * This method returns only for the first grid instance a value.
- * Therefore be sure that only one grid instance is catched by your selector.
- *
- * @method getColumnSettings
- * @return {Array} Returns a list of the column settings.
- * @since 1.2.0
- **/
- Grid.prototype.getColumnSettings = function()
- {
- return $.merge([], this.columns);
- };
-
- /**
- * Gets the current page index.
- * This method returns only for the first grid instance a value.
- * Therefore be sure that only one grid instance is catched by your selector.
- *
- * @method getCurrentPage
- * @return {Number} Returns the current page index.
- * @since 1.2.0
- **/
- Grid.prototype.getCurrentPage = function()
- {
- return this.current;
- };
-
- /**
- * Gets the current rows.
- * This method returns only for the first grid instance a value.
- * Therefore be sure that only one grid instance is catched by your selector.
- *
- * @method getCurrentPage
- * @return {Array} Returns the current rows.
- * @since 1.2.0
- **/
- Grid.prototype.getCurrentRows = function()
- {
- return $.merge([], this.currentRows);
- };
-
- /**
- * Gets a number represents the row count per page.
- * This method returns only for the first grid instance a value.
- * Therefore be sure that only one grid instance is catched by your selector.
- *
- * @method getRowCount
- * @return {Number} Returns the row count per page.
- * @since 1.2.0
- **/
- Grid.prototype.getRowCount = function()
- {
- return this.rowCount;
- };
-
- /**
- * Gets the actual search phrase.
- * This method returns only for the first grid instance a value.
- * Therefore be sure that only one grid instance is catched by your selector.
- *
- * @method getSearchPhrase
- * @return {String} Returns the actual search phrase.
- * @since 1.2.0
- **/
- Grid.prototype.getSearchPhrase = function()
- {
- return this.searchPhrase;
- };
-
- /**
- * Gets the complete list of currently selected rows.
- * This method returns only for the first grid instance a value.
- * Therefore be sure that only one grid instance is catched by your selector.
- *
- * @method getSelectedRows
- * @return {Array} Returns all selected rows.
- * @since 1.2.0
- **/
- Grid.prototype.getSelectedRows = function()
- {
- return $.merge([], this.selectedRows);
- };
-
- /**
- * Gets the sort dictionary which represents the state of column sorting.
- * This method returns only for the first grid instance a value.
- * Therefore be sure that only one grid instance is catched by your selector.
- *
- * @method getSortDictionary
- * @return {Object} Returns the sort dictionary.
- * @since 1.2.0
- **/
- Grid.prototype.getSortDictionary = function()
- {
- return $.extend({}, this.sortDictionary);
- };
-
- /**
- * Gets a number represents the total page count.
- * This method returns only for the first grid instance a value.
- * Therefore be sure that only one grid instance is catched by your selector.
- *
- * @method getTotalPageCount
- * @return {Number} Returns the total page count.
- * @since 1.2.0
- **/
- Grid.prototype.getTotalPageCount = function()
- {
- return this.totalPages;
- };
-
- /**
- * Gets a number represents the total row count.
- * This method returns only for the first grid instance a value.
- * Therefore be sure that only one grid instance is catched by your selector.
- *
- * @method getTotalRowCount
- * @return {Number} Returns the total row count.
- * @since 1.2.0
- **/
- Grid.prototype.getTotalRowCount = function()
- {
- return this.total;
- };
-
- // GRID COMMON TYPE EXTENSIONS
- // ============
-
- $.fn.extend({
- _bgAria: function (name, value)
- {
- return (value) ? this.attr("aria-" + name, value) : this.attr("aria-" + name);
- },
-
- _bgBusyAria: function(busy)
- {
- return (busy == null || busy) ?
- this._bgAria("busy", "true") :
- this._bgAria("busy", "false");
- },
-
- _bgRemoveAria: function (name)
- {
- return this.removeAttr("aria-" + name);
- },
-
- _bgEnableAria: function (enable)
- {
- return (enable == null || enable) ?
- this.removeClass("disabled")._bgAria("disabled", "false") :
- this.addClass("disabled")._bgAria("disabled", "true");
- },
-
- _bgEnableField: function (enable)
- {
- return (enable == null || enable) ?
- this.removeAttr("disabled") :
- this.attr("disabled", "disable");
- },
-
- _bgShowAria: function (show)
- {
- return (show == null || show) ?
- this.show()._bgAria("hidden", "false") :
- this.hide()._bgAria("hidden", "true");
- },
-
- _bgSelectAria: function (select)
- {
- return (select == null || select) ?
- this.addClass("active")._bgAria("selected", "true") :
- this.removeClass("active")._bgAria("selected", "false");
- },
-
- _bgId: function (id)
- {
- return (id) ? this.attr("id", id) : this.attr("id");
- }
- });
-
- if (!String.prototype.resolve)
- {
- var formatter = {
- "checked": function(value)
- {
- if (typeof value === "boolean")
- {
- return (value) ? "checked=\"checked\"" : "";
- }
- return value;
- }
- };
-
- String.prototype.resolve = function (substitutes, prefixes)
- {
- var result = this;
- $.each(substitutes, function (key, value)
- {
- if (value != null && typeof value !== "function")
- {
- if (typeof value === "object")
- {
- var keys = (prefixes) ? $.extend([], prefixes) : [];
- keys.push(key);
- result = result.resolve(value, keys) + "";
- }
- else
- {
- if (formatter && formatter[key] && typeof formatter[key] === "function")
- {
- value = formatter[key](value);
- }
- key = (prefixes) ? prefixes.join(".") + "." + key : key;
- var pattern = new RegExp("\\{\\{" + key + "\\}\\}", "gm");
- result = result.replace(pattern, (value.replace) ? value.replace(/\$/gi, "$") : value);
- }
- }
- });
- return result;
- };
- }
-/* if is conflicted with wavesurfer video.js */
- if (!Array.prototype.first)
- {
- Array.prototype.first = function (condition)
- {
- for (var i = 0; i < this.length; i++)
- {
- var item = this[i];
- if (condition(item))
- {
- return item;
- }
- }
- return null;
- };
- }
-
- if (!Array.prototype.contains)
- {
- Array.prototype.contains = function (condition)
- {
- for (var i = 0; i < this.length; i++)
- {
- var item = this[i];
- if (condition(item))
- {
- return true;
- }
- }
- return false;
- };
- }
-
- if (!Array.prototype.page)
- {
- Array.prototype.page = function (page, size)
- {
- var skip = (page - 1) * size,
- end = skip + size;
- return (this.length > skip) ?
- (this.length > end) ? this.slice(skip, end) :
- this.slice(skip) : [];
- };
- }
-
- if (!Array.prototype.where)
- {
- Array.prototype.where = function (condition)
- {
- var result = [];
- for (var i = 0; i < this.length; i++)
- {
- var item = this[i];
- if (condition(item))
- {
- result.push(item);
- }
- }
- return result;
- };
- }
-
- if (!Array.prototype.propValues)
- {
- Array.prototype.propValues = function (propName)
- {
- var result = [];
- for (var i = 0; i < this.length; i++)
- {
- result.push(this[i][propName]);
- }
- return result;
- };
- }
-
- // GRID PLUGIN DEFINITION
- // =====================
-
- var old = $.fn.bootgrid;
-
- $.fn.bootgrid = function (option)
- {
- var args = Array.prototype.slice.call(arguments, 1),
- returnValue = null,
- elements = this.each(function (index)
- {
- var $this = $(this),
- instance = $this.data(namespace),
- options = typeof option === "object" && option;
-
- if (!instance && option === "destroy")
- {
- return;
- }
- if (!instance)
- {
- $this.data(namespace, (instance = new Grid(this, options)));
- init.call(instance);
- }
- if (typeof option === "string")
- {
- if (option.indexOf("get") === 0 && index === 0)
- {
- returnValue = instance[option].apply(instance, args);
- }
- else if (option.indexOf("get") !== 0)
- {
- return instance[option].apply(instance, args);
- }
- }
- });
- return (typeof option === "string" && option.indexOf("get") === 0) ? returnValue : elements;
- };
-
- $.fn.bootgrid.Constructor = Grid;
-
- // GRID NO CONFLICT
- // ===============
-
- $.fn.bootgrid.noConflict = function ()
- {
- $.fn.bootgrid = old;
- return this;
- };
-
- // GRID DATA-API
- // ============
-
-$("[data-toggle=\"bootgrid\"]").bootgrid();
+/*!
+ * jQuery Bootgrid v1.3.1 - 09/11/2015
+ * Copyright (c) 2014-2015 Rafael Staib (http://www.jquery-bootgrid.com)
+ * Licensed under MIT http://www.opensource.org/licenses/MIT
+ */
+;(function ($, window, undefined)
+{
+ /*jshint validthis: true */
+ "use strict";
+
+ // GRID INTERNAL FIELDS
+ // ====================
+
+ var namespace = ".rs.jquery.bootgrid";
+
+ // GRID INTERNAL FUNCTIONS
+ // =====================
+
+ function appendRow(row)
+ {
+ var that = this;
+
+ function exists(item)
+ {
+ return that.identifier && item[that.identifier] === row[that.identifier];
+ }
+
+ if (!this.rows.contains(exists))
+ {
+ this.rows.push(row);
+ return true;
+ }
+
+ return false;
+ }
+
+ function findFooterAndHeaderItems(selector)
+ {
+ var footer = (this.footer) ? this.footer.find(selector) : $(),
+ header = (this.header) ? this.header.find(selector) : $();
+ return $.merge(footer, header);
+ }
+
+ function getParams(context)
+ {
+ return (context) ? $.extend({}, this.cachedParams, { ctx: context }) :
+ this.cachedParams;
+ }
+
+ function getRequest()
+ {
+ var request = {
+ current: this.current,
+ rowCount: this.rowCount,
+ sort: this.sortDictionary,
+ searchPhrase: this.searchPhrase
+ },
+ post = this.options.post;
+
+ post = ($.isFunction(post)) ? post() : post;
+ return this.options.requestHandler($.extend(true, request, post));
+ }
+
+ function getCssSelector(css)
+ {
+ return "." + $.trim(css).replace(/\s+/gm, ".");
+ }
+
+ function getUrl()
+ {
+ var url = this.options.url;
+ return ($.isFunction(url)) ? url() : url;
+ }
+
+ function init()
+ {
+ this.element.trigger("initialize" + namespace);
+
+ loadColumns.call(this); // Loads columns from HTML thead tag
+ this.selection = this.options.selection && this.identifier != null;
+ loadRows.call(this); // Loads rows from HTML tbody tag if ajax is false
+ prepareTable.call(this);
+ renderTableHeader.call(this);
+ renderSearchField.call(this);
+ renderActions.call(this);
+ loadData.call(this);
+
+ this.element.trigger("initialized" + namespace);
+ }
+
+ function highlightAppendedRows(rows)
+ {
+ if (this.options.highlightRows)
+ {
+ // todo: implement
+ }
+ }
+
+ function isVisible(column)
+ {
+ return column.visible;
+ }
+
+ function loadColumns()
+ {
+ var that = this,
+ firstHeadRow = this.element.find("thead > tr").first(),
+ sorted = false;
+
+ /*jshint -W018*/
+ firstHeadRow.children().each(function ()
+ {
+ var $this = $(this),
+ data = $this.data(),
+ column = {
+ id: data.columnId,
+ identifier: that.identifier == null && data.identifier || false,
+ converter: that.options.converters[data.converter || data.type] || that.options.converters["string"],
+ text: $this.text(),
+ align: data.align || "left",
+ headerAlign: data.headerAlign || "left",
+ cssClass: data.cssClass || "",
+ headerCssClass: data.headerCssClass || "",
+ formatter: that.options.formatters[data.formatter] || null,
+ order: (!sorted && (data.order === "asc" || data.order === "desc")) ? data.order : null,
+ searchable: !(data.searchable === false), // default: true
+ sortable: !(data.sortable === false), // default: true
+ visible: !(data.visible === false), // default: true
+ visibleInSelection: !(data.visibleInSelection === false), // default: true
+ width: ($.isNumeric(data.width)) ? data.width + "px" :
+ (typeof(data.width) === "string") ? data.width : null
+ };
+ that.columns.push(column);
+ if (column.order != null)
+ {
+ that.sortDictionary[column.id] = column.order;
+ }
+
+ // Prevents multiple identifiers
+ if (column.identifier)
+ {
+ that.identifier = column.id;
+ that.converter = column.converter;
+ }
+
+ // ensures that only the first order will be applied in case of multi sorting is disabled
+ if (!that.options.multiSort && column.order !== null)
+ {
+ sorted = true;
+ }
+ });
+ /*jshint +W018*/
+ }
+
+ /*
+ response = {
+ current: 1,
+ rowCount: 10,
+ rows: [{}, {}],
+ sort: [{ "columnId": "asc" }],
+ total: 101
+ }
+ */
+
+ function loadData()
+ {
+ var that = this;
+
+ this.element._bgBusyAria(true).trigger("load" + namespace);
+ showLoading.call(this);
+
+ function containsPhrase(row)
+ {
+ var column,
+ searchPattern = new RegExp(that.searchPhrase, (that.options.caseSensitive) ? "g" : "gi");
+
+ for (var i = 0; i < that.columns.length; i++)
+ {
+ column = that.columns[i];
+ if (column.searchable && column.visible &&
+ column.converter.to(row[column.id]).search(searchPattern) > -1)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ function update(rows, total)
+ {
+ that.currentRows = rows;
+ setTotals.call(that, total);
+
+ if (!that.options.keepSelection)
+ {
+ that.selectedRows = [];
+ }
+
+ renderRows.call(that, rows);
+ renderInfos.call(that);
+ renderPagination.call(that);
+
+ that.element._bgBusyAria(false).trigger("loaded" + namespace);
+ }
+
+ if (this.options.ajax)
+ {
+ var request = getRequest.call(this),
+ url = getUrl.call(this);
+
+ if (url == null || typeof url !== "string" || url.length === 0)
+ {
+ throw new Error("Url setting must be a none empty string or a function that returns one.");
+ }
+
+ // aborts the previous ajax request if not already finished or failed
+ if (this.xqr)
+ {
+ this.xqr.abort();
+ }
+
+ var settings = {
+ url: url,
+ data: request,
+ success: function(response)
+ {
+ that.xqr = null;
+
+ if (typeof (response) === "string")
+ {
+ response = $.parseJSON(response);
+ }
+
+ response = that.options.responseHandler(response);
+
+ that.current = response.current;
+ update(response.rows, response.total);
+ },
+ error: function (jqXHR, textStatus, errorThrown)
+ {
+ that.xqr = null;
+
+ if (textStatus !== "abort")
+ {
+ renderNoResultsRow.call(that); // overrides loading mask
+ that.element._bgBusyAria(false).trigger("loaded" + namespace);
+ }
+ }
+ };
+ settings = $.extend(this.options.ajaxSettings, settings);
+
+ this.xqr = $.ajax(settings);
+ }
+ else
+ {
+ var rows = (this.searchPhrase.length > 0) ? this.rows.where(containsPhrase) : this.rows,
+ total = rows.length;
+ if (this.rowCount !== -1)
+ {
+ rows = rows.page(this.current, this.rowCount);
+ }
+
+ // todo: improve the following comment
+ // setTimeout decouples the initialization so that adding event handlers happens before
+ window.setTimeout(function () { update(rows, total); }, 10);
+ }
+ }
+
+ function loadRows()
+ {
+ if (!this.options.ajax)
+ {
+ var that = this,
+ rows = this.element.find("tbody > tr");
+
+ rows.each(function ()
+ {
+ var $this = $(this),
+ cells = $this.children("td"),
+ row = {};
+
+ $.each(that.columns, function (i, column)
+ {
+ row[column.id] = column.converter.from(cells.eq(i).text());
+ });
+
+ appendRow.call(that, row);
+ });
+
+ setTotals.call(this, this.rows.length);
+ sortRows.call(this);
+ }
+ }
+
+ function setTotals(total)
+ {
+ this.total = total;
+ this.totalPages = (this.rowCount === -1) ? 1 :
+ Math.ceil(this.total / this.rowCount);
+ }
+
+ function prepareTable()
+ {
+ var tpl = this.options.templates,
+ wrapper = (this.element.parent().hasClass(this.options.css.responsiveTable)) ?
+ this.element.parent() : this.element;
+
+ this.element.addClass(this.options.css.table);
+
+ // checks whether there is an tbody element; otherwise creates one
+ if (this.element.children("tbody").length === 0)
+ {
+ this.element.append(tpl.body);
+ }
+
+ if (this.options.navigation & 1)
+ {
+ this.header = $(tpl.header.resolve(getParams.call(this, { id: this.element._bgId() + "-header" })));
+ wrapper.before(this.header);
+ }
+
+ if (this.options.navigation & 2)
+ {
+ this.footer = $(tpl.footer.resolve(getParams.call(this, { id: this.element._bgId() + "-footer" })));
+ wrapper.after(this.footer);
+ }
+ }
+
+ function renderActions()
+ {
+ if (this.options.navigation !== 0)
+ {
+ var css = this.options.css,
+ selector = getCssSelector(css.actions),
+ actionItems = findFooterAndHeaderItems.call(this, selector);
+
+ if (actionItems.length > 0)
+ {
+ var that = this,
+ tpl = this.options.templates,
+ actions = $(tpl.actions.resolve(getParams.call(this)));
+
+ // Refresh Button
+ if (this.options.ajax)
+ {
+ var refreshIcon = tpl.icon.resolve(getParams.call(this, { iconCss: css.iconRefresh })),
+ refresh = $(tpl.actionButton.resolve(getParams.call(this,
+ { content: refreshIcon, text: this.options.labels.refresh })))
+ .on("click" + namespace, function (e)
+ {
+ // todo: prevent multiple fast clicks (fast click detection)
+ e.stopPropagation();
+ that.current = 1;
+ loadData.call(that);
+ });
+ actions.append(refresh);
+ }
+
+ // Row count selection
+ renderRowCountSelection.call(this, actions);
+
+ // Column selection
+ renderColumnSelection.call(this, actions);
+
+ replacePlaceHolder.call(this, actionItems, actions);
+ }
+ }
+ }
+
+ function renderColumnSelection(actions)
+ {
+ if (this.options.columnSelection && this.columns.length > 1)
+ {
+ var that = this,
+ css = this.options.css,
+ tpl = this.options.templates,
+ icon = tpl.icon.resolve(getParams.call(this, { iconCss: css.iconColumns })),
+ dropDown = $(tpl.actionDropDown.resolve(getParams.call(this, { content: icon }))),
+ selector = getCssSelector(css.dropDownItem),
+ checkboxSelector = getCssSelector(css.dropDownItemCheckbox),
+ itemsSelector = getCssSelector(css.dropDownMenuItems);
+
+ $.each(this.columns, function (i, column)
+ {
+ if (column.visibleInSelection)
+ {
+ var item = $(tpl.actionDropDownCheckboxItem.resolve(getParams.call(that,
+ { name: column.id, label: column.text, checked: column.visible })))
+ .on("click" + namespace, selector, function (e)
+ {
+ e.stopPropagation();
+
+ var $this = $(this),
+ checkbox = $this.find(checkboxSelector);
+ if (!checkbox.prop("disabled"))
+ {
+ column.visible = checkbox.prop("checked");
+ var enable = that.columns.where(isVisible).length > 1;
+ $this.parents(itemsSelector).find(selector + ":has(" + checkboxSelector + ":checked)")
+ ._bgEnableAria(enable).find(checkboxSelector)._bgEnableField(enable);
+
+ that.element.find("tbody").empty(); // Fixes an column visualization bug
+ renderTableHeader.call(that);
+ loadData.call(that);
+ }
+ });
+ dropDown.find(getCssSelector(css.dropDownMenuItems)).append(item);
+ }
+ });
+ actions.append(dropDown);
+ }
+ }
+
+ function renderInfos()
+ {
+ if (this.options.navigation !== 0)
+ {
+ var selector = getCssSelector(this.options.css.infos),
+ infoItems = findFooterAndHeaderItems.call(this, selector);
+
+ if (infoItems.length > 0)
+ {
+ var end = (this.current * this.rowCount),
+ infos = $(this.options.templates.infos.resolve(getParams.call(this, {
+ end: (this.total === 0 || end === -1 || end > this.total) ? this.total : end,
+ start: (this.total === 0) ? 0 : (end - this.rowCount + 1),
+ total: this.total
+ })));
+
+ replacePlaceHolder.call(this, infoItems, infos);
+ }
+ }
+ }
+
+ function renderNoResultsRow()
+ {
+ var tbody = this.element.children("tbody").first(),
+ tpl = this.options.templates,
+ count = this.columns.where(isVisible).length;
+
+ if (this.selection)
+ {
+ count = count + 1;
+ }
+ tbody.html(tpl.noResults.resolve(getParams.call(this, { columns: count })));
+ }
+
+ function renderPagination()
+ {
+ if (this.options.navigation !== 0)
+ {
+ var selector = getCssSelector(this.options.css.pagination),
+ paginationItems = findFooterAndHeaderItems.call(this, selector)._bgShowAria(this.rowCount !== -1);
+
+ if (this.rowCount !== -1 && paginationItems.length > 0)
+ {
+ var tpl = this.options.templates,
+ current = this.current,
+ totalPages = this.totalPages,
+ pagination = $(tpl.pagination.resolve(getParams.call(this))),
+ offsetRight = totalPages - current,
+ offsetLeft = (this.options.padding - current) * -1,
+ startWith = ((offsetRight >= this.options.padding) ?
+ Math.max(offsetLeft, 1) :
+ Math.max((offsetLeft - this.options.padding + offsetRight), 1)),
+ maxCount = this.options.padding * 2 + 1,
+ count = (totalPages >= maxCount) ? maxCount : totalPages;
+
+ renderPaginationItem.call(this, pagination, "first", "«", "first")
+ ._bgEnableAria(current > 1);
+ renderPaginationItem.call(this, pagination, "prev", "<", "prev")
+ ._bgEnableAria(current > 1);
+
+ for (var i = 0; i < count; i++)
+ {
+ var pos = i + startWith;
+ renderPaginationItem.call(this, pagination, pos, pos, "page-" + pos)
+ ._bgEnableAria()._bgSelectAria(pos === current);
+ }
+
+ if (count === 0)
+ {
+ renderPaginationItem.call(this, pagination, 1, 1, "page-" + 1)
+ ._bgEnableAria(false)._bgSelectAria();
+ }
+
+ renderPaginationItem.call(this, pagination, "next", ">", "next")
+ ._bgEnableAria(totalPages > current);
+ renderPaginationItem.call(this, pagination, "last", "»", "last")
+ ._bgEnableAria(totalPages > current);
+
+ replacePlaceHolder.call(this, paginationItems, pagination);
+ }
+ }
+ }
+
+ function renderPaginationItem(list, page, text, markerCss)
+ {
+ var that = this,
+ tpl = this.options.templates,
+ css = this.options.css,
+ values = getParams.call(this, { css: markerCss, text: text, page: page }),
+ item = $(tpl.paginationItem.resolve(values))
+ .on("click" + namespace, getCssSelector(css.paginationButton), function (e)
+ {
+ e.stopPropagation();
+ e.preventDefault();
+
+ var $this = $(this),
+ parent = $this.parent();
+ if (!parent.hasClass("active") && !parent.hasClass("disabled"))
+ {
+ var commandList = {
+ first: 1,
+ prev: that.current - 1,
+ next: that.current + 1,
+ last: that.totalPages
+ };
+ var command = $this.data("page");
+ that.current = commandList[command] || command;
+ loadData.call(that);
+ }
+ $this.trigger("blur");
+ });
+
+ list.append(item);
+ return item;
+ }
+
+ function renderRowCountSelection(actions)
+ {
+ var that = this,
+ rowCountList = this.options.rowCount;
+
+ function getText(value)
+ {
+ return (value === -1) ? that.options.labels.all : value;
+ }
+
+ if ($.isArray(rowCountList))
+ {
+ var css = this.options.css,
+ tpl = this.options.templates,
+ dropDown = $(tpl.actionDropDown.resolve(getParams.call(this, { content: getText(this.rowCount) }))),
+ menuSelector = getCssSelector(css.dropDownMenu),
+ menuTextSelector = getCssSelector(css.dropDownMenuText),
+ menuItemsSelector = getCssSelector(css.dropDownMenuItems),
+ menuItemSelector = getCssSelector(css.dropDownItemButton);
+
+ $.each(rowCountList, function (index, value)
+ {
+ var item = $(tpl.actionDropDownItem.resolve(getParams.call(that,
+ { text: getText(value), action: value })))
+ ._bgSelectAria(value === that.rowCount)
+ .on("click" + namespace, menuItemSelector, function (e)
+ {
+ e.preventDefault();
+
+ var $this = $(this),
+ newRowCount = $this.data("action");
+ if (newRowCount !== that.rowCount)
+ {
+ // todo: sophisticated solution needed for calculating which page is selected
+ that.current = 1; // that.rowCount === -1 ---> All
+ that.rowCount = newRowCount;
+ $this.parents(menuItemsSelector).children().each(function ()
+ {
+ var $item = $(this),
+ currentRowCount = $item.find(menuItemSelector).data("action");
+ $item._bgSelectAria(currentRowCount === newRowCount);
+ });
+ $this.parents(menuSelector).find(menuTextSelector).text(getText(newRowCount));
+ loadData.call(that);
+ }
+ });
+ dropDown.find(menuItemsSelector).append(item);
+ });
+ actions.append(dropDown);
+ }
+ }
+
+ function renderRows(rows)
+ {
+ if (rows.length > 0)
+ {
+ var that = this,
+ css = this.options.css,
+ tpl = this.options.templates,
+ tbody = this.element.children("tbody").first(),
+ allRowsSelected = true,
+ html = "";
+
+ $.each(rows, function (index, row)
+ {
+ var cells = "",
+ rowAttr = " data-row-id=\"" + ((that.identifier == null) ? index : row[that.identifier]) + "\"",
+ rowCss = "";
+
+ if (that.selection)
+ {
+ var selected = ($.inArray(row[that.identifier], that.selectedRows) !== -1),
+ selectBox = tpl.select.resolve(getParams.call(that,
+ { type: "checkbox", value: row[that.identifier], checked: selected }));
+ cells += tpl.cell.resolve(getParams.call(that, { content: selectBox, css: css.selectCell }));
+ allRowsSelected = (allRowsSelected && selected);
+ if (selected)
+ {
+ rowCss += css.selected;
+ rowAttr += " aria-selected=\"true\"";
+ }
+ }
+
+ var status = row.status != null && that.options.statusMapping[row.status];
+ if (status)
+ {
+ rowCss += status;
+ }
+
+ $.each(that.columns, function (j, column)
+ {
+ if (column.visible)
+ {
+ var value = ($.isFunction(column.formatter)) ?
+ column.formatter.call(that, column, row) :
+ column.converter.to(row[column.id]),
+ cssClass = (column.cssClass.length > 0) ? " " + column.cssClass : "";
+ cells += tpl.cell.resolve(getParams.call(that, {
+ content: (value == null || value === "") ? " " : value,
+ css: ((column.align === "right") ? css.right : (column.align === "center") ?
+ css.center : css.left) + cssClass,
+ style: (column.width == null) ? "" : "width:" + column.width + ";" }));
+ }
+ });
+
+ if (rowCss.length > 0)
+ {
+ rowAttr += " class=\"" + rowCss + "\"";
+ }
+ html += tpl.row.resolve(getParams.call(that, { attr: rowAttr, cells: cells }));
+ });
+
+ // sets or clears multi selectbox state
+ that.element.find("thead " + getCssSelector(that.options.css.selectBox))
+ .prop("checked", allRowsSelected);
+
+ tbody.html(html);
+
+ registerRowEvents.call(this, tbody);
+ }
+ else
+ {
+ renderNoResultsRow.call(this);
+ }
+ }
+
+ function registerRowEvents(tbody)
+ {
+ var that = this,
+ selectBoxSelector = getCssSelector(this.options.css.selectBox);
+
+ if (this.selection)
+ {
+ tbody.off("click" + namespace, selectBoxSelector)
+ .on("click" + namespace, selectBoxSelector, function(e)
+ {
+ e.stopPropagation();
+
+ var $this = $(this),
+ id = that.converter.from($this.val());
+
+ if ($this.prop("checked"))
+ {
+ that.select([id]);
+ }
+ else
+ {
+ that.deselect([id]);
+ }
+ });
+ }
+
+ tbody.off("click" + namespace, "> tr")
+ .on("click" + namespace, "> tr", function(e)
+ {
+ e.stopPropagation();
+
+ var $this = $(this),
+ id = (that.identifier == null) ? $this.data("row-id") :
+ that.converter.from($this.data("row-id") + ""),
+ row = (that.identifier == null) ? that.currentRows[id] :
+ that.currentRows.first(function (item) { return item[that.identifier] === id; });
+
+ if (that.selection && that.options.rowSelect)
+ {
+ if ($this.hasClass(that.options.css.selected))
+ {
+ that.deselect([id]);
+ }
+ else
+ {
+ that.select([id]);
+ }
+ }
+
+ that.element.trigger("click" + namespace, [that.columns, row]);
+ });
+ }
+
+ function renderSearchField()
+ {
+ if (this.options.navigation !== 0)
+ {
+ var css = this.options.css,
+ selector = getCssSelector(css.search),
+ searchItems = findFooterAndHeaderItems.call(this, selector);
+
+ if (searchItems.length > 0)
+ {
+ var that = this,
+ tpl = this.options.templates,
+ timer = null, // fast keyup detection
+ currentValue = "",
+ searchFieldSelector = getCssSelector(css.searchField),
+ search = $(tpl.search.resolve(getParams.call(this))),
+ searchField = (search.is(searchFieldSelector)) ? search :
+ search.find(searchFieldSelector);
+
+ searchField.on("keyup" + namespace, function (e)
+ {
+ e.stopPropagation();
+ var newValue = $(this).val();
+ if (currentValue !== newValue || (e.which === 13 && newValue !== ""))
+ {
+ currentValue = newValue;
+ if (e.which === 13 || newValue.length === 0 || newValue.length >= that.options.searchSettings.characters)
+ {
+ window.clearTimeout(timer);
+ timer = window.setTimeout(function ()
+ {
+ executeSearch.call(that, newValue);
+ }, that.options.searchSettings.delay);
+ }
+ }
+ });
+
+ replacePlaceHolder.call(this, searchItems, search);
+ }
+ }
+ }
+
+ function executeSearch(phrase)
+ {
+ if (this.searchPhrase !== phrase)
+ {
+ this.current = 1;
+ this.searchPhrase = phrase;
+ loadData.call(this);
+ }
+ }
+
+ function renderTableHeader()
+ {
+ var that = this,
+ headerRow = this.element.find("thead > tr"),
+ css = this.options.css,
+ tpl = this.options.templates,
+ html = "",
+ sorting = this.options.sorting;
+
+ if (this.selection)
+ {
+ var selectBox = (this.options.multiSelect) ?
+ tpl.select.resolve(getParams.call(that, { type: "checkbox", value: "all" })) : "";
+ html += tpl.rawHeaderCell.resolve(getParams.call(that, { content: selectBox,
+ css: css.selectCell }));
+ }
+
+ $.each(this.columns, function (index, column)
+ {
+ if (column.visible)
+ {
+ var sortOrder = that.sortDictionary[column.id],
+ iconCss = ((sorting && sortOrder && sortOrder === "asc") ? css.iconUp :
+ (sorting && sortOrder && sortOrder === "desc") ? css.iconDown : ""),
+ icon = tpl.icon.resolve(getParams.call(that, { iconCss: iconCss })),
+ align = column.headerAlign,
+ cssClass = (column.headerCssClass.length > 0) ? " " + column.headerCssClass : "";
+ html += tpl.headerCell.resolve(getParams.call(that, {
+ column: column, icon: icon, sortable: sorting && column.sortable && css.sortable || "",
+ css: ((align === "right") ? css.right : (align === "center") ?
+ css.center : css.left) + cssClass,
+ style: (column.width == null) ? "" : "width:" + column.width + ";" }));
+ }
+ });
+
+ headerRow.html(html);
+
+ if (sorting)
+ {
+ var sortingSelector = getCssSelector(css.sortable);
+ headerRow.off("click" + namespace, sortingSelector)
+ .on("click" + namespace, sortingSelector, function (e)
+ {
+ e.preventDefault();
+
+ setTableHeaderSortDirection.call(that, $(this));
+ sortRows.call(that);
+ loadData.call(that);
+ });
+ }
+
+ // todo: create a own function for that piece of code
+ if (this.selection && this.options.multiSelect)
+ {
+ var selectBoxSelector = getCssSelector(css.selectBox);
+ headerRow.off("click" + namespace, selectBoxSelector)
+ .on("click" + namespace, selectBoxSelector, function(e)
+ {
+ e.stopPropagation();
+
+ if ($(this).prop("checked"))
+ {
+ that.select();
+ }
+ else
+ {
+ that.deselect();
+ }
+ });
+ }
+ }
+
+ function setTableHeaderSortDirection(element)
+ {
+ var css = this.options.css,
+ iconSelector = getCssSelector(css.icon),
+ columnId = element.data("column-id") || element.parents("th").first().data("column-id"),
+ sortOrder = this.sortDictionary[columnId],
+ icon = element.find(iconSelector);
+
+ if (!this.options.multiSort)
+ {
+ element.parents("tr").first().find(iconSelector).removeClass(css.iconDown + " " + css.iconUp);
+ this.sortDictionary = {};
+ }
+
+ if (sortOrder && sortOrder === "asc")
+ {
+ this.sortDictionary[columnId] = "desc";
+ icon.removeClass(css.iconUp).addClass(css.iconDown);
+ }
+ else if (sortOrder && sortOrder === "desc")
+ {
+ if (this.options.multiSort)
+ {
+ var newSort = {};
+ for (var key in this.sortDictionary)
+ {
+ if (key !== columnId)
+ {
+ newSort[key] = this.sortDictionary[key];
+ }
+ }
+ this.sortDictionary = newSort;
+ icon.removeClass(css.iconDown);
+ }
+ else
+ {
+ this.sortDictionary[columnId] = "asc";
+ icon.removeClass(css.iconDown).addClass(css.iconUp);
+ }
+ }
+ else
+ {
+ this.sortDictionary[columnId] = "asc";
+ icon.addClass(css.iconUp);
+ }
+ }
+
+ function replacePlaceHolder(placeholder, element)
+ {
+ placeholder.each(function (index, item)
+ {
+ // todo: check how append is implemented. Perhaps cloning here is superfluous.
+ $(item).before(element.clone(true)).remove();
+ });
+ }
+
+ function showLoading()
+ {
+ var that = this;
+
+ window.setTimeout(function()
+ {
+ if (that.element._bgAria("busy") === "true")
+ {
+ var tpl = that.options.templates,
+ thead = that.element.children("thead").first(),
+ tbody = that.element.children("tbody").first(),
+ firstCell = tbody.find("tr > td").first(),
+ padding = (that.element.height() - thead.height()) - (firstCell.height() + 20),
+ count = that.columns.where(isVisible).length;
+
+ if (that.selection)
+ {
+ count = count + 1;
+ }
+ tbody.html(tpl.loading.resolve(getParams.call(that, { columns: count })));
+ if (that.rowCount !== -1 && padding > 0)
+ {
+ tbody.find("tr > td").css("padding", "20px 0 " + padding + "px");
+ }
+ }
+ }, 250);
+ }
+
+ function sortRows()
+ {
+ var sortArray = [];
+
+ function sort(x, y, current)
+ {
+ current = current || 0;
+ var next = current + 1,
+ item = sortArray[current];
+
+ function sortOrder(value)
+ {
+ return (item.order === "asc") ? value : value * -1;
+ }
+
+ return (x[item.id] > y[item.id]) ? sortOrder(1) :
+ (x[item.id] < y[item.id]) ? sortOrder(-1) :
+ (sortArray.length > next) ? sort(x, y, next) : 0;
+ }
+
+ if (!this.options.ajax)
+ {
+ var that = this;
+
+ for (var key in this.sortDictionary)
+ {
+ if (this.options.multiSort || sortArray.length === 0)
+ {
+ sortArray.push({
+ id: key,
+ order: this.sortDictionary[key]
+ });
+ }
+ }
+
+ if (sortArray.length > 0)
+ {
+ this.rows.sort(sort);
+ }
+ }
+ }
+
+ // GRID PUBLIC CLASS DEFINITION
+ // ====================
+
+ /**
+ * Represents the jQuery Bootgrid plugin.
+ *
+ * @class Grid
+ * @constructor
+ * @param element {Object} The corresponding DOM element.
+ * @param options {Object} The options to override default settings.
+ * @chainable
+ **/
+ var Grid = function(element, options)
+ {
+ this.element = $(element);
+ this.origin = this.element.clone();
+ this.options = $.extend(true, {}, Grid.defaults, this.element.data(), options);
+ // overrides rowCount explicitly because deep copy ($.extend) leads to strange behaviour
+ var rowCount = this.options.rowCount = this.element.data().rowCount || options.rowCount || this.options.rowCount;
+ this.columns = [];
+ this.current = 1;
+ this.currentRows = [];
+ this.identifier = null; // The first column ID that is marked as identifier
+ this.selection = false;
+ this.converter = null; // The converter for the column that is marked as identifier
+ this.rowCount = ($.isArray(rowCount)) ? rowCount[0] : rowCount;
+ this.rows = [];
+ this.searchPhrase = "";
+ this.selectedRows = [];
+ this.sortDictionary = {};
+ this.total = 0;
+ this.totalPages = 0;
+ this.cachedParams = {
+ lbl: this.options.labels,
+ css: this.options.css,
+ ctx: {}
+ };
+ this.header = null;
+ this.footer = null;
+ this.xqr = null;
+
+ // todo: implement cache
+ };
+
+ /**
+ * An object that represents the default settings.
+ *
+ * @static
+ * @class defaults
+ * @for Grid
+ * @example
+ * // Global approach
+ * $.bootgrid.defaults.selection = true;
+ * @example
+ * // Initialization approach
+ * $("#bootgrid").bootgrid({ selection = true });
+ **/
+ Grid.defaults = {
+ navigation: 3, // it's a flag: 0 = none, 1 = top, 2 = bottom, 3 = both (top and bottom)
+ padding: 2, // page padding (pagination)
+ columnSelection: true,
+ rowCount: [10, 25, 50, -1], // rows per page int or array of int (-1 represents "All")
+
+ /**
+ * Enables row selection (to enable multi selection see also `multiSelect`). Default value is `false`.
+ *
+ * @property selection
+ * @type Boolean
+ * @default false
+ * @for defaults
+ * @since 1.0.0
+ **/
+ selection: false,
+
+ /**
+ * Enables multi selection (`selection` must be set to `true` as well). Default value is `false`.
+ *
+ * @property multiSelect
+ * @type Boolean
+ * @default false
+ * @for defaults
+ * @since 1.0.0
+ **/
+ multiSelect: false,
+
+ /**
+ * Enables entire row click selection (`selection` must be set to `true` as well). Default value is `false`.
+ *
+ * @property rowSelect
+ * @type Boolean
+ * @default false
+ * @for defaults
+ * @since 1.1.0
+ **/
+ rowSelect: false,
+
+ /**
+ * Defines whether the row selection is saved internally on filtering, paging and sorting
+ * (even if the selected rows are not visible).
+ *
+ * @property keepSelection
+ * @type Boolean
+ * @default false
+ * @for defaults
+ * @since 1.1.0
+ **/
+ keepSelection: false,
+
+ highlightRows: false, // highlights new rows (find the page of the first new row)
+ sorting: true,
+ multiSort: false,
+
+ /**
+ * General search settings to configure the search field behaviour.
+ *
+ * @property searchSettings
+ * @type Object
+ * @for defaults
+ * @since 1.2.0
+ **/
+ searchSettings: {
+ /**
+ * The time in milliseconds to wait before search gets executed.
+ *
+ * @property delay
+ * @type Number
+ * @default 250
+ * @for searchSettings
+ **/
+ delay: 250,
+
+ /**
+ * The characters to type before the search gets executed.
+ *
+ * @property characters
+ * @type Number
+ * @default 1
+ * @for searchSettings
+ **/
+ characters: 1
+ },
+
+ /**
+ * Defines whether the data shall be loaded via an asynchronous HTTP (Ajax) request.
+ *
+ * @property ajax
+ * @type Boolean
+ * @default false
+ * @for defaults
+ **/
+ ajax: false,
+
+ /**
+ * Ajax request settings that shall be used for server-side communication.
+ * All setting except data, error, success and url can be overridden.
+ * For the full list of settings go to http://api.jquery.com/jQuery.ajax/.
+ *
+ * @property ajaxSettings
+ * @type Object
+ * @for defaults
+ * @since 1.2.0
+ **/
+ ajaxSettings: {
+ /**
+ * Specifies the HTTP method which shall be used when sending data to the server.
+ * Go to http://api.jquery.com/jQuery.ajax/ for more details.
+ * This setting is overriden for backward compatibility.
+ *
+ * @property method
+ * @type String
+ * @default "POST"
+ * @for ajaxSettings
+ **/
+ method: "POST"
+ },
+
+ /**
+ * Enriches the request object with additional properties. Either a `PlainObject` or a `Function`
+ * that returns a `PlainObject` can be passed. Default value is `{}`.
+ *
+ * @property post
+ * @type Object|Function
+ * @default function (request) { return request; }
+ * @for defaults
+ * @deprecated Use instead `requestHandler`
+ **/
+ post: {}, // or use function () { return {}; } (reserved properties are "current", "rowCount", "sort" and "searchPhrase")
+
+ /**
+ * Sets the data URL to a data service (e.g. a REST service). Either a `String` or a `Function`
+ * that returns a `String` can be passed. Default value is `""`.
+ *
+ * @property url
+ * @type String|Function
+ * @default ""
+ * @for defaults
+ **/
+ url: "", // or use function () { return ""; }
+
+ /**
+ * Defines whether the search is case sensitive or insensitive.
+ *
+ * @property caseSensitive
+ * @type Boolean
+ * @default true
+ * @for defaults
+ * @since 1.1.0
+ **/
+ caseSensitive: true,
+
+ // note: The following properties should not be used via data-api attributes
+
+ /**
+ * Transforms the JSON request object in what ever is needed on the server-side implementation.
+ *
+ * @property requestHandler
+ * @type Function
+ * @default function (request) { return request; }
+ * @for defaults
+ * @since 1.1.0
+ **/
+ requestHandler: function (request) { return request; },
+
+ /**
+ * Transforms the response object into the expected JSON response object.
+ *
+ * @property responseHandler
+ * @type Function
+ * @default function (response) { return response; }
+ * @for defaults
+ * @since 1.1.0
+ **/
+ responseHandler: function (response) { return response; },
+
+ /**
+ * A list of converters.
+ *
+ * @property converters
+ * @type Object
+ * @for defaults
+ * @since 1.0.0
+ **/
+ converters: {
+ numeric: {
+ from: function (value) { return +value; }, // converts from string to numeric
+ to: function (value) { return value + ""; } // converts from numeric to string
+ },
+ string: {
+ // default converter
+ from: function (value) { return value; },
+ to: function (value) { return value; }
+ }
+ },
+
+ /**
+ * Contains all css classes.
+ *
+ * @property css
+ * @type Object
+ * @for defaults
+ **/
+ css: {
+ actions: "actions btn-group", // must be a unique class name or constellation of class names within the header and footer
+ center: "text-center",
+ columnHeaderAnchor: "column-header-anchor", // must be a unique class name or constellation of class names within the column header cell
+ columnHeaderText: "text",
+ dropDownItem: "dropdown-item", // must be a unique class name or constellation of class names within the actionDropDown,
+ dropDownItemButton: "dropdown-item-button", // must be a unique class name or constellation of class names within the actionDropDown
+ dropDownItemCheckbox: "dropdown-item-checkbox", // must be a unique class name or constellation of class names within the actionDropDown
+ dropDownMenu: "dropdown btn-group", // must be a unique class name or constellation of class names within the actionDropDown
+ dropDownMenuItems: "dropdown-menu pull-right", // must be a unique class name or constellation of class names within the actionDropDown
+ dropDownMenuText: "dropdown-text", // must be a unique class name or constellation of class names within the actionDropDown
+ footer: "bootgrid-footer",
+ header: "bootgrid-header",
+ icon: "icon glyphicon",
+ iconColumns: "glyphicon-th-list",
+ iconDown: "glyphicon-chevron-down",
+ iconRefresh: "glyphicon-refresh",
+ iconSearch: "glyphicon-search",
+ iconUp: "glyphicon-chevron-up",
+ infos: "infos", // must be a unique class name or constellation of class names within the header and footer,
+ left: "text-left",
+ pagination: "pagination", // must be a unique class name or constellation of class names within the header and footer
+ paginationButton: "button", // must be a unique class name or constellation of class names within the pagination
+
+ /**
+ * CSS class to select the parent div which activates responsive mode.
+ *
+ * @property responsiveTable
+ * @type String
+ * @default "table-responsive"
+ * @for css
+ * @since 1.1.0
+ **/
+ responsiveTable: "table-responsive",
+
+ right: "text-right",
+ search: "search form-group", // must be a unique class name or constellation of class names within the header and footer
+ searchField: "search-field form-control",
+ selectBox: "select-box", // must be a unique class name or constellation of class names within the entire table
+ selectCell: "select-cell", // must be a unique class name or constellation of class names within the entire table
+
+ /**
+ * CSS class to highlight selected rows.
+ *
+ * @property selected
+ * @type String
+ * @default "active"
+ * @for css
+ * @since 1.1.0
+ **/
+ selected: "active",
+
+ sortable: "sortable",
+ table: "bootgrid-table table"
+ },
+
+ /**
+ * A dictionary of formatters.
+ *
+ * @property formatters
+ * @type Object
+ * @for defaults
+ * @since 1.0.0
+ **/
+ formatters: {},
+
+ /**
+ * Contains all labels.
+ *
+ * @property labels
+ * @type Object
+ * @for defaults
+ **/
+ labels: {
+ all: "All",
+ infos: "Showing {{ctx.start}} to {{ctx.end}} of {{ctx.total}} entries",
+ loading: "Loading...",
+ noResults: "No results found!",
+ refresh: "Refresh",
+ search: "Search"
+ },
+
+ /**
+ * Specifies the mapping between status and contextual classes to color rows.
+ *
+ * @property statusMapping
+ * @type Object
+ * @for defaults
+ * @since 1.2.0
+ **/
+ statusMapping: {
+ /**
+ * Specifies a successful or positive action.
+ *
+ * @property 0
+ * @type String
+ * @for statusMapping
+ **/
+ 0: "success",
+
+ /**
+ * Specifies a neutral informative change or action.
+ *
+ * @property 1
+ * @type String
+ * @for statusMapping
+ **/
+ 1: "info",
+
+ /**
+ * Specifies a warning that might need attention.
+ *
+ * @property 2
+ * @type String
+ * @for statusMapping
+ **/
+ 2: "warning",
+
+ /**
+ * Specifies a dangerous or potentially negative action.
+ *
+ * @property 3
+ * @type String
+ * @for statusMapping
+ **/
+ 3: "danger"
+ },
+
+ /**
+ * Contains all templates.
+ *
+ * @property templates
+ * @type Object
+ * @for defaults
+ **/
+ templates: {
+ actionButton: "",
+ actionDropDown: "",
+ actionDropDownItem: "{{ctx.text}}",
+ actionDropDownCheckboxItem: "",
+ actions: "",
+ body: "",
+ cell: "{{ctx.content}} | ",
+ footer: "",
+ header: "",
+ headerCell: "{{ctx.column.text}}{{ctx.icon}} | ",
+ icon: "",
+ infos: "{{lbl.infos}}
",
+ loading: "{{lbl.loading}} |
",
+ noResults: "{{lbl.noResults}} |
",
+ pagination: "",
+ paginationItem: "",
+ rawHeaderCell: "{{ctx.content}} | ", // Used for the multi select box
+ row: "{{ctx.cells}}
",
+ search: "",
+ select: ""
+ }
+ };
+
+ /**
+ * Appends rows.
+ *
+ * @method append
+ * @param rows {Array} An array of rows to append
+ * @chainable
+ **/
+ Grid.prototype.append = function(rows)
+ {
+ if (this.options.ajax)
+ {
+ // todo: implement ajax PUT
+ }
+ else
+ {
+ var appendedRows = [];
+ for (var i = 0; i < rows.length; i++)
+ {
+ if (appendRow.call(this, rows[i]))
+ {
+ appendedRows.push(rows[i]);
+ }
+ }
+ sortRows.call(this);
+ highlightAppendedRows.call(this, appendedRows);
+ loadData.call(this);
+ this.element.trigger("appended" + namespace, [appendedRows]);
+ }
+
+ return this;
+ };
+
+ /**
+ * Removes all rows.
+ *
+ * @method clear
+ * @chainable
+ **/
+ Grid.prototype.clear = function()
+ {
+ if (this.options.ajax)
+ {
+ // todo: implement ajax POST
+ }
+ else
+ {
+ var removedRows = $.extend([], this.rows);
+ this.rows = [];
+ this.current = 1;
+ this.total = 0;
+ loadData.call(this);
+ this.element.trigger("cleared" + namespace, [removedRows]);
+ }
+
+ return this;
+ };
+
+ /**
+ * Removes the control functionality completely and transforms the current state to the initial HTML structure.
+ *
+ * @method destroy
+ * @chainable
+ **/
+ Grid.prototype.destroy = function()
+ {
+ // todo: this method has to be optimized (the complete initial state must be restored)
+ $(window).off(namespace);
+ if (this.options.navigation & 1)
+ {
+ this.header.remove();
+ }
+ if (this.options.navigation & 2)
+ {
+ this.footer.remove();
+ }
+ this.element.before(this.origin).remove();
+
+ return this;
+ };
+
+ /**
+ * Resets the state and reloads rows.
+ *
+ * @method reload
+ * @chainable
+ **/
+ Grid.prototype.reload = function()
+ {
+ if(!this.current){
+ this.current = 1; // reset
+ }
+ loadData.call(this);
+
+ return this;
+ };
+
+ /**
+ * Removes rows by ids. Removes selected rows if no ids are provided.
+ *
+ * @method remove
+ * @param [rowsIds] {Array} An array of rows ids to remove
+ * @chainable
+ **/
+ Grid.prototype.remove = function(rowIds)
+ {
+ if (this.identifier != null)
+ {
+ var that = this;
+
+ if (this.options.ajax)
+ {
+ // todo: implement ajax DELETE
+ }
+ else
+ {
+ rowIds = rowIds || this.selectedRows;
+ var id,
+ removedRows = [];
+
+ for (var i = 0; i < rowIds.length; i++)
+ {
+ id = rowIds[i];
+
+ for (var j = 0; j < this.rows.length; j++)
+ {
+ if (this.rows[j][this.identifier] === id)
+ {
+ removedRows.push(this.rows[j]);
+ this.rows.splice(j, 1);
+ break;
+ }
+ }
+ }
+
+ this.current = 1; // reset
+ loadData.call(this);
+ this.element.trigger("removed" + namespace, [removedRows]);
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Searches in all rows for a specific phrase (but only in visible cells).
+ * The search filter will be reseted, if no argument is provided.
+ *
+ * @method search
+ * @param [phrase] {String} The phrase to search for
+ * @chainable
+ **/
+ Grid.prototype.search = function(phrase)
+ {
+ phrase = phrase || "";
+
+ if (this.searchPhrase !== phrase)
+ {
+ var selector = getCssSelector(this.options.css.searchField),
+ searchFields = findFooterAndHeaderItems.call(this, selector);
+ searchFields.val(phrase);
+ }
+
+ executeSearch.call(this, phrase);
+
+
+ return this;
+ };
+
+ /**
+ * Selects rows by ids. Selects all visible rows if no ids are provided.
+ * In server-side scenarios only visible rows are selectable.
+ *
+ * @method select
+ * @param [rowsIds] {Array} An array of rows ids to select
+ * @chainable
+ **/
+ Grid.prototype.select = function(rowIds)
+ {
+ if (this.selection)
+ {
+ rowIds = rowIds || this.currentRows.propValues(this.identifier);
+
+ var id, i,
+ selectedRows = [];
+
+ while (rowIds.length > 0 && !(!this.options.multiSelect && selectedRows.length === 1))
+ {
+ id = rowIds.pop();
+ if ($.inArray(id, this.selectedRows) === -1)
+ {
+ for (i = 0; i < this.currentRows.length; i++)
+ {
+ if (this.currentRows[i][this.identifier] === id)
+ {
+ selectedRows.push(this.currentRows[i]);
+ this.selectedRows.push(id);
+ break;
+ }
+ }
+ }
+ }
+
+ if (selectedRows.length > 0)
+ {
+ var selectBoxSelector = getCssSelector(this.options.css.selectBox),
+ selectMultiSelectBox = this.selectedRows.length >= this.currentRows.length;
+
+ i = 0;
+ while (!this.options.keepSelection && selectMultiSelectBox && i < this.currentRows.length)
+ {
+ selectMultiSelectBox = ($.inArray(this.currentRows[i++][this.identifier], this.selectedRows) !== -1);
+ }
+ this.element.find("thead " + selectBoxSelector).prop("checked", selectMultiSelectBox);
+
+ if (!this.options.multiSelect)
+ {
+ this.element.find("tbody > tr " + selectBoxSelector + ":checked")
+ .trigger("click" + namespace);
+ }
+
+ for (i = 0; i < this.selectedRows.length; i++)
+ {
+ this.element.find("tbody > tr[data-row-id=\"" + this.selectedRows[i] + "\"]")
+ .addClass(this.options.css.selected)._bgAria("selected", "true")
+ .find(selectBoxSelector).prop("checked", true);
+ }
+
+ this.element.trigger("selected" + namespace, [selectedRows]);
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Deselects rows by ids. Deselects all visible rows if no ids are provided.
+ * In server-side scenarios only visible rows are deselectable.
+ *
+ * @method deselect
+ * @param [rowsIds] {Array} An array of rows ids to deselect
+ * @chainable
+ **/
+ Grid.prototype.deselect = function(rowIds)
+ {
+ if (this.selection)
+ {
+ rowIds = rowIds || this.currentRows.propValues(this.identifier);
+
+ var id, i, pos,
+ deselectedRows = [];
+
+ while (rowIds.length > 0)
+ {
+ id = rowIds.pop();
+ pos = $.inArray(id, this.selectedRows);
+ if (pos !== -1)
+ {
+ for (i = 0; i < this.currentRows.length; i++)
+ {
+ if (this.currentRows[i][this.identifier] === id)
+ {
+ deselectedRows.push(this.currentRows[i]);
+ this.selectedRows.splice(pos, 1);
+ break;
+ }
+ }
+ }
+ }
+
+ if (deselectedRows.length > 0)
+ {
+ var selectBoxSelector = getCssSelector(this.options.css.selectBox);
+
+ this.element.find("thead " + selectBoxSelector).prop("checked", false);
+ for (i = 0; i < deselectedRows.length; i++)
+ {
+ this.element.find("tbody > tr[data-row-id=\"" + deselectedRows[i][this.identifier] + "\"]")
+ .removeClass(this.options.css.selected)._bgAria("selected", "false")
+ .find(selectBoxSelector).prop("checked", false);
+ }
+
+ this.element.trigger("deselected" + namespace, [deselectedRows]);
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Sorts the rows by a given sort descriptor dictionary.
+ * The sort filter will be reseted, if no argument is provided.
+ *
+ * @method sort
+ * @param [dictionary] {Object} A sort descriptor dictionary that contains the sort information
+ * @chainable
+ **/
+ Grid.prototype.sort = function(dictionary)
+ {
+ var values = (dictionary) ? $.extend({}, dictionary) : {};
+
+ if (values === this.sortDictionary)
+ {
+ return this;
+ }
+
+ this.sortDictionary = values;
+ renderTableHeader.call(this);
+ sortRows.call(this);
+ loadData.call(this);
+
+ return this;
+ };
+
+ /**
+ * Gets a list of the column settings.
+ * This method returns only for the first grid instance a value.
+ * Therefore be sure that only one grid instance is catched by your selector.
+ *
+ * @method getColumnSettings
+ * @return {Array} Returns a list of the column settings.
+ * @since 1.2.0
+ **/
+ Grid.prototype.getColumnSettings = function()
+ {
+ return $.merge([], this.columns);
+ };
+
+ /**
+ * Gets the current page index.
+ * This method returns only for the first grid instance a value.
+ * Therefore be sure that only one grid instance is catched by your selector.
+ *
+ * @method getCurrentPage
+ * @return {Number} Returns the current page index.
+ * @since 1.2.0
+ **/
+ Grid.prototype.getCurrentPage = function()
+ {
+ return this.current;
+ };
+
+ /**
+ * Gets the current rows.
+ * This method returns only for the first grid instance a value.
+ * Therefore be sure that only one grid instance is catched by your selector.
+ *
+ * @method getCurrentPage
+ * @return {Array} Returns the current rows.
+ * @since 1.2.0
+ **/
+ Grid.prototype.getCurrentRows = function()
+ {
+ return $.merge([], this.currentRows);
+ };
+
+ /**
+ * Gets a number represents the row count per page.
+ * This method returns only for the first grid instance a value.
+ * Therefore be sure that only one grid instance is catched by your selector.
+ *
+ * @method getRowCount
+ * @return {Number} Returns the row count per page.
+ * @since 1.2.0
+ **/
+ Grid.prototype.getRowCount = function()
+ {
+ return this.rowCount;
+ };
+
+ /**
+ * Gets the actual search phrase.
+ * This method returns only for the first grid instance a value.
+ * Therefore be sure that only one grid instance is catched by your selector.
+ *
+ * @method getSearchPhrase
+ * @return {String} Returns the actual search phrase.
+ * @since 1.2.0
+ **/
+ Grid.prototype.getSearchPhrase = function()
+ {
+ return this.searchPhrase;
+ };
+
+ /**
+ * Gets the complete list of currently selected rows.
+ * This method returns only for the first grid instance a value.
+ * Therefore be sure that only one grid instance is catched by your selector.
+ *
+ * @method getSelectedRows
+ * @return {Array} Returns all selected rows.
+ * @since 1.2.0
+ **/
+ Grid.prototype.getSelectedRows = function()
+ {
+ return $.merge([], this.selectedRows);
+ };
+
+ /**
+ * Gets the sort dictionary which represents the state of column sorting.
+ * This method returns only for the first grid instance a value.
+ * Therefore be sure that only one grid instance is catched by your selector.
+ *
+ * @method getSortDictionary
+ * @return {Object} Returns the sort dictionary.
+ * @since 1.2.0
+ **/
+ Grid.prototype.getSortDictionary = function()
+ {
+ return $.extend({}, this.sortDictionary);
+ };
+
+ /**
+ * Gets a number represents the total page count.
+ * This method returns only for the first grid instance a value.
+ * Therefore be sure that only one grid instance is catched by your selector.
+ *
+ * @method getTotalPageCount
+ * @return {Number} Returns the total page count.
+ * @since 1.2.0
+ **/
+ Grid.prototype.getTotalPageCount = function()
+ {
+ return this.totalPages;
+ };
+
+ /**
+ * Gets a number represents the total row count.
+ * This method returns only for the first grid instance a value.
+ * Therefore be sure that only one grid instance is catched by your selector.
+ *
+ * @method getTotalRowCount
+ * @return {Number} Returns the total row count.
+ * @since 1.2.0
+ **/
+ Grid.prototype.getTotalRowCount = function()
+ {
+ return this.total;
+ };
+
+ // GRID COMMON TYPE EXTENSIONS
+ // ============
+
+ $.fn.extend({
+ _bgAria: function (name, value)
+ {
+ return (value) ? this.attr("aria-" + name, value) : this.attr("aria-" + name);
+ },
+
+ _bgBusyAria: function(busy)
+ {
+ return (busy == null || busy) ?
+ this._bgAria("busy", "true") :
+ this._bgAria("busy", "false");
+ },
+
+ _bgRemoveAria: function (name)
+ {
+ return this.removeAttr("aria-" + name);
+ },
+
+ _bgEnableAria: function (enable)
+ {
+ return (enable == null || enable) ?
+ this.removeClass("disabled")._bgAria("disabled", "false") :
+ this.addClass("disabled")._bgAria("disabled", "true");
+ },
+
+ _bgEnableField: function (enable)
+ {
+ return (enable == null || enable) ?
+ this.removeAttr("disabled") :
+ this.attr("disabled", "disable");
+ },
+
+ _bgShowAria: function (show)
+ {
+ return (show == null || show) ?
+ this.show()._bgAria("hidden", "false") :
+ this.hide()._bgAria("hidden", "true");
+ },
+
+ _bgSelectAria: function (select)
+ {
+ return (select == null || select) ?
+ this.addClass("active")._bgAria("selected", "true") :
+ this.removeClass("active")._bgAria("selected", "false");
+ },
+
+ _bgId: function (id)
+ {
+ return (id) ? this.attr("id", id) : this.attr("id");
+ }
+ });
+
+ if (!String.prototype.resolve)
+ {
+ var formatter = {
+ "checked": function(value)
+ {
+ if (typeof value === "boolean")
+ {
+ return (value) ? "checked=\"checked\"" : "";
+ }
+ return value;
+ }
+ };
+
+ String.prototype.resolve = function (substitutes, prefixes)
+ {
+ var result = this;
+ $.each(substitutes, function (key, value)
+ {
+ if (value != null && typeof value !== "function")
+ {
+ if (typeof value === "object")
+ {
+ var keys = (prefixes) ? $.extend([], prefixes) : [];
+ keys.push(key);
+ result = result.resolve(value, keys) + "";
+ }
+ else
+ {
+ if (formatter && formatter[key] && typeof formatter[key] === "function")
+ {
+ value = formatter[key](value);
+ }
+ key = (prefixes) ? prefixes.join(".") + "." + key : key;
+ var pattern = new RegExp("\\{\\{" + key + "\\}\\}", "gm");
+ result = result.replace(pattern, (value.replace) ? value.replace(/\$/gi, "$") : value);
+ }
+ }
+ });
+ return result;
+ };
+ }
+/* if is conflicted with wavesurfer video.js */
+ if (!Array.prototype.first)
+ {
+ Array.prototype.first = function (condition)
+ {
+ for (var i = 0; i < this.length; i++)
+ {
+ var item = this[i];
+ if (condition(item))
+ {
+ return item;
+ }
+ }
+ return null;
+ };
+ }
+
+ if (!Array.prototype.contains)
+ {
+ Array.prototype.contains = function (condition)
+ {
+ for (var i = 0; i < this.length; i++)
+ {
+ var item = this[i];
+ if (condition(item))
+ {
+ return true;
+ }
+ }
+ return false;
+ };
+ }
+
+ if (!Array.prototype.page)
+ {
+ Array.prototype.page = function (page, size)
+ {
+ var skip = (page - 1) * size,
+ end = skip + size;
+ return (this.length > skip) ?
+ (this.length > end) ? this.slice(skip, end) :
+ this.slice(skip) : [];
+ };
+ }
+
+ if (!Array.prototype.where)
+ {
+ Array.prototype.where = function (condition)
+ {
+ var result = [];
+ for (var i = 0; i < this.length; i++)
+ {
+ var item = this[i];
+ if (condition(item))
+ {
+ result.push(item);
+ }
+ }
+ return result;
+ };
+ }
+
+ if (!Array.prototype.propValues)
+ {
+ Array.prototype.propValues = function (propName)
+ {
+ var result = [];
+ for (var i = 0; i < this.length; i++)
+ {
+ result.push(this[i][propName]);
+ }
+ return result;
+ };
+ }
+
+ // GRID PLUGIN DEFINITION
+ // =====================
+
+ var old = $.fn.bootgrid;
+
+ $.fn.bootgrid = function (option)
+ {
+ var args = Array.prototype.slice.call(arguments, 1),
+ returnValue = null,
+ elements = this.each(function (index)
+ {
+ var $this = $(this),
+ instance = $this.data(namespace),
+ options = typeof option === "object" && option;
+
+ if (!instance && option === "destroy")
+ {
+ return;
+ }
+ if (!instance)
+ {
+ $this.data(namespace, (instance = new Grid(this, options)));
+ init.call(instance);
+ }
+ if (typeof option === "string")
+ {
+ if (option.indexOf("get") === 0 && index === 0)
+ {
+ returnValue = instance[option].apply(instance, args);
+ }
+ else if (option.indexOf("get") !== 0)
+ {
+ return instance[option].apply(instance, args);
+ }
+ }
+ });
+ return (typeof option === "string" && option.indexOf("get") === 0) ? returnValue : elements;
+ };
+
+ $.fn.bootgrid.Constructor = Grid;
+
+ // GRID NO CONFLICT
+ // ===============
+
+ $.fn.bootgrid.noConflict = function ()
+ {
+ $.fn.bootgrid = old;
+ return this;
+ };
+
+ // GRID DATA-API
+ // ============
+
+$("[data-toggle=\"bootgrid\"]").bootgrid();
})(jQuery, window);
\ No newline at end of file
diff --git a/view/js/bootgrid/jquery.bootgrid.min.js b/view/js/bootgrid/jquery.bootgrid.min.js
index 9ff7c9a6c4..d2e6e91001 100644
--- a/view/js/bootgrid/jquery.bootgrid.min.js
+++ b/view/js/bootgrid/jquery.bootgrid.min.js
@@ -1,6 +1,6 @@
-/*!
- * jQuery Bootgrid v1.3.1 - 09/11/2015
- * Copyright (c) 2014-2015 Rafael Staib (http://www.jquery-bootgrid.com)
- * Licensed under MIT http://www.opensource.org/licenses/MIT
- */
-!function(a,b,c){"use strict";function d(a){function b(b){return c.identifier&&b[c.identifier]===a[c.identifier]}var c=this;return this.rows.contains(b)?!1:(this.rows.push(a),!0)}function e(b){var c=this.footer?this.footer.find(b):a(),d=this.header?this.header.find(b):a();return a.merge(c,d)}function f(b){return b?a.extend({},this.cachedParams,{ctx:b}):this.cachedParams}function g(){var b={current:this.current,rowCount:this.rowCount,sort:this.sortDictionary,searchPhrase:this.searchPhrase},c=this.options.post;return c=a.isFunction(c)?c():c,this.options.requestHandler(a.extend(!0,b,c))}function h(b){return"."+a.trim(b).replace(/\s+/gm,".")}function i(){var b=this.options.url;return a.isFunction(b)?b():b}function j(){this.element.trigger("initialize"+H),m.call(this),this.selection=this.options.selection&&null!=this.identifier,o.call(this),q.call(this),C.call(this),A.call(this),r.call(this),n.call(this),this.element.trigger("initialized"+H)}function k(a){this.options.highlightRows}function l(a){return a.visible}function m(){var b=this,c=this.element.find("thead > tr").first(),d=!1;c.children().each(function(){var c=a(this),e=c.data(),f={id:e.columnId,identifier:null==b.identifier&&e.identifier||!1,converter:b.options.converters[e.converter||e.type]||b.options.converters.string,text:c.text(),align:e.align||"left",headerAlign:e.headerAlign||"left",cssClass:e.cssClass||"",headerCssClass:e.headerCssClass||"",formatter:b.options.formatters[e.formatter]||null,order:d||"asc"!==e.order&&"desc"!==e.order?null:e.order,searchable:!(e.searchable===!1),sortable:!(e.sortable===!1),visible:!(e.visible===!1),visibleInSelection:!(e.visibleInSelection===!1),width:a.isNumeric(e.width)?e.width+"px":"string"==typeof e.width?e.width:null};b.columns.push(f),null!=f.order&&(b.sortDictionary[f.id]=f.order),f.identifier&&(b.identifier=f.id,b.converter=f.converter),b.options.multiSort||null===f.order||(d=!0)})}function n(){function c(a){for(var b,c=new RegExp(e.searchPhrase,e.options.caseSensitive?"g":"gi"),d=0;d-1)return!0;return!1}function d(a,b){e.currentRows=a,p.call(e,b),e.options.keepSelection||(e.selectedRows=[]),y.call(e,a),t.call(e),v.call(e),e.element._bgBusyAria(!1).trigger("loaded"+H)}var e=this;if(this.element._bgBusyAria(!0).trigger("load"+H),F.call(this),this.options.ajax){var f=g.call(this),h=i.call(this);if(null==h||"string"!=typeof h||0===h.length)throw new Error("Url setting must be a none empty string or a function that returns one.");this.xqr&&this.xqr.abort();var j={url:h,data:f,success:function(b){e.xqr=null,"string"==typeof b&&(b=a.parseJSON(b)),b=e.options.responseHandler(b),e.current=b.current,d(b.rows,b.total)},error:function(a,b,c){e.xqr=null,"abort"!==b&&(u.call(e),e.element._bgBusyAria(!1).trigger("loaded"+H))}};j=a.extend(this.options.ajaxSettings,j),this.xqr=a.ajax(j)}else{var k=this.searchPhrase.length>0?this.rows.where(c):this.rows,l=k.length;-1!==this.rowCount&&(k=k.page(this.current,this.rowCount)),b.setTimeout(function(){d(k,l)},10)}}function o(){if(!this.options.ajax){var b=this,c=this.element.find("tbody > tr");c.each(function(){var c=a(this),e=c.children("td"),f={};a.each(b.columns,function(a,b){f[b.id]=b.converter.from(e.eq(a).text())}),d.call(b,f)}),p.call(this,this.rows.length),G.call(this)}}function p(a){this.total=a,this.totalPages=-1===this.rowCount?1:Math.ceil(this.total/this.rowCount)}function q(){var b=this.options.templates,c=this.element.parent().hasClass(this.options.css.responsiveTable)?this.element.parent():this.element;this.element.addClass(this.options.css.table),0===this.element.children("tbody").length&&this.element.append(b.body),1&this.options.navigation&&(this.header=a(b.header.resolve(f.call(this,{id:this.element._bgId()+"-header"}))),c.before(this.header)),2&this.options.navigation&&(this.footer=a(b.footer.resolve(f.call(this,{id:this.element._bgId()+"-footer"}))),c.after(this.footer))}function r(){if(0!==this.options.navigation){var b=this.options.css,c=h(b.actions),d=e.call(this,c);if(d.length>0){var g=this,i=this.options.templates,j=a(i.actions.resolve(f.call(this)));if(this.options.ajax){var k=i.icon.resolve(f.call(this,{iconCss:b.iconRefresh})),l=a(i.actionButton.resolve(f.call(this,{content:k,text:this.options.labels.refresh}))).on("click"+H,function(a){a.stopPropagation(),g.current=1,n.call(g)});j.append(l)}x.call(this,j),s.call(this,j),E.call(this,d,j)}}}function s(b){if(this.options.columnSelection&&this.columns.length>1){var c=this,d=this.options.css,e=this.options.templates,g=e.icon.resolve(f.call(this,{iconCss:d.iconColumns})),i=a(e.actionDropDown.resolve(f.call(this,{content:g}))),j=h(d.dropDownItem),k=h(d.dropDownItemCheckbox),m=h(d.dropDownMenuItems);a.each(this.columns,function(b,g){if(g.visibleInSelection){var o=a(e.actionDropDownCheckboxItem.resolve(f.call(c,{name:g.id,label:g.text,checked:g.visible}))).on("click"+H,j,function(b){b.stopPropagation();var d=a(this),e=d.find(k);if(!e.prop("disabled")){g.visible=e.prop("checked");var f=c.columns.where(l).length>1;d.parents(m).find(j+":has("+k+":checked)")._bgEnableAria(f).find(k)._bgEnableField(f),c.element.find("tbody").empty(),C.call(c),n.call(c)}});i.find(h(d.dropDownMenuItems)).append(o)}}),b.append(i)}}function t(){if(0!==this.options.navigation){var b=h(this.options.css.infos),c=e.call(this,b);if(c.length>0){var d=this.current*this.rowCount,g=a(this.options.templates.infos.resolve(f.call(this,{end:0===this.total||-1===d||d>this.total?this.total:d,start:0===this.total?0:d-this.rowCount+1,total:this.total})));E.call(this,c,g)}}}function u(){var a=this.element.children("tbody").first(),b=this.options.templates,c=this.columns.where(l).length;this.selection&&(c+=1),a.html(b.noResults.resolve(f.call(this,{columns:c})))}function v(){if(0!==this.options.navigation){var b=h(this.options.css.pagination),c=e.call(this,b)._bgShowAria(-1!==this.rowCount);if(-1!==this.rowCount&&c.length>0){var d=this.options.templates,g=this.current,i=this.totalPages,j=a(d.pagination.resolve(f.call(this))),k=i-g,l=-1*(this.options.padding-g),m=k>=this.options.padding?Math.max(l,1):Math.max(l-this.options.padding+k,1),n=2*this.options.padding+1,o=i>=n?n:i;w.call(this,j,"first","«","first")._bgEnableAria(g>1),w.call(this,j,"prev","<","prev")._bgEnableAria(g>1);for(var p=0;o>p;p++){var q=p+m;w.call(this,j,q,q,"page-"+q)._bgEnableAria()._bgSelectAria(q===g)}0===o&&w.call(this,j,1,1,"page-1")._bgEnableAria(!1)._bgSelectAria(),w.call(this,j,"next",">","next")._bgEnableAria(i>g),w.call(this,j,"last","»","last")._bgEnableAria(i>g),E.call(this,c,j)}}}function w(b,c,d,e){var g=this,i=this.options.templates,j=this.options.css,k=f.call(this,{css:e,text:d,page:c}),l=a(i.paginationItem.resolve(k)).on("click"+H,h(j.paginationButton),function(b){b.stopPropagation(),b.preventDefault();var c=a(this),d=c.parent();if(!d.hasClass("active")&&!d.hasClass("disabled")){var e={first:1,prev:g.current-1,next:g.current+1,last:g.totalPages},f=c.data("page");g.current=e[f]||f,n.call(g)}c.trigger("blur")});return b.append(l),l}function x(b){function c(a){return-1===a?d.options.labels.all:a}var d=this,e=this.options.rowCount;if(a.isArray(e)){var g=this.options.css,i=this.options.templates,j=a(i.actionDropDown.resolve(f.call(this,{content:c(this.rowCount)}))),k=h(g.dropDownMenu),l=h(g.dropDownMenuText),m=h(g.dropDownMenuItems),o=h(g.dropDownItemButton);a.each(e,function(b,e){var g=a(i.actionDropDownItem.resolve(f.call(d,{text:c(e),action:e})))._bgSelectAria(e===d.rowCount).on("click"+H,o,function(b){b.preventDefault();var e=a(this),f=e.data("action");f!==d.rowCount&&(d.current=1,d.rowCount=f,e.parents(m).children().each(function(){var b=a(this),c=b.find(o).data("action");b._bgSelectAria(c===f)}),e.parents(k).find(l).text(c(f)),n.call(d))});j.find(m).append(g)}),b.append(j)}}function y(b){if(b.length>0){var c=this,d=this.options.css,e=this.options.templates,g=this.element.children("tbody").first(),i=!0,j="";a.each(b,function(b,g){var h="",k=' data-row-id="'+(null==c.identifier?b:g[c.identifier])+'"',l="";if(c.selection){var m=-1!==a.inArray(g[c.identifier],c.selectedRows),n=e.select.resolve(f.call(c,{type:"checkbox",value:g[c.identifier],checked:m}));h+=e.cell.resolve(f.call(c,{content:n,css:d.selectCell})),i=i&&m,m&&(l+=d.selected,k+=' aria-selected="true"')}var o=null!=g.status&&c.options.statusMapping[g.status];o&&(l+=o),a.each(c.columns,function(b,i){if(i.visible){var j=a.isFunction(i.formatter)?i.formatter.call(c,i,g):i.converter.to(g[i.id]),k=i.cssClass.length>0?" "+i.cssClass:"";h+=e.cell.resolve(f.call(c,{content:null==j||""===j?" ":j,css:("right"===i.align?d.right:"center"===i.align?d.center:d.left)+k,style:null==i.width?"":"width:"+i.width+";"}))}}),l.length>0&&(k+=' class="'+l+'"'),j+=e.row.resolve(f.call(c,{attr:k,cells:h}))}),c.element.find("thead "+h(c.options.css.selectBox)).prop("checked",i),g.html(j),z.call(this,g)}else u.call(this)}function z(b){var c=this,d=h(this.options.css.selectBox);this.selection&&b.off("click"+H,d).on("click"+H,d,function(b){b.stopPropagation();var d=a(this),e=c.converter.from(d.val());d.prop("checked")?c.select([e]):c.deselect([e])}),b.off("click"+H,"> tr").on("click"+H,"> tr",function(b){b.stopPropagation();var d=a(this),e=null==c.identifier?d.data("row-id"):c.converter.from(d.data("row-id")+""),f=null==c.identifier?c.currentRows[e]:c.currentRows.first(function(a){return a[c.identifier]===e});c.selection&&c.options.rowSelect&&(d.hasClass(c.options.css.selected)?c.deselect([e]):c.select([e])),c.element.trigger("click"+H,[c.columns,f])})}function A(){if(0!==this.options.navigation){var c=this.options.css,d=h(c.search),g=e.call(this,d);if(g.length>0){var i=this,j=this.options.templates,k=null,l="",m=h(c.searchField),n=a(j.search.resolve(f.call(this))),o=n.is(m)?n:n.find(m);o.on("keyup"+H,function(c){c.stopPropagation();var d=a(this).val();(l!==d||13===c.which&&""!==d)&&(l=d,(13===c.which||0===d.length||d.length>=i.options.searchSettings.characters)&&(b.clearTimeout(k),k=b.setTimeout(function(){B.call(i,d)},i.options.searchSettings.delay)))}),E.call(this,g,n)}}}function B(a){this.searchPhrase!==a&&(this.current=1,this.searchPhrase=a,n.call(this))}function C(){var b=this,c=this.element.find("thead > tr"),d=this.options.css,e=this.options.templates,g="",i=this.options.sorting;if(this.selection){var j=this.options.multiSelect?e.select.resolve(f.call(b,{type:"checkbox",value:"all"})):"";g+=e.rawHeaderCell.resolve(f.call(b,{content:j,css:d.selectCell}))}if(a.each(this.columns,function(a,c){if(c.visible){var h=b.sortDictionary[c.id],j=i&&h&&"asc"===h?d.iconUp:i&&h&&"desc"===h?d.iconDown:"",k=e.icon.resolve(f.call(b,{iconCss:j})),l=c.headerAlign,m=c.headerCssClass.length>0?" "+c.headerCssClass:"";g+=e.headerCell.resolve(f.call(b,{column:c,icon:k,sortable:i&&c.sortable&&d.sortable||"",css:("right"===l?d.right:"center"===l?d.center:d.left)+m,style:null==c.width?"":"width:"+c.width+";"}))}}),c.html(g),i){var k=h(d.sortable);c.off("click"+H,k).on("click"+H,k,function(c){c.preventDefault(),D.call(b,a(this)),G.call(b),n.call(b)})}if(this.selection&&this.options.multiSelect){var l=h(d.selectBox);c.off("click"+H,l).on("click"+H,l,function(c){c.stopPropagation(),a(this).prop("checked")?b.select():b.deselect()})}}function D(a){var b=this.options.css,c=h(b.icon),d=a.data("column-id")||a.parents("th").first().data("column-id"),e=this.sortDictionary[d],f=a.find(c);if(this.options.multiSort||(a.parents("tr").first().find(c).removeClass(b.iconDown+" "+b.iconUp),this.sortDictionary={}),e&&"asc"===e)this.sortDictionary[d]="desc",f.removeClass(b.iconUp).addClass(b.iconDown);else if(e&&"desc"===e)if(this.options.multiSort){var g={};for(var i in this.sortDictionary)i!==d&&(g[i]=this.sortDictionary[i]);this.sortDictionary=g,f.removeClass(b.iconDown)}else this.sortDictionary[d]="asc",f.removeClass(b.iconDown).addClass(b.iconUp);else this.sortDictionary[d]="asc",f.addClass(b.iconUp)}function E(b,c){b.each(function(b,d){a(d).before(c.clone(!0)).remove()})}function F(){var a=this;b.setTimeout(function(){if("true"===a.element._bgAria("busy")){var b=a.options.templates,c=a.element.children("thead").first(),d=a.element.children("tbody").first(),e=d.find("tr > td").first(),g=a.element.height()-c.height()-(e.height()+20),h=a.columns.where(l).length;a.selection&&(h+=1),d.html(b.loading.resolve(f.call(a,{columns:h}))),-1!==a.rowCount&&g>0&&d.find("tr > td").css("padding","20px 0 "+g+"px")}},250)}function G(){function a(c,d,e){function f(a){return"asc"===h.order?a:-1*a}e=e||0;var g=e+1,h=b[e];return c[h.id]>d[h.id]?f(1):c[h.id]g?a(c,d,g):0}var b=[];if(!this.options.ajax){for(var c in this.sortDictionary)(this.options.multiSort||0===b.length)&&b.push({id:c,order:this.sortDictionary[c]});b.length>0&&this.rows.sort(a)}}var H=".rs.jquery.bootgrid",I=function(b,c){this.element=a(b),this.origin=this.element.clone(),this.options=a.extend(!0,{},I.defaults,this.element.data(),c);var d=this.options.rowCount=this.element.data().rowCount||c.rowCount||this.options.rowCount;this.columns=[],this.current=1,this.currentRows=[],this.identifier=null,this.selection=!1,this.converter=null,this.rowCount=a.isArray(d)?d[0]:d,this.rows=[],this.searchPhrase="",this.selectedRows=[],this.sortDictionary={},this.total=0,this.totalPages=0,this.cachedParams={lbl:this.options.labels,css:this.options.css,ctx:{}},this.header=null,this.footer=null,this.xqr=null};if(I.defaults={navigation:3,padding:2,columnSelection:!0,rowCount:[10,25,50,-1],selection:!1,multiSelect:!1,rowSelect:!1,keepSelection:!1,highlightRows:!1,sorting:!0,multiSort:!1,searchSettings:{delay:250,characters:1},ajax:!1,ajaxSettings:{method:"POST"},post:{},url:"",caseSensitive:!0,requestHandler:function(a){return a},responseHandler:function(a){return a},converters:{numeric:{from:function(a){return+a},to:function(a){return a+""}},string:{from:function(a){return a},to:function(a){return a}}},css:{actions:"actions btn-group",center:"text-center",columnHeaderAnchor:"column-header-anchor",columnHeaderText:"text",dropDownItem:"dropdown-item",dropDownItemButton:"dropdown-item-button",dropDownItemCheckbox:"dropdown-item-checkbox",dropDownMenu:"dropdown btn-group",dropDownMenuItems:"dropdown-menu pull-right",dropDownMenuText:"dropdown-text",footer:"bootgrid-footer container-fluid",header:"bootgrid-header container-fluid",icon:"icon glyphicon",iconColumns:"glyphicon-th-list",iconDown:"glyphicon-chevron-down",iconRefresh:"glyphicon-refresh",iconSearch:"glyphicon-search",iconUp:"glyphicon-chevron-up",infos:"infos",left:"text-left",pagination:"pagination",paginationButton:"button",responsiveTable:"table-responsive",right:"text-right",search:"search form-group",searchField:"search-field form-control",selectBox:"select-box",selectCell:"select-cell",selected:"active",sortable:"sortable",table:"bootgrid-table table"},formatters:{},labels:{all:"All",infos:"Showing {{ctx.start}} to {{ctx.end}} of {{ctx.total}} entries",loading:"Loading...",noResults:"No results found!",refresh:"Refresh",search:"Search"},statusMapping:{0:"success",1:"info",2:"warning",3:"danger"},templates:{actionButton:'',actionDropDown:'',actionDropDownItem:'{{ctx.text}}',actionDropDownCheckboxItem:'',actions:'',body:"",cell:'{{ctx.content}} | ',footer:'',header:'',headerCell:'{{ctx.column.text}}{{ctx.icon}} | ',icon:'',infos:'{{lbl.infos}}
',loading:'{{lbl.loading}} |
',noResults:'{{lbl.noResults}} |
',pagination:'',paginationItem:'',rawHeaderCell:'{{ctx.content}} | ',row:"{{ctx.cells}}
",search:'',select:''}},I.prototype.append=function(a){if(this.options.ajax);else{for(var b=[],c=0;c0&&(this.options.multiSelect||1!==e.length);)if(c=b.pop(),-1===a.inArray(c,this.selectedRows))for(d=0;d0){var f=h(this.options.css.selectBox),g=this.selectedRows.length>=this.currentRows.length;for(d=0;!this.options.keepSelection&&g&&d tr "+f+":checked").trigger("click"+H),d=0;d tr[data-row-id="'+this.selectedRows[d]+'"]').addClass(this.options.css.selected)._bgAria("selected","true").find(f).prop("checked",!0);this.element.trigger("selected"+H,[e])}}return this},I.prototype.deselect=function(b){if(this.selection){b=b||this.currentRows.propValues(this.identifier);for(var c,d,e,f=[];b.length>0;)if(c=b.pop(),e=a.inArray(c,this.selectedRows),-1!==e)for(d=0;d0){var g=h(this.options.css.selectBox);for(this.element.find("thead "+g).prop("checked",!1),d=0;d tr[data-row-id="'+f[d][this.identifier]+'"]').removeClass(this.options.css.selected)._bgAria("selected","false").find(g).prop("checked",!1);this.element.trigger("deselected"+H,[f])}}return this},I.prototype.sort=function(b){var c=b?a.extend({},b):{};return c===this.sortDictionary?this:(this.sortDictionary=c,C.call(this),G.call(this),n.call(this),this)},I.prototype.getColumnSettings=function(){return a.merge([],this.columns)},I.prototype.getCurrentPage=function(){return this.current},I.prototype.getCurrentRows=function(){return a.merge([],this.currentRows)},I.prototype.getRowCount=function(){return this.rowCount},I.prototype.getSearchPhrase=function(){return this.searchPhrase},I.prototype.getSelectedRows=function(){return a.merge([],this.selectedRows)},I.prototype.getSortDictionary=function(){return a.extend({},this.sortDictionary)},I.prototype.getTotalPageCount=function(){return this.totalPages},I.prototype.getTotalRowCount=function(){return this.total},a.fn.extend({_bgAria:function(a,b){return b?this.attr("aria-"+a,b):this.attr("aria-"+a)},_bgBusyAria:function(a){return null==a||a?this._bgAria("busy","true"):this._bgAria("busy","false")},_bgRemoveAria:function(a){return this.removeAttr("aria-"+a)},_bgEnableAria:function(a){return null==a||a?this.removeClass("disabled")._bgAria("disabled","false"):this.addClass("disabled")._bgAria("disabled","true")},_bgEnableField:function(a){return null==a||a?this.removeAttr("disabled"):this.attr("disabled","disable")},_bgShowAria:function(a){return null==a||a?this.show()._bgAria("hidden","false"):this.hide()._bgAria("hidden","true")},_bgSelectAria:function(a){return null==a||a?this.addClass("active")._bgAria("selected","true"):this.removeClass("active")._bgAria("selected","false")},_bgId:function(a){return a?this.attr("id",a):this.attr("id")}}),!String.prototype.resolve){var J={checked:function(a){return"boolean"==typeof a?a?'checked="checked"':"":a}};String.prototype.resolve=function(b,c){var d=this;return a.each(b,function(b,e){if(null!=e&&"function"!=typeof e)if("object"==typeof e){var f=c?a.extend([],c):[];f.push(b),d=d.resolve(e,f)+""}else{J&&J[b]&&"function"==typeof J[b]&&(e=J[b](e)),b=c?c.join(".")+"."+b:b;var g=new RegExp("\\{\\{"+b+"\\}\\}","gm");d=d.replace(g,e.replace?e.replace(/\$/gi,"$"):e)}}),d}}Array.prototype.first||(Array.prototype.first=function(a){for(var b=0;bc?this.length>d?this.slice(c,d):this.slice(c):[]}),Array.prototype.where||(Array.prototype.where=function(a){for(var b=[],c=0;c tr").first(),d=!1;c.children().each(function(){var c=a(this),e=c.data(),f={id:e.columnId,identifier:null==b.identifier&&e.identifier||!1,converter:b.options.converters[e.converter||e.type]||b.options.converters.string,text:c.text(),align:e.align||"left",headerAlign:e.headerAlign||"left",cssClass:e.cssClass||"",headerCssClass:e.headerCssClass||"",formatter:b.options.formatters[e.formatter]||null,order:d||"asc"!==e.order&&"desc"!==e.order?null:e.order,searchable:!(e.searchable===!1),sortable:!(e.sortable===!1),visible:!(e.visible===!1),visibleInSelection:!(e.visibleInSelection===!1),width:a.isNumeric(e.width)?e.width+"px":"string"==typeof e.width?e.width:null};b.columns.push(f),null!=f.order&&(b.sortDictionary[f.id]=f.order),f.identifier&&(b.identifier=f.id,b.converter=f.converter),b.options.multiSort||null===f.order||(d=!0)})}function n(){function c(a){for(var b,c=new RegExp(e.searchPhrase,e.options.caseSensitive?"g":"gi"),d=0;d-1)return!0;return!1}function d(a,b){e.currentRows=a,p.call(e,b),e.options.keepSelection||(e.selectedRows=[]),y.call(e,a),t.call(e),v.call(e),e.element._bgBusyAria(!1).trigger("loaded"+H)}var e=this;if(this.element._bgBusyAria(!0).trigger("load"+H),F.call(this),this.options.ajax){var f=g.call(this),h=i.call(this);if(null==h||"string"!=typeof h||0===h.length)throw new Error("Url setting must be a none empty string or a function that returns one.");this.xqr&&this.xqr.abort();var j={url:h,data:f,success:function(b){e.xqr=null,"string"==typeof b&&(b=a.parseJSON(b)),b=e.options.responseHandler(b),e.current=b.current,d(b.rows,b.total)},error:function(a,b,c){e.xqr=null,"abort"!==b&&(u.call(e),e.element._bgBusyAria(!1).trigger("loaded"+H))}};j=a.extend(this.options.ajaxSettings,j),this.xqr=a.ajax(j)}else{var k=this.searchPhrase.length>0?this.rows.where(c):this.rows,l=k.length;-1!==this.rowCount&&(k=k.page(this.current,this.rowCount)),b.setTimeout(function(){d(k,l)},10)}}function o(){if(!this.options.ajax){var b=this,c=this.element.find("tbody > tr");c.each(function(){var c=a(this),e=c.children("td"),f={};a.each(b.columns,function(a,b){f[b.id]=b.converter.from(e.eq(a).text())}),d.call(b,f)}),p.call(this,this.rows.length),G.call(this)}}function p(a){this.total=a,this.totalPages=-1===this.rowCount?1:Math.ceil(this.total/this.rowCount)}function q(){var b=this.options.templates,c=this.element.parent().hasClass(this.options.css.responsiveTable)?this.element.parent():this.element;this.element.addClass(this.options.css.table),0===this.element.children("tbody").length&&this.element.append(b.body),1&this.options.navigation&&(this.header=a(b.header.resolve(f.call(this,{id:this.element._bgId()+"-header"}))),c.before(this.header)),2&this.options.navigation&&(this.footer=a(b.footer.resolve(f.call(this,{id:this.element._bgId()+"-footer"}))),c.after(this.footer))}function r(){if(0!==this.options.navigation){var b=this.options.css,c=h(b.actions),d=e.call(this,c);if(d.length>0){var g=this,i=this.options.templates,j=a(i.actions.resolve(f.call(this)));if(this.options.ajax){var k=i.icon.resolve(f.call(this,{iconCss:b.iconRefresh})),l=a(i.actionButton.resolve(f.call(this,{content:k,text:this.options.labels.refresh}))).on("click"+H,function(a){a.stopPropagation(),g.current=1,n.call(g)});j.append(l)}x.call(this,j),s.call(this,j),E.call(this,d,j)}}}function s(b){if(this.options.columnSelection&&this.columns.length>1){var c=this,d=this.options.css,e=this.options.templates,g=e.icon.resolve(f.call(this,{iconCss:d.iconColumns})),i=a(e.actionDropDown.resolve(f.call(this,{content:g}))),j=h(d.dropDownItem),k=h(d.dropDownItemCheckbox),m=h(d.dropDownMenuItems);a.each(this.columns,function(b,g){if(g.visibleInSelection){var o=a(e.actionDropDownCheckboxItem.resolve(f.call(c,{name:g.id,label:g.text,checked:g.visible}))).on("click"+H,j,function(b){b.stopPropagation();var d=a(this),e=d.find(k);if(!e.prop("disabled")){g.visible=e.prop("checked");var f=c.columns.where(l).length>1;d.parents(m).find(j+":has("+k+":checked)")._bgEnableAria(f).find(k)._bgEnableField(f),c.element.find("tbody").empty(),C.call(c),n.call(c)}});i.find(h(d.dropDownMenuItems)).append(o)}}),b.append(i)}}function t(){if(0!==this.options.navigation){var b=h(this.options.css.infos),c=e.call(this,b);if(c.length>0){var d=this.current*this.rowCount,g=a(this.options.templates.infos.resolve(f.call(this,{end:0===this.total||-1===d||d>this.total?this.total:d,start:0===this.total?0:d-this.rowCount+1,total:this.total})));E.call(this,c,g)}}}function u(){var a=this.element.children("tbody").first(),b=this.options.templates,c=this.columns.where(l).length;this.selection&&(c+=1),a.html(b.noResults.resolve(f.call(this,{columns:c})))}function v(){if(0!==this.options.navigation){var b=h(this.options.css.pagination),c=e.call(this,b)._bgShowAria(-1!==this.rowCount);if(-1!==this.rowCount&&c.length>0){var d=this.options.templates,g=this.current,i=this.totalPages,j=a(d.pagination.resolve(f.call(this))),k=i-g,l=-1*(this.options.padding-g),m=k>=this.options.padding?Math.max(l,1):Math.max(l-this.options.padding+k,1),n=2*this.options.padding+1,o=i>=n?n:i;w.call(this,j,"first","«","first")._bgEnableAria(g>1),w.call(this,j,"prev","<","prev")._bgEnableAria(g>1);for(var p=0;o>p;p++){var q=p+m;w.call(this,j,q,q,"page-"+q)._bgEnableAria()._bgSelectAria(q===g)}0===o&&w.call(this,j,1,1,"page-1")._bgEnableAria(!1)._bgSelectAria(),w.call(this,j,"next",">","next")._bgEnableAria(i>g),w.call(this,j,"last","»","last")._bgEnableAria(i>g),E.call(this,c,j)}}}function w(b,c,d,e){var g=this,i=this.options.templates,j=this.options.css,k=f.call(this,{css:e,text:d,page:c}),l=a(i.paginationItem.resolve(k)).on("click"+H,h(j.paginationButton),function(b){b.stopPropagation(),b.preventDefault();var c=a(this),d=c.parent();if(!d.hasClass("active")&&!d.hasClass("disabled")){var e={first:1,prev:g.current-1,next:g.current+1,last:g.totalPages},f=c.data("page");g.current=e[f]||f,n.call(g)}c.trigger("blur")});return b.append(l),l}function x(b){function c(a){return-1===a?d.options.labels.all:a}var d=this,e=this.options.rowCount;if(a.isArray(e)){var g=this.options.css,i=this.options.templates,j=a(i.actionDropDown.resolve(f.call(this,{content:c(this.rowCount)}))),k=h(g.dropDownMenu),l=h(g.dropDownMenuText),m=h(g.dropDownMenuItems),o=h(g.dropDownItemButton);a.each(e,function(b,e){var g=a(i.actionDropDownItem.resolve(f.call(d,{text:c(e),action:e})))._bgSelectAria(e===d.rowCount).on("click"+H,o,function(b){b.preventDefault();var e=a(this),f=e.data("action");f!==d.rowCount&&(d.current=1,d.rowCount=f,e.parents(m).children().each(function(){var b=a(this),c=b.find(o).data("action");b._bgSelectAria(c===f)}),e.parents(k).find(l).text(c(f)),n.call(d))});j.find(m).append(g)}),b.append(j)}}function y(b){if(b.length>0){var c=this,d=this.options.css,e=this.options.templates,g=this.element.children("tbody").first(),i=!0,j="";a.each(b,function(b,g){var h="",k=' data-row-id="'+(null==c.identifier?b:g[c.identifier])+'"',l="";if(c.selection){var m=-1!==a.inArray(g[c.identifier],c.selectedRows),n=e.select.resolve(f.call(c,{type:"checkbox",value:g[c.identifier],checked:m}));h+=e.cell.resolve(f.call(c,{content:n,css:d.selectCell})),i=i&&m,m&&(l+=d.selected,k+=' aria-selected="true"')}var o=null!=g.status&&c.options.statusMapping[g.status];o&&(l+=o),a.each(c.columns,function(b,i){if(i.visible){var j=a.isFunction(i.formatter)?i.formatter.call(c,i,g):i.converter.to(g[i.id]),k=i.cssClass.length>0?" "+i.cssClass:"";h+=e.cell.resolve(f.call(c,{content:null==j||""===j?" ":j,css:("right"===i.align?d.right:"center"===i.align?d.center:d.left)+k,style:null==i.width?"":"width:"+i.width+";"}))}}),l.length>0&&(k+=' class="'+l+'"'),j+=e.row.resolve(f.call(c,{attr:k,cells:h}))}),c.element.find("thead "+h(c.options.css.selectBox)).prop("checked",i),g.html(j),z.call(this,g)}else u.call(this)}function z(b){var c=this,d=h(this.options.css.selectBox);this.selection&&b.off("click"+H,d).on("click"+H,d,function(b){b.stopPropagation();var d=a(this),e=c.converter.from(d.val());d.prop("checked")?c.select([e]):c.deselect([e])}),b.off("click"+H,"> tr").on("click"+H,"> tr",function(b){b.stopPropagation();var d=a(this),e=null==c.identifier?d.data("row-id"):c.converter.from(d.data("row-id")+""),f=null==c.identifier?c.currentRows[e]:c.currentRows.first(function(a){return a[c.identifier]===e});c.selection&&c.options.rowSelect&&(d.hasClass(c.options.css.selected)?c.deselect([e]):c.select([e])),c.element.trigger("click"+H,[c.columns,f])})}function A(){if(0!==this.options.navigation){var c=this.options.css,d=h(c.search),g=e.call(this,d);if(g.length>0){var i=this,j=this.options.templates,k=null,l="",m=h(c.searchField),n=a(j.search.resolve(f.call(this))),o=n.is(m)?n:n.find(m);o.on("keyup"+H,function(c){c.stopPropagation();var d=a(this).val();(l!==d||13===c.which&&""!==d)&&(l=d,(13===c.which||0===d.length||d.length>=i.options.searchSettings.characters)&&(b.clearTimeout(k),k=b.setTimeout(function(){B.call(i,d)},i.options.searchSettings.delay)))}),E.call(this,g,n)}}}function B(a){this.searchPhrase!==a&&(this.current=1,this.searchPhrase=a,n.call(this))}function C(){var b=this,c=this.element.find("thead > tr"),d=this.options.css,e=this.options.templates,g="",i=this.options.sorting;if(this.selection){var j=this.options.multiSelect?e.select.resolve(f.call(b,{type:"checkbox",value:"all"})):"";g+=e.rawHeaderCell.resolve(f.call(b,{content:j,css:d.selectCell}))}if(a.each(this.columns,function(a,c){if(c.visible){var h=b.sortDictionary[c.id],j=i&&h&&"asc"===h?d.iconUp:i&&h&&"desc"===h?d.iconDown:"",k=e.icon.resolve(f.call(b,{iconCss:j})),l=c.headerAlign,m=c.headerCssClass.length>0?" "+c.headerCssClass:"";g+=e.headerCell.resolve(f.call(b,{column:c,icon:k,sortable:i&&c.sortable&&d.sortable||"",css:("right"===l?d.right:"center"===l?d.center:d.left)+m,style:null==c.width?"":"width:"+c.width+";"}))}}),c.html(g),i){var k=h(d.sortable);c.off("click"+H,k).on("click"+H,k,function(c){c.preventDefault(),D.call(b,a(this)),G.call(b),n.call(b)})}if(this.selection&&this.options.multiSelect){var l=h(d.selectBox);c.off("click"+H,l).on("click"+H,l,function(c){c.stopPropagation(),a(this).prop("checked")?b.select():b.deselect()})}}function D(a){var b=this.options.css,c=h(b.icon),d=a.data("column-id")||a.parents("th").first().data("column-id"),e=this.sortDictionary[d],f=a.find(c);if(this.options.multiSort||(a.parents("tr").first().find(c).removeClass(b.iconDown+" "+b.iconUp),this.sortDictionary={}),e&&"asc"===e)this.sortDictionary[d]="desc",f.removeClass(b.iconUp).addClass(b.iconDown);else if(e&&"desc"===e)if(this.options.multiSort){var g={};for(var i in this.sortDictionary)i!==d&&(g[i]=this.sortDictionary[i]);this.sortDictionary=g,f.removeClass(b.iconDown)}else this.sortDictionary[d]="asc",f.removeClass(b.iconDown).addClass(b.iconUp);else this.sortDictionary[d]="asc",f.addClass(b.iconUp)}function E(b,c){b.each(function(b,d){a(d).before(c.clone(!0)).remove()})}function F(){var a=this;b.setTimeout(function(){if("true"===a.element._bgAria("busy")){var b=a.options.templates,c=a.element.children("thead").first(),d=a.element.children("tbody").first(),e=d.find("tr > td").first(),g=a.element.height()-c.height()-(e.height()+20),h=a.columns.where(l).length;a.selection&&(h+=1),d.html(b.loading.resolve(f.call(a,{columns:h}))),-1!==a.rowCount&&g>0&&d.find("tr > td").css("padding","20px 0 "+g+"px")}},250)}function G(){function a(c,d,e){function f(a){return"asc"===h.order?a:-1*a}e=e||0;var g=e+1,h=b[e];return c[h.id]>d[h.id]?f(1):c[h.id]g?a(c,d,g):0}var b=[];if(!this.options.ajax){for(var c in this.sortDictionary)(this.options.multiSort||0===b.length)&&b.push({id:c,order:this.sortDictionary[c]});b.length>0&&this.rows.sort(a)}}var H=".rs.jquery.bootgrid",I=function(b,c){this.element=a(b),this.origin=this.element.clone(),this.options=a.extend(!0,{},I.defaults,this.element.data(),c);var d=this.options.rowCount=this.element.data().rowCount||c.rowCount||this.options.rowCount;this.columns=[],this.current=1,this.currentRows=[],this.identifier=null,this.selection=!1,this.converter=null,this.rowCount=a.isArray(d)?d[0]:d,this.rows=[],this.searchPhrase="",this.selectedRows=[],this.sortDictionary={},this.total=0,this.totalPages=0,this.cachedParams={lbl:this.options.labels,css:this.options.css,ctx:{}},this.header=null,this.footer=null,this.xqr=null};if(I.defaults={navigation:3,padding:2,columnSelection:!0,rowCount:[10,25,50,-1],selection:!1,multiSelect:!1,rowSelect:!1,keepSelection:!1,highlightRows:!1,sorting:!0,multiSort:!1,searchSettings:{delay:250,characters:1},ajax:!1,ajaxSettings:{method:"POST"},post:{},url:"",caseSensitive:!0,requestHandler:function(a){return a},responseHandler:function(a){return a},converters:{numeric:{from:function(a){return+a},to:function(a){return a+""}},string:{from:function(a){return a},to:function(a){return a}}},css:{actions:"actions btn-group",center:"text-center",columnHeaderAnchor:"column-header-anchor",columnHeaderText:"text",dropDownItem:"dropdown-item",dropDownItemButton:"dropdown-item-button",dropDownItemCheckbox:"dropdown-item-checkbox",dropDownMenu:"dropdown btn-group",dropDownMenuItems:"dropdown-menu pull-right",dropDownMenuText:"dropdown-text",footer:"bootgrid-footer container-fluid",header:"bootgrid-header container-fluid",icon:"icon glyphicon",iconColumns:"glyphicon-th-list",iconDown:"glyphicon-chevron-down",iconRefresh:"glyphicon-refresh",iconSearch:"glyphicon-search",iconUp:"glyphicon-chevron-up",infos:"infos",left:"text-left",pagination:"pagination",paginationButton:"button",responsiveTable:"table-responsive",right:"text-right",search:"search form-group",searchField:"search-field form-control",selectBox:"select-box",selectCell:"select-cell",selected:"active",sortable:"sortable",table:"bootgrid-table table"},formatters:{},labels:{all:"All",infos:"Showing {{ctx.start}} to {{ctx.end}} of {{ctx.total}} entries",loading:"Loading...",noResults:"No results found!",refresh:"Refresh",search:"Search"},statusMapping:{0:"success",1:"info",2:"warning",3:"danger"},templates:{actionButton:'',actionDropDown:'',actionDropDownItem:'{{ctx.text}}',actionDropDownCheckboxItem:'',actions:'',body:"",cell:'{{ctx.content}} | ',footer:'',header:'',headerCell:'{{ctx.column.text}}{{ctx.icon}} | ',icon:'',infos:'{{lbl.infos}}
',loading:'{{lbl.loading}} |
',noResults:'{{lbl.noResults}} |
',pagination:'',paginationItem:'',rawHeaderCell:'{{ctx.content}} | ',row:"{{ctx.cells}}
",search:'',select:''}},I.prototype.append=function(a){if(this.options.ajax);else{for(var b=[],c=0;c0&&(this.options.multiSelect||1!==e.length);)if(c=b.pop(),-1===a.inArray(c,this.selectedRows))for(d=0;d0){var f=h(this.options.css.selectBox),g=this.selectedRows.length>=this.currentRows.length;for(d=0;!this.options.keepSelection&&g&&d tr "+f+":checked").trigger("click"+H),d=0;d tr[data-row-id="'+this.selectedRows[d]+'"]').addClass(this.options.css.selected)._bgAria("selected","true").find(f).prop("checked",!0);this.element.trigger("selected"+H,[e])}}return this},I.prototype.deselect=function(b){if(this.selection){b=b||this.currentRows.propValues(this.identifier);for(var c,d,e,f=[];b.length>0;)if(c=b.pop(),e=a.inArray(c,this.selectedRows),-1!==e)for(d=0;d0){var g=h(this.options.css.selectBox);for(this.element.find("thead "+g).prop("checked",!1),d=0;d tr[data-row-id="'+f[d][this.identifier]+'"]').removeClass(this.options.css.selected)._bgAria("selected","false").find(g).prop("checked",!1);this.element.trigger("deselected"+H,[f])}}return this},I.prototype.sort=function(b){var c=b?a.extend({},b):{};return c===this.sortDictionary?this:(this.sortDictionary=c,C.call(this),G.call(this),n.call(this),this)},I.prototype.getColumnSettings=function(){return a.merge([],this.columns)},I.prototype.getCurrentPage=function(){return this.current},I.prototype.getCurrentRows=function(){return a.merge([],this.currentRows)},I.prototype.getRowCount=function(){return this.rowCount},I.prototype.getSearchPhrase=function(){return this.searchPhrase},I.prototype.getSelectedRows=function(){return a.merge([],this.selectedRows)},I.prototype.getSortDictionary=function(){return a.extend({},this.sortDictionary)},I.prototype.getTotalPageCount=function(){return this.totalPages},I.prototype.getTotalRowCount=function(){return this.total},a.fn.extend({_bgAria:function(a,b){return b?this.attr("aria-"+a,b):this.attr("aria-"+a)},_bgBusyAria:function(a){return null==a||a?this._bgAria("busy","true"):this._bgAria("busy","false")},_bgRemoveAria:function(a){return this.removeAttr("aria-"+a)},_bgEnableAria:function(a){return null==a||a?this.removeClass("disabled")._bgAria("disabled","false"):this.addClass("disabled")._bgAria("disabled","true")},_bgEnableField:function(a){return null==a||a?this.removeAttr("disabled"):this.attr("disabled","disable")},_bgShowAria:function(a){return null==a||a?this.show()._bgAria("hidden","false"):this.hide()._bgAria("hidden","true")},_bgSelectAria:function(a){return null==a||a?this.addClass("active")._bgAria("selected","true"):this.removeClass("active")._bgAria("selected","false")},_bgId:function(a){return a?this.attr("id",a):this.attr("id")}}),!String.prototype.resolve){var J={checked:function(a){return"boolean"==typeof a?a?'checked="checked"':"":a}};String.prototype.resolve=function(b,c){var d=this;return a.each(b,function(b,e){if(null!=e&&"function"!=typeof e)if("object"==typeof e){var f=c?a.extend([],c):[];f.push(b),d=d.resolve(e,f)+""}else{J&&J[b]&&"function"==typeof J[b]&&(e=J[b](e)),b=c?c.join(".")+"."+b:b;var g=new RegExp("\\{\\{"+b+"\\}\\}","gm");d=d.replace(g,e.replace?e.replace(/\$/gi,"$"):e)}}),d}}Array.prototype.first||(Array.prototype.first=function(a){for(var b=0;bc?this.length>d?this.slice(c,d):this.slice(c):[]}),Array.prototype.where||(Array.prototype.where=function(a){for(var b=[],c=0;cdisableHTMLDescription)) {
}
?>