📄 datatable.js
字号:
//-----------------------------------------------------------------------------// DataTable//-----------------------------------------------------------------------------//A list of all our DataTables//Test if the object have already been initialized (multiple includes)if(typeof dataTables == "undefined") var dataTables = new Object;//DataTable constructorfunction dataTable(){ this.param = new Object;}//Prototype of the DataTable objectdataTable.prototype ={ //initialisation function init: function(workingDivId, domElem) { if(typeof domElem == "undefined") { domElem = $('#'+workingDivId); } this.workingDivId = workingDivId; this.loadedSubDataTable = new Object; this.bindEventsAndApplyStyle(domElem); this.initialized = true; }, //function triggered when user click on column sort onClickSort: function(domElem) { var self = this; var newColumnToSort = $(domElem).attr('id'); // we lookup if the column to sort was already this one, if it is the case then we switch from desc <-> asc if(self.param.filter_sort_column == newColumnToSort) { // toggle the sorted order if(this.param.filter_sort_order == 'asc') { self.param.filter_sort_order = 'desc'; } else { self.param.filter_sort_order = 'asc'; } } self.param.filter_offset = 0; self.param.filter_sort_column = newColumnToSort; self.reloadAjaxDataTable(); }, //Reset DataTable filters (used before a reload or view change) resetAllFilters: function() { var self = this; var FiltersToRestore = new Array(); filters = [ 'filter_column', 'filter_pattern', 'filter_column_recursive', 'filter_pattern_recursive', 'enable_filter_excludelowpop', 'filter_offset', 'filter_limit', 'filter_sort_column', 'filter_sort_order' ]; for(var key in filters) { var value = filters[key]; FiltersToRestore[value] = self.param[value]; delete self.param[value]; } return FiltersToRestore; }, //Restores the filters to the values given in the array in parameters restoreAllFilters: function(FiltersToRestore) { var self = this; for(key in FiltersToRestore) { self.param[key] = FiltersToRestore[key]; } }, //Translate string parameters to javascript builtins //'true' -> true, 'false' -> false //it simplifies condition tests in the code cleanParams: function() { var self = this; for(var key in self.param) { if(self.param[key] == 'true') self.param[key]=true; if(self.param[key] == 'false') self.param[key]=false; } }, // Returns the standard Ajax request object used by the Jquery .ajax method buildAjaxRequest: function(callbackSuccess) { var self = this; //prepare the ajax request var ajaxRequest = { type: 'GET', url: piwik.piwik_url + 'index.php', dataType: 'html', async: true, error: ajaxHandleError, // Callback when the request fails success: callbackSuccess, // Callback when the request succeeds data: new Object }; //Extract the configuration from the datatable and pass it to the API for(var key in self.param) { if(typeof self.param[key] != "undefined") ajaxRequest.data[key] = self.param[key]; } return ajaxRequest; }, // Function called to trigger the AJAX request // The ajax request contains the function callback to trigger if the request is successful or failed // displayLoading = false When we don't want to display the Loading... DIV #loadingDataTable // for example when the script add a Loading... it self and doesn't want to display the generic Loading reloadAjaxDataTable: function(displayLoading, callbackSuccess) { var self = this; if (typeof displayLoading == "undefined") { displayLoading = true; } if (typeof callbackSuccess == "undefined") { callbackSuccess = self.dataTableLoaded; } if(displayLoading) { $('#'+self.workingDivId+' #loadingDataTable').css('display','block'); } $.ajax(self.buildAjaxRequest(callbackSuccess)); }, // Function called when the AJAX request is successful // it looks for the ID of the response and replace the very same ID // in the current page with the AJAX response dataTableLoaded: function(response) { var content = $(response); var idToReplace = $(content).attr('id'); var dataTableSel = $('#'+idToReplace); // if the current dataTable is located inside another datatable table = $(content).parents('table.dataTable'); if(dataTableSel.parents('.dataTable').is('table')) { // we add class to the table so that we can give a different style to the subtable $(content).find('table.dataTable').addClass('subDataTable'); $(content).find('#dataTableFeatures').addClass('subDataTable'); //we force the initialisation of subdatatables dataTableSel.html( $(content).html() ); } else { dataTableSel.html( $(content).html() ); lazyScrollTo(dataTableSel[0], 400); } }, /* This method is triggered when a new DIV is loaded, which happens - at the first loading of the page - after any AJAX loading of a DataTable This method basically add features to the DataTable, - such as column sorting, searching in the rows, displaying Next / Previous links, etc. - add styles to the cells and rows (odd / even styles) - modify some rows to add images if a span img is found, or add a link if a span urlLink is found or truncate the labels when they are too big - bind new events onclick / hover / etc. to trigger AJAX requests, nice hovertip boxes for truncated cells */ bindEventsAndApplyStyle: function(domElem) { var self = this; self.cleanParams(); self.handleSort(domElem); self.handleSearchBox(domElem); self.handleLowPopulationLink(domElem); self.handleOffsetInformation(domElem); self.handleExportBox(domElem); self.applyCosmetics(domElem); self.handleSubDataTable(domElem); }, // if sorting the columns is enabled, when clicking on a column, // - if this column was already the one used for sorting, we revert the order desc<->asc // - we send the ajax request with the new sorting information handleSort: function(domElem) { var self = this; if( self.param.enable_sort ) { $('.sortable', domElem).click( function() { $(this).unbind('click'); self.onClickSort(this); } ); // are we in a subdatatable? var currentIsSubDataTable = $(domElem).parent().hasClass('cellSubDataTable'); var prefixSortIcon = ''; if(currentIsSubDataTable) { prefixSortIcon = '_subtable_'; } var imageSortWidth = 16; var imageSortHeight = 16; // we change the style of the column currently used as sort column // adding an image and the class columnSorted to the TD $(".sortable#"+self.param.filter_sort_column+' #thDIV', domElem).parent() .addClass('columnSorted') .prepend('<div id="sortIconContainer"><img id="sortIcon" width="'+imageSortWidth+'" height="'+imageSortHeight+'" src="'+piwik.piwik_url+'themes/default/images/sort'+prefixSortIcon+ self.param.filter_sort_order+'.png" /></div>'); } }, // Add behaviour to the low population link handleLowPopulationLink: function(domElem, callbackSuccess) { var self = this; // Set the string for the DIV, either "Exclude low pop" or "Include all" $('#dataTableExcludeLowPopulation', domElem) .each( function() { if(typeof self.param.enable_filter_excludelowpop == 'undefined') { self.param.enable_filter_excludelowpop = 0; } if(Number(self.param.enable_filter_excludelowpop) != 0) { string = _pk_translate('CoreHome_IncludeAllPopulation'); self.param.enable_filter_excludelowpop = 1; } else { string = _pk_translate('CoreHome_ExcludeLowPopulation'); self.param.enable_filter_excludelowpop = 0; } $(this).html(string); } ) // Bind a click event to the DIV that triggers the ajax request .click( function() { self.param.enable_filter_excludelowpop = 1 - self.param.enable_filter_excludelowpop; self.param.filter_offset = 0; self.reloadAjaxDataTable(true, callbackSuccess); } ); }, //behaviour for the DataTable 'search box' handleSearchBox: function(domElem, callbackSuccess) { var self = this; var currentPattern = self.param.filter_pattern; if(typeof self.param.filter_pattern != "undefined" && self.param.filter_pattern.length > 0) { currentPattern = self.param.filter_pattern; } else if(typeof self.param.filter_pattern_recursive != "undefined" && self.param.filter_pattern_recursive.length > 0) { currentPattern = self.param.filter_pattern_recursive; } else { currentPattern = ''; } $('#dataTableSearchPattern', domElem) .show() .each(function(){ // when enter is pressed in the input field we submit the form $('#keyword', this) .keypress( function(e) { if(submitOnEnter(e)) { $(this).siblings(':submit').submit(); } } ) .val(currentPattern) ; $(':submit', this).submit( function() { var keyword = $(this).siblings('#keyword').val(); self.param.filter_offset = 0; if(self.param.search_recursive) { self.param.filter_column_recursive = 'label'; self.param.filter_pattern_recursive = keyword; } else { self.param.filter_column = 'label'; self.param.filter_pattern = keyword; } self.reloadAjaxDataTable(true, callbackSuccess); } ); $(':submit', this) .click( function(){ $(this).submit(); }) ; // in the case there is a searched keyword we display the RESET image if(currentPattern) { var target = this; var clearImg = $('<span style="position: relative;">\ <img src="'+piwik.piwik_url+'plugins/CoreHome/templates/images/reset_search.png" style="position: absolute; top: 4px; left: -15px; cursor: pointer; display: inline;" title="Clear"/>\ </span>') .click( function() { $('#keyword', target).val(''); $(':submit', target).submit(); }); $('#keyword',this).after(clearImg); } } ); }, //behaviour for '< prev' 'next >' links and page count handleOffsetInformation: function(domElem) { var self = this; $('#dataTablePages', domElem).each( function(){ var offset = 1+Number(self.param.filter_offset); var offsetEnd = Number(self.param.filter_offset) + Number(self.param.filter_limit); var totalRows = Number(self.param.totalRows); offsetEndDisp = offsetEnd; if(offsetEnd > totalRows) offsetEndDisp = totalRows; // only show this string if there is some rows in the datatable if(totalRows != 0) { var str = sprintf(_pk_translate('CoreHome_PageOf'),offset + '-' + offsetEndDisp,totalRows); $(this).text(str); } } ); // Display the next link if the total Rows is greater than the current end row $('#dataTableNext', domElem) .each(function(){ var offsetEnd = Number(self.param.filter_offset) + Number(self.param.filter_limit); var totalRows = Number(self.param.totalRows); if(offsetEnd < totalRows) { $(this).css('display','inline'); } }) // bind the click event to trigger the ajax request with the new offset .click(function(){ $(this).unbind('click'); self.param.filter_offset = Number(self.param.filter_offset) + Number(self.param.filter_limit); self.reloadAjaxDataTable(); }) ; // Display the previous link if the current offset is not zero $('#dataTablePrevious', domElem) .each(function(){ var offset = 1+Number(self.param.filter_offset); if(offset != 1) { $(this).css('display','inline'); } } ) // bind the click event to trigger the ajax request with the new offset // take care of the negative offset, we setup 0 .click( function(){ $(this).unbind('click'); var offset = Number(self.param.filter_offset) - Number(self.param.filter_limit); if(offset < 0) { offset = 0; } self.param.filter_offset = offset; self.reloadAjaxDataTable(); } ); }, // DataTable view box (data, table, cloud, graph, ...) handleExportBox: function(domElem) { var self = this; if( self.param.idSubtable ) { // no view box for subtables return; } // When the (+) image is hovered, the export buttons are displayed $('#dataTableFooterIconsShow', domElem) .show() .hover( function() { $(this).fadeOut('slow'); $('#exportToFormat', $(this).parent()).show('slow'); }, function(){} ); //timeout object used to hide the datatable export buttons var timeout = null; $('#dataTableFooterIcons', domElem) .hover( function() { //display 'hand' cursor $(this).css({ cursor: "pointer"}); //cancel timeout if necessary if(timeout != null) { clearTimeout(timeout); timeout = null; } }, function() { //display standard cursor $(this).css({ cursor: "auto"}); //set a timeout that will hide export buttons after a few moments var dom = this; timeout = setTimeout(function(){ $('#exportToFormat', dom).fadeOut('fast', function(){ //queue the two actions $('#dataTableFooterIconsShow', dom).show('fast');}); }, 1000); } ); $('.viewDataTable', domElem).click( function(){ var viewDataTable = $(this).attr('format'); self.resetAllFilters(); self.param.viewDataTable = viewDataTable; self.reloadAjaxDataTable(); } ); $('#tableGoals', domElem) .show() .click( function(){ // we only reset the limit filter, in case switch to table view from cloud view where limit is custom set to 30 // this value is stored in config file General->dataTable_default_limit but this is more an edge case so ok to set it to 10 delete self.param.filter_limit; delete self.param.enable_filter_excludelowpop; self.param.viewDataTable = 'tableGoals'; self.reloadAjaxDataTable(); } ); $('#tableAllColumnsSwitch', domElem) .show() .click( function(){ // we only reset the limit filter, in case switch to table view from cloud view where limit is custom set to 30 // this value is stored in config file General->dataTable_default_limit but this is more an edge case so ok to set it to 10 delete self.param.filter_limit; self.param.viewDataTable = self.param.viewDataTable == 'table' ? 'tableAllColumns' : 'table'; // when switching to display simple table, do not exclude low pop by default if(self.param.viewDataTable == 'table') { self.param.enable_filter_excludelowpop = 0; } self.reloadAjaxDataTable(); } );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -