web-apps/vendor/framework7/src/js/dom7-ajax.js
2016-11-11 16:24:21 +03:00

281 lines
10 KiB
JavaScript

// Global Ajax Setup
var globalAjaxOptions = {};
$.ajaxSetup = function (options) {
if (options.type) options.method = options.type;
$.each(options, function (optionName, optionValue) {
globalAjaxOptions[optionName] = optionValue;
});
};
// Ajax
var _jsonpRequests = 0;
$.ajax = function (options) {
var defaults = {
method: 'GET',
data: false,
async: true,
cache: true,
user: '',
password: '',
headers: {},
xhrFields: {},
statusCode: {},
processData: true,
dataType: 'text',
contentType: 'application/x-www-form-urlencoded',
timeout: 0
};
var callbacks = ['beforeSend', 'error', 'complete', 'success', 'statusCode'];
//For jQuery guys
if (options.type) options.method = options.type;
// Merge global and defaults
$.each(globalAjaxOptions, function (globalOptionName, globalOptionValue) {
if (callbacks.indexOf(globalOptionName) < 0) defaults[globalOptionName] = globalOptionValue;
});
// Function to run XHR callbacks and events
function fireAjaxCallback (eventName, eventData, callbackName) {
var a = arguments;
if (eventName) $(document).trigger(eventName, eventData);
if (callbackName) {
// Global callback
if (callbackName in globalAjaxOptions) globalAjaxOptions[callbackName](a[3], a[4], a[5], a[6]);
// Options callback
if (options[callbackName]) options[callbackName](a[3], a[4], a[5], a[6]);
}
}
// Merge options and defaults
$.each(defaults, function (prop, defaultValue) {
if (!(prop in options)) options[prop] = defaultValue;
});
// Default URL
if (!options.url) {
options.url = window.location.toString();
}
// Parameters Prefix
var paramsPrefix = options.url.indexOf('?') >= 0 ? '&' : '?';
// UC method
var _method = options.method.toUpperCase();
// Data to modify GET URL
if ((_method === 'GET' || _method === 'HEAD' || _method === 'OPTIONS' || _method === 'DELETE') && options.data) {
var stringData;
if (typeof options.data === 'string') {
// Should be key=value string
if (options.data.indexOf('?') >= 0) stringData = options.data.split('?')[1];
else stringData = options.data;
}
else {
// Should be key=value object
stringData = $.serializeObject(options.data);
}
if (stringData.length) {
options.url += paramsPrefix + stringData;
if (paramsPrefix === '?') paramsPrefix = '&';
}
}
// JSONP
if (options.dataType === 'json' && options.url.indexOf('callback=') >= 0) {
var callbackName = 'f7jsonp_' + Date.now() + (_jsonpRequests++);
var abortTimeout;
var callbackSplit = options.url.split('callback=');
var requestUrl = callbackSplit[0] + 'callback=' + callbackName;
if (callbackSplit[1].indexOf('&') >= 0) {
var addVars = callbackSplit[1].split('&').filter(function (el) { return el.indexOf('=') > 0; }).join('&');
if (addVars.length > 0) requestUrl += '&' + addVars;
}
// Create script
var script = document.createElement('script');
script.type = 'text/javascript';
script.onerror = function() {
clearTimeout(abortTimeout);
fireAjaxCallback(undefined, undefined, 'error', null, 'scripterror');
};
script.src = requestUrl;
// Handler
window[callbackName] = function (data) {
clearTimeout(abortTimeout);
fireAjaxCallback(undefined, undefined, 'success', data);
script.parentNode.removeChild(script);
script = null;
delete window[callbackName];
};
document.querySelector('head').appendChild(script);
if (options.timeout > 0) {
abortTimeout = setTimeout(function () {
script.parentNode.removeChild(script);
script = null;
fireAjaxCallback(undefined, undefined, 'error', null, 'timeout');
}, options.timeout);
}
return;
}
// Cache for GET/HEAD requests
if (_method === 'GET' || _method === 'HEAD' || _method === 'OPTIONS' || _method === 'DELETE') {
if (options.cache === false) {
options.url += (paramsPrefix + '_nocache=' + Date.now());
}
}
// Create XHR
var xhr = new XMLHttpRequest();
// Save Request URL
xhr.requestUrl = options.url;
xhr.requestParameters = options;
// Open XHR
xhr.open(_method, options.url, options.async, options.user, options.password);
// Create POST Data
var postData = null;
if ((_method === 'POST' || _method === 'PUT' || _method === 'PATCH') && options.data) {
if (options.processData) {
var postDataInstances = [ArrayBuffer, Blob, Document, FormData];
// Post Data
if (postDataInstances.indexOf(options.data.constructor) >= 0) {
postData = options.data;
}
else {
// POST Headers
var boundary = '---------------------------' + Date.now().toString(16);
if (options.contentType === 'multipart\/form-data') {
xhr.setRequestHeader('Content-Type', 'multipart\/form-data; boundary=' + boundary);
}
else {
xhr.setRequestHeader('Content-Type', options.contentType);
}
postData = '';
var _data = $.serializeObject(options.data);
if (options.contentType === 'multipart\/form-data') {
boundary = '---------------------------' + Date.now().toString(16);
_data = _data.split('&');
var _newData = [];
for (var i = 0; i < _data.length; i++) {
_newData.push('Content-Disposition: form-data; name="' + _data[i].split('=')[0] + '"\r\n\r\n' + _data[i].split('=')[1] + '\r\n');
}
postData = '--' + boundary + '\r\n' + _newData.join('--' + boundary + '\r\n') + '--' + boundary + '--\r\n';
}
else {
postData = options.contentType === 'application/x-www-form-urlencoded' ? _data : _data.replace(/&/g, '\r\n');
}
}
}
else {
postData = options.data;
}
}
// Additional headers
if (options.headers) {
$.each(options.headers, function (headerName, headerCallback) {
xhr.setRequestHeader(headerName, headerCallback);
});
}
// Check for crossDomain
if (typeof options.crossDomain === 'undefined') {
options.crossDomain = /^([\w-]+:)?\/\/([^\/]+)/.test(options.url) && RegExp.$2 !== window.location.host;
}
if (!options.crossDomain) {
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
}
if (options.xhrFields) {
$.each(options.xhrFields, function (fieldName, fieldValue) {
xhr[fieldName] = fieldValue;
});
}
var xhrTimeout;
// Handle XHR
xhr.onload = function (e) {
if (xhrTimeout) clearTimeout(xhrTimeout);
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 0) {
var responseData;
if (options.dataType === 'json') {
try {
responseData = JSON.parse(xhr.responseText);
fireAjaxCallback('ajaxSuccess', {xhr: xhr}, 'success', responseData, xhr.status, xhr);
}
catch (err) {
fireAjaxCallback('ajaxError', {xhr: xhr, parseerror: true}, 'error', xhr, 'parseerror');
}
}
else {
responseData = xhr.responseType === 'text' || xhr.responseType === '' ? xhr.responseText : xhr.response;
fireAjaxCallback('ajaxSuccess', {xhr: xhr}, 'success', responseData, xhr.status, xhr);
}
}
else {
fireAjaxCallback('ajaxError', {xhr: xhr}, 'error', xhr, xhr.status);
}
if (options.statusCode) {
if (globalAjaxOptions.statusCode && globalAjaxOptions.statusCode[xhr.status]) globalAjaxOptions.statusCode[xhr.status](xhr);
if (options.statusCode[xhr.status]) options.statusCode[xhr.status](xhr);
}
fireAjaxCallback('ajaxComplete', {xhr: xhr}, 'complete', xhr, xhr.status);
};
xhr.onerror = function (e) {
if (xhrTimeout) clearTimeout(xhrTimeout);
fireAjaxCallback('ajaxError', {xhr: xhr}, 'error', xhr, xhr.status);
};
// Ajax start callback
fireAjaxCallback('ajaxStart', {xhr: xhr}, 'start', xhr);
fireAjaxCallback(undefined, undefined, 'beforeSend', xhr);
// Timeout
if (options.timeout > 0) {
xhr.onabort = function () {
if (xhrTimeout) clearTimeout(xhrTimeout);
};
xhrTimeout = setTimeout(function () {
xhr.abort();
fireAjaxCallback('ajaxError', {xhr: xhr, timeout: true}, 'error', xhr, 'timeout');
fireAjaxCallback('ajaxComplete', {xhr: xhr, timeout: true}, 'complete', xhr, 'timeout');
}, options.timeout);
}
// Send XHR
xhr.send(postData);
// Return XHR object
return xhr;
};
// Shrotcuts
(function () {
var methods = ('get post getJSON').split(' ');
function createMethod(method) {
$[method] = function (url, data, success, error) {
return $.ajax({
url: url,
method: method === 'post' ? 'POST' : 'GET',
data: typeof data === 'function' ? undefined : data,
success: typeof data === 'function' ? data : success,
error: typeof data === 'function' ? success : error,
dataType: method === 'getJSON' ? 'json' : undefined
});
};
}
for (var i = 0; i < methods.length; i++) {
createMethod(methods[i]);
}
})();