|
|
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
|
|
| (function ($, require) { |
|
|
| var exports = require('piwik/UI'), |
| UIControl = exports.UIControl; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function DataTable(element) { |
| UIControl.call(this, element); |
|
|
| this.init(); |
| } |
|
|
| DataTable._footerIconHandlers = {}; |
|
|
| DataTable.initNewDataTables = function (reportId) { |
| var selector = typeof reportId === 'string' ? '[data-report='+JSON.stringify(reportId)+']' : 'div.dataTable'; |
| $(selector).each(function () { |
| if (!$(this).attr('id')) { |
| var tableType = $(this).attr('data-table-type') || 'DataTable', |
| klass = require('piwik/UI')[tableType] || require(tableType); |
|
|
| if (klass && $.isFunction(klass)) { |
| var table = new klass(this); |
| } |
| } |
| }); |
| }; |
|
|
| DataTable.registerFooterIconHandler = function (id, handler) { |
| var handlers = DataTable._footerIconHandlers; |
|
|
| if (handlers[id]) { |
| setTimeout(function () { |
| throw new Exception("DataTable footer icon handler '" + id + "' is already being used.") |
| }, 1); |
| return; |
| } |
|
|
| handlers[id] = handler; |
| }; |
|
|
| |
| |
| |
| |
| |
| |
| |
| DataTable.getDataTableByReport = function (report) { |
| var result = undefined; |
| $('div.dataTable').each(function () { |
| if ($(this).attr('data-report') == report) { |
| result = this; |
| return false; |
| } |
| }); |
| return result; |
| }; |
|
|
| $.extend(DataTable.prototype, UIControl.prototype, { |
|
|
| _init: function (domElem) { |
| |
| }, |
|
|
| _destroy: function() { |
| UIControl.prototype._destroy.call(this); |
| |
| if (this.windowResizeTableAttached) { |
| $(window).off('resize', this._resizeDataTable); |
| } |
| if (this._bodyMouseUp) { |
| $('body').off('mouseup', this._bodyMouseUp); |
| } |
| }, |
|
|
| |
| init: function () { |
| var domElem = this.$element; |
|
|
| this.workingDivId = this._createDivId(); |
| domElem.attr('id', this.workingDivId); |
|
|
| this.loadedSubDataTable = {}; |
| this.isEmpty = $('.pk-emptyDataTable', domElem).length > 0; |
| window.Vue.nextTick().then(() => { |
| this.bindEventsAndApplyStyle(domElem); |
| this._init(domElem); |
| this.enableStickHead(domElem); |
| this.initialized = true; |
| }); |
| }, |
|
|
| enableStickHead: function (domElem) { |
| var resizeTimeout = null; |
| var resize = function(domElem) { |
| var tableScroller = $(domElem).find('.dataTableScroller'); |
| var tableScrollerWidth = tableScroller.width(); |
| var tableWidth = $(domElem).find('table').width(); |
| if (tableScrollerWidth < tableWidth) { |
| tableScroller.css('overflow-x', 'scroll'); |
| } else { |
| tableScroller.css('overflow-x', ''); |
| } |
| }; |
| |
| $(window).on('resize', function () { |
| resize(domElem); |
| |
| |
| if (resizeTimeout) { |
| window.clearTimeout(resizeTimeout); |
| } |
| resizeTimeout = window.setTimeout(function(){ |
| resize(domElem); |
| }, 500); |
| |
| }).resize(); |
| }, |
| |
| onClickSort: function (domElem) { |
| var self = this; |
| var newColumnToSort = $(domElem).attr('id'); |
| |
| if (self.param.filter_sort_column == newColumnToSort) { |
| |
| 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; |
|
|
| if (!self.isDashboard()) { |
| self.notifyWidgetParametersChange(domElem, { |
| filter_sort_column: newColumnToSort, |
| filter_sort_order: self.param.filter_sort_order |
| }); |
| } |
|
|
| self.reloadAjaxDataTable(); |
| }, |
|
|
| setGraphedColumn: function (columnName) { |
| this.param.columns = columnName; |
| }, |
|
|
| isWithinDialog: function (domElem) { |
| return !!$(domElem).parents('.ui-dialog').length; |
| }, |
|
|
| isDashboard: function () { |
| return !!$('#dashboardWidgetsArea').length; |
| }, |
|
|
| getReportMetadata: function () { |
| return JSON.parse(this.$element.attr('data-report-metadata') || '{}'); |
| }, |
|
|
| |
| resetAllFilters: function () { |
| var self = this; |
| var FiltersToRestore = {}; |
| var filters = [ |
| 'filter_column', |
| 'filter_pattern', |
| 'filter_column_recursive', |
| 'filter_pattern_recursive', |
| 'enable_filter_excludelowpop', |
| 'filter_offset', |
| 'filter_limit', |
| 'filter_sort_column', |
| 'filter_sort_order', |
| 'disable_generic_filters', |
| 'columns', |
| 'flat', |
| 'totals', |
| 'include_aggregate_rows', |
| 'totalRows', |
| 'pivotBy', |
| 'pivotByColumn', |
| 'filter_trigger_id' |
| ]; |
|
|
| for (var key = 0; key < filters.length; key++) { |
| var value = filters[key]; |
| FiltersToRestore[value] = self.param[value]; |
| delete self.param[value]; |
| } |
|
|
| return FiltersToRestore; |
| }, |
|
|
| |
| restoreAllFilters: function (FiltersToRestore) { |
| var self = this; |
|
|
| for (var key in FiltersToRestore) { |
| self.param[key] = FiltersToRestore[key]; |
| } |
| }, |
|
|
| |
| |
| |
| 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; |
| } |
| }, |
|
|
| |
| |
| |
| |
| reloadAjaxDataTable: function (displayLoading, callbackSuccess, extraParams) { |
| var self = this; |
|
|
| if (typeof displayLoading == "undefined") { |
| displayLoading = true; |
| } |
| if (typeof callbackSuccess == "undefined") { |
| callbackSuccess = function (response) { |
| self.dataTableLoaded(response, self.workingDivId); |
| }; |
| } |
|
|
| if (displayLoading) { |
| $('#' + self.workingDivId + ' .loadingPiwik').last().css('display', 'block'); |
| } |
|
|
| $('#loadingError').hide(); |
|
|
| |
| if (self && self.param && self.param.viewDataTable && String(self.param.viewDataTable).indexOf('graph') === 0) { |
| delete self.param.filter_offset; |
| delete self.param.filter_limit; |
| } |
|
|
| delete self.param.showtitle; |
|
|
| var container = $('#' + self.workingDivId + ' .piwik-graph'); |
|
|
| var ajaxRequest = new ajaxHelper(); |
|
|
| if (self.param.totalRows) { |
| ajaxRequest.addParams({'totalRows': self.param.totalRows}, 'post'); |
| delete self.param.totalRows; |
| } |
|
|
| var params = {}; |
| for (var key in self.param) { |
| if (typeof self.param[key] != "undefined" && self.param[key] !== null && self.param[key] !== '') { |
| if (key == 'filter_column' || key == 'filter_column_recursive' ) { |
| |
| |
| |
| if (self.param.flat == "1" && self.param.show_dimensions == "1") { |
| params[key] = 'combinedLabel'; |
| } else { |
| params[key] = 'label'; |
| } |
| continue; |
| } |
|
|
| params[key] = self.param[key]; |
| } |
| } |
|
|
| ajaxRequest.addParams(params, 'get'); |
| if (extraParams) { |
| ajaxRequest.addParams(extraParams, 'post'); |
| } |
| ajaxRequest.withTokenInUrl(); |
|
|
| |
| var widgetId = this.findUniqueWidgetId(this.$element); |
| if (widgetId) { |
| var filterParams = this.getFilterParams(Object.assign({}, params, extraParams)); |
| window.CoreHome.SearchFiltersPersistenceStore.setSearchFilters(widgetId, filterParams); |
| } |
|
|
| ajaxRequest.setCallback( |
| function (response) { |
| container.trigger('piwikDestroyPlot'); |
| container.off('piwikDestroyPlot'); |
| callbackSuccess(response); |
| } |
| ); |
| ajaxRequest.setErrorCallback(function (deferred, status) { |
| if (status == 'abort' || !deferred || deferred.status < 400 || deferred.status >= 600) { |
| return; |
| } |
|
|
| $('#' + self.workingDivId + ' .loadingPiwik').last().css('display', 'none'); |
| $('#loadingError').show(); |
| }); |
| ajaxRequest.setFormat('html'); |
|
|
| ajaxRequest.send(); |
| }, |
|
|
| |
| |
| |
| dataTableLoaded: function (response, workingDivId, doScroll) { |
| var content = $(response); |
|
|
| if ($.trim($('.dataTableControls', content).html()) === '') { |
| $('.dataTableControls', content).append(' '); |
| |
| |
| } |
|
|
| var idToReplace = workingDivId || $(content).attr('id'); |
| var dataTableSel = $('#' + idToReplace); |
|
|
| |
| table = $(content).parents('table.dataTable'); |
| if (dataTableSel.parents('.dataTable').is('table')) { |
| |
| $(content).find('table.dataTable').addClass('subDataTable'); |
| $(content).find('.dataTableFeatures').addClass('subDataTable'); |
|
|
| |
| dataTableSel.replaceWith(content); |
| } |
| else { |
| dataTableSel.find('object').remove(); |
| dataTableSel.replaceWith(content); |
| } |
|
|
| content.trigger('piwik:dataTableLoaded'); |
|
|
| if (doScroll || 'undefined' === typeof doScroll) { |
| piwikHelper.lazyScrollTo(content[0], 400); |
| } |
|
|
| piwikHelper.compileVueEntryComponents(content); |
|
|
| return content; |
| }, |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| bindEventsAndApplyStyle: function (domElem) { |
| var self = this; |
| self.cleanParams(); |
| self.preBindEventsAndApplyStyleHook(domElem); |
| self.handleSort(domElem); |
| self.handleLimit(domElem); |
| self.handlePeriod(domElem); |
| self.handleOffsetInformation(domElem); |
| self.handleAnnotationsButton(domElem); |
| self.handleEvolutionAnnotations(domElem); |
| self.handleExportBox(domElem); |
| self.applyCosmetics(domElem); |
| self.handleSubDataTable(domElem); |
| self.handleConfigurationBox(domElem); |
| self.handleSearchBox(domElem); |
| self.handleColumnDocumentation(domElem); |
| self.handleRowActions(domElem); |
| self.handleCellTooltips(domElem); |
| self.handleRelatedReports(domElem); |
| self.handleTriggeredEvents(domElem); |
| self.handleColumnHighlighting(domElem); |
| self.setFixWidthToMakeEllipsisWork(domElem); |
| self.handleSummaryRow(domElem); |
| self.postBindEventsAndApplyStyleHook(domElem); |
| }, |
|
|
| preBindEventsAndApplyStyleHook: function (domElem) { |
|
|
| }, |
| postBindEventsAndApplyStyleHook: function (domElem) { |
|
|
| }, |
|
|
| isWidgetized: function () { |
| return -1 !== location.search.indexOf('module=Widgetize'); |
| }, |
|
|
| setFixWidthToMakeEllipsisWork: function (domElem) { |
| var self = this; |
|
|
| function getTableWidth(domElem) |
| { |
| var totalWidth = $(domElem).width(); |
| var totalWidthTable = $('table.dataTable', domElem).width(); |
|
|
| if (totalWidthTable < totalWidth) { |
| totalWidth = totalWidthTable; |
| } |
|
|
| if (!totalWidth) { |
| totalWidth = 0; |
| } |
|
|
| return parseInt(totalWidth, 10); |
| } |
|
|
| function getLabelWidth(domElem, tableWidth, minLabelWidth, maxLabelWidth) |
| { |
| var labelWidth = minLabelWidth; |
|
|
| var columnsInFirstRow = $('tbody tr:not(.parentComparisonRow):not(.comparePeriod):eq(0) td:not(.label)', domElem); |
|
|
| var widthOfAllColumns = 0; |
| columnsInFirstRow.each(function (index, column) { |
| |
| |
| widthOfAllColumns += Math.round($(column).outerWidth()); |
| }); |
|
|
| if (tableWidth - widthOfAllColumns >= minLabelWidth) { |
| labelWidth = tableWidth - widthOfAllColumns; |
| } else if (widthOfAllColumns >= tableWidth) { |
| labelWidth = tableWidth * 0.5; |
| } |
|
|
| var innerWidth = 0; |
| var innerWrapper = domElem.find('.dataTableWrapper'); |
| if (innerWrapper && innerWrapper.length) { |
| innerWidth = innerWrapper.width(); |
| } |
|
|
| if (labelWidth > maxLabelWidth |
| && !self.isWidgetized() |
| && innerWidth !== domElem.width() |
| && !self.isDashboard() |
| ) { |
| labelWidth = maxLabelWidth; |
| } |
| var allColumns = $('tr:nth-child(1) td.label', domElem).length; |
| var firstTableColumn = $('table:first tbody>tr:first td.label', domElem).length; |
| var amount = allColumns; |
| if (allColumns > 2 * firstTableColumn) { |
| amount = 2 * firstTableColumn; |
| } |
| var newWidth = parseInt(labelWidth / amount, 10) |
| if (newWidth == 0) { |
| newWidth = maxLabelWidth; |
| } |
| return newWidth; |
| } |
|
|
| function getLabelColumnMinWidth(domElem) |
| { |
| var minWidth = 0; |
| var minWidthHead = $('thead .first.label', domElem).css('minWidth'); |
|
|
| if (minWidthHead) { |
| minWidth = parseInt(minWidthHead, 10); |
| } |
|
|
| var minWidthBody = $('tbody tr:nth-child(1) td.label', domElem).css('minWidth'); |
| if (minWidthBody) { |
| minWidthBody = parseInt(minWidthBody, 10); |
| if (minWidthBody && minWidthBody > minWidth) { |
| minWidth = minWidthBody; |
| } |
| } |
|
|
| return parseInt(minWidth, 10); |
| } |
|
|
| function getLabelColumnMaxWidth(domElem) |
| { |
| var maxWidth = 0; |
| var maxWidthHead = $('thead .first.label', domElem).css('maxWidth'); |
|
|
| if (maxWidthHead) { |
| maxWidthHead = parseInt(maxWidthHead, 10); |
| if (maxWidthHead > 0) { |
| maxWidth = parseInt(maxWidthHead, 10); |
| } |
| } |
|
|
| var maxWidthBody = $('tbody tr:nth-child(1) td.label', domElem).css('maxWidth'); |
|
|
| if (maxWidthBody) { |
| maxWidthBody = parseInt(maxWidthBody, 10); |
| if (maxWidthBody && maxWidthBody > 0 && (maxWidth === 0 || maxWidthBody < maxWidth)) { |
| maxWidth = maxWidthBody; |
| } |
| } |
|
|
| return parseInt(maxWidth, 10); |
| } |
|
|
| function removePaddingFromWidth(elem, labelWidth) { |
| var paddingLeft = elem.css('paddingLeft'); |
| paddingLeft = paddingLeft ? Math.round(parseFloat(paddingLeft)) : 0; |
| var paddingRight = elem.css('paddingRight'); |
| paddingRight = paddingRight ? Math.round(parseFloat(paddingRight)) : 0; |
|
|
| if (elem.find('.prefix-numeral').length) { |
| labelWidth -= Math.round(parseFloat(elem.find('.prefix-numeral').outerWidth())); |
| } |
|
|
| return labelWidth - paddingLeft - paddingRight; |
| } |
|
|
| var isTableVisualization = this.param.viewDataTable |
| && typeof this.param.viewDataTable === 'string' |
| && typeof this.param.viewDataTable.indexOf === 'function' |
| && this.param.viewDataTable.indexOf('table') !== -1; |
| if (isTableVisualization) { |
| |
|
|
| var tableWidth = getTableWidth(domElem); |
| var labelColumnMinWidth = getLabelColumnMinWidth(domElem); |
| var labelColumnMaxWidth = getLabelColumnMaxWidth(domElem); |
| var labelColumnWidth = getLabelWidth( |
| domElem, |
| tableWidth, |
| self.props.min_label_width || 125, |
| self.props.max_label_width || 440 |
| ); |
| if (labelColumnMinWidth > labelColumnWidth) { |
| labelColumnWidth = labelColumnMinWidth; |
| } |
| if (labelColumnMaxWidth && labelColumnMaxWidth < labelColumnWidth) { |
| labelColumnWidth = labelColumnMaxWidth; |
| } |
|
|
| |
| if ($(domElem).closest('.subDataTableContainer').length) { |
| var parentTable = $(domElem).closest('table.dataTable'); |
| var tableColumns = $('table:eq(0)>thead th', domElem).length; |
| var parentTableColumns = $('>thead th', parentTable).length; |
| var labelColumn = $('>tbody td.label:eq(0)', parentTable); |
| var labelWidthParentTable = labelColumn.outerWidth(); |
|
|
| |
| if (parentTableColumns === tableColumns) { |
| labelColumnWidth = Math.min(labelColumnWidth, labelWidthParentTable); |
|
|
| |
| $('>tbody>tr:not(.subDataTableContainer)>td.label', parentTable).each(function() { |
| $(this).css({ |
| width: removePaddingFromWidth($(this), labelColumnWidth) + 'px' |
| }); |
| }); |
|
|
| |
| $('>tbody>tr.subDataTableContainer', parentTable).each(function() { |
| if ($('table:eq(0)>thead th', this).length === parentTableColumns) { |
| $(this).css({ |
| width: removePaddingFromWidth($(this), labelColumnWidth) + 'px' |
| }); |
| } |
| }); |
| } |
| } |
|
|
| if (labelColumnWidth) { |
| $('td.label', domElem).each(function() { |
| $(this).css({ |
| width: removePaddingFromWidth($(this), labelColumnWidth) + 'px' |
| }); |
| }); |
| } |
|
|
| $('td span.label', domElem).each(function () { self.tooltip($(this)); }); |
| } |
|
|
| if (!self.windowResizeTableAttached) { |
| self.windowResizeTableAttached = true; |
|
|
| |
| var timeout = null; |
| var windowWidth = 0; |
| var resizeDataTable = function() { |
|
|
| if (windowWidth === $(window).width()) { |
| return; |
| } |
|
|
| if (timeout) { |
| clearTimeout(timeout); |
| } |
|
|
| timeout = setTimeout(function () { |
| var isInDom = domElem && domElem[0] && document && document.body && document.body.contains(domElem[0]); |
| if (isInDom) { |
| |
| |
| if (isTableVisualization) { |
| $('td.label', domElem).width(''); |
| } |
| self.setFixWidthToMakeEllipsisWork(domElem); |
| windowWidth = $(window).width(); |
| } else { |
| $(window).off('resize', resizeDataTable); |
| } |
|
|
| timeout = null; |
| }, Math.floor((Math.random() * 80) + 220)); |
| |
| |
| } |
|
|
| $(window).on('resize', resizeDataTable); |
| self._resizeDataTable = resizeDataTable; |
| } |
| }, |
|
|
| handleLimit: function (domElem) { |
| var tableRowLimits = this.props.datatable_row_limits || piwik.config.datatable_row_limits, |
| evolutionLimits = |
| { |
| day: [8, 30, 60, 90, 180], |
| week: [4, 12, 26, 52, 104], |
| month: [3, 6, 12, 24, 36, 120], |
| year: [3, 5, 10] |
| }; |
|
|
| |
| if (!parseInt(this.param.flat)) { |
| evolutionLimits.day.push(365, 500); |
| evolutionLimits.week.push(500); |
| } |
|
|
| var self = this; |
| if (typeof self.parentId != "undefined" && self.parentId != '') { |
| return; |
| } |
|
|
| if (self.props.disable_all_rows_filter_limit) { |
| var tempTableRowLimits = []; |
| tableRowLimits.forEach(function (limit) { |
| if (limit != -1) { |
| tempTableRowLimits.push(limit); |
| } |
| }); |
| tableRowLimits = tempTableRowLimits; |
| } |
|
|
| |
| var setLimitValue, numbers, limitParamName; |
| if (self.param.viewDataTable == 'graphEvolution') { |
| limitParamName = 'evolution_' + self.param.period + '_last_n'; |
| numbers = evolutionLimits[self.param.period] || tableRowLimits; |
|
|
| setLimitValue = function (params, limit) { |
| params[limitParamName] = limit; |
| }; |
| } |
| else { |
| numbers = tableRowLimits; |
| limitParamName = 'filter_limit'; |
|
|
| setLimitValue = function (params, value) { |
| params.filter_limit = value; |
| params.filter_offset = 0; |
| }; |
| } |
|
|
| function getFilterLimitAsString(limit) { |
| if (limit == '-1') { |
| return _pk_translate('General_All').toLowerCase(); |
| } |
| return limit; |
| } |
|
|
| |
|
|
| var selectionMarkup = '<div class="input-field"><select value="'+ self.param[limitParamName] +'">'; |
| var selectedValue = getFilterLimitAsString(self.param[limitParamName]); |
|
|
| if (self.props.show_limit_control) { |
| for (var i = 0; i < numbers.length; i++) { |
| var currentValue = getFilterLimitAsString(numbers[i]); |
| var optionSelected = ''; |
| if (selectedValue == currentValue) { |
| optionSelected = 'selected'; |
| } |
| selectionMarkup += '<option value="' + numbers[i] + '"' + optionSelected + '>' + currentValue + '</option>'; |
| } |
| selectionMarkup += '</select></div>'; |
|
|
| $('.limitSelection', domElem).append(selectionMarkup); |
|
|
| var $limitSelect = $('.limitSelection select', domElem); |
|
|
| if (!self.isEmpty) { |
|
|
| $limitSelect.on('change', function (event) { |
| var limit = $(this).val(); |
|
|
| if (limit != self.param[limitParamName]) { |
| setLimitValue(self.param, limit); |
| self.reloadAjaxDataTable(); |
|
|
| var data = {}; |
| data[limitParamName] = self.param[limitParamName]; |
| self.notifyWidgetParametersChange(domElem, data); |
| } |
| }); |
| } |
| else { |
| $limitSelect.toggleClass('disabled'); |
| } |
|
|
| $limitSelect.material_select(); |
|
|
| $('.limitSelection input', domElem).attr('title', _pk_translate('General_RowsToDisplay')); |
| } |
| else { |
| $('.limitSelection', domElem).hide(); |
| } |
| }, |
| handlePeriod: function (domElem) { |
| var $periodSelect = $('.dataTablePeriods .tableIcon', domElem); |
|
|
| var self = this; |
| $periodSelect.click(function () { |
| var period = $(this).attr('data-period'); |
| if (!period || period == self.param['period']) { |
| return; |
| } |
|
|
| var piwikPeriods = window.CoreHome.Periods; |
| var formatDate = window.CoreHome.format; |
| if (self.param['dateUsedInGraph']) { |
| |
| |
| var currentPeriod = piwikPeriods.parse('range', self.param['dateUsedInGraph']); |
| } else { |
| var currentPeriod = piwikPeriods.parse(self.param['period'], self.param['date']); |
| } |
| var endDateOfPeriod = currentPeriod.getDateRange()[1]; |
| endDateOfPeriod = formatDate(endDateOfPeriod); |
|
|
| var newPeriod = piwikPeriods.get(period); |
| $('.periodName', domElem).html(newPeriod.getDisplayText()); |
|
|
| self.param['period'] = period; |
| self.param['date'] = endDateOfPeriod; |
| self.reloadAjaxDataTable(); |
| }); |
| }, |
|
|
| |
| |
| |
| handleSort: function (domElem) { |
| var self = this; |
|
|
| if (self.props.enable_sort) { |
| $('.sortable', domElem).off('click.dataTableSort').on('click.dataTableSort', |
| function () { |
| $(this).off('click.dataTableSort'); |
| self.onClickSort(this); |
| } |
| ); |
| } |
|
|
| if (self.param.filter_sort_column) { |
| |
| var currentIsSubDataTable = $(domElem).parent().hasClass('cellSubDataTable'); |
| var imageSortClassType = currentIsSubDataTable ? 'sortSubtable' : '' |
| var imageSortWidth = 16; |
| var imageSortHeight = 16; |
|
|
| var sortOrder = self.param.filter_sort_order || 'desc'; |
|
|
| |
| |
| var head = $('th', domElem).filter(function () { |
| return $(this).attr('id') == self.param.filter_sort_column; |
| }).addClass('columnSorted'); |
|
|
| var sortIconHtml = '<span class="sortIcon ' + sortOrder + ' ' + imageSortClassType +'" width="' + imageSortWidth + '" height="' + imageSortHeight + '" />'; |
|
|
| var div = head.find('.thDIV'); |
| if (head.hasClass('first') || head.attr('id') == 'label') { |
| div.append(sortIconHtml); |
| } else { |
| div.prepend(sortIconHtml); |
| } |
| } |
| }, |
|
|
| |
| 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 = ''; |
| } |
| currentPattern = piwikHelper.htmlDecode(currentPattern); |
|
|
| var patternsToReplace = [{from: '?', to: '\\?'}, {from: '+', to: '\\+'}, {from: '*', to: '\\*'}] |
|
|
| $.each(patternsToReplace, function (index, pattern) { |
| if (0 === currentPattern.indexOf(pattern.to)) { |
| currentPattern = pattern.from + currentPattern.slice(2); |
| } |
| }); |
|
|
| var $searchAction = $('.dataTableAction.searchAction', domElem); |
| if (!$searchAction.length) { |
| return; |
| } |
|
|
| $searchAction.on('click', showSearch); |
| $searchAction.find('.icon-close').on('click', hideSearch); |
|
|
| var $searchInput = $('.dataTableSearchInput', domElem); |
|
|
| function getOptimalWidthForSearchField($searchAction) { |
| var controlBarWidth = $searchAction.parents('.dataTableControls').first().width(); |
| var spaceLeft = controlBarWidth - $searchAction.position().left; |
| var idealWidthForSearchBar = 250; |
| var minimalWidthForSearchBar = 150; |
| var width = idealWidthForSearchBar; |
| if (spaceLeft > minimalWidthForSearchBar && spaceLeft < idealWidthForSearchBar) { |
| width = spaceLeft; |
| } |
|
|
| if (width > controlBarWidth) { |
| width = controlBarWidth; |
| } |
|
|
| return width; |
| } |
|
|
| function hideSearch(event) { |
| event.preventDefault(); |
| event.stopPropagation(); |
|
|
| var $searchAction = $(this).parents('.searchAction').first(); |
| $searchAction.removeClass('searchActive active forceActionVisible'); |
| $searchAction.css('width', ''); |
| $searchAction.on('click', showSearch); |
| $searchAction.find('.icon-search').off('click', searchForPattern); |
|
|
| $searchInput.val(''); |
|
|
| if (currentPattern) { |
| |
| |
| searchForPattern(); |
| } |
| } |
|
|
| function getTriggerField(event) { |
| if (typeof self.param.filter_trigger_id !== "undefined" && |
| self.param.filter_trigger_id.length > 0) { |
| return document.getElementById(self.param.filter_trigger_id); |
| } else { |
| if (event && event.target) { |
| if (event.target.nodeName.toLowerCase() === 'span') { |
| return $(event.target).siblings('input'); |
| } else { |
| return $(event.target).children('input'); |
| } |
| } |
| } |
| } |
|
|
| function restoreSearchFieldFocus(event) |
| { |
| var triggerField = getTriggerField(event); |
|
|
| if (triggerField) { |
| triggerField.focus(); |
| } |
| } |
|
|
| function showSearchInputFields($searchAction) { |
| $searchAction.addClass('searchActive forceActionVisible'); |
| var width = getOptimalWidthForSearchField($searchAction); |
| $searchAction.css('width', width + 'px'); |
| $searchAction.find('.icon-search').on('click', searchForPattern); |
| $searchAction.off('click', showSearch); |
| } |
|
|
| function showSearch(event) { |
| event.preventDefault(); |
| event.stopPropagation(); |
|
|
| showSearchInputFields($(this)); |
| restoreSearchFieldFocus(event); |
| } |
|
|
|
|
| function searchForPattern(event) { |
| var keyword = ''; |
| if (event) { |
| var $input; |
| if (event.target.tagName.toLowerCase() === 'input') { |
| $input = $(event.target); |
| } else if (event.target.tagName.toLowerCase() === 'span') { |
| $input = $(event.target).siblings('input'); |
| } |
|
|
| if ($input && $input.length) { |
| keyword = $input.val(); |
| self.param.filter_trigger_id = $input.attr('id'); |
| } |
| } |
|
|
| if (!keyword && !currentPattern) { |
| |
| |
| return; |
| } |
|
|
| self.param.filter_offset = 0; |
|
|
| $.each(patternsToReplace, function (index, pattern) { |
| if (0 === keyword.indexOf(pattern.from)) { |
| keyword = pattern.to + keyword.slice(1); |
| } |
| }); |
|
|
| 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; |
| } |
|
|
| delete self.param.totalRows; |
|
|
| self.reloadAjaxDataTable(true, callbackSuccess); |
| } |
|
|
| $searchInput.on("keyup", function (e) { |
| if (isEnterKey(e)) { |
| searchForPattern(e); |
| } else if (isEscapeKey(e)) { |
| $searchAction.find('.icon-close').click(); |
| } |
| }); |
|
|
| $searchInput.on("blur", function () { |
| delete self.param.filter_trigger_id; |
| }); |
|
|
| var $dataTable = $searchInput.parents('.dataTable').first(); |
| if (currentPattern) { |
| $dataTable.addClass('hasSearchKeyword'); |
| $searchInput.val(currentPattern); |
| showSearchInputFields($searchAction); |
| restoreSearchFieldFocus(); |
| } else { |
| $dataTable.removeClass('hasSearchKeyword'); |
| } |
|
|
| if (this.isEmpty && !currentPattern) { |
| $searchAction.css({display: 'none'}); |
| } |
| }, |
|
|
| |
| 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); |
| var offsetEndDisp = offsetEnd; |
|
|
| if (self.param.keep_summary_row == 1) --totalRows; |
|
|
| if (offsetEnd > totalRows || Number(self.param.filter_limit) == -1) offsetEndDisp = totalRows; |
|
|
| |
| if (totalRows != 0) { |
| var str = sprintf(_pk_translate('General_Pagination'), offset, offsetEndDisp, totalRows); |
| $(this).text(str); |
| } else { |
| $(this).hide(); |
| } |
| } |
| ); |
|
|
| var $next = $('.dataTableNext', domElem); |
|
|
| |
| |
| $next.each(function () { |
| var offsetEnd = Number(self.param.filter_offset) |
| + Number(self.param.filter_limit); |
| var totalRows = Number(self.param.totalRows); |
| if (self.param.keep_summary_row == 1) --totalRows; |
| if (offsetEnd < totalRows && Number(self.param.filter_limit) > 0) { |
| $(this).css('visibility', 'visible'); |
| } |
| }); |
| |
| $next.off('click'); |
| $next.click(function () { |
| $(this).off('click'); |
| self.param.filter_offset = Number(self.param.filter_offset) + Number(self.param.filter_limit); |
| self.reloadAjaxDataTable(); |
| }); |
|
|
| var $prev = $('.dataTablePrevious', domElem); |
|
|
| |
| $prev.each(function () { |
| var offset = 1 + Number(self.param.filter_offset); |
| if (offset != 1) { |
| $(this).css('visibility', 'visible'); |
| } |
| }); |
|
|
| |
| |
| $prev.off('click'); |
| $prev.click(function () { |
| $(this).off('click'); |
| var offset = Number(self.param.filter_offset) - Number(self.param.filter_limit); |
| if (offset < 0) { offset = 0; } |
| self.param.filter_offset = offset; |
| self.param.previous = 1; |
| self.reloadAjaxDataTable(); |
| }); |
| }, |
|
|
| handleEvolutionAnnotations: function (domElem) { |
| var self = this; |
| if ((self.param.viewDataTable === 'graphEvolution' || self.param.viewDataTable === 'graphStackedBarEvolution') |
| && $('.annotationView', domElem).length > 0) { |
| |
| |
|
|
| $('.dataTableFeatures', domElem).addClass('hasEvolution'); |
|
|
| piwik.annotations.api.getEvolutionIcons( |
| self.param.idSite, |
| self.param.date, |
| self.param.period, |
| self.param['evolution_' + self.param.period + '_last_n'], |
| function (response) { |
| var annotations = $(response), |
| datatableFeatures = $('.dataTableFeatures', domElem), |
| noteSize = 16, |
| annotationAxisHeight = 30 |
| ; |
|
|
| var annotationsCss = {left: 6}; |
|
|
| |
| annotations.css(annotationsCss); |
|
|
| piwik.annotations.placeEvolutionIcons(annotations, domElem); |
|
|
| piwik.annotations.placeEvolutionAnnotations(annotations, domElem); |
|
|
| |
| $('.piwik-graph', domElem).on('resizeGraph', function () { |
| piwik.annotations.placeEvolutionIcons(annotations, domElem); |
| }); |
|
|
| |
| datatableFeatures.on('mouseenter', '.evolution-annotations>span', function () { |
| $(this).css('opacity', 1); |
| }); |
|
|
| datatableFeatures.on('mouseleave', '.evolution-annotations>span', function () { |
| if ($(this).attr('data-count') == 0) |
| { |
| $(this).css('opacity', 0); |
| } |
| }); |
|
|
| |
| datatableFeatures.on('click', '.evolution-annotations>span', function () { |
| var spanSelf = $(this), |
| date = spanSelf.attr('data-date'), |
| oldDate = $('.annotation-manager', domElem).attr('data-date'); |
| if (date) { |
| var period = self.param.period; |
| if (period == 'range') { |
| period = 'day'; |
| } |
|
|
| piwik.annotations.showAnnotationViewer( |
| domElem, |
| self.param.idSite, |
| date, |
| period, |
| undefined, |
| function (manager) { |
| manager.attr('data-is-range', 0); |
| $('.annotationView', domElem) |
| .attr('title', _pk_translate('Annotations_IconDesc')); |
|
|
| var viewAndAdd = _pk_translate('Annotations_ViewAndAddAnnotations'), |
| hideNotes = _pk_translate('Annotations_HideAnnotationsFor'); |
|
|
| |
| if (oldDate) { |
| $('span', annotations).each(function () { |
| if ($(this).attr('data-date') == oldDate) { |
| $(this).attr('title', sprintf(viewAndAdd, oldDate)); |
| return false; |
| } |
| }); |
| } |
|
|
| |
| if (manager.is(':hidden')) { |
| spanSelf.attr('title', sprintf(viewAndAdd, date)); |
| } |
| else { |
| spanSelf.attr('title', sprintf(hideNotes, date)); |
| } |
| } |
| ); |
| } |
| }); |
|
|
| |
| |
| var runningAnimation = null; |
| domElem.on('mouseenter', '.annotation', function (e) { |
| var date = $(this).attr('data-date'); |
|
|
| |
| var icon = $(); |
| $('span', annotations).each(function () { |
| if ($(this).attr('data-date') == date) { |
| icon = $('img', this); |
| return false; |
| } |
| }); |
|
|
| if (icon[0] == runningAnimation) |
| { |
| return; |
| } |
|
|
| |
| $('span', annotations).each(function () { |
| $('img', this).removeAttr('style'); |
| }); |
|
|
| |
| icon.effect("bounce", {times: 1, distance: 10}, 1000); |
| runningAnimation = icon[0]; |
| }); |
|
|
| |
| domElem.on('mouseleave', '.annotations', function (e) { |
| runningAnimation = null; |
| }); |
|
|
| self.$element.trigger('piwik:annotationsLoaded'); |
| } |
| ); |
| } |
| }, |
|
|
| handleAnnotationsButton: function (domElem) { |
| var self = this; |
| if (self.param.idSubtable) |
| { |
| return; |
| } |
|
|
| |
| $('.annotationView', domElem).click(function () { |
| var annotationManager = $('.annotation-manager', domElem); |
|
|
| if (annotationManager.length > 0 |
| && annotationManager.attr('data-is-range') == 1) { |
| if (annotationManager.is(':hidden')) { |
| annotationManager.slideDown('slow'); |
| $(this).attr('title', _pk_translate('Annotations_IconDescHideNotes')); |
| } |
| else { |
| annotationManager.slideUp('slow'); |
| $(this).attr('title', _pk_translate('Annotations_IconDesc')); |
| } |
| } |
| else { |
| |
| var lastN = self.param['evolution_' + self.param.period + '_last_n']; |
| piwik.annotations.showAnnotationViewer( |
| domElem, |
| self.param.idSite, |
| self.param.date, |
| self.param.period, |
| lastN, |
| function (manager) { |
| manager.attr('data-is-range', 1); |
| } |
| ); |
|
|
| |
| $(this).attr('title', _pk_translate('Annotations_IconDescHideNotes')); |
| } |
| }); |
| }, |
|
|
| |
| handleExportBox: function (domElem) { |
| var self = this; |
| if (self.param.idSubtable) { |
| |
| return; |
| } |
|
|
| |
| self.jsViewDataTable = self.param.viewDataTable; |
|
|
| $('.tableAllColumnsSwitch a', domElem).show(); |
|
|
| $('.dataTableFooterIcons .tableIcon', domElem).click(function () { |
| var id = $(this).attr('data-footer-icon-id'); |
| if (!id) { |
| return; |
| } |
|
|
| var handler = DataTable._footerIconHandlers[id]; |
| if (!handler) { |
| handler = DataTable._footerIconHandlers['table']; |
| } |
|
|
| handler(self, id); |
| }); |
|
|
| |
| self.currentGraphViewIcon = 0; |
| self.graphViewEnabled = 0; |
| self.graphViewStartingThreads = 0; |
| self.graphViewStartingKeep = false; |
| }, |
|
|
| handleConfigurationBox: function (domElem, callbackSuccess) { |
| var self = this; |
|
|
| if (typeof self.parentId != "undefined" && self.parentId != '') { |
| |
| return; |
| } |
|
|
| if ((typeof self.numberOfSubtables == 'undefined' || self.numberOfSubtables == 0) |
| && (typeof self.param.flat == 'undefined' || self.param.flat != 1) |
| ) { |
| |
| var dataTableActionsVueApps = $('[vue-entry="CoreHome.DataTableActions"]', domElem); |
| if (dataTableActionsVueApps.length) { |
| dataTableActionsVueApps.each(function() { |
| var appData = $(this).data('vueAppInstance'); |
| if (appData) { |
| appData.showFlattenTable_ = false; |
| } |
| }); |
| } |
| } |
|
|
| var ul = $('ul.tableConfiguration', domElem); |
| if (!ul.find('li').length) { |
| return; |
| } |
|
|
| var generateClickCallback = function (paramName, callbackAfterToggle, setParamCallback) { |
| return function () { |
| if (setParamCallback) { |
| var data = setParamCallback(); |
| } else { |
| self.param[paramName] = (1 - (self.param[paramName] || 0)) + ''; |
| var data = {}; |
| } |
| self.param.filter_offset = 0; |
| delete self.param.totalRows; |
| if (callbackAfterToggle) callbackAfterToggle(); |
| self.reloadAjaxDataTable(true, callbackSuccess); |
| data[paramName] = self.param[paramName]; |
| self.notifyWidgetParametersChange(domElem, data); |
| }; |
| }; |
|
|
| |
| $('.dataTableExcludeLowPopulation', domElem) |
| .click(generateClickCallback('enable_filter_excludelowpop')); |
|
|
| |
| $('.dataTableFlatten', domElem) |
| .click(generateClickCallback('flat')); |
|
|
| |
| $('.dataTableShowTotalsRow', domElem) |
| .click(generateClickCallback('keep_totals_row')); |
|
|
| $('.dataTableIncludeAggregateRows', domElem) |
| .click(generateClickCallback('include_aggregate_rows', function () { |
| if (self.param.include_aggregate_rows == 1) { |
| |
| |
| self.param.filter_sort_column = ''; |
| self.notifyWidgetParametersChange(domElem, {filter_sort_column: ''}); |
| } |
| })); |
|
|
| $('.dataTableShowDimensions', domElem) |
| .click(generateClickCallback('show_dimensions')); |
|
|
| |
| $('.dataTablePivotBySubtable', domElem) |
| .click(generateClickCallback('pivotBy', null, function () { |
| if (self.param.pivotBy |
| && self.param.pivotBy != '0' |
| ) { |
| self.param.pivotBy = '0'; |
| self.param.pivotByColumn = '0'; |
| } else { |
| self.param.pivotBy = self.props.pivot_by_dimension; |
| if (self.props.pivot_by_column) { |
| self.param.pivotByColumn = self.props.pivot_by_column; |
| } |
| } |
|
|
| |
| self.param.filter_sort_column = ''; |
| return {filter_sort_column: ''}; |
| })); |
| }, |
|
|
| findUniqueWidgetId: function (domWidget) { |
| |
| var widget = $(domWidget).closest('[widgetId]'); |
| if (widget && widget.length && widget[0].hasAttribute('widgetId')) { |
| return widget[0].getAttribute('widgetId'); |
| } |
|
|
| |
| widget = $(domWidget).closest('.matomo-widget'); |
| if (widget && widget.length && widget[0].hasAttribute('id')) { |
| return widget[0].getAttribute('id'); |
| } |
|
|
| return ''; |
| }, |
|
|
| getFilterParams: function (params) { |
| return Object.keys(params) |
| .filter(key => key.startsWith('filter_column') || key.startsWith('filter_pattern')) |
| .reduce((filterParams, key) => { |
| filterParams[key] = params[key]; |
| return filterParams; |
| }, {}); |
| }, |
|
|
| notifyWidgetParametersChange: function (domWidget, parameters) { |
| var widget = $(domWidget).closest('[widgetId],[containerid]'); |
| |
|
|
| |
| |
| |
| if (widget && widget.length && widget[0].hasAttribute('widgetId')) { |
| widget.trigger('setParameters', parameters); |
| } else { |
| if (!piwik.isUserIsAnonymous) { |
| var containerId = widget && widget.length ? widget.attr('containerid') : undefined; |
| var reportId = $(domWidget).closest('[data-report]').attr('data-report'); |
|
|
| var ajaxRequest = new ajaxHelper(); |
| ajaxRequest.addParams({ |
| module: 'CoreHome', |
| action: 'saveViewDataTableParameters', |
| report_id: reportId, |
| containerId: containerId |
| }, 'get'); |
| ajaxRequest.withTokenInUrl(); |
| ajaxRequest.addParams({ |
| parameters: JSON.stringify(parameters) |
| }, 'post'); |
| ajaxRequest.setCallback(function () { |
| }); |
| ajaxRequest.setFormat('html'); |
| ajaxRequest.send(); |
| } |
| } |
| }, |
|
|
| tooltip: function (domElement) { |
|
|
| function isTextEllipsized($element) |
| { |
| return !($element && $element[0] && $element.outerWidth() >= $element[0].scrollWidth); |
| } |
|
|
| var $domElement = $(domElement); |
|
|
| if ($domElement.data('tooltip') == 'enabled') { |
| return; |
| } |
|
|
| $domElement.data('tooltip', 'enabled'); |
|
|
| if (!isTextEllipsized($domElement)) { |
| return; |
| } |
|
|
| var customToolTipText = $domElement.attr('title') || $domElement.text(); |
|
|
| if (customToolTipText) { |
| $domElement.attr('title', customToolTipText); |
| } |
|
|
| $domElement.tooltip({ |
| track: true, |
| show: false, |
| hide: false |
| }); |
| }, |
|
|
| |
| applyCosmetics: function (domElem) { |
| |
| }, |
|
|
| handleColumnHighlighting: function (domElem) { |
|
|
| var currentNthChild = null; |
| var self = this; |
|
|
| |
| $(domElem).on('mouseenter', 'td:not(.cellSubDataTable)', function (e) { |
| e.stopPropagation(); |
| var $this = $(e.target); |
| if ($this.hasClass('label')) { |
| return; |
| } |
|
|
| var table = $this.closest('table'); |
| var nthChild = $this.parent('tr').children().index($(e.target)) + 1; |
| var rows = $('> tbody > tr', table); |
|
|
| if (currentNthChild === nthChild) { |
| return; |
| } |
|
|
| currentNthChild = nthChild; |
|
|
| rows.children("td:nth-child(" + (nthChild) + ")").addClass('highlight'); |
| self.repositionRowActions($this.parent('tr')); |
| }); |
|
|
| $(domElem).on('mouseleave', 'td', function(event) { |
| var $this = $(event.target); |
| var table = $this.closest('table'); |
| var $parentTr = $this.parent('tr'); |
| var tr = $parentTr.children(); |
| var nthChild = $parentTr.children().index($this); |
| var targetTd = $(event.relatedTarget).closest('td'); |
| var nthChildTarget = targetTd.parent('tr').children().index(targetTd); |
|
|
| if (nthChild == nthChildTarget) { |
| return; |
| } |
|
|
| currentNthChild = null; |
|
|
| var rows = $('tr', table); |
| rows.find("td:nth-child(" + (nthChild + 1) + ")").removeClass('highlight'); |
| }); |
| }, |
|
|
| getComparisonIdSubtables: function ($row) { |
| if ($row.is('.parentComparisonRow')) { |
| var comparisonRows = $row.nextUntil('.parentComparisonRow').filter('.comparisonRow'); |
|
|
| var comparisonIdSubtables = {}; |
| comparisonRows.each(function () { |
| var comparisonSeriesIndex = +$(this).data('comparison-series'); |
| comparisonIdSubtables[comparisonSeriesIndex] = $(this).data('idsubtable'); |
| }); |
|
|
| return JSON.stringify(comparisonIdSubtables); |
| } |
| return undefined; |
| }, |
|
|
| |
| handleSubDataTable: function (domElem) { |
| var self = this; |
| |
| self.numberOfSubtables = $('tr.subDataTable', domElem) |
| .click( |
| function () { |
| |
| var idSubTable = $(this).attr('id'); |
| var divIdToReplaceWithSubTable = 'subDataTable_' + idSubTable; |
|
|
| |
| if (typeof self.loadedSubDataTable[divIdToReplaceWithSubTable] == "undefined") { |
| var numberOfColumns = $(this).closest('table').find('thead tr').first().children().length; |
|
|
| var $insertAfter = $(this).nextUntil(':not(.comparePeriod):not(.comparisonRow)').last(); |
| if (!$insertAfter.length) { |
| $insertAfter = $(this); |
| } |
|
|
| |
| |
| var newRow = $insertAfter.after( |
| '<tr class="subDataTableContainer">' + |
| '<td colspan="' + numberOfColumns + '" class="cellSubDataTable">' + |
| '<div id="' + divIdToReplaceWithSubTable + '">' + |
| '<span class="loadingPiwik" style="display:inline"><span class="matomo-loader"><span></span><span></span><span></span></span>' + _pk_translate('General_Loading') + '</span>' + |
| '</div>' + |
| '</td>' + |
| '</tr>' |
| ); |
|
|
| piwikHelper.lazyScrollTo(newRow); |
|
|
| var savedActionVariable = self.param.action; |
|
|
| |
| var filtersToRestore = self.resetAllFilters(); |
| |
| self.param.enable_filter_excludelowpop = filtersToRestore.enable_filter_excludelowpop; |
|
|
| self.param.idSubtable = idSubTable; |
| self.param.action = self.props.subtable_controller_action; |
|
|
| delete self.param.totalRows; |
|
|
| var extraParams = {}; |
| extraParams.comparisonIdSubtables = self.getComparisonIdSubtables($(this)); |
|
|
| self.reloadAjaxDataTable(false, function(response) { |
| self.dataTableLoaded(response, divIdToReplaceWithSubTable); |
| }, extraParams); |
|
|
| self.param.action = savedActionVariable; |
| delete self.param.idSubtable; |
| self.restoreAllFilters(filtersToRestore); |
|
|
| self.loadedSubDataTable[divIdToReplaceWithSubTable] = true; |
|
|
| |
| |
| $(this).find('div.dataTableRowActions').hide(); |
| } else { |
| var $toToggle = $(this).nextUntil('.subDataTableContainer').last(); |
| $toToggle = $toToggle.length ? $toToggle : $(this); |
| $toToggle.next().toggle(); |
| } |
|
|
| $(this).toggleClass('expanded'); |
| self.repositionRowActions($(this)); |
| } |
| ).length; |
| }, |
|
|
| |
| handleColumnDocumentation: function (domElem) { |
| if (this.isDashboard()) { |
| |
| |
| return; |
| } |
|
|
| $('th:has(.columnDocumentation)', domElem).each(function () { |
| var th = $(this); |
| var tooltip = th.find('.columnDocumentation'); |
|
|
| tooltip.next().hover(function () { |
| var left = (-1 * tooltip.outerWidth() / 2) + th.width() / 2; |
| var top = -1 * tooltip.outerHeight(); |
| var thPos = th.position(); |
| var distance = tooltip.parent().offset().top; |
| var scroller = tooltip.closest('.dataTableScroller'); |
|
|
| var thPosTop = 0; |
|
|
| if (thPos && thPos.top) { |
| thPosTop = thPos.top; |
| } |
|
|
| |
| |
| top = top + thPosTop; |
|
|
| if ($(window).scrollTop() >= distance - 100 || scroller.css('overflow-x')==='scroll') { |
| top = tooltip.parent().outerHeight() |
| } |
|
|
| if (!th.next().length) { |
| left = (-1 * tooltip.outerWidth()) + th.width() + |
| parseInt(th.css('padding-right'), 10); |
| } |
|
|
| if (th.offset().top + top < 0) { |
| top = thPosTop + th.outerHeight(); |
| } |
|
|
| tooltip.css({ |
| marginLeft: left, |
| marginTop: top, |
| top: 0 |
| }); |
|
|
| $(".dataTable thead").addClass('with-z-index'); |
| tooltip.stop(true, true).fadeIn(250); |
| }, |
| function () { |
| $(this).prev().stop(true, true).fadeOut(250); |
| $(".dataTable thead").removeClass('with-z-index'); |
| }); |
| }); |
| }, |
|
|
| handleRowActions: function (domElem) { |
| this.doHandleRowActions(domElem.find('table > tbody > tr')); |
| }, |
|
|
| handleCellTooltips: function(domElem) { |
| domElem.find('span.cell-tooltip').tooltip({ |
| track: true, |
| items: 'span', |
| content: function() { |
| return $(this).parent().data('tooltip'); |
| }, |
| show: false, |
| hide: false, |
| tooltipClass: 'small' |
| }); |
| domElem.find('span.ratio').tooltip({ |
| track: true, |
| content: function() { |
| var title = $(this).attr('title'); |
| return piwikHelper.escape(title.replace(/\n/g, '<br />')); |
| }, |
| show: {delay: 700, duration: 200}, |
| hide: false |
| }) |
| }, |
|
|
| handleRelatedReports: function (domElem) { |
| var self = this, |
| hideShowRelatedReports = function (thisReport) { |
| $('span', $(thisReport).parent().parent()).each(function () { |
| if (thisReport == this) |
| $(this).hide(); |
| else |
| $(this).show(); |
| }); |
| }, |
| |
| thisReport = $('.datatableRelatedReports span:hidden', domElem)[0]; |
|
|
| function replaceReportTitleAndHelp(domElem, relatedReportName) { |
| if (!domElem || !domElem.length) { |
| return; |
| } |
|
|
| var $title = ''; |
| var $headline = domElem.prev('h2'); |
|
|
| if ($headline.length) { |
| $title = $headline.find('.title:not(.ng-hide)'); |
| } else { |
| var $widget = domElem.parents('.widget'); |
| if ($widget.length) { |
| $title = $widget.find('.widgetName > span'); |
| } |
| } |
|
|
| if ($title.length) { |
| $title.text(relatedReportName); |
|
|
| var scope = $title.scope(); |
|
|
| if (scope) { |
| var $doc = domElem.find('.reportDocumentation'); |
| if ($doc.length) { |
| |
| |
| |
| var helpParagraph = $doc.attr('data-content'); |
|
|
| if (helpParagraph.length) { |
| helpParagraph.html(window.vueSanitize(helpParagraph)); |
| } |
|
|
| scope.inlineHelp = $.trim($doc.html()); |
|
|
| } |
| scope.featureName = $.trim(relatedReportName); |
| setTimeout(function (){ |
| scope.$apply(); |
| }, 1); |
| } |
| } |
| } |
|
|
| hideShowRelatedReports(thisReport); |
|
|
| var relatedReports = $('.datatableRelatedReports span', domElem); |
|
|
| if (!relatedReports.length) { |
| $('.datatableRelatedReports', domElem).hide(); |
| } |
|
|
| relatedReports.each(function () { |
| var clicked = this; |
| $(this).unbind('click').click(function (e) { |
| var $this = $(this); |
| var url = $this.attr('href'); |
|
|
| |
| self.resetAllFilters(); |
| var newParams = broadcast.getValuesFromUrl(url); |
| var isSecondaryDimensionReport = self.param.module === newParams.module && self.param.action === newParams.action && newParams.secondaryDimension; |
|
|
| for (var key in newParams) { |
| self.param[key] = decodeURIComponent(newParams[key]); |
| } |
|
|
| delete self.param.pivotBy; |
| delete self.param.pivotByColumn; |
|
|
| var relatedReportName = $this.text(); |
|
|
| |
| self.reloadAjaxDataTable(true, (function (relatedReportName, isSecondaryDimensionReport) { |
|
|
| return function (newReport) { |
| var newDomElem = self.dataTableLoaded(newReport, self.workingDivId); |
| hideShowRelatedReports(clicked); |
| if (!isSecondaryDimensionReport) { |
| replaceReportTitleAndHelp(newDomElem, relatedReportName); |
| } |
| } |
| })(relatedReportName, isSecondaryDimensionReport)); |
| }); |
| }); |
| }, |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| handleTriggeredEvents: function (domElem) { |
| var self = this; |
|
|
| |
| $(domElem).bind('reload', function (e, paramOverride) { |
| paramOverride = paramOverride || {}; |
| for (var name in paramOverride) { |
| self.param[name] = paramOverride[name]; |
| } |
|
|
| self.reloadAjaxDataTable(true); |
| }); |
| }, |
|
|
| handleSummaryRow: function (domElem) { |
| var details = _pk_translate('General_LearnMore', [' (<a href="' |
| + _pk_externalRawLink('https://matomo.org/faq/how-to/faq_54/') + '" rel="noreferrer noopener" target="_blank">', '</a>)']); |
|
|
| domElem.find('tr.summaryRow').each(function () { |
| var labelSpan = $(this).find('.label .value').filter(function(index, elem){ |
| return $(elem).text() != '-'; |
| }).last(); |
| var defaultLabel = labelSpan.text(); |
|
|
| $(this).hover(function() { |
| labelSpan.html(piwikHelper.htmlEntities(defaultLabel) + details); |
| }, |
| function() { |
| labelSpan.text(defaultLabel); |
| }); |
| }); |
| }, |
|
|
| |
| doHandleRowActions: function (trs) { |
| if (!trs || !trs.length || !trs[0]) { |
| return; |
| } |
| var parent = $(trs[0]).closest('table'); |
|
|
| var self = this; |
|
|
| var merged = $.extend({}, self.param, self.props); |
| var availableActionsForReport = DataTable_RowActions_Registry.getAvailableActionsForReport(merged); |
|
|
| if (availableActionsForReport.length == 0) { |
| return; |
| } |
|
|
| var actionInstances = {}; |
| for (var i = 0; i < availableActionsForReport.length; i++) { |
| var action = availableActionsForReport[i]; |
| actionInstances[action.name] = action.createInstance(self); |
| } |
|
|
| var useTouchEvent = false; |
| var listenEvent = 'mouseenter'; |
| var userAgent = String(navigator.userAgent).toLowerCase(); |
| if (userAgent.match(/(iPod|iPhone|iPad|Android|IEMobile|Windows Phone)/i)) { |
| useTouchEvent = true; |
| listenEvent = 'click'; |
| } |
|
|
| parent.on(listenEvent, 'tr:not(.subDataTableContainer)', function () { |
| var tr = this; |
| var $tr = $(tr); |
| var td = $tr.find('td.label:last'); |
|
|
| |
| for (var i = 0; i < availableActionsForReport.length; i++) { |
| var action = availableActionsForReport[i]; |
| actionInstances[action.name].initTr($tr); |
| } |
|
|
| |
| td.css('minWidth', $tr.is('.comparisonRow') ? '117px' : '145px'); |
|
|
| if ($(this).is('.parentComparisonRow,.comparePeriod').length) { |
| return; |
| } |
|
|
| if (useTouchEvent && tr.actionsDom && tr.actionsDom.prop('rowActionsVisible')) { |
| tr.actionsDom.prop('rowActionsVisible', false); |
| tr.actionsDom.hide(); |
| return; |
| } |
|
|
| if (!tr.actionsDom) { |
| |
| tr.actionsDom = self.createRowActions(availableActionsForReport, $tr, actionInstances); |
| td.prepend(tr.actionsDom); |
| } |
|
|
| |
| self.repositionRowActions($tr); |
| if ($(window).width() >= 600 || useTouchEvent) { |
| tr.actionsDom.show(); |
| } |
|
|
| if (useTouchEvent) { |
| tr.actionsDom.prop('rowActionsVisible', true); |
| } |
| }); |
| if (!useTouchEvent) { |
| parent.on('mouseleave', 'tr', function () { |
| var tr = this; |
| if (tr.actionsDom) { |
| tr.actionsDom.hide(); |
| } |
| }); |
| } |
| }, |
|
|
| createRowActions: function (availableActionsForReport, tr, actionInstances) { |
| var container = $(document.createElement('div')).addClass('dataTableRowActions'); |
|
|
| for (var i = availableActionsForReport.length - 1; i >= 0; i--) { |
| var action = availableActionsForReport[i]; |
|
|
| if (!action.isAvailableOnRow(this.param, tr)) { |
| continue; |
| } |
|
|
| var actionEl = $(document.createElement('a')).attr({href: '#'}).addClass('action' + action.name); |
|
|
| if (action.dataTableIcon.indexOf('icon-') === 0) { |
| actionEl.append($(document.createElement('span')).addClass(action.dataTableIcon + ' rowActionIcon')); |
| } else { |
| actionEl.append($(document.createElement('img')).attr({src: action.dataTableIcon})); |
| } |
|
|
| container.append(actionEl); |
|
|
| if (i == availableActionsForReport.length - 1) { |
| actionEl.addClass('leftmost'); |
| } |
| if (i == 0) { |
| actionEl.addClass('rightmost'); |
| } |
|
|
| actionEl.click((function (action, el) { |
| return function (e) { |
| $(this).blur().tooltip('close'); |
| container.hide(); |
| if (typeof actionInstances[action.name].onClick == 'function') { |
| return actionInstances[action.name].onClick(el, tr, e); |
| } |
| actionInstances[action.name].trigger(tr, e); |
| return false; |
| } |
| })(action, actionEl)); |
|
|
| if (typeof action.dataTableIconHover != 'undefined') { |
| actionEl.append($(document.createElement('img')).attr({src: action.dataTableIconHover}).hide()); |
|
|
| actionEl.hover(function () { |
| var img = $(this).find('img'); |
| img.eq(0).hide(); |
| img.eq(1).show(); |
| }, |
| function () { |
| var img = $(this).find('img'); |
| img.eq(1).hide(); |
| img.eq(0).show(); |
| }); |
| } |
|
|
| if (typeof action.dataTableIconTooltip != 'undefined') { |
| actionEl.tooltip({ |
| track: true, |
| items: 'a', |
| content: '<h3>'+action.dataTableIconTooltip[0]+'</h3>'+action.dataTableIconTooltip[1], |
| tooltipClass: 'rowActionTooltip', |
| |
| |
| open: function() { |
| var tooltip = $(this).parents('.matomo-widget').tooltip('instance'); |
| if (tooltip) { |
| tooltip.disable(); |
| } |
| }, |
| close: function() { |
| var tooltip = $(this).parents('.matomo-widget').tooltip('instance'); |
| if (tooltip) { |
| tooltip.enable(); |
| } |
| }, |
| show: false, |
| hide: false |
| }); |
| } |
| } |
|
|
| return container; |
| }, |
|
|
| repositionRowActions: function (tr) { |
| if (!tr) { |
| return; |
| } |
|
|
| var td = tr.find('td.label:last'); |
| var actions = tr.find('div.dataTableRowActions'); |
|
|
| if (!actions) { |
| return; |
| } |
|
|
| actions.height(tr.innerHeight() - 6); |
| actions.css('marginLeft', (td.width() - 3 - actions.outerWidth()) + 'px'); |
| }, |
|
|
| _findReportHeader: function (domElem) { |
| var h2 = false; |
| if (domElem.prev().is('h2')) { |
| h2 = domElem.prev(); |
| } |
| else if (this.param.viewDataTable == 'tableGoals') { |
| h2 = $('#titleGoalsByDimension'); |
| } |
| else if ($('h2', domElem)) { |
| h2 = $('h2', domElem); |
| } |
| return h2; |
| }, |
|
|
| _createDivId: function () { |
| return 'dataTable_' + this._controlId; |
| } |
| }); |
|
|
| |
| var switchToHtmlTable = function (dataTable, viewDataTable) { |
| |
| |
|
|
| dataTable.param.viewDataTable = viewDataTable; |
|
|
| |
| delete dataTable.param.enable_filter_excludelowpop; |
| delete dataTable.param.filter_sort_column; |
| delete dataTable.param.filter_sort_order; |
| delete dataTable.param.columns; |
| delete dataTable.param.totals; |
| dataTable.reloadAjaxDataTable(); |
| dataTable.notifyWidgetParametersChange(dataTable.$element, {viewDataTable: viewDataTable}); |
| }; |
|
|
| var switchToEcommerceView = function (dataTable, viewDataTable) { |
| if (viewDataTable == 'ecommerceOrder') { |
| dataTable.param.abandonedCarts = '0'; |
| } else { |
| dataTable.param.abandonedCarts = '1'; |
| } |
|
|
| var viewDataTable = dataTable.param.viewDataTable; |
| if (viewDataTable == 'ecommerceOrder' || viewDataTable == 'ecommerceAbandonedCart') { |
| viewDataTable = 'table'; |
| } |
|
|
| switchToHtmlTable(dataTable, viewDataTable); |
| }; |
|
|
| DataTable.registerFooterIconHandler('table', switchToHtmlTable); |
| DataTable.registerFooterIconHandler('tableAllColumns', switchToHtmlTable); |
| DataTable.registerFooterIconHandler('tableGoals', switchToHtmlTable); |
| DataTable.registerFooterIconHandler('ecommerceOrder', switchToEcommerceView); |
| DataTable.registerFooterIconHandler('ecommerceAbandonedCart', switchToEcommerceView); |
|
|
| |
| DataTable.switchToGraph = function (dataTable, viewDataTable) { |
| var filters = dataTable.resetAllFilters(); |
| dataTable.param.flat = filters.flat; |
| dataTable.param.keep_totals_row = filters.keep_totals_row; |
| dataTable.param.columns = filters.columns; |
|
|
| dataTable.param.viewDataTable = viewDataTable; |
| dataTable.reloadAjaxDataTable(); |
| dataTable.notifyWidgetParametersChange(dataTable.$element, {viewDataTable: viewDataTable}); |
| }; |
|
|
| DataTable.registerFooterIconHandler('cloud', DataTable.switchToGraph); |
|
|
| exports.DataTable = DataTable; |
|
|
| })(jQuery, require); |
|
|