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é
/**
* Callback function to be executed on complete (after error or success)
*/
this.completeCallback = function () {};
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;
};
/**
* Sets the complete callback which is called after an error or success callback.
*
* @param {function} callback Callback function
* @return {void}
*/
this.setCompleteCallback = function (callback) {
this.completeCallback = 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',
complete: this.completeCallback,
error: function () {
--globalAjaxQueue.active;
if (that.errorCallback) {
that.errorCallback.apply(this, arguments);
}
},
Thomas Steur
a validé
success: function (response, status, request) {
sgiehl
a validé
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 {
Thomas Steur
a validé
that.callback(response, status, request);
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é
return $.ajax(ajaxCall);
};
Thomas Steur
a validé
this._getDefaultPostParams = function () {
return {
token_auth: piwik.token_auth
};
}
sgiehl
a validé
/**
* Mixin the default parameters to send as POST
*
* @param {object} params parameter object
* @return {object}
* @private
*/
this._mixinDefaultPostParams = function (params) {
Thomas Steur
a validé
var defaultParams = this._getDefaultPostParams();
sgiehl
a validé
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;