Newer
Older
sgiehl
a validé
/*!
* Piwik - free/libre analytics platform
sgiehl
a validé
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
/**
* global ajax queue
*
* @type {Array} array holding XhrRequests with automatic cleanup
*/
Benaka Moorthi
a validé
globalAjaxQueue.active = 0;
sgiehl
a validé
/**
Benaka Moorthi
a validé
* Removes all finished requests from the queue.
Benaka Moorthi
a validé
* @return {void}
sgiehl
a validé
*/
Benaka Moorthi
a validé
globalAjaxQueue.clean = function () {
sgiehl
a validé
for (var i = this.length; i--;) {
if (!this[i] || this[i].readyState == 4) {
this.splice(i, 1);
}
}
Benaka Moorthi
a validé
};
/**
* Extend Array.push with automatic cleanup for finished requests
*
* @return {Object}
*/
globalAjaxQueue.push = function () {
this.active += arguments.length;
// cleanup ajax queue
this.clean();
sgiehl
a validé
// call original array push
return Array.prototype.push.apply(this, arguments);
};
/**
* Extend with abort function to abort all queued requests
*
* @return {void}
*/
globalAjaxQueue.abort = function () {
// abort all queued requests
for (var i = this.length; i--;) {
this[i] && this[i].abort && this[i].abort(); // abort if possible
}
// remove all elements from array
this.splice(0, this.length);
Benaka Moorthi
a validé
this.active = 0;
sgiehl
a validé
};
/**
* Global ajax helper to handle requests within piwik
*
* @type {Object}
sgiehl
a validé
*/
function ajaxHelper() {
/**
* Format of response
* @type {String}
*/
this.format = 'json';
/**
* Should ajax request be asynchronous
sgiehl
a validé
* @type {Boolean}
*/
this.async = true;
Thomas Steur
a validé
/**
* A timeout for the request which will override any global timeout
* @type {Boolean}
*/
this.timeout = null;
sgiehl
a validé
/**
* Callback function to be executed on success
*/
this.callback = function () {};
/**
* Use this.callback if an error is returned
* @type {Boolean}
*/
this.useRegularCallbackInCaseOfError = false;
Timo Besenreuther
a validé
sgiehl
a validé
/**
* Callback function to be executed on error
*/
this.errorCallback = this.defaultErrorCallback;
sgiehl
a validé
/**
* Params to be passed as GET params
* @type {Object}
* @see ajaxHelper._mixinDefaultGetParams
*/
this.getParams = {};
Benaka Moorthi
a validé
/**
* Base URL used in the AJAX request. Can be set by setUrl.
*
* It is set to '?' rather than 'index.php?' to increase chances that it works
* including for users who have an automatic 301 redirection from index.php? to ?
* POST values are missing when there is such 301 redirection. So by by-passing
* this 301 redirection, we avoid this issue.
*
Benaka Moorthi
a validé
* @type {String}
* @see ajaxHelper.setUrl
*/
this.getUrl = '?';
Benaka Moorthi
a validé
sgiehl
a validé
/**
* Params to be passed as GET params
* @type {Object}
* @see ajaxHelper._mixinDefaultPostParams
*/
this.postParams = {};
/**
* Element to be displayed while loading
* @type {String}
*/
this.loadingElement = null;
/**
* Element to be displayed on error
* @type {String}
*/
this.errorElement = '#ajaxError';
sgiehl
a validé
/**
* Handle for current request
* @type {XMLHttpRequest}
*/
this.requestHandle = null;
/**
* Adds params to the request.
* If params are given more then once, the latest given value is used for the request
*
* @param {object} params
* @param {string} type type of given parameters (POST or GET)
* @return {void}
*/
this.addParams = function (params, type) {
Benaka Moorthi
a validé
if (typeof params == 'string') {
params = broadcast.getValuesFromUrl(params);
}
for (var key in params) {
if(type.toLowerCase() == 'get') {
this.getParams[key] = params[key];
} else if(type.toLowerCase() == 'post') {
this.postParams[key] = params[key];
}
sgiehl
a validé
}
};
Benaka Moorthi
a validé
/**
* Sets the base URL to use in the AJAX request.
Benaka Moorthi
a validé
* @param {string} url
*/
this.setUrl = function (url) {
Benaka Moorthi
a validé
this.addParams(broadcast.getValuesFromUrl(url), 'GET');
Benaka Moorthi
a validé
};
/**
* Gets this helper instance ready to send a bulk request. Each argument to this
* function is a single request to use.
*/
this.setBulkRequests = function () {
var urls = [];
for (var i = 0; i != arguments.length; ++i) {
urls.push($.param(arguments[i]));
}
this.addParams({
module: 'API',
method: 'API.getBulkRequest',
};
sgiehl
a validé
Thomas Steur
a validé
/**
* Set a timeout (in milliseconds) for the request. This will override any global timeout.
*
* @param {integer} timeout Timeout in milliseconds
* @return {void}
*/
this.setTimeout = function (timeout) {
this.timeout = timeout;
};
sgiehl
a validé
/**
* Sets the callback called after the request finishes
*
* @param {function} callback Callback function
* @return {void}
*/
this.setCallback = function (callback) {
this.callback = callback;
};
/**
* Set that the callback passed to setCallback() should be used if an application error (i.e. an
* Exception in PHP) is returned.
*/
this.useCallbackInCaseOfError = function () {
this.useRegularCallbackInCaseOfError = true;
};
Timo Besenreuther
a validé
/**
* Set callback to redirect on success handler
* &update=1(+x) will be appended to the current url
*
* @param {object} [params] to modify in redirect url
* @return {void}
*/
this.redirectOnSuccess = function (params) {
Thomas Steur
a validé
this.setCallback(function() {
piwikHelper.redirect(params);
sgiehl
a validé
/**
* Sets the callback called in case of an error within the request
*
* @param {function} callback Callback function
* @return {void}
*/
this.setErrorCallback = function (callback) {
this.errorCallback = callback;
};
/**
* error callback to use by default
*
* @param deferred
* @param status
*/
this.defaultErrorCallback = function(deferred, status)
{
// do not display error message if request was aborted
if(status == 'abort') {
return;
}
$('#loadingError').show();
setTimeout( function(){
$('#loadingError').fadeOut('slow');
}, 2000);
};
sgiehl
a validé
/**
* Sets the response format for the request
*
* @param {string} format response format (e.g. json, html, ...)
* @return {void}
*/
this.setFormat = function (format) {
this.format = format;
};
/**
* Set the div element to show while request is loading
*
* @param {String} [element] selector for the loading element
sgiehl
a validé
*/
this.setLoadingElement = function (element) {
if (!element) {
sgiehl
a validé
}
this.loadingElement = element;
};
/**
* Set the div element to show on error
*
* @param {String} element selector for the error element
*/
this.setErrorElement = function (element) {
if (!element) {
return;
}
this.errorElement = element;
};
sgiehl
a validé
/**
* Send the request
* @param {Boolean} [sync] indicates if the request should be synchronous (defaults to false)
sgiehl
a validé
* @return {void}
*/
this.send = function (sync) {
if (sync === true) {
this.async = false;
}
if ($(this.errorElement).length) {
$(this.errorElement).hide();
}
sgiehl
a validé
if (this.loadingElement) {
$(this.loadingElement).fadeIn();
}
sgiehl
a validé
this.requestHandle = this._buildAjaxCall();
globalAjaxQueue.push(this.requestHandle);
};
/**
* Aborts the current request if it is (still) running
* @return {void}
*/
this.abort = function () {
if (this.requestHandle && typeof this.requestHandle.abort == 'function') {
this.requestHandle.abort();
this.requestHandle = null;
}
};
/**
* Builds and sends the ajax requests
* @return {XMLHttpRequest}
* @private
*/
this._buildAjaxCall = function () {
var that = this;
Benaka Moorthi
a validé
var url = this.getUrl;
if (url[url.length - 1] != '?') {
url += '&';
}
// we took care of encoding &segment properly already, so we don't use $.param for it ($.param URL encodes the values)
if(parameters['segment']) {
url += 'segment=' + parameters['segment'] + '&';
delete parameters['segment'];
}
if(parameters['date']) {
url += 'date=' + decodeURIComponent(parameters['date']) + '&';
delete parameters['date'];
}
sgiehl
a validé
var ajaxCall = {
type: 'POST',
async: this.async !== false,
sgiehl
a validé
dataType: this.format || 'json',
error: function () {
--globalAjaxQueue.active;
if (that.errorCallback) {
that.errorCallback.apply(this, arguments);
}
},
sgiehl
a validé
success: function (response) {
if (that.loadingElement) {
$(that.loadingElement).hide();
}
Timo Besenreuther
a validé
if (response && response.result == 'error' && !that.useRegularCallbackInCaseOfError) {
var placeAt = null;
if ($(that.errorElement).length && response.message) {
$(that.errorElement).show();
placeAt = that.errorElement;
}
if (response.message) {
var UI = require('piwik/UI');
var notification = new UI.Notification();
notification.show(response.message, {
placeat: placeAt,
id: 'ajaxHelper'
});
notification.scrollToNotification();
Benaka Moorthi
a validé
} else {
that.callback(response);
Benaka Moorthi
a validé
--globalAjaxQueue.active;
var piwik = window.piwik;
if (piwik
&& piwik.ajaxRequestFinished
) {
piwik.ajaxRequestFinished();
}
sgiehl
a validé
},
data: this._mixinDefaultPostParams(this.postParams)
};
Thomas Steur
a validé
if (this.timeout !== null) {
ajaxCall.timeout = this.timeout;
}
sgiehl
a validé
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
return $.ajax(ajaxCall);
};
/**
* Mixin the default parameters to send as POST
*
* @param {object} params parameter object
* @return {object}
* @private
*/
this._mixinDefaultPostParams = function (params) {
var defaultParams = {
token_auth: piwik.token_auth
};
for (var index in defaultParams) {
if (!params[index]) {
params[index] = defaultParams[index];
}
}
return params;
};
/**
* Mixin the default parameters to send as GET
*
* @param {object} params parameter object
* @return {object}
* @private
*/
this._mixinDefaultGetParams = function (params) {
var defaultParams = {
idSite: piwik.idSite || broadcast.getValueFromUrl('idSite'),
period: piwik.period || broadcast.getValueFromUrl('period'),
segment: broadcast.getValueFromHash('segment', window.location.href.split('#')[1])
sgiehl
a validé
};
// never append token_auth to url
if (params.token_auth) {
params.token_auth = null;
delete params.token_auth;
}
for (var key in defaultParams) {
if (!params[key] && !this.postParams[key] && defaultParams[key]) {
sgiehl
a validé
params[key] = defaultParams[key];
}
}
// handle default date & period if not already set
if (!params.date && !this.postParams.date) {
sgiehl
a validé
params.date = piwik.currentDateString || broadcast.getValueFromUrl('date');
if (params.period == 'range' && piwik.currentDateString) {
benakamoorthi
a validé
params.date = piwik.startDateString + ',' + params.date;
sgiehl
a validé
}
}
return params;
};
return this;