/*globals define*/ /*jslint nomen:true*/ /** * @class jQuery.ui.uiDatatable * @author Copyright 2006-2013, epages GmbH, All Rights Reserved * * The datatable widget adds to a simple table-tag dynamically content. * * ### Example * HTML: * * <table class="ep-table"></table> * * JavaScript: * * $('.ep-datatable').uiDatatable({ * action: 'JSONSearchProductsToInsert' * }); * * @uses jQuery.ui.widget * @uses ep * * @chainable * @return {Object} ep */ define('ep/ui/datatable', [ 'jquery/ui/widget', 'ep/ui/input', '$tmpl!ep/ui/datatable', '$dict!ep/dict' ], function ($, ep, tableTemplate, dict) { 'use strict'; $.widget('ui.uiDatatable', { /** * Options to be passed to the widgt on initialzation * * @cfg {Object} options * @cfg {String} options.action ViewAction which is used to get data for table * @cfg {String} [options.searchString=''] String to search for * @cfg {Number} [options.pageSize=10] Number of table entries per page * @cfg {Number} [options.pages=5] Number of pages which should be loaded via one request * @cfg {Number} [options.pagerSize=5] Number of pages which should be displayed in the pager */ options: { action: undefined, searchString: undefined, pageSize: 10, pages: 5, pagerSize: 5 }, /* * Set classes and call method the render table content * * @since 6.17.0 * @private */ _create: function () { var self = this, o = self.options; self.element.addClass('ep-uiDatatable ContentList RowSelection'); self.data = {}; self._loadTableData(1); }, /* * Loads table content with the given data and calls method to render this content. * Already loaded data is cached. * * @since 6.17.0 * @private * @param {Number} page The value of the page which should be displayed */ _loadTableData: function (page) { var self = this, o = self.options, sortOrderNotChanged = self.data.orderBy === self.orderBy && self.data.orderDesc === self.orderDesc, loader = $('<span class="data-loading" />'); if (self.data.currentPage !== page || !sortOrderNotChanged) { self.data.currentPage = page; // use cached data if (self.data.tableContent && self.data.tableContent[page] && sortOrderNotChanged) { self._renderTable(); // get new data } else { self.element.parent().prepend(loader); ep.ajax({ type: 'POST', dataType: 'json', data: $.extend({ 'ObjectID': ep.config.siteId, 'ViewAction': o.action, 'WildSearchString': o.searchString, 'pageEntries': o.pageSize, 'pages': o.pages, 'ParentObjectID': o.parentObjectId || undefined, 'currentPage': page, 'orderBy': self.orderBy || undefined, 'orderDesc': self.orderDesc || undefined }, o.otherParameters) }).done(function (data) { if (self.data.tableContent && sortOrderNotChanged) { $.extend(self.data.tableContent, data.tableContent); } else { self.data = data; $.extend(self.data, { currentPage: page, iconRoot: ep.config.iconsRoot }); } if (self.data.isHighlighted) { self.element.addClass('highlight'); } // set default sorting options self.orderBy = self.data.orderBy; self.orderDesc = self.data.orderDesc; self._renderTable(); loader.remove(); self.element.trigger('datatablerendered', data); }); } } }, /* * Renders table with the given data and adds event listener for sorting, check all entries and the pager. * * @since 6.17.0 * @private */ _renderTable: function () { var self = this, checkboxes; // tell the datatable in which context it is rendered (icon for variation products, etc...) $.extend(self.data, { context: self.options.context }); // render table with given data self.renderedTable = tableTemplate(self.data) .dictParse(dict, true) .find('td') .dictParseAttr(dict, 'title') .end() .find('img') .dictParseAttr(dict, 'title') .end(); $.extend(self, $.tmplItem(self.renderedTable).elements); self.element .empty() .html(self.renderedTable); self.element.find('input').uiInput(); self._setPager(); // Get the currently cklicked checkbox by comparing all object ids of the page with the checkbox values self.element.find('tbody input').on('click', function (event) { /** * @event itemselected Fired when a checkbox is clicked. Contains all data of the selected item */ $(this).trigger('selectionstatechanged', self._getItemData(event.target.value)); }); // select all checkboxes when clicking on checkbox in table head checkboxes = self.element.find('thead input[type="checkbox"]'); if (checkboxes.length) { checkboxes.on('click', function () { var inputs = self.element.find('tbody input[name="' + $(this).attr('name') + '"]'); if ($(this).attr('checked')) { inputs.filter(':not(:checked)').trigger('click'); } else { inputs.filter(':checked').trigger('click'); } }); } // add event listeners for sorting self.element.find('th[data-id]').on('click', function () { self.orderBy = $(this).data('id'); self.orderDesc = $(this).data('orderdesc') === undefined ? 0 : ($(this).data('orderdesc') ? 0 : 1); self._loadTableData(1); }); // trigger event 'changecontent' when clicking on link in table body self.element.find('tbody a').on('click', function (event) { /** * @event changecontent Fired when a link in the table body was clicked. ID of element will be send. */ $(this).trigger('changecontent', self._getItemData($(this).data('id'))[0].ObjectID); }); }, /* * Builds the pager items corresponding on the current displayed page * * @since 6.17.0 * @private */ _setPager: function () { var self = this, o = self.options, offset = Math.floor(o.pagerSize / 2), start, end, i; if (self.data.lastPage > 1) { self.pagerItems.empty(); self.element.find('.Opacity30').removeClass('Opacity30'); // current page is the first one if (self.data.currentPage - offset <= 1) { start = 1; end = o.pagerSize > self.data.lastPage ? self.data.lastPage : o.pagerSize; // current page is the last one } else if (self.data.currentPage + offset >= self.data.lastPage) { start = self.data.lastPage - o.pagerSize + 1 < 1 ? 1 : self.data.lastPage - o.pagerSize + 1; end = self.data.lastPage; // current page is between first and last page } else { start = self.data.currentPage - offset < 1 ? 1 : self.data.currentPage - offset; end = self.data.currentPage + offset > self.data.lastPage ? self.data.lastPage : self.data.currentPage + offset; } // render pager elements for (i = start; i <= end; i += 1) { self.pagerItems.append('<a class="paginate_button" data-page="' + i + '">' + i + '</a>'); } // disable next buttons if we are on last page if (self.data.currentPage === self.data.lastPage) { self.element.find('.ep-datatable-navigate.next').addClass('Opacity30'); } // disable back button if we are on first page if (self.data.currentPage === 1) { self.element.find('.ep-datatable-navigate.back').addClass('Opacity30'); } self.element.find('.paginate_button').on('click', function () { var page = $(this).data('page'); self._loadTableData(page); self.element.trigger('pagechanged', page); }); } self._setCurrentPage(); }, /* * Sets currently displayed page in the pager as active * * @since 6.17.0 * @private */ _setCurrentPage: function () { var self = this; self.element.find('.SelectedItem') .removeClass('SelectedItem'); if (self.data.lastPage > 1) { self.pagerItems.find('a[data-page="' + self.data.currentPage + '"]') .addClass('SelectedItem'); } if (self.data.lastPage > 0) { self.currentPageNode.html(self.data.currentPage); } }, /** * Get the data of a table item * * @since 6.17.0 * @return {Object} Object containing all attributes of the item */ _getItemData: function (objectid) { var self = this, pageElements = self.data.tableContent[self.data.currentPage], hasObjectId = function (item) { return parseInt(item.ObjectID, 10) === parseInt(objectid, 10); }, itemData = $.grep(pageElements, hasObjectId); // to get item data from a path element we need to check the parents of the actual element since they are not part (elems) of the actual page if (itemData.length === 0) { $.each(pageElements, function () { itemData = $.grep(this.Parents, hasObjectId); }); } return itemData; }, /** * Removes all added elements and classes * * @since 6.17.0 */ destroy: function () { var self = this; self.element .removeClass('ep-uiDatatable ContentList RowSelection') .empty(); } }); return ep; });