diff --git a/dist/jquery.bootgrid.js b/dist/jquery.bootgrid.js
index ffda62a..2c1b454 100644
--- a/dist/jquery.bootgrid.js
+++ b/dist/jquery.bootgrid.js
@@ -1,6 +1,6 @@
/*!
- * jQuery Bootgrid v1.1.4 - 11/23/2014
- * Copyright (c) 2014 Rafael Staib (http://www.jquery-bootgrid.com)
+ * jQuery Bootgrid v1.1.4 - 01/30/2015
+ * Copyright (c) 2015 Rafael Staib (http://www.jquery-bootgrid.com)
* Licensed under MIT http://www.opensource.org/licenses/MIT
*/
;(function ($, window, undefined)
@@ -8,1741 +8,1756 @@
/*jshint validthis: true */
"use strict";
- // GRID INTERNAL FIELDS
- // ====================
+// GRID INTERNAL FIELDS
+// ====================
- var namespace = ".rs.jquery.bootgrid";
+var namespace = ".rs.jquery.bootgrid";
- // GRID INTERNAL FUNCTIONS
- // =====================
+// 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 appendRow(row)
+{
+ var that = this;
- function getParams(context)
+ function exists(item)
{
- return (context) ? $.extend({}, this.cachedParams, { ctx: context }) :
- this.cachedParams;
+ return that.identifier && item[that.identifier] === row[that.identifier];
}
- function getRequest()
+ if (!this.rows.contains(exists))
{
- var request = {
- current: this.current,
- rowCount: this.rowCount,
- sort: this.sort,
- searchPhrase: this.searchPhrase
- },
- post = this.options.post;
-
- post = ($.isFunction(post)) ? post() : post;
- return this.options.requestHandler($.extend(true, request, post));
+ this.rows.push(row);
+ return true;
}
- function getCssSelector(css)
- {
- return "." + $.trim(css).replace(/\s+/gm, ".");
- }
+ return false;
+}
+
+function getParams(context)
+{
+ return (context) ? $.extend({}, this.cachedParams, { ctx: context }) :
+ this.cachedParams;
+}
- function getUrl()
+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)
{
- var url = this.options.url;
- return ($.isFunction(url)) ? url() : url;
+ // todo: implement
}
+}
- 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);
+function isVisible(column)
+{
+ return column.visible;
+}
- this.element.trigger("initialized" + namespace);
- }
+function loadColumns()
+{
+ var that = this,
+ firstHeadRow = this.element.find("thead > tr").first(),
+ sorted = false;
- function highlightAppendedRows(rows)
+ /*jshint -W018*/
+ firstHeadRow.children().each(function ()
{
- if (this.options.highlightRows)
+ 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
+ };
+ that.columns.push(column);
+ if (column.order != null)
{
- // todo: implement
+ that.sortDictionary[column.id] = column.order;
}
- }
- function isVisible(column)
+ // 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,
+ request = getRequest.call(this),
+ url = getUrl.call(this);
+
+ if (this.options.ajax && (url == null || typeof url !== "string" || url.length === 0))
{
- return column.visible;
+ throw new Error("Url setting must be a none empty string or a function that returns one.");
}
- function loadColumns()
+ this.element._bgBusyAria(true).trigger("load" + namespace);
+ showLoading.call(this);
+
+ function containsPhrase(row)
{
- var that = this,
- firstHeadRow = this.element.find("thead > tr").first(),
- sorted = false;
+ var column,
+ searchPattern = new RegExp(that.searchPhrase, (that.options.caseSensitive) ? "g" : "gi");
- /*jshint -W018*/
- firstHeadRow.children().each(function ()
+ for (var i = 0; i < that.columns.length; i++)
{
- 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
- };
- that.columns.push(column);
- if (column.order != null)
- {
- that.sort[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)
+ column = that.columns[i];
+ if (column.searchable && column.visible &&
+ column.converter.to(row[column.id]).search(searchPattern) > -1)
{
- sorted = true;
+ return true;
}
- });
- /*jshint +W018*/
- }
+ }
- /*
- response = {
- current: 1,
- rowCount: 10,
- rows: [{}, {}],
- sort: [{ "columnId": "asc" }],
- total: 101
+ return false;
}
- */
- function loadData()
+ function update(rows, total)
{
- var that = this,
- request = getRequest.call(this),
- url = getUrl.call(this);
+ that.currentRows = rows;
+ that.total = total;
+ that.totalPages = Math.ceil(total / that.rowCount);
- if (this.options.ajax && (url == null || typeof url !== "string" || url.length === 0))
+ if (!that.options.keepSelection)
{
- throw new Error("Url setting must be a none empty string or a function that returns one.");
+ that.selectedRows = [];
}
- 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");
+ renderRows.call(that, rows);
+ renderInfos.call(that);
+ renderPagination.call(that);
- 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;
- }
- }
+ that.element._bgBusyAria(false).trigger("loaded" + namespace);
+ }
- return false;
+ if (this.options.ajax)
+ {
+ // aborts the previous ajax request if not already finished or failed
+ if (that.xqr)
+ {
+ that.xqr.abort();
}
- function update(rows, total)
+ that.xqr = $.post(url, request, function (response)
{
- that.currentRows = rows;
- that.total = total;
- that.totalPages = Math.ceil(total / that.rowCount);
+ that.xqr = null;
- if (!that.options.keepSelection)
+ if (typeof (response) === "string")
{
- that.selectedRows = [];
+ response = $.parseJSON(response);
}
- renderRows.call(that, rows);
- renderInfos.call(that);
- renderPagination.call(that);
-
- that.element._bgBusyAria(false).trigger("loaded" + namespace);
- }
+ response = that.options.responseHandler(response);
- if (this.options.ajax)
+ that.current = response.current;
+ update(response.rows, response.total);
+ }).fail(function (jqXHR, textStatus, errorThrown)
{
- // aborts the previous ajax request if not already finished or failed
- if (that.xqr)
- {
- that.xqr.abort();
- }
-
- that.xqr = $.post(url, request, function (response)
- {
- that.xqr = null;
-
- if (typeof (response) === "string")
- {
- response = $.parseJSON(response);
- }
+ that.xqr = null;
- response = that.options.responseHandler(response);
-
- that.current = response.current;
- update(response.rows, response.total);
- }).fail(function (jqXHR, textStatus, errorThrown)
- {
- that.xqr = null;
-
- if (textStatus !== "abort")
- {
- renderNoResultsRow.call(that); // overrides loading mask
- that.element._bgBusyAria(false).trigger("loaded" + namespace);
- }
- });
- }
- else
- {
- var rows = (this.searchPhrase.length > 0) ? this.rows.where(containsPhrase) : this.rows,
- total = rows.length;
- if (this.rowCount !== -1)
+ if (textStatus !== "abort")
{
- rows = rows.page(this.current, this.rowCount);
+ renderNoResultsRow.call(that); // overrides loading mask
+ that.element._bgBusyAria(false).trigger("loaded" + namespace);
}
-
- // todo: improve the following comment
- // setTimeout decouples the initialization so that adding event handlers happens before
- window.setTimeout(function () { update(rows, total); }, 10);
+ });
+ }
+ 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()
+function loadRows()
+{
+ if (!this.options.ajax)
{
- if (!this.options.ajax)
+ var that = this,
+ rows = this.element.find("tbody > tr");
+
+ rows.each(function ()
{
- var that = this,
- rows = this.element.find("tbody > tr");
+ var $this = $(this),
+ cells = $this.children("td"),
+ row = {};
- rows.each(function ()
+ $.each(that.columns, function (i, column)
{
- 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);
+ row[column.id] = column.converter.from(cells.eq(i).text());
});
- this.total = this.rows.length;
- this.totalPages = (this.rowCount === -1) ? 1 :
- Math.ceil(this.total / this.rowCount);
-
- sortRows.call(this);
- }
- }
+ appendRow.call(that, row);
+ });
- function prepareTable()
- {
- var tpl = this.options.templates,
- wrapper = (this.element.parent().hasClass(this.options.css.responsiveTable)) ?
- this.element.parent() : this.element;
+ this.total = this.rows.length;
+ this.totalPages = (this.rowCount === -1) ? 1 :
+ Math.ceil(this.total / this.rowCount);
- this.element.addClass(this.options.css.table);
+ sortRows.call(this);
+ }
+}
- // checks whether there is an tbody element; otherwise creates one
- if (this.element.children("tbody").length === 0)
- {
- this.element.append(tpl.body);
- }
+function prepareTable()
+{
+ var tpl = this.options.templates,
+ wrapper = (this.element.parent().hasClass(this.options.css.responsiveTable)) ?
+ this.element.parent() : this.element;
- if (this.options.navigation & 1)
- {
- this.header = $(tpl.header.resolve(getParams.call(this, { id: this.element._bgId() + "-header" })));
- wrapper.before(this.header);
- }
+ this.element.addClass(this.options.css.table);
- if (this.options.navigation & 2)
- {
- this.footer = $(tpl.footer.resolve(getParams.call(this, { id: this.element._bgId() + "-footer" })));
- wrapper.after(this.footer);
- }
+ // checks whether there is an tbody element; otherwise creates one
+ if (this.element.children("tbody").length === 0)
+ {
+ this.element.append(tpl.body);
}
- function renderActions()
+ if (this.options.navigation & 1)
{
- if (this.options.navigation !== 0)
- {
- var css = this.options.css,
- selector = getCssSelector(css.actions),
- headerActions = this.header.find(selector),
- footerActions = this.footer.find(selector);
-
- if ((headerActions.length + footerActions.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);
+ this.header = $(tpl.header.resolve(getParams.call(this, { id: this.element._bgId() + "-header" })));
+ wrapper.before(this.header);
+ }
- replacePlaceHolder.call(this, headerActions, actions, 1);
- replacePlaceHolder.call(this, footerActions, actions, 2);
- }
- }
+ if (this.options.navigation & 2)
+ {
+ this.footer = $(tpl.footer.resolve(getParams.call(this, { id: this.element._bgId() + "-footer" })));
+ wrapper.after(this.footer);
}
+}
- function renderColumnSelection(actions)
+function renderActions()
+{
+ if (this.options.navigation !== 0)
{
- if (this.options.columnSelection && this.columns.length > 1)
+ var css = this.options.css,
+ selector = getCssSelector(css.actions),
+ headerActions = this.header.find(selector),
+ footerActions = this.footer.find(selector);
+
+ if ((headerActions.length + footerActions.length) > 0)
{
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);
+ actions = $(tpl.actions.resolve(getParams.call(this)));
- $.each(this.columns, function (i, column)
+ // Refresh Button
+ if (this.options.ajax)
{
- var item = $(tpl.actionDropDownCheckboxItem.resolve(getParams.call(that,
- { name: column.id, label: column.text, checked: column.visible })))
- .on("click" + namespace, selector, function (e)
+ 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();
-
- 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);
- }
+ that.current = 1;
+ loadData.call(that);
});
- dropDown.find(getCssSelector(css.dropDownMenuItems)).append(item);
- });
- actions.append(dropDown);
+ actions.append(refresh);
+ }
+
+ // Row count selection
+ renderRowCountSelection.call(this, actions);
+
+ // Column selection
+ renderColumnSelection.call(this, actions);
+
+ replacePlaceHolder.call(this, headerActions, actions, 1);
+ replacePlaceHolder.call(this, footerActions, actions, 2);
}
}
+}
- function renderInfos()
+function renderColumnSelection(actions)
+{
+ if (this.options.columnSelection && this.columns.length > 1)
{
- if (this.options.navigation !== 0)
+ 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)
{
- var selector = getCssSelector(this.options.css.infos),
- headerInfos = this.header.find(selector),
- footerInfos = this.footer.find(selector);
+ 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();
- if ((headerInfos.length + footerInfos.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, headerInfos, infos, 1);
- replacePlaceHolder.call(this, footerInfos, infos, 2);
- }
- }
+ 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 renderNoResultsRow()
+function renderInfos()
+{
+ if (this.options.navigation !== 0)
{
- var tbody = this.element.children("tbody").first(),
- tpl = this.options.templates,
- count = this.columns.where(isVisible).length;
+ var selector = getCssSelector(this.options.css.infos),
+ headerInfos = this.header.find(selector),
+ footerInfos = this.footer.find(selector);
- if (this.selection)
+ if ((headerInfos.length + footerInfos.length) > 0)
{
- count = count + 1;
+ 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, headerInfos, infos, 1);
+ replacePlaceHolder.call(this, footerInfos, infos, 2);
}
- tbody.html(tpl.noResults.resolve(getParams.call(this, { columns: count })));
}
+}
+
+function renderNoResultsRow()
+{
+ var tbody = this.element.children("tbody").first(),
+ tpl = this.options.templates,
+ count = this.columns.where(isVisible).length;
- function renderPagination()
+ if (this.selection)
{
- if (this.options.navigation !== 0)
- {
- var selector = getCssSelector(this.options.css.pagination),
- headerPagination = this.header.find(selector)._bgShowAria(this.rowCount !== -1),
- footerPagination = this.footer.find(selector)._bgShowAria(this.rowCount !== -1);
+ 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),
+ headerPagination = this.header.find(selector)._bgShowAria(this.rowCount !== -1),
+ footerPagination = this.footer.find(selector)._bgShowAria(this.rowCount !== -1);
- if (this.rowCount !== -1 && (headerPagination.length + footerPagination.length) > 0)
+ if (this.rowCount !== -1 && (headerPagination.length + footerPagination.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 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);
- }
+ 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();
- }
+ 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);
+ renderPaginationItem.call(this, pagination, "next", ">", "next")
+ ._bgEnableAria(totalPages > current);
+ renderPaginationItem.call(this, pagination, "last", "»", "last")
+ ._bgEnableAria(totalPages > current);
- replacePlaceHolder.call(this, headerPagination, pagination, 1);
- replacePlaceHolder.call(this, footerPagination, pagination, 2);
- }
+ replacePlaceHolder.call(this, headerPagination, pagination, 1);
+ replacePlaceHolder.call(this, footerPagination, pagination, 2);
}
}
+}
- function renderPaginationItem(list, uri, text, markerCss)
- {
- var that = this,
- tpl = this.options.templates,
- css = this.options.css,
- values = getParams.call(this, { css: markerCss, text: text, uri: "#" + uri }),
- item = $(tpl.paginationItem.resolve(values))
- .on("click" + namespace, getCssSelector(css.paginationButton), function (e)
+function renderPaginationItem(list, uri, text, markerCss)
+{
+ var that = this,
+ tpl = this.options.templates,
+ css = this.options.css,
+ values = getParams.call(this, { css: markerCss, text: text, uri: "#" + uri }),
+ item = $(tpl.paginationItem.resolve(values))
+ .on("click" + namespace, getCssSelector(css.paginationButton), function (e)
+ {
+ e.stopPropagation();
+
+ var $this = $(this),
+ parent = $this.parent();
+ if (!parent.hasClass("active") && !parent.hasClass("disabled"))
{
- e.stopPropagation();
+ var commandList = {
+ first: 1,
+ prev: that.current - 1,
+ next: that.current + 1,
+ last: that.totalPages
+ };
+ var command = $this.attr("href").substr(1);
+ that.current = commandList[command] || +command; // + converts string to int
+ loadData.call(that);
+ }
+ $this.trigger("blur");
+ });
- 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.attr("href").substr(1);
- that.current = commandList[command] || +command; // + converts string to int
- loadData.call(that);
- }
- $this.trigger("blur");
- });
+ list.append(item);
+ return item;
+}
- list.append(item);
- return item;
- }
+function renderRowCountSelection(actions)
+{
+ var that = this,
+ rowCountList = this.options.rowCount;
- function renderRowCountSelection(actions)
+ function getText(value)
{
- var that = this,
- rowCountList = this.options.rowCount;
+ return (value === -1) ? that.options.labels.all : value;
+ }
- 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: this.rowCount }))),
+ menuSelector = getCssSelector(css.dropDownMenu),
+ menuTextSelector = getCssSelector(css.dropDownMenuText),
+ menuItemsSelector = getCssSelector(css.dropDownMenuItems),
+ menuItemSelector = getCssSelector(css.dropDownItemButton);
- if ($.isArray(rowCountList))
+ $.each(rowCountList, function (index, value)
{
- var css = this.options.css,
- tpl = this.options.templates,
- dropDown = $(tpl.actionDropDown.resolve(getParams.call(this, { content: this.rowCount }))),
- menuSelector = getCssSelector(css.dropDownMenu),
- menuTextSelector = getCssSelector(css.dropDownMenuText),
- menuItemsSelector = getCssSelector(css.dropDownMenuItems),
- menuItemSelector = getCssSelector(css.dropDownItemButton);
+ var item = $(tpl.actionDropDownItem.resolve(getParams.call(that,
+ { text: getText(value), uri: "#" + value })))
+ ._bgSelectAria(value === that.rowCount)
+ .on("click" + namespace, menuItemSelector, function (e)
+ {
+ e.preventDefault();
- $.each(rowCountList, function (index, value)
- {
- var item = $(tpl.actionDropDownItem.resolve(getParams.call(that,
- { text: getText(value), uri: "#" + value })))
- ._bgSelectAria(value === that.rowCount)
- .on("click" + namespace, menuItemSelector, function (e)
+ var $this = $(this),
+ newRowCount = +$this.attr("href").substr(1);
+ if (newRowCount !== that.rowCount)
{
- e.preventDefault();
-
- var $this = $(this),
- newRowCount = +$this.attr("href").substr(1);
- 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 ()
{
- // 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).attr("href").substr(1);
- $item._bgSelectAria(currentRowCount === newRowCount);
- });
- $this.parents(menuSelector).find(menuTextSelector).text(getText(newRowCount));
- loadData.call(that);
- }
- });
- dropDown.find(menuItemsSelector).append(item);
- });
- actions.append(dropDown);
- }
+ var $item = $(this),
+ currentRowCount = +$item.find(menuItemSelector).attr("href").substr(1);
+ $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)
+function renderRows(rows)
+{
+ if (rows.length > 0)
{
- if (rows.length > 0)
+ var that = this,
+ css = this.options.css,
+ tpl = this.options.templates,
+ tbody = this.element.children("tbody").first(),
+ allRowsSelected = true,
+ html = "",
+ cells = "",
+ rowAttr = "",
+ rowCss = "";
+
+ $.each(rows, function (index, row)
{
- var that = this,
- css = this.options.css,
- tpl = this.options.templates,
- tbody = this.element.children("tbody").first(),
- allRowsSelected = true,
- html = "",
- cells = "",
- rowAttr = "",
- rowCss = "";
-
- $.each(rows, function (index, row)
- {
- cells = "";
- rowAttr = " data-row-id=\"" + ((that.identifier == null) ? index : row[that.identifier]) + "\"";
- rowCss = "";
+ cells = "";
+ rowAttr = " data-row-id=\"" + ((that.identifier == null) ? index : row[that.identifier]) + "\"";
+ rowCss = "";
- if (that.selection)
+ 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)
{
- 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\"";
- }
+ rowCss += css.selected;
+ rowAttr += " aria-selected=\"true\"";
}
+ }
- $.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 }));
- }
- });
-
- if (rowCss.length > 0)
+ $.each(that.columns, function (j, column)
+ {
+ if (column.visible)
{
- rowAttr += " class=\"" + rowCss + "\"";
+ 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 }));
}
- 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);
+ if (rowCss.length > 0)
+ {
+ rowAttr += " class=\"" + rowCss + "\"";
+ }
+ html += tpl.row.resolve(getParams.call(that, { attr: rowAttr, cells: cells }));
+ });
- tbody.html(html);
+ // sets or clears multi selectbox state
+ that.element.find("thead " + getCssSelector(that.options.css.selectBox))
+ .prop("checked", allRowsSelected);
- registerRowEvents.call(this, tbody);
- }
- else
- {
- renderNoResultsRow.call(this);
- }
- }
+ tbody.html(html);
- function registerRowEvents(tbody)
+ registerRowEvents.call(this, tbody);
+ }
+ else
{
- 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());
+ renderNoResultsRow.call(this);
+ }
+}
- if ($this.prop("checked"))
- {
- that.select([id]);
- }
- else
- {
- that.deselect([id]);
- }
- });
- }
+function registerRowEvents(tbody)
+{
+ var that = this,
+ selectBoxSelector = getCssSelector(this.options.css.selectBox);
- tbody.off("click" + namespace, "> tr")
- .on("click" + namespace, "> tr", function(e)
+ if (this.selection)
+ {
+ tbody.off("click" + namespace, selectBoxSelector)
+ .on("click" + namespace, selectBoxSelector, 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; });
+ id = that.converter.from($this.val());
- if (that.selection && that.options.rowSelect)
+ if ($this.prop("checked"))
{
- if ($this.hasClass(that.options.css.selected))
- {
- that.deselect([id]);
- }
- else
- {
- that.select([id]);
- }
+ that.select([id]);
+ }
+ else
+ {
+ that.deselect([id]);
}
-
- that.element.trigger("click" + namespace, [that.columns, row]);
});
}
- function renderSearchField()
- {
- if (this.options.navigation !== 0)
+ tbody.off("click" + namespace, "> tr")
+ .on("click" + namespace, "> tr", function(e)
{
- var css = this.options.css,
- selector = getCssSelector(css.search),
- headerSearch = this.header.find(selector),
- footerSearch = this.footer.find(selector);
+ e.stopPropagation();
- if ((headerSearch.length + footerSearch.length) > 0)
+ 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)
{
- 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)
+ if ($this.hasClass(that.options.css.selected))
+ {
+ that.deselect([id]);
+ }
+ else
{
- e.stopPropagation();
- var newValue = $(this).val();
- if (currentValue !== newValue)
+ 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),
+ headerSearch = this.header.find(selector),
+ footerSearch = this.footer.find(selector);
+
+ if ((headerSearch.length + footerSearch.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)
+ {
+ currentValue = newValue;
+ window.clearTimeout(timer);
+ timer = window.setTimeout(function ()
{
- currentValue = newValue;
- window.clearTimeout(timer);
- timer = window.setTimeout(function ()
- {
- that.search(newValue);
- }, 250);
- }
- });
+ that.search(newValue);
+ }, 250);
+ }
+ });
- replacePlaceHolder.call(this, headerSearch, search, 1);
- replacePlaceHolder.call(this, footerSearch, search, 2);
- }
+ replacePlaceHolder.call(this, headerSearch, search, 1);
+ replacePlaceHolder.call(this, footerSearch, search, 2);
}
}
+}
- function renderTableHeader()
+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 that = this,
- headerRow = this.element.find("thead > tr"),
- css = this.options.css,
- tpl = this.options.templates,
- html = "",
- sorting = this.options.sorting;
+ 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 }));
+ }
- if (this.selection)
+ $.each(this.columns, function (index, column)
+ {
+ if (column.visible)
{
- 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 }));
+ 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 }));
}
+ });
- $.each(this.columns, function (index, column)
- {
- if (column.visible)
- {
- var sortOrder = that.sort[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 }));
- }
- });
+ headerRow.html(html);
- headerRow.html(html);
+ // todo: create a own function for that piece of code
+ if (sorting)
+ {
+ var sortingSelector = getCssSelector(css.sortable);
+ headerRow.off("click" + namespace, sortingSelector)
+ .on("click" + namespace, sortingSelector, function (e)
+ {
+ e.preventDefault();
- // todo: create a own function for that piece of code
- if (sorting)
- {
- var sortingSelector = getCssSelector(css.sortable),
- iconSelector = getCssSelector(css.icon);
- headerRow.off("click" + namespace, sortingSelector)
- .on("click" + namespace, sortingSelector, function (e)
- {
- e.preventDefault();
- var $this = $(this),
- columnId = $this.data("column-id") || $this.parents("th").first().data("column-id"),
- sortOrder = that.sort[columnId],
- icon = $this.find(iconSelector);
+ setTableHeaderSortDirection.call(this, that);
+ sortRows.call(that);
+ loadData.call(that);
+ });
+ }
- if (!that.options.multiSort)
- {
- $this.parents("tr").first().find(iconSelector).removeClass(css.iconDown + " " + css.iconUp);
- that.sort = {};
- }
+ // 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 (sortOrder && sortOrder === "asc")
- {
- that.sort[columnId] = "desc";
- icon.removeClass(css.iconUp).addClass(css.iconDown);
- }
- else if (sortOrder && sortOrder === "desc")
- {
- if (that.options.multiSort)
- {
- var newSort = {};
- for (var key in that.sort)
- {
- if (key !== columnId)
- {
- newSort[key] = that.sort[key];
- }
- }
- that.sort = newSort;
- icon.removeClass(css.iconDown);
- }
- else
- {
- that.sort[columnId] = "asc";
- icon.removeClass(css.iconDown).addClass(css.iconUp);
- }
- }
- else
- {
- that.sort[columnId] = "asc";
- icon.addClass(css.iconUp);
- }
+ if ($(this).prop("checked"))
+ {
+ that.select();
+ }
+ else
+ {
+ that.deselect();
+ }
+ });
+ }
+}
- sortRows.call(that);
- loadData.call(that);
- });
- }
+function setTableHeaderSortDirection(instance)
+{
+ var $this = $(this),
+ css = instance.options.css,
+ iconSelector = getCssSelector(css.icon),
+ columnId = $this.data("column-id") || $this.parents("th").first().data("column-id"),
+ sortOrder = instance.sortDictionary[columnId],
+ icon = $this.find(iconSelector);
+
+ if (!instance.options.multiSort)
+ {
+ $this.parents("tr").first().find(iconSelector).removeClass(css.iconDown + " " + css.iconUp);
+ instance.sortDictionary = {};
+ }
- // todo: create a own function for that piece of code
- if (this.selection && this.options.multiSelect)
+ if (sortOrder && sortOrder === "asc")
+ {
+ instance.sortDictionary[columnId] = "desc";
+ icon.removeClass(css.iconUp).addClass(css.iconDown);
+ }
+ else if (sortOrder && sortOrder === "desc")
+ {
+ if (instance.options.multiSort)
{
- var selectBoxSelector = getCssSelector(css.selectBox);
- headerRow.off("click" + namespace, selectBoxSelector)
- .on("click" + namespace, selectBoxSelector, function(e)
+ var newSort = {};
+ for (var key in instance.sortDictionary)
+ {
+ if (key !== columnId)
{
- e.stopPropagation();
-
- if ($(this).prop("checked"))
- {
- that.select();
- }
- else
- {
- that.deselect();
- }
- });
+ newSort[key] = instance.sortDictionary[key];
+ }
+ }
+ instance.sortDictionary = newSort;
+ icon.removeClass(css.iconDown);
+ }
+ else
+ {
+ instance.sortDictionary[columnId] = "asc";
+ icon.removeClass(css.iconDown).addClass(css.iconUp);
}
}
+ else
+ {
+ instance.sortDictionary[columnId] = "asc";
+ icon.addClass(css.iconUp);
+ }
+}
- function replacePlaceHolder(placeholder, element, flag)
+function replacePlaceHolder(placeholder, element, flag)
+{
+ if (this.options.navigation & flag)
{
- if (this.options.navigation & flag)
+ placeholder.each(function (index, item)
{
- placeholder.each(function (index, item)
- {
- // todo: check how append is implemented. Perhaps cloning here is superfluous.
- $(item).before(element.clone(true)).remove();
- });
- }
+ // todo: check how append is implemented. Perhaps cloning here is superfluous.
+ $(item).before(element.clone(true)).remove();
+ });
}
+}
- function showLoading()
+function showLoading()
+{
+ var tpl = this.options.templates,
+ thead = this.element.children("thead").first(),
+ tbody = this.element.children("tbody").first(),
+ firstCell = tbody.find("tr > td").first(),
+ padding = (this.element.height() - thead.height()) - (firstCell.height() + 20),
+ count = this.columns.where(isVisible).length;
+
+ if (this.selection)
{
- var tpl = this.options.templates,
- thead = this.element.children("thead").first(),
- tbody = this.element.children("tbody").first(),
- firstCell = tbody.find("tr > td").first(),
- padding = (this.element.height() - thead.height()) - (firstCell.height() + 20),
- count = this.columns.where(isVisible).length;
+ count = count + 1;
+ }
+ tbody.html(tpl.loading.resolve(getParams.call(this, { columns: count })));
+ if (this.rowCount !== -1 && padding > 0)
+ {
+ tbody.find("tr > td").css("padding", "20px 0 " + padding + "px");
+ }
+}
- if (this.selection)
- {
- count = count + 1;
- }
- tbody.html(tpl.loading.resolve(getParams.call(this, { columns: count })));
- if (this.rowCount !== -1 && padding > 0)
+function sortRows()
+{
+ var sortArray = [];
+
+ function sort(x, y, current)
+ {
+ current = current || 0;
+ var next = current + 1,
+ item = sortArray[current];
+
+ function sortOrder(value)
{
- tbody.find("tr > td").css("padding", "20px 0 " + padding + "px");
+ 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;
}
- function sortRows()
+ if (!this.options.ajax)
{
- var sortArray = [];
+ var that = this;
- function sort(x, y, current)
+ for (var key in this.sortDictionary)
{
- current = current || 0;
- var next = current + 1,
- item = sortArray[current];
-
- function sortOrder(value)
+ if (this.options.multiSort || sortArray.length === 0)
{
- return (item.order === "asc") ? value : value * -1;
+ sortArray.push({
+ id: key,
+ order: this.sortDictionary[key]
+ });
}
-
- 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)
+ if (sortArray.length > 0)
{
- var that = this;
-
- for (var key in this.sort)
- {
- if (this.options.multiSort || sortArray.length === 0)
- {
- sortArray.push({
- id: key,
- order: this.sort[key]
- });
- }
- }
-
- if (sortArray.length > 0)
- {
- this.rows.sort(sort);
- }
+ this.rows.sort(sort);
}
}
+ }
- // GRID PUBLIC CLASS DEFINITION
- // ====================
+// 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.
+ * There are two ways to override the sub-properties.
+ * Either by doing it generally (global) or on initialization.
+ *
+ * @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")
/**
- * Represents the jQuery Bootgrid plugin.
+ * Enables row selection (to enable multi selection see also `multiSelect`). Default value is `false`.
*
- * @class Grid
- * @constructor
- * @param element {Object} The corresponding DOM element.
- * @param options {Object} The options to override default settings.
- * @chainable
+ * @property selection
+ * @type Boolean
+ * @default false
+ * @for defaults
+ * @since 1.0.0
**/
- 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.sort = {};
- 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
- };
+ selection: false,
/**
- * An object that represents the default settings.
- * There are two ways to override the sub-properties.
- * Either by doing it generally (global) or on initialization.
+ * Enables multi selection (`selection` must be set to `true` as well). Default value is `false`.
*
- * @static
- * @class defaults
- * @for Grid
- * @example
- * // Global approach
- * $.bootgrid.defaults.selection = true;
- * @example
- * // Initialization approach
- * $("#bootgrid").bootgrid({ selection = true });
+ * @property multiSelect
+ * @type Boolean
+ * @default false
+ * @for defaults
+ * @since 1.0.0
**/
- 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,
+ multiSelect: 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,
+ /**
+ * 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,
+ /**
+ * 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,
- ajax: false, // todo: find a better name for this property to differentiate between client-side and server-side data
+ highlightRows: false, // highlights new rows (find the page of the first new row)
+ sorting: true,
+ multiSort: false,
+ ajax: false, // todo: find a better name for this property to differentiate between client-side and server-side data
- /**
- * 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")
+ /**
+ * 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 ""; }
+ /**
+ * 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,
+ /**
+ * 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
+ // 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 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; },
+ /**
+ * 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; }
- }
+ /**
+ * 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 container-fluid",
- header: "bootgrid-header container-fluid",
- icon: "icon glyphicon",
- iconColumns: "glyphicon-th-list",
- iconDown: "glyphicon-chevron-down",
- iconRefresh: "glyphicon-refresh",
- 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"
- },
+ /**
+ * 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 container-fluid",
+ header: "bootgrid-header container-fluid",
+ icon: "icon glyphicon",
+ iconColumns: "glyphicon-th-list",
+ iconDown: "glyphicon-chevron-down",
+ iconRefresh: "glyphicon-refresh",
+ 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
/**
- * A dictionary of formatters.
+ * CSS class to select the parent div which activates responsive mode.
*
- * @property formatters
- * @type Object
- * @for defaults
- * @since 1.0.0
+ * @property responsiveTable
+ * @type String
+ * @default "table-responsive"
+ * @for css
+ * @since 1.1.0
**/
- formatters: {},
+ responsiveTable: "table-responsive",
- /**
- * 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"
- },
+ 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
/**
- * Contains all templates.
+ * CSS class to highlight selected rows.
*
- * @property templates
- * @type Object
- * @for defaults
+ * @property selected
+ * @type String
+ * @default "active"
+ * @for css
+ * @since 1.1.0
**/
- 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: ""
- }
- };
+ selected: "active",
+
+ sortable: "sortable",
+ table: "bootgrid-table table"
+ },
/**
- * Appends rows.
+ * A dictionary of formatters.
*
- * @method append
- * @param rows {Array} An array of rows to append
- * @chainable
+ * @property formatters
+ * @type Object
+ * @for defaults
+ * @since 1.0.0
**/
- Grid.prototype.append = function(rows)
- {
- if (this.options.ajax)
- {
- // todo: implement ajax DELETE
- }
- 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;
- };
+ formatters: {},
/**
- * Removes all rows.
+ * Contains all labels.
*
- * @method clear
- * @chainable
+ * @property labels
+ * @type Object
+ * @for defaults
**/
- 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;
- };
+ labels: {
+ all: "All",
+ infos: "Showing {{ctx.start}} to {{ctx.end}} of {{ctx.total}} entries",
+ loading: "Loading...",
+ noResults: "No results found!",
+ refresh: "Refresh",
+ search: "Search"
+ },
/**
- * Removes the control functionality completely and transforms the current state to the initial HTML structure.
+ * Contains all templates.
*
- * @method destroy
- * @chainable
+ * @property templates
+ * @type Object
+ * @for defaults
**/
- Grid.prototype.destroy = function()
+ 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: 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)
+ // todo: implement ajax DELETE
+ }
+ else
+ {
+ var appendedRows = [];
+ for (var i = 0; i < rows.length; i++)
{
- this.footer.remove();
+ if (appendRow.call(this, rows[i]))
+ {
+ appendedRows.push(rows[i]);
+ }
}
- this.element.before(this.origin).remove();
+ sortRows.call(this);
+ highlightAppendedRows.call(this, appendedRows);
+ loadData.call(this);
+ this.element.trigger("appended" + namespace, [appendedRows]);
+ }
- return this;
- };
+ return this;
+};
- /**
- * Resets the state and reloads rows.
- *
- * @method reload
- * @chainable
- **/
- Grid.prototype.reload = function()
+/**
+ * Removes all rows.
+ *
+ * @method clear
+ * @chainable
+ **/
+Grid.prototype.clear = function()
+{
+ if (this.options.ajax)
+ {
+ // todo: implement ajax POST
+ }
+ else
{
- this.current = 1; // reset
+ var removedRows = $.extend([], this.rows);
+ this.rows = [];
+ this.current = 1;
+ this.total = 0;
loadData.call(this);
+ this.element.trigger("cleared" + namespace, [removedRows]);
+ }
- return 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)
+/**
+ * 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)
{
- if (this.identifier != null)
+ 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()
+{
+ 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)
{
- var that = this;
+ // todo: implement ajax DELETE
+ }
+ else
+ {
+ rowIds = rowIds || this.selectedRows;
+ var id,
+ removedRows = [];
- if (this.options.ajax)
+ for (var i = 0; i < rowIds.length; i++)
{
- // todo: implement ajax DELETE
- }
- else
- {
- rowIds = rowIds || this.selectedRows;
- var id,
- removedRows = [];
+ id = rowIds[i];
- for (var i = 0; i < rowIds.length; i++)
+ for (var j = 0; j < this.rows.length; j++)
{
- id = rowIds[i];
-
- for (var j = 0; j < this.rows.length; j++)
+ if (this.rows[j][this.identifier] === id)
{
- if (this.rows[j][this.identifier] === id)
- {
- removedRows.push(this.rows[j]);
- this.rows.splice(j, 1);
- break;
- }
+ 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).
- *
- * @method search
- * @param phrase {String} The phrase to search for
- * @chainable
- **/
- Grid.prototype.search = function(phrase)
- {
- if (this.searchPhrase !== phrase)
- {
- this.current = 1;
- this.searchPhrase = phrase;
+ this.current = 1; // reset
loadData.call(this);
+ this.element.trigger("removed" + namespace, [removedRows]);
}
+ }
- return this;
- };
+ return this;
+};
+
+/**
+ * Searches in all rows for a specific phrase (but only in visible cells).
+ *
+ * @method search
+ * @param phrase {String} The phrase to search for
+ * @chainable
+ **/
+Grid.prototype.search = function(phrase)
+{
+ if (this.searchPhrase !== phrase)
+ {
+ this.current = 1;
+ this.searchPhrase = phrase;
+ loadData.call(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)
+ 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)
{
- if (this.selection)
- {
- rowIds = rowIds || this.currentRows.propValues(this.identifier);
+ rowIds = rowIds || this.currentRows.propValues(this.identifier);
- var id, i,
- selectedRows = [];
+ var id, i,
+ selectedRows = [];
- while (rowIds.length > 0 && !(!this.options.multiSelect && selectedRows.length === 1))
+ while (rowIds.length > 0 && !(!this.options.multiSelect && selectedRows.length === 1))
+ {
+ id = rowIds.pop();
+ if ($.inArray(id, this.selectedRows) === -1)
{
- id = rowIds.pop();
- if ($.inArray(id, this.selectedRows) === -1)
+ for (i = 0; i < this.currentRows.length; i++)
{
- for (i = 0; i < this.currentRows.length; i++)
+ if (this.currentRows[i][this.identifier] === id)
{
- if (this.currentRows[i][this.identifier] === id)
- {
- selectedRows.push(this.currentRows[i]);
- this.selectedRows.push(id);
- break;
- }
+ 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 (selectedRows.length > 0)
+ {
+ var selectBoxSelector = getCssSelector(this.options.css.selectBox),
+ selectMultiSelectBox = this.selectedRows.length >= this.currentRows.length;
- if (!this.options.multiSelect)
- {
- this.element.find("tbody > tr " + selectBoxSelector + ":checked")
- .trigger("click" + namespace);
- }
+ 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);
- 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);
- }
+ if (!this.options.multiSelect)
+ {
+ this.element.find("tbody > tr " + selectBoxSelector + ":checked")
+ .trigger("click" + namespace);
+ }
- this.element.trigger("selected" + namespace, [selectedRows]);
+ 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);
}
- }
- return this;
- };
+ this.element.trigger("selected" + namespace, [selectedRows]);
+ }
+ }
- /**
- * 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)
+ 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)
{
- if (this.selection)
- {
- rowIds = rowIds || this.currentRows.propValues(this.identifier);
+ rowIds = rowIds || this.currentRows.propValues(this.identifier);
- var id, i, pos,
- deselectedRows = [];
+ var id, i, pos,
+ deselectedRows = [];
- while (rowIds.length > 0)
+ while (rowIds.length > 0)
+ {
+ id = rowIds.pop();
+ pos = $.inArray(id, this.selectedRows);
+ if (pos !== -1)
{
- id = rowIds.pop();
- pos = $.inArray(id, this.selectedRows);
- if (pos !== -1)
+ for (i = 0; i < this.currentRows.length; i++)
{
- for (i = 0; i < this.currentRows.length; i++)
+ if (this.currentRows[i][this.identifier] === id)
{
- if (this.currentRows[i][this.identifier] === id)
- {
- deselectedRows.push(this.currentRows[i]);
- this.selectedRows.splice(pos, 1);
- break;
- }
+ deselectedRows.push(this.currentRows[i]);
+ this.selectedRows.splice(pos, 1);
+ break;
}
}
}
+ }
- if (deselectedRows.length > 0)
- {
- var selectBoxSelector = getCssSelector(this.options.css.selectBox);
+ 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]);
+ 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;
- };
+ return this;
+};
- /**
- * Sorts rows.
- *
- * @method sort
- * @param dictionary {Object} A dictionary which contains the sort information
- * @chainable
- **/
- Grid.prototype.sort = function(dictionary)
+/**
+ * Sorts rows.
+ *
+ * @method sort
+ * @param dictionary {Object} A dictionary which contains the sort information
+ * @chainable
+ **/
+Grid.prototype.sort = function(dictionary)
+{
+ var values = (dictionary) ? $.extend({}, dictionary) : {},
+ columnHeader;
+
+ if (values === this.sortDictionary)
{
- var values = (dictionary) ? $.extend({}, dictionary) : {};
- if (values === this.sort)
- {
- return this;
- }
+ return this;
+ }
- this.sort = values;
+ $.each(values, $.proxy(function (key, value) {
+ // Have to flip these values, because the setTableHeaderSortDirection assumes we're
+ // flipping the direction of whatever the current sort order is, and flips it itself
+ values[key] = (value === 'asc' ? 'desc' : 'asc');
+ columnHeader = columnHeader || this.element.find('[data-column-id="' + key + '"]');
+ }, this));
- renderTableHeader.call(this);
- sortRows.call(this);
- loadData.call(this);
+ this.sortDictionary = values;
- return this;
+ setTableHeaderSortDirection.call(columnHeader[0], this);
+ sortRows.call(this);
+ loadData.call(this);
+
+ return this;
};
- // GRID COMMON TYPE EXTENSIONS
- // ============
+// GRID COMMON TYPE EXTENSIONS
+// ============
- $.fn.extend({
- _bgAria: function (name, value)
- {
- return this.attr("aria-" + name, value);
- },
+$.fn.extend({
+ _bgAria: function (name, value)
+ {
+ return this.attr("aria-" + name, value);
+ },
- _bgBusyAria: function(busy)
- {
- return (busy == null || busy) ?
- this._bgAria("busy", "true") :
- this._bgAria("busy", "false");
- },
+ _bgBusyAria: function(busy)
+ {
+ return (busy == null || busy) ?
+ this._bgAria("busy", "true") :
+ this._bgAria("busy", "false");
+ },
- _bgRemoveAria: function (name)
- {
- return this.removeAttr("aria-" + name);
- },
+ _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");
- },
+ _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");
- },
+ _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");
- },
+ _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");
- },
+ _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");
+ }
+});
- _bgId: function (id)
+if (!String.prototype.resolve)
+{
+ var formatter = {
+ "checked": function(value)
{
- return (id) ? this.attr("id", id) : this.attr("id");
+ if (typeof value === "boolean")
+ {
+ return (value) ? "checked=\"checked\"" : "";
+ }
+ return value;
}
- });
+ };
- if (!String.prototype.resolve)
+ String.prototype.resolve = function (substitutes, prefixes)
{
- var formatter = {
- "checked": function(value)
+ var result = this;
+ $.each(substitutes, function (key, value)
+ {
+ if (value != null && typeof value !== "function")
{
- if (typeof value === "boolean")
+ if (typeof value === "object")
{
- return (value) ? "checked=\"checked\"" : "";
+ var keys = (prefixes) ? $.extend([], prefixes) : [];
+ keys.push(key);
+ result = result.resolve(value, keys) + "";
}
- return value;
- }
- };
-
- String.prototype.resolve = function (substitutes, prefixes)
- {
- var result = this;
- $.each(substitutes, function (key, value)
- {
- if (value != null && typeof value !== "function")
+ else
{
- if (typeof value === "object")
+ if (formatter && formatter[key] && typeof formatter[key] === "function")
{
- 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);
+ 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;
- };
- }
+ }
+ });
+ return result;
+ };
+}
- if (!Array.prototype.first)
+if (!Array.prototype.first)
+{
+ Array.prototype.first = function (condition)
{
- Array.prototype.first = function (condition)
+ for (var i = 0; i < this.length; i++)
{
- for (var i = 0; i < this.length; i++)
+ var item = this[i];
+ if (condition(item))
{
- var item = this[i];
- if (condition(item))
- {
- return item;
- }
+ return item;
}
- return null;
- };
- }
+ }
+ return null;
+ };
+}
- if (!Array.prototype.contains)
+if (!Array.prototype.contains)
+{
+ Array.prototype.contains = function (condition)
{
- Array.prototype.contains = function (condition)
+ for (var i = 0; i < this.length; i++)
{
- for (var i = 0; i < this.length; i++)
+ var item = this[i];
+ if (condition(item))
{
- var item = this[i];
- if (condition(item))
- {
- return true;
- }
+ return true;
}
- return false;
- };
- }
+ }
+ return false;
+ };
+}
- if (!Array.prototype.page)
+if (!Array.prototype.page)
+{
+ Array.prototype.page = function (page, size)
{
- 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) : [];
- };
- }
+ 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)
+if (!Array.prototype.where)
+{
+ Array.prototype.where = function (condition)
{
- Array.prototype.where = function (condition)
+ var result = [];
+ for (var i = 0; i < this.length; i++)
{
- var result = [];
- for (var i = 0; i < this.length; i++)
+ var item = this[i];
+ if (condition(item))
{
- var item = this[i];
- if (condition(item))
- {
- result.push(item);
- }
+ result.push(item);
}
- return result;
- };
- }
+ }
+ return result;
+ };
+}
- if (!Array.prototype.propValues)
+if (!Array.prototype.propValues)
+{
+ Array.prototype.propValues = function (propName)
{
- Array.prototype.propValues = function (propName)
+ var result = [];
+ for (var i = 0; i < this.length; i++)
{
- var result = [];
- for (var i = 0; i < this.length; i++)
- {
- result.push(this[i][propName]);
- }
- return result;
- };
+ result.push(this[i][propName]);
+ }
+ return result;
+ };
}
- // GRID PLUGIN DEFINITION
- // =====================
+// GRID PLUGIN DEFINITION
+// =====================
- var old = $.fn.bootgrid;
+var old = $.fn.bootgrid;
- $.fn.bootgrid = function (option)
+$.fn.bootgrid = function (option)
+{
+ var args = Array.prototype.slice.call(arguments, 1);
+ return this.each(function ()
{
- var args = Array.prototype.slice.call(arguments, 1);
- return this.each(function ()
- {
- var $this = $(this),
- instance = $this.data(namespace),
- options = typeof option === "object" && option;
+ 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")
- {
- return instance[option].apply(instance, args);
- }
- });
- };
+ if (!instance && option === "destroy")
+ {
+ return;
+ }
+ if (!instance)
+ {
+ $this.data(namespace, (instance = new Grid(this, options)));
+ init.call(instance);
+ }
+ if (typeof option === "string")
+ {
+ return instance[option].apply(instance, args);
+ }
+ });
+};
- $.fn.bootgrid.Constructor = Grid;
+$.fn.bootgrid.Constructor = Grid;
- // GRID NO CONFLICT
- // ===============
+// GRID NO CONFLICT
+// ===============
- $.fn.bootgrid.noConflict = function ()
- {
- $.fn.bootgrid = old;
- return this;
- };
+$.fn.bootgrid.noConflict = function ()
+{
+ $.fn.bootgrid = old;
+ return this;
+};
- // GRID DATA-API
- // ============
+// GRID DATA-API
+// ============
$("[data-toggle=\"bootgrid\"]").bootgrid();
})(jQuery, window);
\ No newline at end of file
diff --git a/dist/jquery.bootgrid.min.js b/dist/jquery.bootgrid.min.js
index 985f194..5f04a5d 100644
--- a/dist/jquery.bootgrid.min.js
+++ b/dist/jquery.bootgrid.min.js
@@ -1,6 +1,6 @@
/*!
- * jQuery Bootgrid v1.1.4 - 11/23/2014
- * Copyright (c) 2014 Rafael Staib (http://www.jquery-bootgrid.com)
+ * jQuery Bootgrid v1.1.4 - 01/30/2015
+ * Copyright (c) 2015 Rafael Staib (http://www.jquery-bootgrid.com)
* Licensed under MIT http://www.opensource.org/licenses/MIT
*/
-!function(a,b){"use strict";function c(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 d(b){return b?a.extend({},this.cachedParams,{ctx:b}):this.cachedParams}function e(){var b={current:this.current,rowCount:this.rowCount,sort:this.sort,searchPhrase:this.searchPhrase},c=this.options.post;return c=a.isFunction(c)?c():c,this.options.requestHandler(a.extend(!0,b,c))}function f(b){return"."+a.trim(b).replace(/\s+/gm,".")}function g(){var b=this.options.url;return a.isFunction(b)?b():b}function h(){this.element.trigger("initialize"+C),k.call(this),this.selection=this.options.selection&&null!=this.identifier,m.call(this),n.call(this),y.call(this),x.call(this),o.call(this),l.call(this),this.element.trigger("initialized"+C)}function i(){this.options.highlightRows}function j(a){return a.visible}function k(){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)};b.columns.push(f),null!=f.order&&(b.sort[f.id]=f.order),f.identifier&&(b.identifier=f.id,b.converter=f.converter),b.options.multiSort||null===f.order||(d=!0)})}function l(){function c(a){for(var b,c=new RegExp(f.searchPhrase,f.options.caseSensitive?"g":"gi"),d=0;d-1)return!0;return!1}function d(a,b){f.currentRows=a,f.total=b,f.totalPages=Math.ceil(b/f.rowCount),f.options.keepSelection||(f.selectedRows=[]),v.call(f,a),q.call(f),s.call(f),f.element._bgBusyAria(!1).trigger("loaded"+C)}var f=this,h=e.call(this),i=g.call(this);if(this.options.ajax&&(null==i||"string"!=typeof i||0===i.length))throw new Error("Url setting must be a none empty string or a function that returns one.");if(this.element._bgBusyAria(!0).trigger("load"+C),A.call(this),this.options.ajax)f.xqr&&f.xqr.abort(),f.xqr=a.post(i,h,function(b){f.xqr=null,"string"==typeof b&&(b=a.parseJSON(b)),b=f.options.responseHandler(b),f.current=b.current,d(b.rows,b.total)}).fail(function(a,b){f.xqr=null,"abort"!==b&&(r.call(f),f.element._bgBusyAria(!1).trigger("loaded"+C))});else{var j=this.searchPhrase.length>0?this.rows.where(c):this.rows,k=j.length;-1!==this.rowCount&&(j=j.page(this.current,this.rowCount)),b.setTimeout(function(){d(j,k)},10)}}function m(){if(!this.options.ajax){var b=this,d=this.element.find("tbody > tr");d.each(function(){var d=a(this),e=d.children("td"),f={};a.each(b.columns,function(a,b){f[b.id]=b.converter.from(e.eq(a).text())}),c.call(b,f)}),this.total=this.rows.length,this.totalPages=-1===this.rowCount?1:Math.ceil(this.total/this.rowCount),B.call(this)}}function n(){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(d.call(this,{id:this.element._bgId()+"-header"}))),c.before(this.header)),2&this.options.navigation&&(this.footer=a(b.footer.resolve(d.call(this,{id:this.element._bgId()+"-footer"}))),c.after(this.footer))}function o(){if(0!==this.options.navigation){var b=this.options.css,c=f(b.actions),e=this.header.find(c),g=this.footer.find(c);if(e.length+g.length>0){var h=this,i=this.options.templates,j=a(i.actions.resolve(d.call(this)));if(this.options.ajax){var k=i.icon.resolve(d.call(this,{iconCss:b.iconRefresh})),m=a(i.actionButton.resolve(d.call(this,{content:k,text:this.options.labels.refresh}))).on("click"+C,function(a){a.stopPropagation(),h.current=1,l.call(h)});j.append(m)}u.call(this,j),p.call(this,j),z.call(this,e,j,1),z.call(this,g,j,2)}}}function p(b){if(this.options.columnSelection&&this.columns.length>1){var c=this,e=this.options.css,g=this.options.templates,h=g.icon.resolve(d.call(this,{iconCss:e.iconColumns})),i=a(g.actionDropDown.resolve(d.call(this,{content:h}))),k=f(e.dropDownItem),m=f(e.dropDownItemCheckbox),n=f(e.dropDownMenuItems);a.each(this.columns,function(b,h){var o=a(g.actionDropDownCheckboxItem.resolve(d.call(c,{name:h.id,label:h.text,checked:h.visible}))).on("click"+C,k,function(b){b.stopPropagation();var d=a(this),e=d.find(m);if(!e.prop("disabled")){h.visible=e.prop("checked");var f=c.columns.where(j).length>1;d.parents(n).find(k+":has("+m+":checked)")._bgEnableAria(f).find(m)._bgEnableField(f),c.element.find("tbody").empty(),y.call(c),l.call(c)}});i.find(f(e.dropDownMenuItems)).append(o)}),b.append(i)}}function q(){if(0!==this.options.navigation){var b=f(this.options.css.infos),c=this.header.find(b),e=this.footer.find(b);if(c.length+e.length>0){var g=this.current*this.rowCount,h=a(this.options.templates.infos.resolve(d.call(this,{end:0===this.total||-1===g||g>this.total?this.total:g,start:0===this.total?0:g-this.rowCount+1,total:this.total})));z.call(this,c,h,1),z.call(this,e,h,2)}}}function r(){var a=this.element.children("tbody").first(),b=this.options.templates,c=this.columns.where(j).length;this.selection&&(c+=1),a.html(b.noResults.resolve(d.call(this,{columns:c})))}function s(){if(0!==this.options.navigation){var b=f(this.options.css.pagination),c=this.header.find(b)._bgShowAria(-1!==this.rowCount),e=this.footer.find(b)._bgShowAria(-1!==this.rowCount);if(-1!==this.rowCount&&c.length+e.length>0){var g=this.options.templates,h=this.current,i=this.totalPages,j=a(g.pagination.resolve(d.call(this))),k=i-h,l=-1*(this.options.padding-h),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;t.call(this,j,"first","«","first")._bgEnableAria(h>1),t.call(this,j,"prev","<","prev")._bgEnableAria(h>1);for(var p=0;o>p;p++){var q=p+m;t.call(this,j,q,q,"page-"+q)._bgEnableAria()._bgSelectAria(q===h)}0===o&&t.call(this,j,1,1,"page-1")._bgEnableAria(!1)._bgSelectAria(),t.call(this,j,"next",">","next")._bgEnableAria(i>h),t.call(this,j,"last","»","last")._bgEnableAria(i>h),z.call(this,c,j,1),z.call(this,e,j,2)}}}function t(b,c,e,g){var h=this,i=this.options.templates,j=this.options.css,k=d.call(this,{css:g,text:e,uri:"#"+c}),m=a(i.paginationItem.resolve(k)).on("click"+C,f(j.paginationButton),function(b){b.stopPropagation();var c=a(this),d=c.parent();if(!d.hasClass("active")&&!d.hasClass("disabled")){var e={first:1,prev:h.current-1,next:h.current+1,last:h.totalPages},f=c.attr("href").substr(1);h.current=e[f]||+f,l.call(h)}c.trigger("blur")});return b.append(m),m}function u(b){function c(a){return-1===a?e.options.labels.all:a}var e=this,g=this.options.rowCount;if(a.isArray(g)){var h=this.options.css,i=this.options.templates,j=a(i.actionDropDown.resolve(d.call(this,{content:this.rowCount}))),k=f(h.dropDownMenu),m=f(h.dropDownMenuText),n=f(h.dropDownMenuItems),o=f(h.dropDownItemButton);a.each(g,function(b,f){var g=a(i.actionDropDownItem.resolve(d.call(e,{text:c(f),uri:"#"+f})))._bgSelectAria(f===e.rowCount).on("click"+C,o,function(b){b.preventDefault();var d=a(this),f=+d.attr("href").substr(1);f!==e.rowCount&&(e.current=1,e.rowCount=f,d.parents(n).children().each(function(){var b=a(this),c=+b.find(o).attr("href").substr(1);b._bgSelectAria(c===f)}),d.parents(k).find(m).text(c(f)),l.call(e))});j.find(n).append(g)}),b.append(j)}}function v(b){if(b.length>0){var c=this,e=this.options.css,g=this.options.templates,h=this.element.children("tbody").first(),i=!0,j="",k="",l="",m="";a.each(b,function(b,f){if(k="",l=' data-row-id="'+(null==c.identifier?b:f[c.identifier])+'"',m="",c.selection){var h=-1!==a.inArray(f[c.identifier],c.selectedRows),n=g.select.resolve(d.call(c,{type:"checkbox",value:f[c.identifier],checked:h}));k+=g.cell.resolve(d.call(c,{content:n,css:e.selectCell})),i=i&&h,h&&(m+=e.selected,l+=' aria-selected="true"')}a.each(c.columns,function(b,h){if(h.visible){var i=a.isFunction(h.formatter)?h.formatter.call(c,h,f):h.converter.to(f[h.id]),j=h.cssClass.length>0?" "+h.cssClass:"";k+=g.cell.resolve(d.call(c,{content:null==i||""===i?" ":i,css:("right"===h.align?e.right:"center"===h.align?e.center:e.left)+j}))}}),m.length>0&&(l+=' class="'+m+'"'),j+=g.row.resolve(d.call(c,{attr:l,cells:k}))}),c.element.find("thead "+f(c.options.css.selectBox)).prop("checked",i),h.html(j),w.call(this,h)}else r.call(this)}function w(b){var c=this,d=f(this.options.css.selectBox);this.selection&&b.off("click"+C,d).on("click"+C,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"+C,"> tr").on("click"+C,"> 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"+C,[c.columns,f])})}function x(){if(0!==this.options.navigation){var c=this.options.css,e=f(c.search),g=this.header.find(e),h=this.footer.find(e);if(g.length+h.length>0){var i=this,j=this.options.templates,k=null,l="",m=f(c.searchField),n=a(j.search.resolve(d.call(this))),o=n.is(m)?n:n.find(m);o.on("keyup"+C,function(c){c.stopPropagation();var d=a(this).val();l!==d&&(l=d,b.clearTimeout(k),k=b.setTimeout(function(){i.search(d)},250))}),z.call(this,g,n,1),z.call(this,h,n,2)}}}function y(){var b=this,c=this.element.find("thead > tr"),e=this.options.css,g=this.options.templates,h="",i=this.options.sorting;if(this.selection){var j=this.options.multiSelect?g.select.resolve(d.call(b,{type:"checkbox",value:"all"})):"";h+=g.rawHeaderCell.resolve(d.call(b,{content:j,css:e.selectCell}))}if(a.each(this.columns,function(a,c){if(c.visible){var f=b.sort[c.id],j=i&&f&&"asc"===f?e.iconUp:i&&f&&"desc"===f?e.iconDown:"",k=g.icon.resolve(d.call(b,{iconCss:j})),l=c.headerAlign,m=c.headerCssClass.length>0?" "+c.headerCssClass:"";h+=g.headerCell.resolve(d.call(b,{column:c,icon:k,sortable:i&&c.sortable&&e.sortable||"",css:("right"===l?e.right:"center"===l?e.center:e.left)+m}))}}),c.html(h),i){var k=f(e.sortable),m=f(e.icon);c.off("click"+C,k).on("click"+C,k,function(c){c.preventDefault();var d=a(this),f=d.data("column-id")||d.parents("th").first().data("column-id"),g=b.sort[f],h=d.find(m);if(b.options.multiSort||(d.parents("tr").first().find(m).removeClass(e.iconDown+" "+e.iconUp),b.sort={}),g&&"asc"===g)b.sort[f]="desc",h.removeClass(e.iconUp).addClass(e.iconDown);else if(g&&"desc"===g)if(b.options.multiSort){var i={};for(var j in b.sort)j!==f&&(i[j]=b.sort[j]);b.sort=i,h.removeClass(e.iconDown)}else b.sort[f]="asc",h.removeClass(e.iconDown).addClass(e.iconUp);else b.sort[f]="asc",h.addClass(e.iconUp);B.call(b),l.call(b)})}if(this.selection&&this.options.multiSelect){var n=f(e.selectBox);c.off("click"+C,n).on("click"+C,n,function(c){c.stopPropagation(),a(this).prop("checked")?b.select():b.deselect()})}}function z(b,c,d){this.options.navigation&d&&b.each(function(b,d){a(d).before(c.clone(!0)).remove()})}function A(){var a=this.options.templates,b=this.element.children("thead").first(),c=this.element.children("tbody").first(),e=c.find("tr > td").first(),f=this.element.height()-b.height()-(e.height()+20),g=this.columns.where(j).length;this.selection&&(g+=1),c.html(a.loading.resolve(d.call(this,{columns:g}))),-1!==this.rowCount&&f>0&&c.find("tr > td").css("padding","20px 0 "+f+"px")}function B(){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.sort)(this.options.multiSort||0===b.length)&&b.push({id:c,order:this.sort[c]});b.length>0&&this.rows.sort(a)}}var C=".rs.jquery.bootgrid",D=function(b,c){this.element=a(b),this.origin=this.element.clone(),this.options=a.extend(!0,{},D.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.sort={},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(D.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,ajax:!1,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",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"},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:''}},D.prototype.append=function(a){if(this.options.ajax);else{for(var b=[],d=0;d0&&(this.options.multiSelect||1!==e.length);)if(c=b.pop(),-1===a.inArray(c,this.selectedRows))for(d=0;d0){var g=f(this.options.css.selectBox),h=this.selectedRows.length>=this.currentRows.length;for(d=0;!this.options.keepSelection&&h&&d tr "+g+":checked").trigger("click"+C),d=0;d tr[data-row-id="'+this.selectedRows[d]+'"]').addClass(this.options.css.selected)._bgAria("selected","true").find(g).prop("checked",!0);this.element.trigger("selected"+C,[e])}}return this},D.prototype.deselect=function(b){if(this.selection){b=b||this.currentRows.propValues(this.identifier);for(var c,d,e,g=[];b.length>0;)if(c=b.pop(),e=a.inArray(c,this.selectedRows),-1!==e)for(d=0;d0){var h=f(this.options.css.selectBox);for(this.element.find("thead "+h).prop("checked",!1),d=0;d tr[data-row-id="'+g[d][this.identifier]+'"]').removeClass(this.options.css.selected)._bgAria("selected","false").find(h).prop("checked",!1);this.element.trigger("deselected"+C,[g])}}return this},D.prototype.sort=function(b){var c=b?a.extend({},b):{};return c===this.sort?this:(this.sort=c,y.call(this),B.call(this),l.call(this),this)},a.fn.extend({_bgAria:function(a,b){return this.attr("aria-"+a,b)},_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 E={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{E&&E[b]&&"function"==typeof E[b]&&(e=E[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)};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 l(){function c(a){for(var b,c=new RegExp(f.searchPhrase,f.options.caseSensitive?"g":"gi"),d=0;d-1)return!0;return!1}function d(a,b){f.currentRows=a,f.total=b,f.totalPages=Math.ceil(b/f.rowCount),f.options.keepSelection||(f.selectedRows=[]),v.call(f,a),q.call(f),s.call(f),f.element._bgBusyAria(!1).trigger("loaded"+D)}var f=this,h=e.call(this),i=g.call(this);if(this.options.ajax&&(null==i||"string"!=typeof i||0===i.length))throw new Error("Url setting must be a none empty string or a function that returns one.");if(this.element._bgBusyAria(!0).trigger("load"+D),B.call(this),this.options.ajax)f.xqr&&f.xqr.abort(),f.xqr=a.post(i,h,function(b){f.xqr=null,"string"==typeof b&&(b=a.parseJSON(b)),b=f.options.responseHandler(b),f.current=b.current,d(b.rows,b.total)}).fail(function(a,b){f.xqr=null,"abort"!==b&&(r.call(f),f.element._bgBusyAria(!1).trigger("loaded"+D))});else{var j=this.searchPhrase.length>0?this.rows.where(c):this.rows,k=j.length;-1!==this.rowCount&&(j=j.page(this.current,this.rowCount)),b.setTimeout(function(){d(j,k)},10)}}function m(){if(!this.options.ajax){var b=this,d=this.element.find("tbody > tr");d.each(function(){var d=a(this),e=d.children("td"),f={};a.each(b.columns,function(a,b){f[b.id]=b.converter.from(e.eq(a).text())}),c.call(b,f)}),this.total=this.rows.length,this.totalPages=-1===this.rowCount?1:Math.ceil(this.total/this.rowCount),C.call(this)}}function n(){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(d.call(this,{id:this.element._bgId()+"-header"}))),c.before(this.header)),2&this.options.navigation&&(this.footer=a(b.footer.resolve(d.call(this,{id:this.element._bgId()+"-footer"}))),c.after(this.footer))}function o(){if(0!==this.options.navigation){var b=this.options.css,c=f(b.actions),e=this.header.find(c),g=this.footer.find(c);if(e.length+g.length>0){var h=this,i=this.options.templates,j=a(i.actions.resolve(d.call(this)));if(this.options.ajax){var k=i.icon.resolve(d.call(this,{iconCss:b.iconRefresh})),m=a(i.actionButton.resolve(d.call(this,{content:k,text:this.options.labels.refresh}))).on("click"+D,function(a){a.stopPropagation(),h.current=1,l.call(h)});j.append(m)}u.call(this,j),p.call(this,j),A.call(this,e,j,1),A.call(this,g,j,2)}}}function p(b){if(this.options.columnSelection&&this.columns.length>1){var c=this,e=this.options.css,g=this.options.templates,h=g.icon.resolve(d.call(this,{iconCss:e.iconColumns})),i=a(g.actionDropDown.resolve(d.call(this,{content:h}))),k=f(e.dropDownItem),m=f(e.dropDownItemCheckbox),n=f(e.dropDownMenuItems);a.each(this.columns,function(b,h){var o=a(g.actionDropDownCheckboxItem.resolve(d.call(c,{name:h.id,label:h.text,checked:h.visible}))).on("click"+D,k,function(b){b.stopPropagation();var d=a(this),e=d.find(m);if(!e.prop("disabled")){h.visible=e.prop("checked");var f=c.columns.where(j).length>1;d.parents(n).find(k+":has("+m+":checked)")._bgEnableAria(f).find(m)._bgEnableField(f),c.element.find("tbody").empty(),y.call(c),l.call(c)}});i.find(f(e.dropDownMenuItems)).append(o)}),b.append(i)}}function q(){if(0!==this.options.navigation){var b=f(this.options.css.infos),c=this.header.find(b),e=this.footer.find(b);if(c.length+e.length>0){var g=this.current*this.rowCount,h=a(this.options.templates.infos.resolve(d.call(this,{end:0===this.total||-1===g||g>this.total?this.total:g,start:0===this.total?0:g-this.rowCount+1,total:this.total})));A.call(this,c,h,1),A.call(this,e,h,2)}}}function r(){var a=this.element.children("tbody").first(),b=this.options.templates,c=this.columns.where(j).length;this.selection&&(c+=1),a.html(b.noResults.resolve(d.call(this,{columns:c})))}function s(){if(0!==this.options.navigation){var b=f(this.options.css.pagination),c=this.header.find(b)._bgShowAria(-1!==this.rowCount),e=this.footer.find(b)._bgShowAria(-1!==this.rowCount);if(-1!==this.rowCount&&c.length+e.length>0){var g=this.options.templates,h=this.current,i=this.totalPages,j=a(g.pagination.resolve(d.call(this))),k=i-h,l=-1*(this.options.padding-h),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;t.call(this,j,"first","«","first")._bgEnableAria(h>1),t.call(this,j,"prev","<","prev")._bgEnableAria(h>1);for(var p=0;o>p;p++){var q=p+m;t.call(this,j,q,q,"page-"+q)._bgEnableAria()._bgSelectAria(q===h)}0===o&&t.call(this,j,1,1,"page-1")._bgEnableAria(!1)._bgSelectAria(),t.call(this,j,"next",">","next")._bgEnableAria(i>h),t.call(this,j,"last","»","last")._bgEnableAria(i>h),A.call(this,c,j,1),A.call(this,e,j,2)}}}function t(b,c,e,g){var h=this,i=this.options.templates,j=this.options.css,k=d.call(this,{css:g,text:e,uri:"#"+c}),m=a(i.paginationItem.resolve(k)).on("click"+D,f(j.paginationButton),function(b){b.stopPropagation();var c=a(this),d=c.parent();if(!d.hasClass("active")&&!d.hasClass("disabled")){var e={first:1,prev:h.current-1,next:h.current+1,last:h.totalPages},f=c.attr("href").substr(1);h.current=e[f]||+f,l.call(h)}c.trigger("blur")});return b.append(m),m}function u(b){function c(a){return-1===a?e.options.labels.all:a}var e=this,g=this.options.rowCount;if(a.isArray(g)){var h=this.options.css,i=this.options.templates,j=a(i.actionDropDown.resolve(d.call(this,{content:this.rowCount}))),k=f(h.dropDownMenu),m=f(h.dropDownMenuText),n=f(h.dropDownMenuItems),o=f(h.dropDownItemButton);a.each(g,function(b,f){var g=a(i.actionDropDownItem.resolve(d.call(e,{text:c(f),uri:"#"+f})))._bgSelectAria(f===e.rowCount).on("click"+D,o,function(b){b.preventDefault();var d=a(this),f=+d.attr("href").substr(1);f!==e.rowCount&&(e.current=1,e.rowCount=f,d.parents(n).children().each(function(){var b=a(this),c=+b.find(o).attr("href").substr(1);b._bgSelectAria(c===f)}),d.parents(k).find(m).text(c(f)),l.call(e))});j.find(n).append(g)}),b.append(j)}}function v(b){if(b.length>0){var c=this,e=this.options.css,g=this.options.templates,h=this.element.children("tbody").first(),i=!0,j="",k="",l="",m="";a.each(b,function(b,f){if(k="",l=' data-row-id="'+(null==c.identifier?b:f[c.identifier])+'"',m="",c.selection){var h=-1!==a.inArray(f[c.identifier],c.selectedRows),n=g.select.resolve(d.call(c,{type:"checkbox",value:f[c.identifier],checked:h}));k+=g.cell.resolve(d.call(c,{content:n,css:e.selectCell})),i=i&&h,h&&(m+=e.selected,l+=' aria-selected="true"')}a.each(c.columns,function(b,h){if(h.visible){var i=a.isFunction(h.formatter)?h.formatter.call(c,h,f):h.converter.to(f[h.id]),j=h.cssClass.length>0?" "+h.cssClass:"";k+=g.cell.resolve(d.call(c,{content:null==i||""===i?" ":i,css:("right"===h.align?e.right:"center"===h.align?e.center:e.left)+j}))}}),m.length>0&&(l+=' class="'+m+'"'),j+=g.row.resolve(d.call(c,{attr:l,cells:k}))}),c.element.find("thead "+f(c.options.css.selectBox)).prop("checked",i),h.html(j),w.call(this,h)}else r.call(this)}function w(b){var c=this,d=f(this.options.css.selectBox);this.selection&&b.off("click"+D,d).on("click"+D,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"+D,"> tr").on("click"+D,"> 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"+D,[c.columns,f])})}function x(){if(0!==this.options.navigation){var c=this.options.css,e=f(c.search),g=this.header.find(e),h=this.footer.find(e);if(g.length+h.length>0){var i=this,j=this.options.templates,k=null,l="",m=f(c.searchField),n=a(j.search.resolve(d.call(this))),o=n.is(m)?n:n.find(m);o.on("keyup"+D,function(c){c.stopPropagation();var d=a(this).val();l!==d&&(l=d,b.clearTimeout(k),k=b.setTimeout(function(){i.search(d)},250))}),A.call(this,g,n,1),A.call(this,h,n,2)}}}function y(){var b=this,c=this.element.find("thead > tr"),e=this.options.css,g=this.options.templates,h="",i=this.options.sorting;if(this.selection){var j=this.options.multiSelect?g.select.resolve(d.call(b,{type:"checkbox",value:"all"})):"";h+=g.rawHeaderCell.resolve(d.call(b,{content:j,css:e.selectCell}))}if(a.each(this.columns,function(a,c){if(c.visible){var f=b.sortDictionary[c.id],j=i&&f&&"asc"===f?e.iconUp:i&&f&&"desc"===f?e.iconDown:"",k=g.icon.resolve(d.call(b,{iconCss:j})),l=c.headerAlign,m=c.headerCssClass.length>0?" "+c.headerCssClass:"";h+=g.headerCell.resolve(d.call(b,{column:c,icon:k,sortable:i&&c.sortable&&e.sortable||"",css:("right"===l?e.right:"center"===l?e.center:e.left)+m}))}}),c.html(h),i){var k=f(e.sortable);c.off("click"+D,k).on("click"+D,k,function(a){a.preventDefault(),z.call(this,b),C.call(b),l.call(b)})}if(this.selection&&this.options.multiSelect){var m=f(e.selectBox);c.off("click"+D,m).on("click"+D,m,function(c){c.stopPropagation(),a(this).prop("checked")?b.select():b.deselect()})}}function z(b){var c=a(this),d=b.options.css,e=f(d.icon),g=c.data("column-id")||c.parents("th").first().data("column-id"),h=b.sortDictionary[g],i=c.find(e);if(b.options.multiSort||(c.parents("tr").first().find(e).removeClass(d.iconDown+" "+d.iconUp),b.sortDictionary={}),h&&"asc"===h)b.sortDictionary[g]="desc",i.removeClass(d.iconUp).addClass(d.iconDown);else if(h&&"desc"===h)if(b.options.multiSort){var j={};for(var k in b.sortDictionary)k!==g&&(j[k]=b.sortDictionary[k]);b.sortDictionary=j,i.removeClass(d.iconDown)}else b.sortDictionary[g]="asc",i.removeClass(d.iconDown).addClass(d.iconUp);else b.sortDictionary[g]="asc",i.addClass(d.iconUp)}function A(b,c,d){this.options.navigation&d&&b.each(function(b,d){a(d).before(c.clone(!0)).remove()})}function B(){var a=this.options.templates,b=this.element.children("thead").first(),c=this.element.children("tbody").first(),e=c.find("tr > td").first(),f=this.element.height()-b.height()-(e.height()+20),g=this.columns.where(j).length;this.selection&&(g+=1),c.html(a.loading.resolve(d.call(this,{columns:g}))),-1!==this.rowCount&&f>0&&c.find("tr > td").css("padding","20px 0 "+f+"px")}function C(){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 D=".rs.jquery.bootgrid",E=function(b,c){this.element=a(b),this.origin=this.element.clone(),this.options=a.extend(!0,{},E.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(E.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,ajax:!1,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",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"},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:''}},E.prototype.append=function(a){if(this.options.ajax);else{for(var b=[],d=0;d0&&(this.options.multiSelect||1!==e.length);)if(c=b.pop(),-1===a.inArray(c,this.selectedRows))for(d=0;d0){var g=f(this.options.css.selectBox),h=this.selectedRows.length>=this.currentRows.length;for(d=0;!this.options.keepSelection&&h&&d tr "+g+":checked").trigger("click"+D),d=0;d tr[data-row-id="'+this.selectedRows[d]+'"]').addClass(this.options.css.selected)._bgAria("selected","true").find(g).prop("checked",!0);this.element.trigger("selected"+D,[e])}}return this},E.prototype.deselect=function(b){if(this.selection){b=b||this.currentRows.propValues(this.identifier);for(var c,d,e,g=[];b.length>0;)if(c=b.pop(),e=a.inArray(c,this.selectedRows),-1!==e)for(d=0;d0){var h=f(this.options.css.selectBox);for(this.element.find("thead "+h).prop("checked",!1),d=0;d tr[data-row-id="'+g[d][this.identifier]+'"]').removeClass(this.options.css.selected)._bgAria("selected","false").find(h).prop("checked",!1);this.element.trigger("deselected"+D,[g])}}return this},E.prototype.sort=function(b){var c,d=b?a.extend({},b):{};return d===this.sortDictionary?this:(a.each(d,a.proxy(function(a,b){d[a]="asc"===b?"desc":"asc",c=c||this.element.find('[data-column-id="'+a+'"]')},this)),this.sortDictionary=d,z.call(c[0],this),C.call(this),l.call(this),this)},a.fn.extend({_bgAria:function(a,b){return this.attr("aria-"+a,b)},_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 F={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{F&&F[b]&&"function"==typeof F[b]&&(e=F[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< that.columns.length; i++)
{
column = that.columns[i];
- if (column.searchable && column.visible &&
+ if (column.searchable && column.visible &&
column.converter.to(row[column.id]).search(searchPattern) > -1)
{
return true;
@@ -271,7 +271,7 @@ function loadRows()
function prepareTable()
{
var tpl = this.options.templates,
- wrapper = (this.element.parent().hasClass(this.options.css.responsiveTable)) ?
+ wrapper = (this.element.parent().hasClass(this.options.css.responsiveTable)) ?
this.element.parent() : this.element;
this.element.addClass(this.options.css.table);
@@ -573,7 +573,7 @@ function renderRows(rows)
if (that.selection)
{
var selected = ($.inArray(row[that.identifier], that.selectedRows) !== -1),
- selectBox = tpl.select.resolve(getParams.call(that,
+ 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);
@@ -588,13 +588,13 @@ function renderRows(rows)
{
if (column.visible)
{
- var value = ($.isFunction(column.formatter)) ?
- column.formatter.call(that, column, row) :
+ 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: ((column.align === "right") ? css.right : (column.align === "center") ?
css.center : css.left) + cssClass }));
}
});
@@ -652,9 +652,9 @@ function registerRowEvents(tbody)
e.stopPropagation();
var $this = $(this),
- id = (that.identifier == null) ? $this.data("row-id") :
+ id = (that.identifier == null) ? $this.data("row-id") :
that.converter.from($this.data("row-id") + ""),
- row = (that.identifier == null) ? that.currentRows[id] :
+ row = (that.identifier == null) ? that.currentRows[id] :
that.currentRows.first(function (item) { return item[that.identifier] === id; });
if (that.selection && that.options.rowSelect)
@@ -725,9 +725,9 @@ function renderTableHeader()
if (this.selection)
{
- var selectBox = (this.options.multiSelect) ?
+ var selectBox = (this.options.multiSelect) ?
tpl.select.resolve(getParams.call(that, { type: "checkbox", value: "all" })) : "";
- html += tpl.rawHeaderCell.resolve(getParams.call(that, { content: selectBox,
+ html += tpl.rawHeaderCell.resolve(getParams.call(that, { content: selectBox,
css: css.selectCell }));
}
@@ -735,7 +735,7 @@ function renderTableHeader()
{
if (column.visible)
{
- var sortOrder = that.sort[column.id],
+ 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 })),
@@ -743,7 +743,7 @@ function renderTableHeader()
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: ((align === "right") ? css.right : (align === "center") ?
css.center : css.left) + cssClass }));
}
});
@@ -753,55 +753,13 @@ function renderTableHeader()
// todo: create a own function for that piece of code
if (sorting)
{
- var sortingSelector = getCssSelector(css.sortable),
- iconSelector = getCssSelector(css.icon);
+ var sortingSelector = getCssSelector(css.sortable);
headerRow.off("click" + namespace, sortingSelector)
.on("click" + namespace, sortingSelector, function (e)
{
e.preventDefault();
- var $this = $(this),
- columnId = $this.data("column-id") || $this.parents("th").first().data("column-id"),
- sortOrder = that.sort[columnId],
- icon = $this.find(iconSelector);
-
- if (!that.options.multiSort)
- {
- $this.parents("tr").first().find(iconSelector).removeClass(css.iconDown + " " + css.iconUp);
- that.sort = {};
- }
-
- if (sortOrder && sortOrder === "asc")
- {
- that.sort[columnId] = "desc";
- icon.removeClass(css.iconUp).addClass(css.iconDown);
- }
- else if (sortOrder && sortOrder === "desc")
- {
- if (that.options.multiSort)
- {
- var newSort = {};
- for (var key in that.sort)
- {
- if (key !== columnId)
- {
- newSort[key] = that.sort[key];
- }
- }
- that.sort = newSort;
- icon.removeClass(css.iconDown);
- }
- else
- {
- that.sort[columnId] = "asc";
- icon.removeClass(css.iconDown).addClass(css.iconUp);
- }
- }
- else
- {
- that.sort[columnId] = "asc";
- icon.addClass(css.iconUp);
- }
+ setTableHeaderSortDirection.call(this, that);
sortRows.call(that);
loadData.call(that);
});
@@ -828,6 +786,54 @@ function renderTableHeader()
}
}
+function setTableHeaderSortDirection(instance)
+{
+ var $this = $(this),
+ css = instance.options.css,
+ iconSelector = getCssSelector(css.icon),
+ columnId = $this.data("column-id") || $this.parents("th").first().data("column-id"),
+ sortOrder = instance.sortDictionary[columnId],
+ icon = $this.find(iconSelector);
+
+ if (!instance.options.multiSort)
+ {
+ $this.parents("tr").first().find(iconSelector).removeClass(css.iconDown + " " + css.iconUp);
+ instance.sortDictionary = {};
+ }
+
+ if (sortOrder && sortOrder === "asc")
+ {
+ instance.sortDictionary[columnId] = "desc";
+ icon.removeClass(css.iconUp).addClass(css.iconDown);
+ }
+ else if (sortOrder && sortOrder === "desc")
+ {
+ if (instance.options.multiSort)
+ {
+ var newSort = {};
+ for (var key in instance.sortDictionary)
+ {
+ if (key !== columnId)
+ {
+ newSort[key] = instance.sortDictionary[key];
+ }
+ }
+ instance.sortDictionary = newSort;
+ icon.removeClass(css.iconDown);
+ }
+ else
+ {
+ instance.sortDictionary[columnId] = "asc";
+ icon.removeClass(css.iconDown).addClass(css.iconUp);
+ }
+ }
+ else
+ {
+ instance.sortDictionary[columnId] = "asc";
+ icon.addClass(css.iconUp);
+ }
+}
+
function replacePlaceHolder(placeholder, element, flag)
{
if (this.options.navigation & flag)
@@ -884,13 +890,13 @@ function sortRows()
{
var that = this;
- for (var key in this.sort)
+ for (var key in this.sortDictionary)
{
if (this.options.multiSort || sortArray.length === 0)
{
sortArray.push({
id: key,
- order: this.sort[key]
+ order: this.sortDictionary[key]
});
}
}
@@ -900,4 +906,4 @@ function sortRows()
this.rows.sort(sort);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/public.js b/src/public.js
index f9fba6f..2f7e9ed 100644
--- a/src/public.js
+++ b/src/public.js
@@ -27,7 +27,7 @@ var Grid = function(element, options)
this.rows = [];
this.searchPhrase = "";
this.selectedRows = [];
- this.sort = {};
+ this.sortDictionary = {};
this.total = 0;
this.totalPages = 0;
this.cachedParams = {
@@ -97,7 +97,7 @@ Grid.defaults = {
rowSelect: false,
/**
- * Defines whether the row selection is saved internally on filtering, paging and sorting
+ * Defines whether the row selection is saved internally on filtering, paging and sorting
* (even if the selected rows are not visible).
*
* @property keepSelection
@@ -114,7 +114,7 @@ Grid.defaults = {
ajax: false, // todo: find a better name for this property to differentiate between client-side and server-side data
/**
- * Enriches the request object with additional properties. Either a `PlainObject` or a `Function`
+ * 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
@@ -126,7 +126,7 @@ Grid.defaults = {
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`
+ * 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
@@ -484,7 +484,7 @@ Grid.prototype.select = function(rowIds)
{
rowIds = rowIds || this.currentRows.propValues(this.identifier);
- var id, i,
+ var id, i,
selectedRows = [];
while (rowIds.length > 0 && !(!this.options.multiSelect && selectedRows.length === 1))
@@ -582,7 +582,7 @@ Grid.prototype.deselect = function(rowIds)
.removeClass(this.options.css.selected)._bgAria("selected", "false")
.find(selectBoxSelector).prop("checked", false);
}
-
+
this.element.trigger("deselected" + namespace, [deselectedRows]);
}
}
@@ -600,17 +600,26 @@ Grid.prototype.deselect = function(rowIds)
**/
Grid.prototype.sort = function(dictionary)
{
- var values = (dictionary) ? $.extend({}, dictionary) : {};
- if (values === this.sort)
+ var values = (dictionary) ? $.extend({}, dictionary) : {},
+ columnHeader;
+
+ if (values === this.sortDictionary)
{
return this;
}
- this.sort = values;
+ $.each(values, $.proxy(function (key, value) {
+ // Have to flip these values, because the setTableHeaderSortDirection assumes we're
+ // flipping the direction of whatever the current sort order is, and flips it itself
+ values[key] = (value === 'asc' ? 'desc' : 'asc');
+ columnHeader = columnHeader || this.element.find('[data-column-id="' + key + '"]');
+ }, this));
- renderTableHeader.call(this);
+ this.sortDictionary = values;
+
+ setTableHeaderSortDirection.call(columnHeader[0], this);
sortRows.call(this);
loadData.call(this);
return this;
-};
\ No newline at end of file
+};
diff --git a/test/tests-internal.js b/test/tests-internal.js
index 2e292d3..b18351d 100644
--- a/test/tests-internal.js
+++ b/test/tests-internal.js
@@ -27,7 +27,7 @@ test("getRequest post function test", 1, function ()
},
current: 1,
rowCount: 5,
- sort: [],
+ sortDictionary: [],
searchPhrase: ""
},
expected = {
@@ -56,7 +56,7 @@ test("getRequest post object test", 1, function() {
},
current: 1,
rowCount: 5,
- sort: [],
+ sortDictionary: [],
searchPhrase: ""
},
expected = {
@@ -119,4 +119,4 @@ test("getUrl string test", 1, function ()
// then
equal(result, "url/test/1", "Valid URL");
-});
\ No newline at end of file
+});