Newer
Older
* Piwik - Web Analytics
*
* @link http://piwik.org
*/
htmlDecode: function(value)
{
return $('<div/>').html(value).text();
},
htmlEntities: function(value)
{
var findReplace = [[/&/g, "&"], [/</g, "<"], [/>/g, ">"], [/"/g, """]];
for(var item in findReplace) {
value = value.replace(findReplace[item][0], findReplace[item][1]);
}
return value;
},
/**
* Add break points to a string so that it can be displayed more compactly
*/
addBreakpoints: function(text, breakpointMarkup)
{
return text.replace(/([\/&=?\.%#:])/g, '$1' +
(typeof breakpointMarkup == 'undefined' ? '<wbr>' : breakpointMarkup));
},
/**
* Add breakpoints to a URL
* urldecodes and encodes htmlentities to display utf8 urls without XSS vulnerabilities
*/
addBreakpointsToUrl: function(url)
{
try {
url = decodeURIComponent(url);
} catch (e) {
// might throw "URI malformed"
}
url = piwikHelper.addBreakpoints(url, '|||');
url = $(document.createElement('p')).text(url).html();
url = url.replace(/\|\|\|/g, '<wbr />');
return url;
},
/**
* Displays a Modal dialog. Text will be taken from the DOM node domSelector.
* Given callback handles will be mapped to the buttons having a role attriute
*
* Dialog will be closed when a button is clicked and callback handle will be
* called, if one was given for the clicked role
*
* @param {string} domSelector domSelector for modal window
* @param {object} handles callback functions for available roles
* @return {void}
*/
modalConfirm: function( domSelector, handles )
{
var domElem = $(domSelector);
var buttons = {};
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
$('[role]', domElem).each(function(){
var role = $(this).attr('role');
var text = $(this).val();
if(typeof handles[role] == 'function') {
buttons[text] = function(){$(this).dialog("close"); handles[role].apply()};
} else {
buttons[text] = function(){$(this).dialog("close");};
}
$(this).hide();
});
domElem.dialog({
resizable: false,
modal: true,
buttons: buttons,
width: 650,
position: ['center', 90]
});
},
/**
* Array holding all running ajax requests
* @type {Array}
*/
globalAjaxQueue: [],
/**
* Registers the given requests to the list of running requests
* @param {XMLHttpRequest} request Request to be registered
* @return {void}
*/
queueAjaxRequest: function( request )
{
this.globalAjaxQueue.push(request);
// clean up finished requests
for(var i = this.globalAjaxQueue.length; i--; ) {
if(!this.globalAjaxQueue[i] || this.globalAjaxQueue[i].readyState == 4) {
this.globalAjaxQueue.splice(i, 1);
}
/**
* Call an API method
*
* @param method API method name, i.e. Plugin.Method
* @param params parameters for the request
* @param callback regular callback
* @param async defines if the request should be asnyc (default: true)
*
* @return {void}
*/
ajaxCallApi: function(method, params, callback, async)
{
params.method = method;
piwikHelper.ajaxCall('API', false, params, callback, async);
},
/**
* Do an AJAX request
*
* @param module plugin name
* @param action method name
* @param params parameters for the request
* @param callback regular callback
* @param format response format, default json
* @param async defines if the request should be asnyc (default: true)
*
* @return {void}
*/
ajaxCall: function(module, action, params, callback, format, async) {
if (action)
{
params.idSite = params.idSite ? params.idSite : piwik.idSite;
params.period = params.period ? params.period : piwik.period;
params.date = piwik.currentDateString;
if (params.period == 'range')
params.date = piwik.startDateString + ',' + params.date;
// never append token_auth to url
if(params.token_auth) {
params.token_auth = null;
delete params.token_auth;
}
var segment = params.segment ? params.segment : broadcast.getValueFromHash('segment', window.location.href);
if (segment)
{
var ajaxRequest =
{
type: 'POST',
async: async !== false,
url: 'index.php?' + $.param(params),
dataType: format || 'json',
error: piwikHelper.ajaxHandleError,
success: callback,
data: {token_auth: piwik.token_auth}
};
piwikHelper.queueAjaxRequest($.ajax(ajaxRequest));
/**
* Aborts all registered running ajax requests
* @return {Boolean}
*/
abortQueueAjax: function()
{
for(var request in this.globalAjaxQueue) {
this.globalAjaxQueue[request].abort();
}
this.globalAjaxQueue = [];
return true;
},
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/**
* Returns the current query string with the given parameters modified
* @param {object} newparams parameters to be modified
* @return {String}
*/
getCurrentQueryStringWithParametersModified: function(newparams)
{
var parameters = String(window.location.search);
if(newparams) {
if(parameters != '') {
var r, i, keyvalue, keysvalues = newparams.split('&');
for(i in keysvalues) {
keyvalue = keysvalues[i].split('=');
r = new RegExp('(^|[?&])'+keyvalue[0]+'=[^&]*');
parameters = parameters.replace(r, '');
}
parameters += '&' + newparams;
if(parameters[0] == '&') {
parameters = '?' + parameters.substring(1);
}
} else {
parameters = '?' + newparams;
}
}
return String(window.location.pathname) + parameters;
},
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/**
* Returns query string for an object of key,values
* Note: we don't use $.param from jquery as it doesn't return array values the PHP way (returns a=v1&a=v2 instead of a[]=v1&a[]=v2)
* Example:
* piwikHelper.getQueryStringFromParameters({"a":"va","b":["vb","vc"],"c":1})
* Returns:
* a=va&b[]=vb&b[]=vc&c=1
* @param {object} parameters
* @return {string}
*/
getQueryStringFromParameters: function(parameters)
{
var queryString = '';
if(!parameters || parameters.length==0) {
return queryString;
}
for(var name in parameters) {
var value = parameters[name];
if(typeof value == 'object') {
for(var i in value) {
queryString += name + '[]=' + value[i] + '&';
}
} else {
queryString += name + '=' + value + '&';
}
}
return queryString.substring(0, queryString.length-1);
},
/**
* Displays the given ajax error message within the given id element
* @param {string} message error message
* @param {string} errorDivID id of the domNode (defaults to ajaxError)
* @return {void}
*/
showAjaxError: function( message, errorDivID )
{
errorDivID = errorDivID || 'ajaxError';
$('#'+errorDivID).html(message).show();
},
/**
* Hides the error message with the given id
* @param {string} errorDivID id of the domNode (defaults to ajaxError)
* @return {void}
*/
hideAjaxError: function(errorDivID)
{
errorDivID = errorDivID || 'ajaxError';
$('#'+errorDivID).hide();
},
/**
* Shows the loading message with the given Id
* @param {string} loadingDivID id of the domNode (defaults to ajaxLoading)
* @return {void}
*/
showAjaxLoading: function(loadingDivID)
{
loadingDivID = loadingDivID || 'ajaxLoading';
$('#'+loadingDivID).show();
},
/**
* Hides the loading message with the given id
* @param {string} loadingDivID id of the domNode (defaults to ajaxLoading)
* @return {void}
*/
hideAjaxLoading: function(loadingDivID)
{
loadingDivID = loadingDivID || 'ajaxLoading';
$('#'+loadingDivID).hide();
},
/**
* Returns default configuration for ajax requests
* @param {string} loadingDivID id of domNode used for loading message
* @param {string} errorDivID id of domNode used for error messages
* @param {object} params params used for handling response
* @return {object}
*/
getStandardAjaxConf: function(loadingDivID, errorDivID, params)
{
piwikHelper.showAjaxLoading(loadingDivID);
piwikHelper.hideAjaxError(errorDivID);
var ajaxRequest = {};
ajaxRequest.type = 'GET';
ajaxRequest.url = 'index.php';
ajaxRequest.dataType = 'json';
ajaxRequest.error = piwikHelper.ajaxHandleError;
ajaxRequest.success = function(response) { piwikHelper.ajaxHandleResponse(response, loadingDivID, errorDivID, params); };
return ajaxRequest;
},
/**
* Reloads the page after the given period
* @param {int} timeoutPeriod
* @return void
*/
refreshAfter: function(timeoutPeriod)
{
if(timeoutPeriod == 0) {
/**
* Redirect to the given url
* @param {string} url
*/
redirectToUrl: function(url)
{
window.location = url;
},
/**
* Method to handle ajax errors
* @param {XMLHttpRequest} deferred
* @param {string} status
* @return {void}
*/
ajaxHandleError: function(deferred, status)
{
// do not display error message if request was aborted
if(status == 'abort') {
return;
}
$('#loadingError').show();
setTimeout( function(){
$('#loadingError').fadeOut('slow');
}, 2000);
},
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
/**
* Method to handle ajax response
* @param {} response
* @param {string} loadingDivID
* @param {string} errorDivID
* @param {object} params
* @return {void}
*/
ajaxHandleResponse: function(response, loadingDivID, errorDivID, params)
{
if(response.result == "error")
{
piwikHelper.hideAjaxLoading(loadingDivID);
piwikHelper.showAjaxError(response.message, errorDivID);
}
else
{
// add updated=1 to the URL so that a "Your changes have been saved" message is displayed
var urlToRedirect = piwikHelper.getCurrentQueryStringWithParametersModified(params);
var updatedUrl = new RegExp('&updated=([0-9]+)');
var updatedCounter = updatedUrl.exec(urlToRedirect);
if(!updatedCounter)
{
urlToRedirect += '&updated=1';
}
else
{
updatedCounter = 1 + parseInt(updatedCounter[1]);
urlToRedirect = urlToRedirect.replace(new RegExp('(&updated=[0-9]+)'), '&updated=' + updatedCounter);
}
var currentHashStr = window.location.hash;
if(currentHashStr.length > 0) {
urlToRedirect += currentHashStr;
}
piwikHelper.redirectToUrl(urlToRedirect);
}
},
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
/**
* Scrolls the window to the jquery element 'elem'
* if the top of the element is not currently visible on screen
* @param {string} elem Selector for the DOM node to scroll to, eg. '#myDiv'
* @param {int} time Specifies the duration of the animation in ms
* @return {void}
*/
lazyScrollTo: function(elem, time)
{
var elemTop = $(elem).offset().top;
// only scroll the page if the graph is not visible
if(elemTop < $(window).scrollTop()
|| elemTop > $(window).scrollTop()+$(window).height())
{
// scroll the page smoothly to the graph
$.scrollTo(elem, time);
}
},
/**
* Returns the filtered/converted content of a textarea to be used for api requests
* @param {string} textareaContent
* @return {string}
*/
getApiFormatTextarea: function (textareaContent)
{
return textareaContent.trim().split("\n").join(',');
}
};
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g,"");
};
/**
* Returns true if the event keypress passed in parameter is the ENTER key
* @param {Event} e current window event
* @return {boolean}
*/
return (window.event?window.event.keyCode:e.which)==13;
// workarounds
(function($){
try { // this code is not vital, so we make sure any errors are ignored
// monkey patch that works around bug in arc function of some browsers where
// nothing gets drawn if angles are 2 * PI apart and in counter-clockwise direction.
// affects some versions of chrome & IE 8
var oldArc = CanvasRenderingContext2D.prototype.arc;
CanvasRenderingContext2D.prototype.arc = function(x, y, r, sAngle, eAngle, clockwise) {
if (Math.abs(eAngle - sAngle - Math.PI * 2) < 0.000001 && !clockwise)
eAngle -= 0.000001;
oldArc.call(this, x, y, r, sAngle, eAngle, clockwise);
};
} catch (e) {}
}(jQuery));