File: src/Ajax/Ajax.js
/**
Calls KnowRe-style AJAX.
glesea.ajax({
method: 'get',
url: '/api/foo',
input: {
key: 'value'
},
// ...
});
@method ajax
@for glesea
@param {String} [method='get'] HTTP method
@param {String} [url='/'] Address to call
@param {Number} [port=443] Port to connect
@param {Object} [headers={}] Additional headers
@param {Object} [input={}] Payload
@param {Function} [onSuccess=Function] Callback on success
@param {Function} [onFailure=Function] Callback on failure
@param {Boolean} [https=true] Whether to convert every request to https
@param {Boolean} [needLogin=true] Whether needs session logged in
@param {Boolean} [swintStyle=true] Whether to apply Swint-style API(input payload and session-error-output tuple)
@param {Number} [timeOut=0] Timeout. Void when set to 0. Milliseconds.
@param {Boolean} [timeOutPopup=true] Whether to show popup window when timeout occurs
@param {Boolean} [errorPopup=true] Whether to show popup window when server/session error occurs
@param {Object} [loadingIndicator={on: Function, off: Function}] Callback when loading indicator needs to be turned on/off.
@param {Function} [sessionError=Function] Callback especially on session error. On default, it redirects to the root(/) instead of executing onFailure.
@param {Function} [serverError=Function] Callback especially on 500 server error. After closing modaless dialog, it executes onFailure.
@param {Function} [aborted=Function] Callback especially on timeout. After closing modaless dialog, it executes onFailure.
@return nothing
**/
(function(glesea) {
glesea.ajax = function(options) {
var sTimeOut,
input,
oli = document.createElement('oreesh-loading-indicator'),
od = document.createElement('oreesh-dialog');
glesea.defaultize({
method: 'get',
url: '/',
headers: {},
input: {},
onSuccess: function() {},
onFailure: function() {},
port: (function() {
var currPort = Number(document.location.port);
if (currPort === 0) {
if (document.location.protocol.match('https')) {
currPort = 443;
} else {
currPort = 80;
}
}
if (document.location.protocol.match('https')) {
if (options.hasOwnProperty('https')) {
if (options.https) {
return currPort;
} else {
return currPort > 1024 ? 8080 : 80;
}
} else {
return currPort;
}
} else {
if (options.hasOwnProperty('https')) {
if (options.https) {
return currPort > 1024 ? 8443 : 443;
} else {
return currPort;
}
} else {
return currPort > 1024 ? 8443 : 443;
}
}
})(),
cache: 'no-cache',
https: true,
needLogin: true,
timeOut: 0,
timeOutPopup: true,
errorPopup: true,
swintStyle: true,
sessionErrorRedirectURL : '/',
loadingIndicator: {
on: function() {
document.querySelector('body').appendChild(oli);
},
off: function() {
if (oli.parentNode) {
oli.parentNode.removeChild(oli);
}
}
},
sessionError: function(output) {
if (output.session) return;
if (options.errorPopup) {
od.message = output.error || glesea.i18n[glesea.setting.locale].ajax.sessionError;
od.setAttribute('small-icon', 'error');
document.querySelector('body').appendChild(od);
od.yesButtonCallback = function() {
options.onFailure(output.data);
document.location.href = options.sessionErrorRedirectURL;
};
} else {
options.onFailure(output.data);
}
options.loadingIndicator.off();
},
serverError: function(output) {
if (options.errorPopup) {
od.message = output.error || glesea.i18n[glesea.setting.locale].ajax.defaultError;
od.setAttribute('small-icon', 'error');
document.querySelector('body').appendChild(od);
od.yesButtonCallback = function() {
options.onFailure(output.data);
};
} else {
options.onFailure(output.data);
}
options.loadingIndicator.off();
},
aborted: function() {
if (options.timeOutPopup) {
od.message = glesea.i18n[glesea.setting.locale].ajax.aborted;
od.setAttribute('small-icon', 'error');
document.querySelector('body').appendChild(od);
od.yesButtonCallback = function() {
options.onFailure({});
};
} else {
options.onFailure({});
}
options.loadingIndicator.off();
}
}, options);
options.loadingIndicator.on();
if (options.https) {
if (options.url.match(/\:/)) {
var urlArr = options.url.split(':');
urlArr[0] = 'https';
options.url = urlArr.join(':');
} else {
var hostname = window.location.hostname;
if (options.port !== 443) {
hostname += ':' + options.port;
}
if (options.url[0] === '/') {
options.url = 'https://' + hostname + options.url;
} else {
options.url = 'https://' + hostname + '/' + options.url;
}
}
}
input = encodeURIComponent(JSON.stringify(options.input));
var opt = {
method: options.method,
headers : options.headers,
cache: options.cache,
credentials: options.needLogin ? 'include' : 'same-origin'
},
isTimeout = false;
switch (options.method) {
case 'get':
options.url += '?input=' + input;
if (opt.cache === 'no-cache') {
options.url += '&_=' + Date.now();
}
break;
case 'post':
case 'put':
opt.headers['Content-Type'] = 'application/x-www-form-urlencoded';
opt.body = 'input=' + input;
break;
default:
break;
}
fetch(options.url, opt).then(function(resp) {
if (sTimeOut) clearTimeout(sTimeOut);
options.loadingIndicator.off();
if (Math.floor(resp.status / 100) !== 2) {
var error = new Error(resp.statusText);
error.resp = resp;
throw error;
}
if (options.swintStyle) {
return resp.json();
} else {
return resp.text();
}
}).then(function(output) {
if (isTimeout) return;
if (options.swintStyle) {
if (output.success) {
options.onSuccess(output.data);
} else if (!output.session && options.needLogin) {
options.sessionError(output);
} else {
options.serverError(output);
}
} else {
options.onSuccess(output);
}
}).catch(function(ex) {
print(4, ex);
if (options.swintStyle) {
ex.resp.json().then(function(json) {
if (!json.session && options.needLogin) {
options.sessionError(json);
} else {
options.serverError(json);
}
});
} else {
options.serverError(ex);
}
});
if (options.timeOut !== 0) {
sTimeOut = setTimeout(function() {
isTimeout = true;
options.aborted();
}, options.timeOut);
}
};
})(glesea);