update Piwik to version 2.16 (fixes #91)
This commit is contained in:
parent
296343bf3b
commit
d885a4baa9
5833 changed files with 418860 additions and 226988 deletions
|
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* Piwik - Web Analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -54,9 +54,9 @@ var broadcast = {
|
|||
}
|
||||
broadcast._isInit = true;
|
||||
|
||||
// Initialize history plugin.
|
||||
// The callback is called at once by present location.hash
|
||||
$.history.init(broadcast.pageload, {unescape: true});
|
||||
angular.element(document).injector().invoke(function (historyService) {
|
||||
historyService.init();
|
||||
});
|
||||
|
||||
if(noLoadingMessage != true) {
|
||||
piwikHelper.showAjaxLoading();
|
||||
|
|
@ -151,7 +151,7 @@ var broadcast = {
|
|||
var handlerName = popoverParamParts[0];
|
||||
popoverParamParts.shift();
|
||||
var param = popoverParamParts.join(':');
|
||||
if (typeof broadcast.popoverHandlers[handlerName] != 'undefined') {
|
||||
if (typeof broadcast.popoverHandlers[handlerName] != 'undefined' && !broadcast.isLoginPage()) {
|
||||
broadcast.popoverHandlers[handlerName](param);
|
||||
}
|
||||
}
|
||||
|
|
@ -164,6 +164,14 @@ var broadcast = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns if the current page is the login page
|
||||
* @return {boolean}
|
||||
*/
|
||||
isLoginPage: function() {
|
||||
return !!$('body#loginPage').length;
|
||||
},
|
||||
|
||||
/**
|
||||
* propagateAjax -- update hash values then make ajax calls.
|
||||
* example :
|
||||
|
|
@ -197,7 +205,7 @@ var broadcast = {
|
|||
// if the module is not 'Goals', we specifically unset the 'idGoal' parameter
|
||||
// this is to ensure that the URLs are clean (and that clicks on graphs work as expected - they are broken with the extra parameter)
|
||||
var action = broadcast.getParamValue('action', currentHashStr);
|
||||
if (action != 'goalReport' && action != 'ecommerceReport') {
|
||||
if (action != 'goalReport' && action != 'ecommerceReport' && action != 'products' && action != 'sales') {
|
||||
currentHashStr = broadcast.updateParamValue('idGoal=', currentHashStr);
|
||||
}
|
||||
// unset idDashboard if use doesn't display a dashboard
|
||||
|
|
@ -206,15 +214,21 @@ var broadcast = {
|
|||
currentHashStr = broadcast.updateParamValue('idDashboard=', currentHashStr);
|
||||
}
|
||||
|
||||
if (module != 'CustomDimensions') {
|
||||
currentHashStr = broadcast.updateParamValue('idDimension=', currentHashStr);
|
||||
}
|
||||
|
||||
if (disableHistory) {
|
||||
var newLocation = window.location.href.split('#')[0] + '#' + currentHashStr;
|
||||
var newLocation = window.location.href.split('#')[0] + '#?' + currentHashStr;
|
||||
// window.location.replace changes the current url without pushing it on the browser's history stack
|
||||
window.location.replace(newLocation);
|
||||
}
|
||||
else {
|
||||
// Let history know about this new Hash and load it.
|
||||
broadcast.forceReload = true;
|
||||
$.history.load(currentHashStr);
|
||||
angular.element(document).injector().invoke(function (historyService) {
|
||||
historyService.load(currentHashStr);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -324,17 +338,17 @@ var broadcast = {
|
|||
/**
|
||||
* Loads a popover by adding a 'popover' query parameter to the current URL and
|
||||
* indirectly executing the popover handler.
|
||||
*
|
||||
*
|
||||
* This function should be called to open popovers that can be opened by URL alone.
|
||||
* That is, if you want users to be able to copy-paste the URL displayed when a popover
|
||||
* is open into a new browser window/tab and have the same popover open, you should
|
||||
* call this function.
|
||||
*
|
||||
*
|
||||
* In order for this function to open a popover, there must be a popover handler
|
||||
* associated with handlerName. To associate one, call broadcast.addPopoverHandler.
|
||||
*
|
||||
*
|
||||
* @param {String} handlerName The name of the popover handler.
|
||||
* @param {String} value The String value that should be passed to the popover
|
||||
* @param {String} value The String value that should be passed to the popover
|
||||
* handler.
|
||||
*/
|
||||
propagateNewPopoverParameter: function (handlerName, value) {
|
||||
|
|
@ -370,14 +384,16 @@ var broadcast = {
|
|||
}
|
||||
|
||||
broadcast.forceReload = false;
|
||||
$.history.load(newHash);
|
||||
angular.element(document).injector().invoke(function (historyService) {
|
||||
historyService.load(newHash);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a handler for the 'popover' query parameter.
|
||||
*
|
||||
*
|
||||
* @see broadcast#propagateNewPopoverParameter
|
||||
*
|
||||
*
|
||||
* @param {String} handlerName The handler name, eg, 'visitorProfile'. Should identify
|
||||
* the popover that the callback will open up.
|
||||
* @param {Function} callback This function should open the popover. It should take
|
||||
|
|
@ -397,11 +413,31 @@ var broadcast = {
|
|||
*/
|
||||
loadAjaxContent: function (urlAjax) {
|
||||
if (typeof piwikMenu !== 'undefined') {
|
||||
piwikMenu.activateMenu(
|
||||
broadcast.getParamValue('module', urlAjax),
|
||||
broadcast.getParamValue('action', urlAjax),
|
||||
broadcast.getParamValue('idGoal', urlAjax) || broadcast.getParamValue('idDashboard', urlAjax)
|
||||
);
|
||||
// we have to use a $timeout since menu groups are displayed using an angular directive, and on initial
|
||||
// page load, the dropdown will not be completely rendered at this point. using 2 $timeouts (to push
|
||||
// the menu activation logic to the end of the event queue twice), seems to work.
|
||||
angular.element(document).injector().invoke(function ($timeout) {
|
||||
$timeout(function () {
|
||||
$timeout(function () {
|
||||
piwikMenu.activateMenu(
|
||||
broadcast.getParamValue('module', urlAjax),
|
||||
broadcast.getParamValue('action', urlAjax),
|
||||
{
|
||||
idGoal: broadcast.getParamValue('idGoal', urlAjax),
|
||||
idDashboard: broadcast.getParamValue('idDashboard', urlAjax),
|
||||
idDimension: broadcast.getParamValue('idDimension', urlAjax)
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if(broadcast.getParamValue('module', urlAjax) == 'API') {
|
||||
broadcast.lastUrlRequested = null;
|
||||
$('#content').html("Loading content from the API and displaying it within Piwik is not allowed.");
|
||||
piwikHelper.hideAjaxLoading();
|
||||
return false;
|
||||
}
|
||||
|
||||
piwikHelper.hideAjaxError('loadingError');
|
||||
|
|
@ -411,7 +447,24 @@ var broadcast = {
|
|||
|
||||
urlAjax = urlAjax.match(/^\?/) ? urlAjax : "?" + urlAjax;
|
||||
broadcast.lastUrlRequested = urlAjax;
|
||||
function sectionLoaded(content) {
|
||||
|
||||
function sectionLoaded(content, status, request) {
|
||||
if (request) {
|
||||
var responseHeader = request.getResponseHeader('Content-Type');
|
||||
if (responseHeader && 0 <= responseHeader.toLowerCase().indexOf('json')) {
|
||||
var message = 'JSON cannot be displayed for';
|
||||
if (this.getParams && this.getParams['module']) {
|
||||
message += ' module=' + this.getParams['module'];
|
||||
}
|
||||
if (this.getParams && this.getParams['action']) {
|
||||
message += ' action=' + this.getParams['action'];
|
||||
}
|
||||
$('#content').text(message);
|
||||
piwikHelper.hideAjaxLoading();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if content is whole HTML document, do not show it, otherwise recursive page load could occur
|
||||
var htmlDocType = '<!DOCTYPE';
|
||||
if (content.substring(0, htmlDocType.length) == htmlDocType) {
|
||||
|
|
@ -437,6 +490,9 @@ var broadcast = {
|
|||
|
||||
var ajax = new ajaxHelper();
|
||||
ajax.setUrl(urlAjax);
|
||||
ajax._getDefaultPostParams = function () {
|
||||
return {};
|
||||
};
|
||||
ajax.setErrorCallback(broadcast.customAjaxHandleError);
|
||||
ajax.setCallback(sectionLoaded);
|
||||
ajax.setFormat('html');
|
||||
|
|
@ -454,14 +510,14 @@ var broadcast = {
|
|||
customAjaxHandleError: function (deferred, status) {
|
||||
broadcast.lastUrlRequested = null;
|
||||
|
||||
piwikHelper.hideAjaxLoading();
|
||||
|
||||
// do not display error message if request was aborted
|
||||
if(status == 'abort') {
|
||||
return;
|
||||
}
|
||||
|
||||
$('#loadingError').show();
|
||||
setTimeout( function(){
|
||||
$('#loadingError').fadeOut('slow');
|
||||
}, 2000);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -551,7 +607,6 @@ var broadcast = {
|
|||
return this.extractKeyValuePairsFromQueryString(searchString);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* help to get param value for any given url string with provided param name
|
||||
* if no url is provided, it will get param from current address.
|
||||
|
|
@ -584,7 +639,6 @@ var broadcast = {
|
|||
return broadcast.getParamValue(param, hashStr);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* return value for the requested param, will return the first match.
|
||||
* out side of this class should use getValueFromHash() or getValueFromUrl() instead.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* Piwik - Web Analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -131,55 +131,55 @@
|
|||
stepMonths: 1,
|
||||
// jquery-ui-i18n 1.7.2 lacks some translations, so we use our own
|
||||
dayNamesMin: [
|
||||
_pk_translate('General_DaySu'),
|
||||
_pk_translate('General_DayMo'),
|
||||
_pk_translate('General_DayTu'),
|
||||
_pk_translate('General_DayWe'),
|
||||
_pk_translate('General_DayTh'),
|
||||
_pk_translate('General_DayFr'),
|
||||
_pk_translate('General_DaySa')],
|
||||
_pk_translate('Intl_Day_Min_StandAlone_7'),
|
||||
_pk_translate('Intl_Day_Min_StandAlone_1'),
|
||||
_pk_translate('Intl_Day_Min_StandAlone_2'),
|
||||
_pk_translate('Intl_Day_Min_StandAlone_3'),
|
||||
_pk_translate('Intl_Day_Min_StandAlone_4'),
|
||||
_pk_translate('Intl_Day_Min_StandAlone_5'),
|
||||
_pk_translate('Intl_Day_Min_StandAlone_6')],
|
||||
dayNamesShort: [
|
||||
_pk_translate('General_ShortDay_7'), // start with sunday
|
||||
_pk_translate('General_ShortDay_1'),
|
||||
_pk_translate('General_ShortDay_2'),
|
||||
_pk_translate('General_ShortDay_3'),
|
||||
_pk_translate('General_ShortDay_4'),
|
||||
_pk_translate('General_ShortDay_5'),
|
||||
_pk_translate('General_ShortDay_6')],
|
||||
_pk_translate('Intl_Day_Short_StandAlone_7'), // start with sunday
|
||||
_pk_translate('Intl_Day_Short_StandAlone_1'),
|
||||
_pk_translate('Intl_Day_Short_StandAlone_2'),
|
||||
_pk_translate('Intl_Day_Short_StandAlone_3'),
|
||||
_pk_translate('Intl_Day_Short_StandAlone_4'),
|
||||
_pk_translate('Intl_Day_Short_StandAlone_5'),
|
||||
_pk_translate('Intl_Day_Short_StandAlone_6')],
|
||||
dayNames: [
|
||||
_pk_translate('General_LongDay_7'), // start with sunday
|
||||
_pk_translate('General_LongDay_1'),
|
||||
_pk_translate('General_LongDay_2'),
|
||||
_pk_translate('General_LongDay_3'),
|
||||
_pk_translate('General_LongDay_4'),
|
||||
_pk_translate('General_LongDay_5'),
|
||||
_pk_translate('General_LongDay_6')],
|
||||
_pk_translate('Intl_Day_Long_StandAlone_7'), // start with sunday
|
||||
_pk_translate('Intl_Day_Long_StandAlone_1'),
|
||||
_pk_translate('Intl_Day_Long_StandAlone_2'),
|
||||
_pk_translate('Intl_Day_Long_StandAlone_3'),
|
||||
_pk_translate('Intl_Day_Long_StandAlone_4'),
|
||||
_pk_translate('Intl_Day_Long_StandAlone_5'),
|
||||
_pk_translate('Intl_Day_Long_StandAlone_6')],
|
||||
monthNamesShort: [
|
||||
_pk_translate('General_ShortMonth_1'),
|
||||
_pk_translate('General_ShortMonth_2'),
|
||||
_pk_translate('General_ShortMonth_3'),
|
||||
_pk_translate('General_ShortMonth_4'),
|
||||
_pk_translate('General_ShortMonth_5'),
|
||||
_pk_translate('General_ShortMonth_6'),
|
||||
_pk_translate('General_ShortMonth_7'),
|
||||
_pk_translate('General_ShortMonth_8'),
|
||||
_pk_translate('General_ShortMonth_9'),
|
||||
_pk_translate('General_ShortMonth_10'),
|
||||
_pk_translate('General_ShortMonth_11'),
|
||||
_pk_translate('General_ShortMonth_12')],
|
||||
_pk_translate('Intl_Month_Short_StandAlone_1'),
|
||||
_pk_translate('Intl_Month_Short_StandAlone_2'),
|
||||
_pk_translate('Intl_Month_Short_StandAlone_3'),
|
||||
_pk_translate('Intl_Month_Short_StandAlone_4'),
|
||||
_pk_translate('Intl_Month_Short_StandAlone_5'),
|
||||
_pk_translate('Intl_Month_Short_StandAlone_6'),
|
||||
_pk_translate('Intl_Month_Short_StandAlone_7'),
|
||||
_pk_translate('Intl_Month_Short_StandAlone_8'),
|
||||
_pk_translate('Intl_Month_Short_StandAlone_9'),
|
||||
_pk_translate('Intl_Month_Short_StandAlone_10'),
|
||||
_pk_translate('Intl_Month_Short_StandAlone_11'),
|
||||
_pk_translate('Intl_Month_Short_StandAlone_12')],
|
||||
monthNames: [
|
||||
_pk_translate('General_LongMonth_1'),
|
||||
_pk_translate('General_LongMonth_2'),
|
||||
_pk_translate('General_LongMonth_3'),
|
||||
_pk_translate('General_LongMonth_4'),
|
||||
_pk_translate('General_LongMonth_5'),
|
||||
_pk_translate('General_LongMonth_6'),
|
||||
_pk_translate('General_LongMonth_7'),
|
||||
_pk_translate('General_LongMonth_8'),
|
||||
_pk_translate('General_LongMonth_9'),
|
||||
_pk_translate('General_LongMonth_10'),
|
||||
_pk_translate('General_LongMonth_11'),
|
||||
_pk_translate('General_LongMonth_12')]
|
||||
_pk_translate('Intl_Month_Long_StandAlone_1'),
|
||||
_pk_translate('Intl_Month_Long_StandAlone_2'),
|
||||
_pk_translate('Intl_Month_Long_StandAlone_3'),
|
||||
_pk_translate('Intl_Month_Long_StandAlone_4'),
|
||||
_pk_translate('Intl_Month_Long_StandAlone_5'),
|
||||
_pk_translate('Intl_Month_Long_StandAlone_6'),
|
||||
_pk_translate('Intl_Month_Long_StandAlone_7'),
|
||||
_pk_translate('Intl_Month_Long_StandAlone_8'),
|
||||
_pk_translate('Intl_Month_Long_StandAlone_9'),
|
||||
_pk_translate('Intl_Month_Long_StandAlone_10'),
|
||||
_pk_translate('Intl_Month_Long_StandAlone_11'),
|
||||
_pk_translate('Intl_Month_Long_StandAlone_12')]
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -294,7 +294,6 @@
|
|||
var togglePeriodPickers = function (showSingle) {
|
||||
$('#periodString').find('.period-date').toggle(showSingle);
|
||||
$('#periodString').find('.period-range').toggle(!showSingle);
|
||||
$('#calendarRangeApply').toggle(!showSingle);
|
||||
};
|
||||
|
||||
//
|
||||
|
|
@ -354,12 +353,25 @@
|
|||
}
|
||||
});
|
||||
|
||||
// Hack to get around firefox bug. When double clicking a label in firefox, the 'click'
|
||||
// event of its associated input will not be fired twice. We want to change the period
|
||||
// if clicking the select period's label OR input, so we catch the click event on the
|
||||
// label & the input.
|
||||
var reloading = false;
|
||||
var changePeriodOnClick = function (periodInput) {
|
||||
|
||||
var changePeriodWithPageReload = function (periodInput) {
|
||||
var url = periodInput.val(),
|
||||
period = broadcast.getValueFromUrl('period', url);
|
||||
|
||||
// if clicking on the selected period, change the period but not the date
|
||||
if (period != 'range' && !reloading) {
|
||||
// only reload if current period is different from selected
|
||||
reloading = true;
|
||||
selectedPeriod = period;
|
||||
updateDate(piwik.currentDateString);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
var changePeriodOnClickIfPeriodChanged = function (periodInput) {
|
||||
if (reloading) // if a click event resulted in reloading, don't reload again
|
||||
{
|
||||
return;
|
||||
|
|
@ -371,29 +383,62 @@
|
|||
// if clicking on the selected period, change the period but not the date
|
||||
if (selectedPeriod == period && selectedPeriod != 'range') {
|
||||
// only reload if current period is different from selected
|
||||
if (piwik.period != selectedPeriod && !reloading) {
|
||||
reloading = true;
|
||||
selectedPeriod = period;
|
||||
updateDate(piwik.currentDateString);
|
||||
if (piwik.period != selectedPeriod) {
|
||||
return changePeriodWithPageReload(periodInput);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
$("#otherPeriods").find("label").on('click', function (e) {
|
||||
$("#otherPeriods").find("label,input").on('dblclick', function (e) {
|
||||
var id = $(e.target).attr('for');
|
||||
changePeriodOnClick($('#' + id));
|
||||
changePeriodOnClickIfPeriodChanged($('#' + id));
|
||||
});
|
||||
|
||||
$("#otherPeriods").find("label,input").on('dblclick', function (e) {
|
||||
var id = $(e.target).attr('for');
|
||||
changePeriodOnClickIfPeriodChanged($('#' + id));
|
||||
});
|
||||
|
||||
// Apply date range button will reload the page with the selected range
|
||||
$('#calendarApply')
|
||||
.on('click', function () {
|
||||
var $selectedPeriod = $('#periodMore [name=period]:checked');
|
||||
|
||||
if (!$selectedPeriod.is('#period_id_range')) {
|
||||
changePeriodWithPageReload($selectedPeriod);
|
||||
return true;
|
||||
}
|
||||
|
||||
var dateFrom = $('#inputCalendarFrom').val(),
|
||||
dateTo = $('#inputCalendarTo').val(),
|
||||
oDateFrom = $.datepicker.parseDate('yy-mm-dd', dateFrom),
|
||||
oDateTo = $.datepicker.parseDate('yy-mm-dd', dateTo);
|
||||
|
||||
if (!isValidDate(oDateFrom)
|
||||
|| !isValidDate(oDateTo)
|
||||
|| oDateFrom > oDateTo) {
|
||||
$('#alert').find('h2').text(_pk_translate('General_InvalidDateRange'));
|
||||
piwikHelper.modalConfirm('#alert', {});
|
||||
return false;
|
||||
}
|
||||
piwikHelper.showAjaxLoading('ajaxLoadingCalendar');
|
||||
broadcast.propagateNewPage('period=range&date=' + dateFrom + ',' + dateTo);
|
||||
})
|
||||
.show();
|
||||
|
||||
|
||||
|
||||
// when non-range period is clicked, change the period & refresh the date picker
|
||||
$("#otherPeriods").find("input").on('click', function (e) {
|
||||
var request_URL = $(e.target).val(),
|
||||
period = broadcast.getValueFromUrl('period', request_URL),
|
||||
lastPeriod = selectedPeriod;
|
||||
|
||||
if (changePeriodOnClick($(e.target))) {
|
||||
if (changePeriodOnClickIfPeriodChanged($(e.target))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -444,21 +489,6 @@
|
|||
toggleMonthDropdown(selectedPeriod == 'year');
|
||||
});
|
||||
|
||||
// reset date/period when opening calendar
|
||||
$("#periodString").on('click', "#date,.calendar-icon", function () {
|
||||
var periodMore = $("#periodMore").toggle();
|
||||
if (periodMore.is(":visible")) {
|
||||
periodMore.find(".ui-state-highlight").removeClass('ui-state-highlight');
|
||||
}
|
||||
});
|
||||
|
||||
$('body').on('click', function(e) {
|
||||
var target = $(e.target);
|
||||
if (target.closest('html').length && !target.closest('#periodString').length && !target.is('option') && $("#periodMore").is(":visible")) {
|
||||
$("#periodMore").hide();
|
||||
}
|
||||
});
|
||||
|
||||
function onDateRangeSelect(dateText, inst) {
|
||||
var toOrFrom = inst.id == 'calendarFrom' ? 'From' : 'To';
|
||||
$('#inputCalendar' + toOrFrom).val(dateText);
|
||||
|
|
@ -488,32 +518,9 @@
|
|||
$('#calendarTo').datepicker(options).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', piwik.endDateString));
|
||||
onDateRangeSelect(piwik.endDateString, { "id": "calendarTo" });
|
||||
|
||||
|
||||
// If not called, the first date appears light brown instead of dark brown
|
||||
$('.ui-state-hover').removeClass('ui-state-hover');
|
||||
|
||||
// Apply date range button will reload the page with the selected range
|
||||
$('#calendarRangeApply')
|
||||
.on('click', function () {
|
||||
var request_URL = $(e.target).val();
|
||||
var dateFrom = $('#inputCalendarFrom').val(),
|
||||
dateTo = $('#inputCalendarTo').val(),
|
||||
oDateFrom = $.datepicker.parseDate('yy-mm-dd', dateFrom),
|
||||
oDateTo = $.datepicker.parseDate('yy-mm-dd', dateTo);
|
||||
|
||||
if (!isValidDate(oDateFrom)
|
||||
|| !isValidDate(oDateTo)
|
||||
|| oDateFrom > oDateTo) {
|
||||
$('#alert').find('h2').text(_pk_translate('General_InvalidDateRange'));
|
||||
piwikHelper.modalConfirm('#alert', {});
|
||||
return false;
|
||||
}
|
||||
piwikHelper.showAjaxLoading('ajaxLoadingCalendar');
|
||||
broadcast.propagateNewPage('period=range&date=' + dateFrom + ',' + dateTo);
|
||||
})
|
||||
.show();
|
||||
|
||||
|
||||
// Bind the input fields to update the calendar's date when date is manually changed
|
||||
$('#inputCalendarFrom, #inputCalendarTo')
|
||||
.keyup(function (e) {
|
||||
|
|
@ -526,7 +533,7 @@
|
|||
}
|
||||
$("#calendar" + fromOrTo).datepicker("setDate", newDate);
|
||||
if (e.keyCode == 13) {
|
||||
$('#calendarRangeApply').click();
|
||||
$('#calendarApply').click();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* Piwik - Web Analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -29,28 +29,28 @@
|
|||
* components that don't manage HTML (like jqPlot or sparklines). Such components
|
||||
* can't use CSS colors directly since the colors are used to generate images
|
||||
* or by <canvas> elements.
|
||||
*
|
||||
*
|
||||
* Colors obtained via ColorManager are defined in CSS like this:
|
||||
*
|
||||
*
|
||||
* .my-color-namespace[data-name=color-name] {
|
||||
* color: #fff
|
||||
* }
|
||||
*
|
||||
*
|
||||
* and can be accessed in JavaScript like this:
|
||||
*
|
||||
*
|
||||
* piwik.ColorManager.getColor("my-color-namespace", "color-name");
|
||||
*
|
||||
*
|
||||
* The singleton instance of this class can be accessed via piwik.ColorManager.
|
||||
*/
|
||||
var ColorManager = function () {
|
||||
// empty
|
||||
};
|
||||
|
||||
|
||||
ColorManager.prototype = {
|
||||
|
||||
/**
|
||||
* Returns the color for a namespace and name.
|
||||
*
|
||||
*
|
||||
* @param {String} namespace The string identifier that groups related colors
|
||||
* together. For example, 'sparkline-colors'.
|
||||
* @param {String} name The name of the color to retrieve. For example, 'lineColor'.
|
||||
|
|
@ -63,10 +63,10 @@
|
|||
|
||||
return this._normalizeColor(element.css('color'));
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns the colors for a namespace and a list of names.
|
||||
*
|
||||
*
|
||||
* @param {String} namespace The string identifier that groups related colors
|
||||
* together. For example, 'sparkline-colors'.
|
||||
* @param {Array} names An array of color names to retrieve.
|
||||
|
|
@ -92,7 +92,7 @@
|
|||
|
||||
/**
|
||||
* Returns a color that is N % between two other colors.
|
||||
*
|
||||
*
|
||||
* @param {String|Array} spectrumStart The start color. If percentFromStart is 0, this color will
|
||||
* be returned. Can be either a hex color or RGB array.
|
||||
* It will be converted to an RGB array if a hex color is supplied.
|
||||
|
|
@ -125,7 +125,7 @@
|
|||
/**
|
||||
* Utility function that converts a hex color (ie, #fff or #1a1a1a) to an array of
|
||||
* RGB values.
|
||||
*
|
||||
*
|
||||
* @param {String} hexColor The color to convert.
|
||||
* @return {Array} An array with three integers between 0 and 255.
|
||||
*/
|
||||
|
|
@ -151,7 +151,7 @@
|
|||
|
||||
/**
|
||||
* Utility function that converts an RGB array to a hex color.
|
||||
*
|
||||
*
|
||||
* @param {Array} rgbColor An array with three integers between 0 and 255.
|
||||
* @return {String} The hex color, eg, #1a1a1a.
|
||||
*/
|
||||
|
|
@ -190,7 +190,7 @@
|
|||
}
|
||||
return color;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns the manufactured <div> element used to obtain color data. When
|
||||
* getting color data the class and data-name attribute of this element are
|
||||
|
|
@ -219,7 +219,7 @@
|
|||
return this.transparentColor;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
piwik.ColorManager = new ColorManager();
|
||||
|
||||
}(jQuery));
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* Piwik - Web Analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -27,16 +27,23 @@
|
|||
module: 'CoreHome',
|
||||
action: 'checkForUpdates'
|
||||
}, 'get');
|
||||
|
||||
var $titleElement = $(this);
|
||||
$titleElement.addClass('activityIndicator');
|
||||
ajaxRequest.setCallback(function (response) {
|
||||
headerMessage.fadeOut('slow', function () {
|
||||
response = $(response);
|
||||
|
||||
$titleElement.removeClass('activityIndicator');
|
||||
|
||||
var newVersionAvailable = response.hasClass('header_alert');
|
||||
if (newVersionAvailable) {
|
||||
headerMessage.replaceWith(response);
|
||||
headerMessage.show();
|
||||
}
|
||||
else {
|
||||
headerMessage.html(_pk_translate('CoreHome_YouAreUsingTheLatestVersion')).show();
|
||||
headerMessage.find('.title').html(_pk_translate('CoreHome_YouAreUsingTheLatestVersion'));
|
||||
headerMessage.show();
|
||||
setTimeout(function () {
|
||||
headerMessage.fadeOut('slow', function () {
|
||||
headerMessage.replaceWith(response);
|
||||
|
|
@ -54,7 +61,7 @@
|
|||
// when clicking the header message, show the long message w/o needing to hover
|
||||
headerMessageParent.on('click', '#header_message', function (e) {
|
||||
if (e.target.tagName.toLowerCase() != 'a') {
|
||||
$(this).toggleClass('active');
|
||||
$(this).toggleClass('expanded');
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -142,19 +149,48 @@
|
|||
var widgetUniqueId = widgetParams.module + widgetParams.action;
|
||||
currentWidgetLoading = widgetUniqueId;
|
||||
|
||||
widgetsHelper.loadWidgetAjax(widgetUniqueId, widgetParams, function (response) {
|
||||
var ajaxRequest = new ajaxHelper();
|
||||
ajaxRequest.addParams(widgetParams, 'get');
|
||||
ajaxRequest.setCallback(function (response) {
|
||||
// if the widget that was loaded was not for the latest clicked link, do nothing w/ the response
|
||||
if (widgetUniqueId != currentWidgetLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
loading.hide();
|
||||
report.html($(response)).css('display', 'inline-block');
|
||||
report.css('display', 'inline-block').html($(response));
|
||||
|
||||
// scroll to report
|
||||
piwikHelper.lazyScrollTo(report, 400);
|
||||
});
|
||||
ajaxRequest.setErrorCallback(function (deferred, status) {
|
||||
if (status == 'abort' || !deferred || deferred.status < 400 || deferred.status >= 600) {
|
||||
return;
|
||||
}
|
||||
|
||||
loading.hide();
|
||||
|
||||
var errorMessage = _pk_translate('General_ErrorRequest', ['', '']);
|
||||
if ($('#loadingError').html()) {
|
||||
errorMessage = $('#loadingError').html();
|
||||
}
|
||||
|
||||
report.css('display', 'inline-block').html('<div class="dimensionLoadingError">' + errorMessage + '</div>');
|
||||
});
|
||||
ajaxRequest.setFormat('html');
|
||||
ajaxRequest.send(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}(jQuery));
|
||||
|
||||
$( document ).ready(function() {
|
||||
$('.accessibility-skip-to-content').click(function(e){
|
||||
$('a[name="main"]').attr('tabindex', -1).focus();
|
||||
$(window).scrollTo($('a[name="main"]'));
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* Piwik - Web Analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -22,7 +22,7 @@ var exports = require('piwik/UI'),
|
|||
* method, and this class instance is stored using the jQuery $.data function
|
||||
* with the 'uiControlObject' key.
|
||||
*
|
||||
* To find a datatable element by report (ie, 'UserSettings.getBrowser'),
|
||||
* To find a datatable element by report (ie, 'DevicesDetection.getBrowsers'),
|
||||
* use piwik.DataTable.getDataTableByReport.
|
||||
*
|
||||
* To get the dataTable JS instance (an instance of this class) for a
|
||||
|
|
@ -42,8 +42,11 @@ DataTable.initNewDataTables = function () {
|
|||
$('div.dataTable').each(function () {
|
||||
if (!$(this).attr('id')) {
|
||||
var tableType = $(this).attr('data-table-type') || 'DataTable',
|
||||
klass = require('piwik/UI')[tableType] || require(tableType),
|
||||
table = new klass(this);
|
||||
klass = require('piwik/UI')[tableType] || require(tableType);
|
||||
|
||||
if (klass && $.isFunction(klass)) {
|
||||
var table = new klass(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
@ -64,7 +67,7 @@ DataTable.registerFooterIconHandler = function (id, handler) {
|
|||
/**
|
||||
* Returns the first datatable div displaying a specific report.
|
||||
*
|
||||
* @param {string} report The report, eg, UserSettings.getWideScreen
|
||||
* @param {string} report The report, eg, UserLanguage.getLanguage
|
||||
* @return {Element} The datatable div displaying the report, or undefined if
|
||||
* it cannot be found.
|
||||
*/
|
||||
|
|
@ -115,6 +118,14 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
}
|
||||
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();
|
||||
},
|
||||
|
||||
|
|
@ -130,6 +141,10 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
return !!$('#dashboardWidgetsArea').length;
|
||||
},
|
||||
|
||||
getReportMetadata: function () {
|
||||
return JSON.parse(this.$element.attr('data-report-metadata') || '{}');
|
||||
},
|
||||
|
||||
//Reset DataTable filters (used before a reload or view change)
|
||||
resetAllFilters: function () {
|
||||
var self = this;
|
||||
|
|
@ -148,7 +163,9 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
'columns',
|
||||
'flat',
|
||||
'include_aggregate_rows',
|
||||
'totalRows'
|
||||
'totalRows',
|
||||
'pivotBy',
|
||||
'pivotByColumn'
|
||||
];
|
||||
|
||||
for (var key = 0; key < filters.length; key++) {
|
||||
|
|
@ -200,15 +217,16 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
$('#' + self.workingDivId + ' .loadingPiwik').last().css('display', 'block');
|
||||
}
|
||||
|
||||
$('#loadingError').hide();
|
||||
|
||||
// when switching to display graphs, reset limit
|
||||
if (self.param.viewDataTable && self.param.viewDataTable.indexOf('graph') === 0) {
|
||||
if (self && self.param && self.param.viewDataTable && String(self.param.viewDataTable).indexOf('graph') === 0) {
|
||||
delete self.param.filter_offset;
|
||||
delete self.param.filter_limit;
|
||||
}
|
||||
|
||||
var container = $('#' + self.workingDivId + ' .piwik-graph');
|
||||
|
||||
|
||||
var params = {};
|
||||
for (var key in self.param) {
|
||||
if (typeof self.param[key] != "undefined" && self.param[key] != '')
|
||||
|
|
@ -226,10 +244,17 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
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(false);
|
||||
|
||||
},
|
||||
|
||||
// Function called when the AJAX request is successful
|
||||
|
|
@ -295,12 +320,19 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
self.handleColumnHighlighting(domElem);
|
||||
self.handleExpandFooter(domElem);
|
||||
self.setFixWidthToMakeEllipsisWork(domElem);
|
||||
self.handleSummaryRow(domElem);
|
||||
},
|
||||
|
||||
setFixWidthToMakeEllipsisWork: function (domElem) {
|
||||
var self = this;
|
||||
|
||||
function getTableWidth(domElem) {
|
||||
function isWidgetized()
|
||||
{
|
||||
return -1 !== location.search.indexOf('module=Widgetize');
|
||||
}
|
||||
|
||||
function getTableWidth(domElem)
|
||||
{
|
||||
var totalWidth = $(domElem).width();
|
||||
var totalWidthTable = $('table.dataTable', domElem).width(); // fixes tables in dbstats, referrers, ...
|
||||
|
||||
|
|
@ -315,6 +347,28 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
return parseInt(totalWidth, 10);
|
||||
}
|
||||
|
||||
function setMaxTableWidthIfNeeded (domElem, maxTableWidth)
|
||||
{
|
||||
var tableWidth = getTableWidth(domElem);
|
||||
|
||||
if (tableWidth <= maxTableWidth) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isWidgetized() || self.isDashboard()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$(domElem).width(maxTableWidth);
|
||||
|
||||
var parentDataTable = $(domElem).parent('.dataTable');
|
||||
if (parentDataTable && parentDataTable.length) {
|
||||
// makes sure dataTableWrapper and DataTable has same size => makes sure maxLabelWidth does not get
|
||||
// applied in getLabelWidth() since they will have the same size.
|
||||
parentDataTable.width(maxTableWidth);
|
||||
}
|
||||
}
|
||||
|
||||
function getLabelWidth(domElem, tableWidth, minLabelWidth, maxLabelWidth)
|
||||
{
|
||||
var labelWidth = minLabelWidth;
|
||||
|
|
@ -332,10 +386,15 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
labelWidth = tableWidth * 0.5;
|
||||
}
|
||||
|
||||
var isWidgetized = -1 !== location.search.indexOf('module=Widgetize');
|
||||
var innerWidth = 0;
|
||||
var innerWrapper = domElem.find('.dataTableWrapper');
|
||||
if (innerWrapper && innerWrapper.length) {
|
||||
innerWidth = innerWrapper.width();
|
||||
}
|
||||
|
||||
if (labelWidth > maxLabelWidth
|
||||
&& !isWidgetized
|
||||
&& !isWidgetized()
|
||||
&& innerWidth !== domElem.width()
|
||||
&& !self.isDashboard()) {
|
||||
labelWidth = maxLabelWidth; // prevent for instance table in Actions-Pages is not too wide
|
||||
}
|
||||
|
|
@ -365,16 +424,26 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
}
|
||||
|
||||
function removePaddingFromWidth(domElem, labelWidth) {
|
||||
var maxPaddingLeft = 0;
|
||||
var maxPaddingRight = 0;
|
||||
|
||||
var firstLabel = $('tbody tr:nth-child(1) td.label', domElem);
|
||||
|
||||
var paddingLeft = firstLabel.css('paddingLeft');
|
||||
paddingLeft = paddingLeft ? parseInt(paddingLeft, 10) : 0;
|
||||
$('tbody tr td.label', domElem).each(function (i, node) {
|
||||
$node = $(node);
|
||||
|
||||
var paddingRight = firstLabel.css('paddingRight');
|
||||
paddingRight = paddingRight ? parseInt(paddingRight, 10) : 0;
|
||||
var paddingLeft = $node.css('paddingLeft');
|
||||
paddingLeft = paddingLeft ? Math.round(parseFloat(paddingLeft)) : 0;
|
||||
var paddingRight = $node.css('paddingRight');
|
||||
paddingRight = paddingRight ? Math.round(parseFloat(paddingLeft)) : 0;
|
||||
|
||||
labelWidth = labelWidth - paddingLeft - paddingRight;
|
||||
if (paddingLeft > maxPaddingLeft) {
|
||||
maxPaddingLeft = paddingLeft;
|
||||
}
|
||||
if (paddingRight > maxPaddingRight) {
|
||||
maxPaddingRight = paddingRight;
|
||||
}
|
||||
});
|
||||
|
||||
labelWidth = labelWidth - maxPaddingLeft - maxPaddingRight;
|
||||
|
||||
return labelWidth;
|
||||
}
|
||||
|
|
@ -382,7 +451,8 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
var minLabelWidth = 125;
|
||||
var maxLabelWidth = 440;
|
||||
|
||||
var tableWidth = getTableWidth(domElem);
|
||||
setMaxTableWidthIfNeeded(domElem, 1200);
|
||||
var tableWidth = getTableWidth(domElem);
|
||||
var labelColumnMinWidth = getLabelColumnMinWidth(domElem);
|
||||
var labelColumnWidth = getLabelWidth(domElem, tableWidth, 125, 440);
|
||||
|
||||
|
|
@ -400,7 +470,7 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
},
|
||||
|
||||
handleLimit: function (domElem) {
|
||||
var tableRowLimits = [5, 10, 25, 50, 100, 250, 500],
|
||||
var tableRowLimits = piwik.config.datatable_row_limits,
|
||||
evolutionLimits =
|
||||
{
|
||||
day: [30, 60, 90, 180, 365, 500],
|
||||
|
|
@ -436,13 +506,20 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
};
|
||||
}
|
||||
|
||||
function getFilterLimitAsString(limit) {
|
||||
if (limit == '-1') {
|
||||
return _pk_translate('General_All').toLowerCase();
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
|
||||
// setup limit control
|
||||
$('.limitSelection', domElem).append('<div><span>' + self.param[limitParamName] + '</span></div><ul></ul>');
|
||||
$('.limitSelection', domElem).append('<div><span value="'+ self.param[limitParamName] +'">' + getFilterLimitAsString(self.param[limitParamName]) + '</span></div><ul></ul>');
|
||||
|
||||
if (self.props.show_limit_control) {
|
||||
$('.limitSelection ul', domElem).hide();
|
||||
for (var i = 0; i < numbers.length; i++) {
|
||||
$('.limitSelection ul', domElem).append('<li value="' + numbers[i] + '"><span>' + numbers[i] + '</span></li>');
|
||||
$('.limitSelection ul', domElem).append('<li value="' + numbers[i] + '"><span>' + getFilterLimitAsString(numbers[i]) + '</span></li>');
|
||||
}
|
||||
$('.limitSelection ul li:last', domElem).addClass('last');
|
||||
|
||||
|
|
@ -465,12 +542,12 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
$('.limitSelection', domElem).is('.visible') ? hide() : show();
|
||||
});
|
||||
$('.limitSelection ul li', domElem).on('click', function (event) {
|
||||
var limit = parseInt($(event.target).text());
|
||||
var limit = parseInt($(event.target).closest('li').attr('value'));
|
||||
|
||||
hide();
|
||||
if (limit != self.param[limitParamName]) {
|
||||
setLimitValue(self.param, limit);
|
||||
$('.limitSelection>div>span', domElem).text(limit);
|
||||
$('.limitSelection>div>span', domElem).text( getFilterLimitAsString(limit)).attr('value', limit);
|
||||
self.reloadAjaxDataTable();
|
||||
|
||||
var data = {};
|
||||
|
|
@ -494,24 +571,6 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
handleSort: function (domElem) {
|
||||
var self = this;
|
||||
|
||||
function getSortImageSrc() {
|
||||
var imageSortSrc = false;
|
||||
if (currentIsSubDataTable) {
|
||||
if (self.param.filter_sort_order == 'asc') {
|
||||
imageSortSrc = 'plugins/Zeitgeist/images/sort_subtable_asc.png';
|
||||
} else {
|
||||
imageSortSrc = 'plugins/Zeitgeist/images/sort_subtable_desc.png';
|
||||
}
|
||||
} else {
|
||||
if (self.param.filter_sort_order == 'asc') {
|
||||
imageSortSrc = 'plugins/Zeitgeist/images/sortasc.png';
|
||||
} else {
|
||||
imageSortSrc = 'plugins/Zeitgeist/images/sortdesc.png';
|
||||
}
|
||||
}
|
||||
return imageSortSrc;
|
||||
}
|
||||
|
||||
if (self.props.enable_sort) {
|
||||
$('.sortable', domElem).off('click.dataTableSort').on('click.dataTableSort',
|
||||
function () {
|
||||
|
|
@ -524,18 +583,26 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
if (self.param.filter_sort_column) {
|
||||
// are we in a subdatatable?
|
||||
var currentIsSubDataTable = $(domElem).parent().hasClass('cellSubDataTable');
|
||||
var imageSortSrc = getSortImageSrc();
|
||||
var imageSortClassType = currentIsSubDataTable ? 'sortSubtable' : ''
|
||||
var imageSortWidth = 16;
|
||||
var imageSortHeight = 16;
|
||||
|
||||
var sortOrder = self.param.filter_sort_order || 'desc';
|
||||
var ImageSortClass = sortOrder.charAt(0).toUpperCase() + sortOrder.substr(1);
|
||||
|
||||
// we change the style of the column currently used as sort column
|
||||
// adding an image and the class columnSorted to the TD
|
||||
$("th#" + self.param.filter_sort_column + ' #thDIV', domElem).parent()
|
||||
.addClass('columnSorted')
|
||||
.prepend('<div class="sortIconContainer sortIconContainer' + ImageSortClass + '"><img class="sortIcon" width="' + imageSortWidth + '" height="' + imageSortHeight + '" src="' + imageSortSrc + '" /></div>');
|
||||
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);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -557,6 +624,14 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
}
|
||||
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.substr(2);
|
||||
}
|
||||
});
|
||||
|
||||
$('.dataTableSearchPattern', domElem)
|
||||
.css({display: 'block'})
|
||||
.each(function () {
|
||||
|
|
@ -577,6 +652,12 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
var keyword = $(this).siblings('.searchInput').val();
|
||||
self.param.filter_offset = 0;
|
||||
|
||||
$.each(patternsToReplace, function (index, pattern) {
|
||||
if (0 === keyword.indexOf(pattern.from)) {
|
||||
keyword = pattern.to + keyword.substr(1);
|
||||
}
|
||||
});
|
||||
|
||||
if (self.param.search_recursive) {
|
||||
self.param.filter_column_recursive = 'label';
|
||||
self.param.filter_pattern_recursive = keyword;
|
||||
|
|
@ -642,46 +723,47 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
}
|
||||
);
|
||||
|
||||
var $next = $('.dataTableNext', domElem);
|
||||
|
||||
// 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 (self.param.keep_summary_row == 1) --totalRows;
|
||||
if (offsetEnd < totalRows) {
|
||||
$(this).css('display', 'inline');
|
||||
}
|
||||
})
|
||||
// bind the click event to trigger the ajax request with the new offset
|
||||
.click(function () {
|
||||
$(this).off('click');
|
||||
self.param.filter_offset = Number(self.param.filter_offset) + Number(self.param.filter_limit);
|
||||
self.reloadAjaxDataTable();
|
||||
})
|
||||
;
|
||||
$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) {
|
||||
$(this).css('display', 'inline');
|
||||
}
|
||||
});
|
||||
// bind the click event to trigger the ajax request with the new offset
|
||||
$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);
|
||||
|
||||
// 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');
|
||||
}
|
||||
$prev.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).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();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// bind the click event to trigger the ajax request with the new offset
|
||||
// take care of the negative offset, we setup 0
|
||||
$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) {
|
||||
|
|
@ -706,9 +788,6 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
;
|
||||
|
||||
var annotationsCss = {left: 6}; // padding-left of .jqplot-graph element (in _dataTableViz_jqplotGraph.tpl)
|
||||
if (!self.isDashboard() && !self.isWithinDialog(domElem)) {
|
||||
annotationsCss['top'] = -datatableFeatures.height() - annotationAxisHeight + noteSize / 2;
|
||||
}
|
||||
|
||||
// set position of evolution annotation icons
|
||||
annotations.css(annotationsCss);
|
||||
|
|
@ -716,11 +795,7 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
piwik.annotations.placeEvolutionIcons(annotations, domElem);
|
||||
|
||||
// add new section under axis
|
||||
if (self.isDashboard() || self.isWithinDialog(domElem)) {
|
||||
annotations.insertAfter($('.datatableRelatedReports', domElem));
|
||||
} else {
|
||||
datatableFeatures.append(annotations);
|
||||
}
|
||||
annotations.insertAfter($('.datatableRelatedReports', domElem));
|
||||
|
||||
// reposition annotation icons every time the graph is resized
|
||||
$('.piwik-graph', domElem).on('resizeGraph', function () {
|
||||
|
|
@ -971,14 +1046,13 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
$('.exportToFormatItems a', domElem)
|
||||
// prevent click jacking attacks by dynamically adding the token auth when the link is clicked
|
||||
.click(function () {
|
||||
$(this).attr('href', function () {
|
||||
var url = $(this).attr('href') + '&token_auth=' + piwik.token_auth;
|
||||
|
||||
var limit = $('.limitSelection>div>span', domElem).text();
|
||||
var limit = $('.limitSelection>div>span', domElem).attr('value');
|
||||
var defaultLimit = $(this).attr('filter_limit');
|
||||
if (!limit || 'undefined' === limit || defaultLimit == -1) {
|
||||
limit = defaultLimit;
|
||||
|
|
@ -991,9 +1065,18 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
.attr('href', function () {
|
||||
var format = $(this).attr('format');
|
||||
var method = $(this).attr('methodToCall');
|
||||
var params = $(this).attr('requestParams');
|
||||
|
||||
if (params) {
|
||||
params = JSON.parse(params)
|
||||
} else {
|
||||
params = {};
|
||||
}
|
||||
|
||||
var segment = self.param.segment;
|
||||
var label = self.param.label;
|
||||
var idGoal = self.param.idGoal;
|
||||
var idDimension = self.param.idDimension;
|
||||
var param_date = self.param.date;
|
||||
var date = $(this).attr('date');
|
||||
if (typeof date != 'undefined') {
|
||||
|
|
@ -1015,6 +1098,7 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
&& self.param.viewDataTable == "graphEvolution") {
|
||||
period = 'day';
|
||||
}
|
||||
|
||||
var str = 'index.php?module=API'
|
||||
+ '&method=' + method
|
||||
+ '&format=' + format
|
||||
|
|
@ -1024,10 +1108,15 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
+ ( typeof self.param.filter_pattern != "undefined" ? '&filter_pattern=' + self.param.filter_pattern : '')
|
||||
+ ( typeof self.param.filter_pattern_recursive != "undefined" ? '&filter_pattern_recursive=' + self.param.filter_pattern_recursive : '');
|
||||
|
||||
if ($.isPlainObject(params)) {
|
||||
$.each(params, function (index, param) {
|
||||
str += '&' + index + '=' + encodeURIComponent(param);
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof self.param.flat != "undefined") {
|
||||
str += '&flat=' + (self.param.flat == 0 ? '0' : '1');
|
||||
if (typeof self.param.include_aggregate_rows != "undefined" && self.param.include_aggregate_rows) {
|
||||
if (typeof self.param.include_aggregate_rows != "undefined" && self.param.include_aggregate_rows == '1') {
|
||||
str += '&include_aggregate_rows=1';
|
||||
}
|
||||
if (!self.param.flat
|
||||
|
|
@ -1039,6 +1128,12 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
} else {
|
||||
str += '&expanded=1';
|
||||
}
|
||||
if (self.param.pivotBy) {
|
||||
str += '&pivotBy=' + self.param.pivotBy + '&pivotByColumnLimit=20';
|
||||
if (self.props.pivot_by_column) {
|
||||
str += '&pivotByColumn=' + self.props.pivot_by_column;
|
||||
}
|
||||
}
|
||||
if (format == 'CSV' || format == 'TSV' || format == 'RSS') {
|
||||
str += '&translateColumnNames=1&language=' + piwik.language;
|
||||
}
|
||||
|
|
@ -1050,6 +1145,11 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
&& idGoal != '-1') {
|
||||
str += '&idGoal=' + idGoal;
|
||||
}
|
||||
// Export Dimension specific reports
|
||||
if (typeof idDimension != 'undefined'
|
||||
&& idDimension != '-1') {
|
||||
str += '&idDimension=' + idDimension;
|
||||
}
|
||||
if (label) {
|
||||
label = label.split(',');
|
||||
|
||||
|
|
@ -1083,6 +1183,7 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
// no manipulation when loading subtables
|
||||
return;
|
||||
}
|
||||
|
||||
if ((typeof self.numberOfSubtables == 'undefined' || self.numberOfSubtables == 0)
|
||||
&& (typeof self.param.flat == 'undefined' || self.param.flat != 1)) {
|
||||
// if there are no subtables, remove the flatten action
|
||||
|
|
@ -1120,28 +1221,36 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
};
|
||||
$('div.tableConfiguration', domElem).hover(open, close);
|
||||
|
||||
var generateClickCallback = function (paramName, callbackAfterToggle) {
|
||||
var generateClickCallback = function (paramName, callbackAfterToggle, setParamCallback) {
|
||||
return function () {
|
||||
close();
|
||||
self.param[paramName] = 1 - self.param[paramName];
|
||||
if (setParamCallback) {
|
||||
var data = setParamCallback();
|
||||
} else {
|
||||
self.param[paramName] = (1 - self.param[paramName]) + '';
|
||||
var data = {};
|
||||
}
|
||||
self.param.filter_offset = 0;
|
||||
delete self.param.totalRows;
|
||||
if (callbackAfterToggle) callbackAfterToggle();
|
||||
self.reloadAjaxDataTable(true, callbackSuccess);
|
||||
var data = {};
|
||||
data[paramName] = self.param[paramName];
|
||||
self.notifyWidgetParametersChange(domElem, data);
|
||||
};
|
||||
};
|
||||
|
||||
var getText = function (text, addDefault) {
|
||||
text = _pk_translate(text);
|
||||
if (text.indexOf('%s') > 0) {
|
||||
text = text.replace('%s', '<br /><span class="action">» ');
|
||||
var getText = function (text, addDefault, replacement) {
|
||||
if (/(%(.\$)?s+)/g.test(_pk_translate(text))) {
|
||||
var values = ['<br /><span class="action">» '];
|
||||
if(replacement) {
|
||||
values.push(replacement);
|
||||
}
|
||||
text = _pk_translate(text, values);
|
||||
if (addDefault) text += ' (' + _pk_translate('CoreHome_Default') + ')';
|
||||
text += '</span>';
|
||||
return text;
|
||||
}
|
||||
return text;
|
||||
return _pk_translate(text);
|
||||
};
|
||||
|
||||
var setText = function (el, paramName, textA, textB) {
|
||||
|
|
@ -1196,6 +1305,37 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
}
|
||||
}));
|
||||
|
||||
// handle pivot by
|
||||
$('.dataTablePivotBySubtable', domElem)
|
||||
.each(function () {
|
||||
if (self.param.pivotBy
|
||||
&& self.param.pivotBy != '0'
|
||||
) {
|
||||
$(this).html(getText('CoreHome_UndoPivotBySubtable', true));
|
||||
iconHighlighted = true;
|
||||
} else {
|
||||
var optionLabelText = getText('CoreHome_PivotBySubtable', false, self.props.pivot_dimension_name);
|
||||
$(this).html(optionLabelText);
|
||||
}
|
||||
})
|
||||
.click(generateClickCallback('pivotBy', null, function () {
|
||||
if (self.param.pivotBy
|
||||
&& self.param.pivotBy != '0'
|
||||
) {
|
||||
self.param.pivotBy = '0'; // set to '0' so it will be sent in the request and override the saved param
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// remove sorting so it will default to first column in table
|
||||
self.param.filter_sort_column = '';
|
||||
return {filter_sort_column: ''};
|
||||
}));
|
||||
|
||||
// handle highlighted icon
|
||||
if (iconHighlighted) {
|
||||
icon.addClass('highlighted');
|
||||
|
|
@ -1217,7 +1357,10 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
var width = 0;
|
||||
ul.find('li').each(function () {
|
||||
width = Math.max(width, $(this).width());
|
||||
}).width(width);
|
||||
});
|
||||
if (width > 0) {
|
||||
ul.find('li').width(width);
|
||||
}
|
||||
close();
|
||||
}, 400);
|
||||
}
|
||||
|
|
@ -1227,7 +1370,26 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
notifyWidgetParametersChange: function (domWidget, parameters) {
|
||||
var widget = $(domWidget).closest('[widgetId]');
|
||||
// trigger setParameters event on base element
|
||||
widget.trigger('setParameters', parameters);
|
||||
|
||||
if (widget && widget.length) {
|
||||
widget.trigger('setParameters', parameters);
|
||||
} else {
|
||||
|
||||
var reportId = $(domWidget).closest('[data-report]').attr('data-report');
|
||||
|
||||
var ajaxRequest = new ajaxHelper();
|
||||
ajaxRequest.addParams({
|
||||
module: 'CoreHome',
|
||||
action: 'saveViewDataTableParameters',
|
||||
report_id: reportId
|
||||
}, 'get');
|
||||
ajaxRequest.addParams({
|
||||
parameters: JSON.stringify(parameters)
|
||||
}, 'post');
|
||||
ajaxRequest.setCallback(function () {});
|
||||
ajaxRequest.setFormat('html');
|
||||
ajaxRequest.send(false);
|
||||
}
|
||||
},
|
||||
|
||||
tooltip: function (domElement) {
|
||||
|
|
@ -1269,29 +1431,35 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
// Add some styles on the cells even/odd
|
||||
// label (first column of a data row) or not
|
||||
$("th:first-child", domElem).addClass('label');
|
||||
$("td:first-child:odd", domElem).addClass('label labeleven');
|
||||
$("td:first-child:even", domElem).addClass('label labelodd');
|
||||
$("tr:odd td", domElem).slice(1).addClass('column columnodd');
|
||||
$("tr:even td", domElem).slice(1).addClass('column columneven');
|
||||
$("td:first-child", domElem).addClass('label');
|
||||
$("tr td", domElem).addClass('column');
|
||||
},
|
||||
|
||||
handleExpandFooter: function (domElem) {
|
||||
if (!this.isDashboard() && !this.isWithinDialog(domElem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var footerIcons = $('.dataTableFooterIcons', domElem);
|
||||
|
||||
if (!footerIcons.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isWithinDialog(domElem)) {
|
||||
$('.dataTableFeatures', domElem).addClass('expanded');
|
||||
}
|
||||
|
||||
var self = this;
|
||||
function toggleFooter()
|
||||
function toggleFooter(event)
|
||||
{
|
||||
if (self.isWithinDialog(domElem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var icons = $('.dataTableFooterIcons', domElem);
|
||||
$('.dataTableFeatures', domElem).toggleClass('expanded');
|
||||
|
||||
if (event && event.doNotNotifyChange) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.notifyWidgetParametersChange(domElem, {
|
||||
isFooterExpandedInDashboard: icons.is(':visible')
|
||||
});
|
||||
|
|
@ -1306,9 +1474,10 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
|
||||
$('.expandDataTableFooterDrawer', domElem).after(footerIcons);
|
||||
|
||||
var controls = $('.controls', domElem);
|
||||
if (controls.length) {
|
||||
$('.foldDataTableFooterDrawer', domElem).after(controls);
|
||||
var controls = $('.controls', domElem);
|
||||
var footerWrap = $('.dataTableFooterWrap', domElem);
|
||||
if (controls.length && footerWrap.length) {
|
||||
$('.dataTableFooterWrap', domElem).before(controls);
|
||||
}
|
||||
|
||||
var loadingPiwikBelow = $('.loadingPiwikBelow', domElem);
|
||||
|
|
@ -1317,10 +1486,12 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
}
|
||||
|
||||
if (this.param.isFooterExpandedInDashboard) {
|
||||
toggleFooter();
|
||||
toggleFooter({doNotNotifyChange: true});
|
||||
}
|
||||
|
||||
$('.foldDataTableFooterDrawer, .expandDataTableFooterDrawer', domElem).on('click', toggleFooter);
|
||||
var $nodes = $('.foldDataTableFooterDrawer, .expandDataTableFooterDrawer', domElem);
|
||||
$nodes.off('click');
|
||||
$nodes.on('click', toggleFooter);
|
||||
},
|
||||
|
||||
handleColumnHighlighting: function (domElem) {
|
||||
|
|
@ -1332,19 +1503,24 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
// higlight all columns on hover
|
||||
$('td', domElem).hover(
|
||||
function() {
|
||||
|
||||
if ($(this).hasClass('label')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var table = $(this).closest('table');
|
||||
var nthChild = $(this).parent('tr').children().index($(this)) + 1;
|
||||
var rows = $('> tbody > tr', table);
|
||||
|
||||
if (!maxWidth[nthChild]) {
|
||||
maxWidth[nthChild] = 0;
|
||||
rows.find("td:nth-child(" + (nthChild) + ") .column .value").each(function (index, element) {
|
||||
var width = $(element).width();
|
||||
rows.find("td:nth-child(" + (nthChild) + ").column .value").each(function (index, element) {
|
||||
var width = $(element).width();
|
||||
if (width > maxWidth[nthChild]) {
|
||||
maxWidth[nthChild] = width;
|
||||
}
|
||||
});
|
||||
rows.find("td:nth-child(" + (nthChild) + ") .column .value").each(function (index, element) {
|
||||
rows.find("td:nth-child(" + (nthChild) + ").column .value").each(function (index, element) {
|
||||
$(element).css({width: maxWidth[nthChild], display: 'inline-block'});
|
||||
});
|
||||
}
|
||||
|
|
@ -1399,7 +1575,7 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
'<tr>' +
|
||||
'<td colspan="' + numberOfColumns + '" class="cellSubDataTable">' +
|
||||
'<div id="' + divIdToReplaceWithSubTable + '">' +
|
||||
'<span class="loadingPiwik" style="display:inline"><img src="plugins/Zeitgeist/images/loading-blue.gif" />' + _pk_translate('General_Loading') + '</span>' +
|
||||
'<span class="loadingPiwik" style="display:inline"><img src="plugins/Morpheus/images/loading-blue.gif" />' + _pk_translate('General_Loading') + '</span>' +
|
||||
'</div>' +
|
||||
'</td>' +
|
||||
'</tr>'
|
||||
|
|
@ -1435,6 +1611,7 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
}
|
||||
|
||||
$(this).next().toggle();
|
||||
$(this).toggleClass('expanded');
|
||||
self.repositionRowActions($(this));
|
||||
}
|
||||
).size();
|
||||
|
|
@ -1540,6 +1717,9 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
self.param[key] = decodeURIComponent(newParams[key]);
|
||||
}
|
||||
|
||||
delete self.param.pivotBy;
|
||||
delete self.param.pivotByColumn;
|
||||
|
||||
// do ajax request
|
||||
self.reloadAjaxDataTable(true, function (newReport) {
|
||||
var newDomElem = self.dataTableLoaded(newReport, self.workingDivId);
|
||||
|
|
@ -1576,6 +1756,22 @@ $.extend(DataTable.prototype, UIControl.prototype, {
|
|||
});
|
||||
},
|
||||
|
||||
handleSummaryRow: function (domElem) {
|
||||
var details = _pk_translate('General_LearnMore', [' (<a href="http://piwik.org/faq/how-to/faq_54/" rel="noreferrer" target="_blank">', '</a>)']);
|
||||
|
||||
domElem.find('tr.summaryRow').each(function () {
|
||||
var labelSpan = $(this).find('.label .value');
|
||||
var defaultLabel = labelSpan.text();
|
||||
|
||||
$(this).hover(function() {
|
||||
labelSpan.html(defaultLabel + details);
|
||||
},
|
||||
function() {
|
||||
labelSpan.text(defaultLabel);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// also used in action data table
|
||||
doHandleRowActions: function (trs) {
|
||||
var self = this;
|
||||
|
|
@ -1743,11 +1939,26 @@ var switchToHtmlTable = function (dataTable, viewDataTable) {
|
|||
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', switchToHtmlTable);
|
||||
DataTable.registerFooterIconHandler('ecommerceAbandonedCart', switchToHtmlTable);
|
||||
DataTable.registerFooterIconHandler('ecommerceOrder', switchToEcommerceView);
|
||||
DataTable.registerFooterIconHandler('ecommerceAbandonedCart', switchToEcommerceView);
|
||||
|
||||
// generic function to handle switch to graph visualizations
|
||||
DataTable.switchToGraph = function (dataTable, viewDataTable) {
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ DataTable_RowActions_Registry.register({
|
|||
|
||||
name: 'RowEvolution',
|
||||
|
||||
dataTableIcon: 'plugins/Zeitgeist/images/row_evolution.png',
|
||||
dataTableIconHover: 'plugins/Zeitgeist/images/row_evolution_hover.png',
|
||||
dataTableIcon: 'plugins/Morpheus/images/row_evolution.png',
|
||||
dataTableIconHover: 'plugins/Morpheus/images/row_evolution_hover.png',
|
||||
|
||||
order: 50,
|
||||
|
||||
|
|
@ -110,7 +110,6 @@ DataTable_RowActions_Registry.register({
|
|||
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* DataTable Row Actions
|
||||
*
|
||||
|
|
@ -125,7 +124,6 @@ DataTable_RowActions_Registry.register({
|
|||
* The two template methods are performAction and doOpenPopover
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// BASE CLASS
|
||||
//
|
||||
|
|
@ -161,11 +159,10 @@ DataTable_RowAction.prototype.initTr = function (tr) {
|
|||
DataTable_RowAction.prototype.trigger = function (tr, e, subTableLabel) {
|
||||
var label = this.getLabelFromTr(tr);
|
||||
|
||||
label = label.trim();
|
||||
// if we have received the event from the sub table, add the label
|
||||
if (subTableLabel) {
|
||||
var separator = ' > '; // LabelFilter::SEPARATOR_RECURSIVE_LABEL
|
||||
label += separator + subTableLabel.trim();
|
||||
label += separator + subTableLabel;
|
||||
}
|
||||
|
||||
// handle sub tables in nested reports: forward to parent
|
||||
|
|
@ -188,7 +185,7 @@ DataTable_RowAction.prototype.trigger = function (tr, e, subTableLabel) {
|
|||
var findLevel = 'level' + (level - 1);
|
||||
var ptr = tr;
|
||||
while ((ptr = ptr.prev()).size() > 0) {
|
||||
if (!ptr.hasClass(findLevel)) {
|
||||
if (!ptr.hasClass(findLevel) || ptr.hasClass('nodata')) {
|
||||
continue;
|
||||
}
|
||||
ptr.trigger(this.trEventName, {
|
||||
|
|
@ -214,8 +211,14 @@ DataTable_RowAction.prototype.getLabelFromTr = function (tr) {
|
|||
value = label.text();
|
||||
}
|
||||
value = value.trim();
|
||||
value = encodeURIComponent(value);
|
||||
|
||||
return encodeURIComponent(value);
|
||||
// if tr is a terminal node, we use the @ operator to distinguish it from branch nodes w/ the same name
|
||||
if (!tr.hasClass('subDataTable')) {
|
||||
value = '@' + value;
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -244,7 +247,6 @@ DataTable_RowAction.prototype.performAction = function (label, tr, e) {
|
|||
DataTable_RowAction.prototype.doOpenPopover = function (parameter) {
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// ROW EVOLUTION
|
||||
//
|
||||
|
|
@ -272,16 +274,22 @@ DataTable_RowActions_RowEvolution.prototype.performAction = function (label, tr,
|
|||
return;
|
||||
}
|
||||
|
||||
// check whether we have rows marked for multi row evolution
|
||||
var isMultiRowEvolution = '0';
|
||||
this.addMultiEvolutionRow(label);
|
||||
|
||||
// check whether we have rows marked for multi row evolution
|
||||
var extraParams = {};
|
||||
if (this.multiEvolutionRows.length > 1) {
|
||||
isMultiRowEvolution = '1';
|
||||
extraParams.action = 'getMultiRowEvolutionPopover';
|
||||
label = this.multiEvolutionRows.join(',');
|
||||
}
|
||||
|
||||
// check if abandonedCarts is in the dataTable params and if so, propagate to row evolution request
|
||||
if (this.dataTable.param.abandonedCarts !== undefined) {
|
||||
extraParams['abandonedCarts'] = this.dataTable.param.abandonedCarts;
|
||||
}
|
||||
|
||||
var apiMethod = this.dataTable.param.module + '.' + this.dataTable.param.action;
|
||||
this.openPopover(apiMethod, isMultiRowEvolution, label);
|
||||
this.openPopover(apiMethod, extraParams, label);
|
||||
};
|
||||
|
||||
DataTable_RowActions_RowEvolution.prototype.addMultiEvolutionRow = function (label) {
|
||||
|
|
@ -290,27 +298,37 @@ DataTable_RowActions_RowEvolution.prototype.addMultiEvolutionRow = function (lab
|
|||
}
|
||||
};
|
||||
|
||||
DataTable_RowActions_RowEvolution.prototype.openPopover = function (apiMethod, multiRowEvolutionParam, label) {
|
||||
var urlParam = apiMethod + ':' + multiRowEvolutionParam + ':' + label;
|
||||
DataTable_RowActions_RowEvolution.prototype.openPopover = function (apiMethod, extraParams, label) {
|
||||
var urlParam = apiMethod + ':' + encodeURIComponent(JSON.stringify(extraParams)) + ':' + label;
|
||||
DataTable_RowAction.prototype.openPopover.apply(this, [urlParam]);
|
||||
};
|
||||
|
||||
DataTable_RowActions_RowEvolution.prototype.doOpenPopover = function (urlParam) {
|
||||
var urlParamParts = urlParam.split(':');
|
||||
|
||||
var apiMethod = urlParamParts[0];
|
||||
urlParamParts.shift();
|
||||
var apiMethod = urlParamParts.shift();
|
||||
|
||||
var multiRowEvolutionParam = urlParamParts[0];
|
||||
urlParamParts.shift();
|
||||
var extraParamsString = urlParamParts.shift(),
|
||||
extraParams = {}; // 0/1 or "0"/"1"
|
||||
try {
|
||||
extraParams = JSON.parse(decodeURIComponent(extraParamsString));
|
||||
} catch (e) {
|
||||
// assume the parameter is an int/string describing whether to use multi row evolution
|
||||
if (extraParamsString == '1') {
|
||||
extraParams.action = 'getMultiRowEvolutionPopover';
|
||||
} else if (extraParamsString != '0') {
|
||||
extraParams.action = 'getMultiRowEvolutionPopover';
|
||||
extraParams.column = extraParamsString;
|
||||
}
|
||||
}
|
||||
|
||||
var label = urlParamParts.join(':');
|
||||
|
||||
this.showRowEvolution(apiMethod, label, multiRowEvolutionParam);
|
||||
this.showRowEvolution(apiMethod, label, extraParams);
|
||||
};
|
||||
|
||||
/** Open the row evolution popover */
|
||||
DataTable_RowActions_RowEvolution.prototype.showRowEvolution = function (apiMethod, label, multiRowEvolutionParam) {
|
||||
DataTable_RowActions_RowEvolution.prototype.showRowEvolution = function (apiMethod, label, extraParams) {
|
||||
|
||||
var self = this;
|
||||
|
||||
|
|
@ -325,17 +343,6 @@ DataTable_RowActions_RowEvolution.prototype.showRowEvolution = function (apiMeth
|
|||
disableLink: 1
|
||||
};
|
||||
|
||||
// derive api action and requested column from multiRowEvolutionParam
|
||||
var action;
|
||||
if (multiRowEvolutionParam == '0') {
|
||||
action = 'getRowEvolutionPopover';
|
||||
} else if (multiRowEvolutionParam == '1') {
|
||||
action = 'getMultiRowEvolutionPopover';
|
||||
} else {
|
||||
action = 'getMultiRowEvolutionPopover';
|
||||
requestParams.column = multiRowEvolutionParam;
|
||||
}
|
||||
|
||||
var callback = function (html) {
|
||||
Piwik_Popover.setContent(html);
|
||||
|
||||
|
|
@ -353,7 +360,7 @@ DataTable_RowActions_RowEvolution.prototype.showRowEvolution = function (apiMeth
|
|||
|
||||
if (self.dataTable !== null) {
|
||||
// remember label for multi row evolution
|
||||
box.find('a.rowevolution-startmulti').click(function () {
|
||||
box.find('.rowevolution-startmulti').click(function () {
|
||||
Piwik_Popover.onClose(false); // unbind listener that resets multiEvolutionRows
|
||||
Piwik_Popover.close();
|
||||
return false;
|
||||
|
|
@ -369,15 +376,29 @@ DataTable_RowActions_RowEvolution.prototype.showRowEvolution = function (apiMeth
|
|||
box.find('select.multirowevoltion-metric').change(function () {
|
||||
var metric = $(this).val();
|
||||
Piwik_Popover.onClose(false); // unbind listener that resets multiEvolutionRows
|
||||
self.openPopover(apiMethod, metric, label);
|
||||
var extraParams = {action: 'getMultiRowEvolutionPopover', column: metric};
|
||||
self.openPopover(apiMethod, extraParams, label);
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
requestParams.module = 'CoreHome';
|
||||
requestParams.action = action;
|
||||
requestParams.action = 'getRowEvolutionPopover';
|
||||
requestParams.colors = JSON.stringify(piwik.getSparklineColors());
|
||||
|
||||
var idDimension;
|
||||
if (broadcast.getValueFromUrl('module') === 'Widgetize') {
|
||||
idDimension = broadcast.getValueFromUrl('idDimension');
|
||||
} else {
|
||||
idDimension = broadcast.getValueFromHash('idDimension');
|
||||
}
|
||||
|
||||
if (idDimension) {
|
||||
requestParams.idDimension = parseInt(idDimension, 10);
|
||||
}
|
||||
|
||||
$.extend(requestParams, extraParams);
|
||||
|
||||
var ajaxRequest = new ajaxHelper();
|
||||
ajaxRequest.addParams(requestParams, 'get');
|
||||
ajaxRequest.setCallback(callback);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* Piwik - Web Analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -24,10 +24,10 @@
|
|||
// set's the correct amount text & smiley face image based on the position of the slider
|
||||
var setSmileyFaceAndAmount = function (slider, pos) {
|
||||
// set text yearly amount
|
||||
$('.slider-donate-amount', slider).text('$' + donateAmounts[pos] + '/' + _pk_translate('General_YearShort'));
|
||||
$('.slider-donate-amount', slider).text('$' + donateAmounts[pos] + '/' + _pk_translate('Intl_Year_Short'));
|
||||
|
||||
// set the right smiley face
|
||||
$('.slider-smiley-face').attr('src', 'plugins/Zeitgeist/images/smileyprog_' + pos + '.png');
|
||||
$('.slider-smiley-face').attr('src', 'plugins/Morpheus/images/smileyprog_' + pos + '.png');
|
||||
|
||||
// set the hidden option input for paypal
|
||||
var option = Math.max(1, pos);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* Piwik - Web Analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -16,50 +16,78 @@ menu.prototype =
|
|||
{
|
||||
resetTimer: null,
|
||||
|
||||
adaptSubMenuHeight: function() {
|
||||
var subNavHeight = $('.sfHover > ul').outerHeight();
|
||||
$('.nav_sep').height(subNavHeight);
|
||||
onItemClick: function (e) {
|
||||
if (e.which === 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
$('#secondNavBar').removeClass('open fadeInLeft');
|
||||
|
||||
var $link = $(this);
|
||||
var href = $link.attr('href');
|
||||
|
||||
if (!$('#content.admin').size()) {
|
||||
if (!href && $link.parent().is('.menuTab')) {
|
||||
var $li = $link.parents('li').first();
|
||||
|
||||
if ($li.hasClass('sfActive')) {
|
||||
$li.removeClass('sfActive');
|
||||
} else {
|
||||
$li.siblings().removeClass('sfActive');
|
||||
$li.addClass('sfActive');
|
||||
}
|
||||
|
||||
var $children = $li.find('ul li > .item');
|
||||
if ($children.length === 1) {
|
||||
$children.first().click();
|
||||
}
|
||||
|
||||
|
||||
} else if (href) {
|
||||
$('#secondNavBar').trigger('piwikSwitchPage', this);
|
||||
|
||||
broadcast.propagateAjax(href.substr(1));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return !!href;
|
||||
},
|
||||
|
||||
overMainLI: function () {
|
||||
var $this = $(this);
|
||||
$this.siblings().removeClass('sfHover');
|
||||
$this.addClass('sfHover');
|
||||
menu.prototype.adaptSubMenuHeight();
|
||||
clearTimeout(menu.prototype.resetTimer);
|
||||
},
|
||||
|
||||
outMainLI: function () {
|
||||
clearTimeout(menu.prototype.resetTimer);
|
||||
menu.prototype.resetTimer = setTimeout(function() {
|
||||
$('.Menu-tabList > .sfHover', this.menuNode).removeClass('sfHover');
|
||||
$('.Menu-tabList > .sfActive', this.menuNode).addClass('sfHover');
|
||||
menu.prototype.adaptSubMenuHeight();
|
||||
}, 2000);
|
||||
},
|
||||
|
||||
onItemClick: function (item) {
|
||||
$('.Menu--dashboard').trigger('piwikSwitchPage', item);
|
||||
broadcast.propagateAjax( $(item).attr('href').substr(1) );
|
||||
return false;
|
||||
isAdmin: function () {
|
||||
return !!$('#content.admin').size();
|
||||
},
|
||||
|
||||
init: function () {
|
||||
this.menuNode = $('.Menu--dashboard');
|
||||
|
||||
this.menuNode.find("li:has(ul)").hover(this.overMainLI, this.outMainLI);
|
||||
this.menuNode = $('#secondNavBar');
|
||||
|
||||
// add id to all li menu to support menu identification.
|
||||
// for all sub menu we want to have a unique id based on their module and action
|
||||
// for main menu we want to add just the module as its id.
|
||||
this.menuNode.find('li').each(function () {
|
||||
var url = $(this).find('a').attr('href').substr(1);
|
||||
var module = broadcast.getValueFromUrl("module", url);
|
||||
var action = broadcast.getValueFromUrl("action", url);
|
||||
var $this = $(this);
|
||||
var link = $this.find('a');
|
||||
|
||||
var main_menu = $this.parent().hasClass('navbar') ? true : false;
|
||||
|
||||
if (!link) {
|
||||
return;
|
||||
}
|
||||
|
||||
var href = link.attr('href');
|
||||
if (!href) {
|
||||
return;
|
||||
}
|
||||
var url = href.substr(1);
|
||||
|
||||
var module = broadcast.getValueFromUrl('module', url);
|
||||
var action = broadcast.getValueFromUrl('action', url);
|
||||
|
||||
var moduleId = broadcast.getValueFromUrl("idGoal", url) || broadcast.getValueFromUrl("idDashboard", url);
|
||||
var main_menu = $(this).parent().hasClass('Menu-tabList') ? true : false;
|
||||
|
||||
if (main_menu) {
|
||||
$(this).attr({id: module});
|
||||
$this.attr({id: module});
|
||||
}
|
||||
// if there's a idGoal or idDashboard, use this in the ID
|
||||
else if (moduleId != '') {
|
||||
|
|
@ -70,27 +98,65 @@ menu.prototype =
|
|||
}
|
||||
});
|
||||
|
||||
menu.prototype.adaptSubMenuHeight();
|
||||
this.menuNode.find('a.item').click(this.onItemClick);
|
||||
|
||||
var self = this;
|
||||
$('#header .toggle-second-menu').click(function () {
|
||||
self.menuNode.toggleClass('open fadeInLeft');
|
||||
});
|
||||
},
|
||||
|
||||
activateMenu: function (module, action, id) {
|
||||
this.menuNode.find('li').removeClass('sfHover').removeClass('sfActive');
|
||||
var $li = this.getSubmenuID(module, id, action);
|
||||
var mainLi = $("#" + module);
|
||||
if (!mainLi.length) {
|
||||
mainLi = $li.parents('li');
|
||||
}
|
||||
activateMenu: function (module, action, params) {
|
||||
params = params || {};
|
||||
params.module = module;
|
||||
params.action = action;
|
||||
|
||||
mainLi.addClass('sfActive').addClass('sfHover');
|
||||
this.menuNode.find('li').removeClass('sfActive');
|
||||
|
||||
$li.addClass('sfHover');
|
||||
var isAdmin = this.isAdmin();
|
||||
|
||||
var $activeLink = this.menuNode.find('a').filter(function () {
|
||||
var url = $(this).attr('href');
|
||||
if (!url) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var found = false;
|
||||
for (var key in params) {
|
||||
if (!params.hasOwnProperty(key)
|
||||
|| !params[key]
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var actual;
|
||||
|
||||
if (isAdmin) {
|
||||
actual = broadcast.getValueFromUrl(key, url);
|
||||
} else {
|
||||
actual = broadcast.getValueFromHash(key, url);
|
||||
}
|
||||
|
||||
if (actual != params[key]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
found = true;
|
||||
// at least one param must match. Otherwise all menu items might be highlighted if params[key] = null;
|
||||
}
|
||||
|
||||
return found;
|
||||
});
|
||||
|
||||
$activeLink.closest('li').addClass('sfActive');
|
||||
$activeLink.closest('li.menuTab').addClass('sfActive');
|
||||
},
|
||||
|
||||
// getting the right li is a little tricky since goals uses idGoal, and overview is index.
|
||||
getSubmenuID: function (module, id, action) {
|
||||
var $li = '';
|
||||
// So, if module is Goals, id is present, and action is not Index, must be one of the goals
|
||||
if (module == 'Goals' && id != '' && (action != 'index')) {
|
||||
if ((module == 'Goals' || module == 'Ecommerce') && id != '' && (action != 'index')) {
|
||||
$li = $("#" + module + "_" + action + "_" + id);
|
||||
// if module is Dashboard and id is present, must be one of the dashboards
|
||||
} else if (module == 'Dashboard') {
|
||||
|
|
@ -104,7 +170,7 @@ menu.prototype =
|
|||
|
||||
loadFirstSection: function () {
|
||||
if (broadcast.isHashExists() == false) {
|
||||
$('li:first a:first', this.menuNode).click().addClass('sfHover').addClass('sfActive');
|
||||
$('.navbar li:first ul a:first', this.menuNode).click().addClass('sfActive');
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
@ -1,19 +1,40 @@
|
|||
$(function () {
|
||||
var isPageHasMenu = $('.Menu--dashboard').size();
|
||||
var isPageHasMenu = $('#secondNavBar').size();
|
||||
var isPageIsAdmin = $('#content.admin').size();
|
||||
|
||||
if (isPageHasMenu) {
|
||||
piwikMenu = new menu();
|
||||
piwikMenu.init();
|
||||
piwikMenu.loadFirstSection();
|
||||
if (isPageIsAdmin) {
|
||||
piwikMenu.activateMenu(broadcast.getValueFromUrl('module'), broadcast.getValueFromUrl('action'), '');
|
||||
} else {
|
||||
piwikMenu.loadFirstSection();
|
||||
}
|
||||
} else if (!isPageIsAdmin) {
|
||||
// eg multisites
|
||||
initTopControls();
|
||||
}
|
||||
|
||||
if(isPageIsAdmin) {
|
||||
// don't use broadcast in admin pages
|
||||
if (isPageIsAdmin) {
|
||||
// don't use broadcast in admin page
|
||||
initTopControls();
|
||||
return;
|
||||
}
|
||||
if(isPageHasMenu) {
|
||||
|
||||
if (isPageHasMenu) {
|
||||
broadcast.init();
|
||||
} else {
|
||||
broadcast.init(true);
|
||||
}
|
||||
|
||||
$('.menuTab').keydown(function(e){
|
||||
if(e.which==27){
|
||||
var isFocusedInSubmenu = !$(':focus').parent().hasClass('menuTab')
|
||||
if(isFocusedInSubmenu){
|
||||
$(this).closest('.menuTab').attr('tabindex', -1).focus();
|
||||
$('body').scrollTop(0);
|
||||
}
|
||||
$('.sfActive').removeClass('sfActive');
|
||||
}
|
||||
})
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Piwik - Web Analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -50,26 +50,18 @@
|
|||
options = {};
|
||||
}
|
||||
|
||||
if ('persistent' == options.type) {
|
||||
// otherwise it is never possible to dismiss the notification
|
||||
options.noclear = false;
|
||||
}
|
||||
var template = generateNotificationHtmlMarkup(options, message);
|
||||
this.$node = placeNotification(template, options);
|
||||
};
|
||||
|
||||
closeExistingNotificationHavingSameIdIfNeeded(options);
|
||||
|
||||
var template = generateNotificationHtmlMarkup(options, message);
|
||||
var $notificationNode = placeNotification(template, options);
|
||||
this.$node = $notificationNode;
|
||||
|
||||
if ('persistent' == options.type) {
|
||||
addPersistentEvent($notificationNode);
|
||||
} else if ('toast' == options.type) {
|
||||
addToastEvent($notificationNode);
|
||||
}
|
||||
|
||||
if (!options.noclear) {
|
||||
addCloseEvent($notificationNode);
|
||||
}
|
||||
/**
|
||||
* Removes a previously shown notification having the given notification id.
|
||||
*
|
||||
*
|
||||
* @param {string} notificationId The id of a notification that was previously registered.
|
||||
*/
|
||||
Notification.prototype.remove = function (notificationId) {
|
||||
$('[piwik-notification][notification-id=' + notificationId + ']').remove();
|
||||
};
|
||||
|
||||
Notification.prototype.scrollToNotification = function () {
|
||||
|
|
@ -80,69 +72,37 @@
|
|||
|
||||
exports.Notification = Notification;
|
||||
|
||||
function closeExistingNotificationHavingSameIdIfNeeded(options)
|
||||
{
|
||||
if (!options.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $existingNode = $('.system.notification[data-id=' + options.id + ']');
|
||||
if ($existingNode && $existingNode.length) {
|
||||
$existingNode.remove();
|
||||
}
|
||||
}
|
||||
|
||||
function generateNotificationHtmlMarkup(options, message) {
|
||||
var template = buildNotificationStart(options);
|
||||
var attributeMapping = {
|
||||
id: 'notification-id',
|
||||
title: 'notification-title',
|
||||
context: 'context',
|
||||
type: 'type',
|
||||
noclear: 'noclear'
|
||||
},
|
||||
html = '<div piwik-notification';
|
||||
|
||||
if (!options.noclear) {
|
||||
template += buildClearButton();
|
||||
for (var key in attributeMapping) {
|
||||
if (attributeMapping.hasOwnProperty(key)
|
||||
&& options[key]
|
||||
) {
|
||||
html += ' ' + attributeMapping[key] + '="' + options[key].toString().replace(/"/g, """) + '"';
|
||||
}
|
||||
}
|
||||
|
||||
if (options.title) {
|
||||
template += buildTitle(options);
|
||||
}
|
||||
html += '>' + message + '</div>';
|
||||
|
||||
template += message;
|
||||
template += buildNotificationEnd();
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
function buildNotificationStart(options) {
|
||||
var template = '<div class="notification system';
|
||||
|
||||
if (options.context) {
|
||||
template += ' notification-' + options.context;
|
||||
}
|
||||
|
||||
template += '"';
|
||||
|
||||
if (options.id) {
|
||||
template += ' data-id="' + options.id + '"';
|
||||
}
|
||||
|
||||
template += '>';
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
function buildNotificationEnd() {
|
||||
return '</div>';
|
||||
}
|
||||
|
||||
function buildClearButton() {
|
||||
return '<button type="button" class="close" data-dismiss="alert">×</button>';
|
||||
}
|
||||
|
||||
function buildTitle(options) {
|
||||
return '<strong>' + options.title + '</strong> ';
|
||||
return html;
|
||||
}
|
||||
|
||||
function placeNotification(template, options) {
|
||||
|
||||
var $notificationNode = $(template);
|
||||
|
||||
// compile the template in angular
|
||||
angular.element(document).injector().invoke(function ($compile, $rootScope) {
|
||||
$compile($notificationNode)($rootScope.$new(true));
|
||||
});
|
||||
|
||||
if (options.style) {
|
||||
$notificationNode.css(options.style);
|
||||
}
|
||||
|
|
@ -159,40 +119,4 @@
|
|||
return $notificationNode;
|
||||
}
|
||||
|
||||
function addToastEvent($notificationNode)
|
||||
{
|
||||
setTimeout(function () {
|
||||
$notificationNode.fadeOut( 'slow', function() {
|
||||
$notificationNode.remove();
|
||||
$notificationNode = null;
|
||||
});
|
||||
}, 12 * 1000);
|
||||
}
|
||||
|
||||
function addCloseEvent($notificationNode) {
|
||||
$notificationNode.on('click', '.close', function (event) {
|
||||
if (event && event.delegateTarget) {
|
||||
$(event.delegateTarget).remove();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function addPersistentEvent($notificationNode) {
|
||||
var notificationId = $notificationNode.data('id');
|
||||
|
||||
if (!notificationId) {
|
||||
return;
|
||||
}
|
||||
|
||||
$notificationNode.on('click', '.close', function (event) {
|
||||
var ajaxHandler = new ajaxHelper();
|
||||
ajaxHandler.addParams({
|
||||
module: 'CoreHome',
|
||||
action: 'markNotificationAsRead'
|
||||
}, 'GET');
|
||||
ajaxHandler.addParams({notificationId: notificationId}, 'POST');
|
||||
ajaxHandler.send(true);
|
||||
});
|
||||
};
|
||||
|
||||
})(jQuery, require);
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Piwik - Web Analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
|
|||
143
www/analytics/plugins/CoreHome/javascripts/numberFormatter.js
Normal file
143
www/analytics/plugins/CoreHome/javascripts/numberFormatter.js
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*!
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Number Formatter for formatting numbers, percent and currencies values
|
||||
*
|
||||
* @type {object}
|
||||
*/
|
||||
var NumberFormatter = (function () {
|
||||
|
||||
var minimumFractionDigits = 0;
|
||||
var maximumFractionDigits = 2;
|
||||
|
||||
/**
|
||||
* Formats the given numeric value with the given pattern
|
||||
*
|
||||
* @param value
|
||||
* @param pattern
|
||||
* @returns {string}
|
||||
*/
|
||||
function format(value, pattern) {
|
||||
|
||||
if (!$.isNumeric(value)) {
|
||||
return value;
|
||||
}
|
||||
pattern = pattern || piwik.numbers.patternNumber;
|
||||
|
||||
var patterns = pattern.split(';');
|
||||
if (patterns.length == 1) {
|
||||
// No explicit negative pattern was provided, construct it.
|
||||
patterns.push('-' + patterns[0])
|
||||
}
|
||||
|
||||
// Ensure that the value is positive and has the right number of digits.
|
||||
var negative = value < 0;
|
||||
pattern = negative ? patterns[1] : patterns[0];
|
||||
|
||||
var usesGrouping = (pattern.indexOf(',') != -1);
|
||||
// if pattern has number groups, parse them.
|
||||
if (usesGrouping) {
|
||||
var primaryGroupMatches = pattern.match(/#+0/);
|
||||
var primaryGroupSize = primaryGroupMatches[0].length;
|
||||
var secondaryGroupSize = primaryGroupMatches[0].length;
|
||||
var numberGroups = pattern.split(',');
|
||||
// check for distinct secondary group size.
|
||||
if (numberGroups.length > 2) {
|
||||
secondaryGroupSize = numberGroups[1].length;
|
||||
}
|
||||
}
|
||||
|
||||
var signMultiplier = negative ? '-1' : '1';
|
||||
value = value * signMultiplier;
|
||||
// Split the number into major and minor digits.
|
||||
var valueParts = value.toString().split('.');
|
||||
var majorDigits = valueParts[0];
|
||||
// Account for maximumFractionDigits = 0, where the number won't
|
||||
// have a decimal point, and $valueParts[1] won't be set.
|
||||
minorDigits = valueParts[1] || '';
|
||||
if (usesGrouping) {
|
||||
// Reverse the major digits, since they are grouped from the right.
|
||||
majorDigits = majorDigits.split('').reverse();
|
||||
// Group the major digits.
|
||||
var groups = [];
|
||||
groups.push(majorDigits.splice(0, primaryGroupSize).reverse().join(''));
|
||||
while (majorDigits.length) {
|
||||
groups.push(majorDigits.splice(0, secondaryGroupSize).reverse().join(''));
|
||||
}
|
||||
// Reverse the groups and the digits inside of them.
|
||||
groups = groups.reverse();
|
||||
// Reconstruct the major digits.
|
||||
majorDigits = groups.join(',');
|
||||
}
|
||||
if (minimumFractionDigits < maximumFractionDigits) {
|
||||
// Strip any trailing zeroes.
|
||||
var minorDigits = minorDigits.replace(/0+$/,'');
|
||||
if (minorDigits.length < minimumFractionDigits) {
|
||||
// Now there are too few digits, re-add trailing zeroes
|
||||
// until the desired length is reached.
|
||||
var neededZeroes = minimumFractionDigits - minorDigits.length;
|
||||
minorDigits += (new Array(neededZeroes+1)).join('0');
|
||||
}
|
||||
}
|
||||
// Assemble the final number and insert it into the pattern.
|
||||
value = minorDigits ? majorDigits + '.' + minorDigits : majorDigits;
|
||||
value = pattern.replace(/#(?:[\.,]#+)*0(?:[,\.][0#]+)*/, value);
|
||||
// Localize the number.
|
||||
return replaceSymbols(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the placeholders with real symbols
|
||||
*
|
||||
* @param value
|
||||
* @returns {string}
|
||||
*/
|
||||
function replaceSymbols(value) {
|
||||
var replacements = {
|
||||
'.': piwik.numbers.symbolDecimal,
|
||||
',': piwik.numbers.symbolGroup,
|
||||
'+': piwik.numbers.symbolPlus,
|
||||
'-': piwik.numbers.symbolMinus,
|
||||
'%': piwik.numbers.symbolPercent
|
||||
};
|
||||
|
||||
var newValue = '';
|
||||
var valueParts = value.split('');
|
||||
|
||||
$.each(valueParts, function(index, value) {
|
||||
$.each(replacements, function(char, replacement) {
|
||||
if (value.indexOf(char) != -1) {
|
||||
value = value.replace(char, replacement);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
newValue += value;
|
||||
});
|
||||
|
||||
return newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public available methods
|
||||
*/
|
||||
return {
|
||||
|
||||
formatNumber: function (value) {
|
||||
return format(value, piwik.numbers.patternNumber);
|
||||
},
|
||||
|
||||
formatPercent: function (value) {
|
||||
return format(value, piwik.numbers.patternPercent);
|
||||
},
|
||||
|
||||
formatCurrency: function (value, currency) {
|
||||
var formatted = format(value, piwik.numbers.patternCurrency);
|
||||
return formatted.replace('¤', currency);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* Piwik - Web Analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -20,11 +20,11 @@ var Piwik_Popover = (function () {
|
|||
var openPopover = function (title, dialogClass) {
|
||||
createContainer();
|
||||
|
||||
var options =
|
||||
var options =
|
||||
{
|
||||
title: title,
|
||||
modal: true,
|
||||
width: '950px',
|
||||
width: '1050px',
|
||||
position: ['center', 'center'],
|
||||
resizable: false,
|
||||
autoOpen: true,
|
||||
|
|
@ -142,7 +142,17 @@ var Piwik_Popover = (function () {
|
|||
|
||||
/** Set the title of the popover */
|
||||
setTitle: function (titleHtml) {
|
||||
var titleText = piwikHelper.htmlDecode(titleHtml);
|
||||
if (titleText.length > 60) {
|
||||
titleHtml = $('<span>').attr('class', 'tooltip').attr('title', titleText).html(titleHtml);
|
||||
}
|
||||
container.dialog('option', 'title', titleHtml);
|
||||
try {
|
||||
$('.tooltip', container.parentNode).tooltip('destroy');
|
||||
} catch (e) {}
|
||||
if (titleText.length > 60) {
|
||||
$('.tooltip', container.parentNode).tooltip({track: true, items: '.tooltip'});
|
||||
}
|
||||
},
|
||||
|
||||
/** Set inner HTML of the popover */
|
||||
|
|
@ -209,11 +219,11 @@ var Piwik_Popover = (function () {
|
|||
|
||||
/**
|
||||
* Create a Popover and load the specified URL in it.
|
||||
*
|
||||
*
|
||||
* Note: If you want the popover to be persisted in the URL (so if the URL is copy/pasted
|
||||
* to a new window/tab it will be opened there), use broadcast.propagateNewPopoverParameter
|
||||
* with a popover handler function that calls this one.
|
||||
*
|
||||
*
|
||||
* @param {string} url
|
||||
* @param {string} loadingName
|
||||
* @param {string} [dialogClass] css class to add to dialog
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
$(function () {
|
||||
$('#piwik-promo-thumbnail').click(function () {
|
||||
var promoEmbed = $('#piwik-promo-embed'),
|
||||
widgetWidth = $(this).closest('.widgetContent').width(),
|
||||
height = (266 * widgetWidth) / 421,
|
||||
embedHtml = '<iframe width="100%" height="' + height + '" src="http://www.youtube.com/embed/OslfF_EH81g?autoplay=1&vq=hd720&wmode=transparent" frameborder="0" wmode="Opaque"></iframe>';
|
||||
|
||||
$(this).hide();
|
||||
promoEmbed.height(height).html(embedHtml);
|
||||
promoEmbed.show();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Piwik - Web Analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* Module creation & inclusion for Piwik.
|
||||
*
|
||||
|
|
@ -13,9 +13,9 @@
|
|||
|
||||
/**
|
||||
* Returns a module for its ID. Empty modules are created if they does not exist.
|
||||
*
|
||||
*
|
||||
* Modules are currently stored in the window object.
|
||||
*
|
||||
*
|
||||
* @param {String} moduleId e.g. 'piwik/UserCountryMap' or 'myPlugin/Widgets/FancySchmancyThing'.
|
||||
* The following characters can be used to separate individual modules:
|
||||
* '/', '.' or '\'.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* Piwik - Web Analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -17,11 +17,11 @@ piwik.getSparklineColors = function () {
|
|||
piwik.initSparklines = function() {
|
||||
$('.sparkline > img').each(function () {
|
||||
var $self = $(this);
|
||||
|
||||
|
||||
if ($self.attr('src')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var colors = JSON.stringify(piwik.getSparklineColors());
|
||||
var appendToSparklineUrl = '&colors=' + encodeURIComponent(colors);
|
||||
|
||||
|
|
@ -42,10 +42,14 @@ window.initializeSparklines = function () {
|
|||
|
||||
// try to find sparklines and add them clickable behaviour
|
||||
graph.parent().find('div.sparkline').each(function () {
|
||||
|
||||
// find the sparkline and get it's src attribute
|
||||
var sparklineUrl = $('img', this).attr('data-src');
|
||||
|
||||
if (sparklineUrl != "") {
|
||||
|
||||
$(this).addClass('linked');
|
||||
|
||||
var params = broadcast.getValuesFromUrl(sparklineUrl);
|
||||
for (var i = 0; i != sparklineUrlParamsToIgnore.length; ++i) {
|
||||
delete params[sparklineUrlParamsToIgnore[i]];
|
||||
|
|
@ -60,7 +64,8 @@ window.initializeSparklines = function () {
|
|||
}
|
||||
|
||||
// on click, reload the graph with the new url
|
||||
$(this).click(function () {
|
||||
$(this).off('click.sparkline');
|
||||
$(this).on('click.sparkline', function () {
|
||||
var reportId = graph.attr('data-graph-id'),
|
||||
dataTable = $(require('piwik/UI').DataTable.getDataTableByReport(reportId));
|
||||
|
||||
|
|
@ -69,7 +74,11 @@ window.initializeSparklines = function () {
|
|||
// if this happens, we can't find the graph using $('#'+idDataTable+"Chart");
|
||||
// instead, we just use the first evolution graph we can find.
|
||||
if (dataTable.length == 0) {
|
||||
dataTable = $('div.dataTableVizEvolution');
|
||||
if ($(this).closest('.widget').length) {
|
||||
dataTable = $(this).closest('.widget').find('div.dataTableVizEvolution');
|
||||
} else {
|
||||
dataTable = $('div.dataTableVizEvolution');
|
||||
}
|
||||
}
|
||||
|
||||
// reload the datatable w/ a new column & scroll to the graph
|
||||
|
|
|
|||
|
|
@ -1,13 +1,33 @@
|
|||
/*!
|
||||
* Piwik - Web Analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
function initTopControls() {
|
||||
function getOverlap(element1, element2)
|
||||
{
|
||||
if (!element1 || !element1.getBoundingClientRect || !element2 || !element2.getBoundingClientRect) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var rect1 = element1.getBoundingClientRect();
|
||||
var rect2 = element2.getBoundingClientRect();
|
||||
|
||||
var doOverlap = !(rect1.right < rect2.left || rect1.left > rect2.right);
|
||||
|
||||
if (doOverlap) {
|
||||
return rect1.left - rect2.right;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
var $topControlsContainer = $('.top_controls'),
|
||||
left = 0;
|
||||
|
||||
|
||||
var allRendered = true;
|
||||
|
||||
if ($topControlsContainer.length) {
|
||||
$('.piwikTopControl').each(function () {
|
||||
var $control = $(this);
|
||||
|
|
@ -16,12 +36,79 @@ function initTopControls() {
|
|||
}
|
||||
|
||||
$control.css('left', left);
|
||||
var width = $control.outerWidth(true);
|
||||
|
||||
if (!$.contains($topControlsContainer[0], this)) {
|
||||
$control.detach().appendTo($topControlsContainer);
|
||||
var isControlFullyRendered = width >= 30;
|
||||
if (!isControlFullyRendered) {
|
||||
allRendered = false;
|
||||
}
|
||||
|
||||
left += $control.outerWidth(true);
|
||||
left += width;
|
||||
});
|
||||
|
||||
if (allRendered) {
|
||||
// we make top controls visible only after all selectors are rendered
|
||||
$('.top_controls').css('visibility', 'visible');
|
||||
$('.top_controls').css('opacity', '1');
|
||||
}
|
||||
|
||||
var header = $('#header_message.isPiwikDemo');
|
||||
if (header.length) {
|
||||
// make sure isPiwikDemo message is always fully visible, move it to the right if needed
|
||||
var lastSelector = $('.top_controls .piwikTopControl:last');
|
||||
|
||||
var overlap = getOverlap(header[0], lastSelector[0]);
|
||||
if (header[0] !== lastSelector[0] && overlap !== 0) {
|
||||
header.css('right', (Math.abs(overlap) + 18) * -1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Keyboard controls for Top Controls Calendar through tab and enter.
|
||||
$( document ).ready(function() {
|
||||
$('.periodSelector').keydown(function(e){
|
||||
toggleCalendar(e);
|
||||
})
|
||||
|
||||
blockPropegation();
|
||||
|
||||
$('.periodSelector .form-radio').keydown(function(e){
|
||||
e.stopPropagation();
|
||||
if(e.which==13){
|
||||
selectPeriodRadioButton($(this));
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
function toggleCalendar(e){
|
||||
var calendarOpen = $('.periodSelector').hasClass('expanded');
|
||||
|
||||
$('.periodSelector .ui-datepicker-month').attr('tabindex','4');
|
||||
$('.periodSelector td a').attr('tabindex','4');
|
||||
$('.periodSelector .ui-datepicker-year').attr('tabindex','4');
|
||||
$('.periodSelector .form-radio').attr('tabindex','4');
|
||||
|
||||
if(e.which==13){
|
||||
if(calendarOpen){
|
||||
$('.periodSelector').removeClass('expanded');
|
||||
}else{
|
||||
$('.periodSelector').addClass('expanded');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function selectPeriodRadioButton(button){
|
||||
$('.periodSelector .form-radio').removeClass('checked');
|
||||
button.addClass('checked');
|
||||
button.find('input').click();
|
||||
|
||||
blockPropegation();
|
||||
}
|
||||
|
||||
function blockPropegation(){
|
||||
$('.ui-datepicker-month, .ui-datepicker-year, .periodSelector td a').keydown(function(e){
|
||||
e.stopPropagation();
|
||||
})
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Piwik - Web Analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* Visitor profile popup control.
|
||||
*
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
/**
|
||||
* Base type for Piwik UI controls. Provides functionality that all controls need (such as
|
||||
* cleanup on destruction).
|
||||
*
|
||||
*
|
||||
* @param {Element} element The root element of the control.
|
||||
*/
|
||||
var UIControl = function (element) {
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
}
|
||||
}
|
||||
this.param = params;
|
||||
|
||||
|
||||
this.props = JSON.parse($element.attr('data-props') || '{}');
|
||||
};
|
||||
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
/**
|
||||
* Utility method that will clean up all piwik UI controls whose elements are not attached
|
||||
* to the DOM.
|
||||
*
|
||||
*
|
||||
* TODO: instead of having other pieces of the UI manually calling cleanupUnusedControls,
|
||||
* MutationObservers should be used
|
||||
*/
|
||||
|
|
@ -95,8 +95,8 @@
|
|||
|
||||
/**
|
||||
* Handle the widget resize event, if we're currently in a widget.
|
||||
*
|
||||
* TODO: should use proper resize detection (see
|
||||
*
|
||||
* TODO: should use proper resize detection (see
|
||||
* http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/ )
|
||||
* with timeouts (since resizing widgets can be expensive)
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue