oxjs/source/Ox/js/Request.js

337 lines
11 KiB
JavaScript
Raw Normal View History

2011-11-05 17:46:53 +01:00
'use strict';
2026-02-09 18:59:12 +01:00
import * as OxArray from './Array.js';
import * as OxObject from './Object.js';
import * as OxConstants from './Constants.js';
import * as OxMath from './Math.js';
import * as OxString from './String.js';
import * as OxType from './Type.js';
import * as OxCollection from './Collection.js';
const Ox = {};
Object.assign(Ox,
OxArray,
OxObject,
OxConstants,
OxMath,
OxString,
OxType,
OxCollection,
);
/*@
Ox.get <f> Get a remote resource
(url, callback) -> <u> undefined
url <s> Remote URL
callback <f> Callback function
data <s|null> The contents of the remote resource, or `null` on error
error <o|null> Error, or `null` on success
code <n> Status code
text <s> Status text
@*/
2026-02-09 18:59:12 +01:00
export function get(url, callback) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.onreadystatechange = function() {
if (request.readyState == 4) {
if (request.status == 200) {
callback(request.responseText, null);
} else {
callback(null, {
code: request.status,
text: request.statusText
});
}
}
};
2016-05-17 14:49:37 +02:00
request.send();
};
/*@
Ox.getAsync <f> Runs an asynchonous loader for an array of URLs
2012-06-27 14:55:49 +02:00
(urls, get, callback) -> <u> undefined
2013-12-05 15:53:41 +01:00
urls <s|[s]> URL or array of URLs or array of such arrays
Multiple URLs in the same array will be processed simultaneously, but
2013-12-05 00:23:36 +01:00
multiple arrays of URLs will be processed sequentially
2012-06-27 14:55:49 +02:00
get <f> Asynchronous function that loads a URL (for example Ox.get)
url <s> URL
callback <f> Callback function
result <s|null> Result, or `null` on error
error <o|null> Error, or `null` on success
2012-06-27 14:55:49 +02:00
code <n> Status code
text <s> Status text
callback <f> Callback function
2013-12-05 00:31:18 +01:00
result <*|o|null> Result(s), or `null` on error
2013-12-05 00:23:36 +01:00
For multiple URLs, keys are URLs, values are results, `{}` on error
2013-12-05 00:31:18 +01:00
error <o|null> Error(s), or `null` on success
2013-12-05 00:23:36 +01:00
For multiple URLs, keys are URLs, values are errors, `{}` on success
2013-12-05 00:31:18 +01:00
code <n> Error code (like `404`)
text <s> Error text (like `'Not Found'`)
@*/
2026-02-09 18:59:12 +01:00
export function getAsync(urls, get, callback) {
2013-12-04 16:49:42 +01:00
urls = Ox.makeArray(urls);
var errors = {}, i = 0, n = urls.length, results = {};
function done() {
2013-12-04 16:49:42 +01:00
callback && callback(filter(results), filter(errors));
}
2013-12-04 16:49:42 +01:00
function extend(object, value, urls) {
value !== null && Ox.extend.apply(null, [object].concat(
urls.length === 1 ? [urls[0], value] : [value]
));
}
function filter(object) {
return n == 1 ? object[urls[0]] : Ox.filter(object, function(value) {
return value !== null;
});
}
2013-12-04 16:49:42 +01:00
function getParallel() {
urls.forEach(function(url) {
2012-06-27 14:55:49 +02:00
get(url, function(result, error) {
2013-05-09 22:32:19 +02:00
results[url] = result;
errors[url] = error;
++i == n && done();
});
});
}
2013-12-04 16:49:42 +01:00
function getSerial() {
var url = urls.shift();
2026-02-09 18:59:12 +01:00
getAsync(url, get, function(result, error) {
2013-12-04 16:49:42 +01:00
extend(results, result, url);
extend(errors, error, url);
urls.length ? getSerial() : done();
});
}
urls.some(Ox.isArray) ? getSerial() : getParallel();
2011-11-23 15:53:17 +01:00
};
2026-02-09 18:59:12 +01:00
var cache = {},
head = document.head
|| document.getElementsByTagName('head')[0]
|| document.documentElement;
2026-02-09 18:59:12 +01:00
function _getFile(type, url, callback) {
var element, tagValue, typeValue, urlKey;
if (!cache[url]) {
if (!type) {
type = Ox.parseURL(url).pathname.split('.').pop();
type = type == 'css' ? 'stylesheet'
: type == 'js' ? 'script' : 'image';
}
if (type == 'image') {
element = new Image();
element.onerror = onError;
element.onload = onLoad;
element.src = url;
} else {
tagValue = type == 'script' ? 'script' : 'link';
typeValue = type == 'script' ? 'text/javascript' : 'text/css';
urlKey = type == 'script' ? 'src' : 'href';
if (Ox.some(
document.getElementsByTagName(tagValue),
function(element) {
return element[urlKey] == url;
}
2026-02-09 18:59:12 +01:00
)) {
onLoad();
} else {
element = document.createElement(tagValue);
element.onerror = onError;
element.onload = element.onreadystatechange = onLoad;
element.type = typeValue;
element[urlKey] = url;
if (type == 'stylesheet') {
2026-02-09 18:59:12 +01:00
element.rel = 'stylesheet';
}
2026-02-09 18:59:12 +01:00
head.appendChild(element);
}
2026-02-09 18:59:12 +01:00
if (type == 'stylesheet') {
//fixme only call if browser does not support onload
// Safari 5 does not fire onload
waitForCSS();
}
}
2026-02-09 18:59:12 +01:00
} else {
callback(cache[url], null);
}
function onError() {
callback(null, {code: 404, text: 'Not Found'});
}
function onLoad() {
if (
!this || !this.readyState
|| this.readyState == 'loaded' || this.readyState == 'complete'
) {
// for an image, keep a reference to the element
// to keep the image in the browser cache
cache[url] = type == 'image' ? this : true;
callback(cache[url], null);
}
}
2026-02-09 18:59:12 +01:00
function waitForCSS() {
var error = false;
try {
element.sheet.cssRule;
} catch (e) {
error = true;
setTimeout(function() {
waitForCSS();
}, 25);
}
!error && onLoad();
}
2026-02-09 18:59:12 +01:00
}
2026-02-09 18:59:12 +01:00
function getFiles(type, urls, callback) {
getAsync(urls, function(url, callback) {
_getFile(type, url, callback);
}, callback);
}
2026-02-09 18:59:12 +01:00
/*@
Ox.getFile <f> Loads a file (image, script or stylesheet)
(file, callback) -> <u> undefined
file <s|[s]> Local path or remote URL, or array of those, or array of such arrays
Multiple files in the same array will be processed simultaneously,
but multiple arrays of files will be processed in that order.
callback <f> Callback function
image <h> DOM element (if the file is an image)
@*/
export function getFile(url, callback) {
getFiles(null, url, callback);
};
2026-02-09 18:59:12 +01:00
/*@
Ox.getImage <f> Loads an image
(file, callback) -> <u> undefined
file <s|[s]> Local path or remote URL, or array of those, or array of such arrays
Multiple files in the same array will be processed simultaneously,
but multiple arrays of files will be processed in that order.
callback <f> Callback function
image <h> DOM element
@*/
export function getImage(url, callback) {
getFiles('image', url, callback);
};
2026-02-09 18:59:12 +01:00
/*@
Ox.getScript <f> Loads a script
(file, callback) -> <u> undefined
file <s|[s]> Local path or remote URL, or array of those, or array of such arrays
Multiple files in the same array will be processed simultaneously,
but multiple arrays of files will be processed in that order.
callback <f> Callback function
@*/
export function getScript(url, callback) {
getFiles('script', url, callback);
};
2026-02-09 18:59:12 +01:00
/*@
Ox.getStylesheet <f> Loads a stylesheet
(file, callback) -> <u> undefined
file <s|[s]> Local path or remote URL, or array of those, or array of such arrays
Multiple files in the same array will be processed simultaneously,
but multiple arrays of files will be processed in that order.
callback <f> Callback function
@*/
export function getStylesheet(url, callback) {
getFiles('stylesheet', url, callback);
};
2012-04-19 11:13:43 +00:00
/*@
Ox.getJSON <f> Get and parse one or more remote JSON files
(url, callback) -> <u> undefined
2013-12-05 15:53:41 +01:00
url <s|[s]> One or more remote URLs
2012-04-19 11:13:43 +00:00
callback <f> Callback function
2013-12-05 00:31:18 +01:00
data <*|o|null> Parsed contents, or `null` on error
For multiple URLs, keys are URLs, values are data, `{}` on error
error <o|null> Error(s), or `null` on success
For multiple URLs, keys are URLs, values are errors, `{}` on success
code <n> Error code (like `404`)
text <s> Error text (like `'Not Found'`)
2012-04-19 11:13:43 +00:00
@*/
2026-02-09 18:59:12 +01:00
export function getJSON(url, callback, isJSONC) {
var urls = Ox.makeArray(url);
2026-02-09 18:59:12 +01:00
getAsync(urls, function(url, callback) {
get(url, function(data, error) {
callback(JSON.parse(
isJSONC ? Ox.minify(data || '') : data
), error);
2012-04-19 11:13:43 +00:00
});
}, callback);
};
/*@
Ox.getJSONC <f> Get and parse a remote JSONC file
JSONC is JSON with JavaScript line or block comments
(url, callback) -> <u> undefined
2013-12-05 15:53:41 +01:00
url <s|[s]> One or more remote URLs
callback <f> Callback function
2013-12-05 00:31:18 +01:00
data <*|o|null> Parsed contents, or `null` on error
For multiple URLs, keys are URLs, values are data, `{}` on error
error <o|null> Error(s), or `null` on success
For multiple URLs, keys are URLs, values are errors, `{}` on success
code <n> Error code (like `404`)
text <s> Error text (like `'Not Found'`)
@*/
2026-02-09 18:59:12 +01:00
export function getJSONC(url, callback) {
Ox.getJSON(url, callback, true);
};
/*@
Ox.getJSONP <f> Get and parse one or more remote JSONP files
(url, callback) -> <u> undefined
2013-12-05 15:53:41 +01:00
url <s|[s]> One or more remote URLs
{callback} gets replaced with jsonp callback function name
callback <f> Callback function
2013-12-05 00:31:18 +01:00
data <*|o|null> Parsed contents, or `null` on error
For multiple URLs, keys are URLs, values are data, `{}` on error
error <o|null> Error(s), or `null` on success
For multiple URLs, keys are URLs, values are errors, `{}` on success
code <n> Error code (like `404`)
text <s> Error text (like `'Not Found'`)
@*/
2026-02-09 18:59:12 +01:00
export function getJSONP(url, callback) {
var urls = Ox.makeArray(url);
2026-02-09 18:59:12 +01:00
getAsync(urls, function(url, callback) {
var id = 'callback' + Ox.uid();
Ox.getJSONP[id] = function(data) {
delete Ox.getJSONP[id];
callback(data, null);
};
Ox.$('body').append(Ox.$('<script>').attr({
'src': url.replace('{callback}', 'Ox.getJSONP.' + id),
'type': 'text/javascript'
}));
}, callback);
};
2015-03-14 11:25:45 +05:30
/*@
Ox.post <f> post to a remote resource
(url, data, callback) -> <u> undefined
url <s> Remote URL
data <s> data to send in post request
callback <f> Callback function
data <s|null> The contents of the remote resource, or `null` on error
error <o|null> Error, or `null` on success
code <n> Status code
text <s> Status text
@*/
2026-02-09 18:59:12 +01:00
export function post(url, data, callback) {
2015-03-14 11:25:45 +05:30
var request = new XMLHttpRequest();
request.open('post', url, true);
request.onreadystatechange = function() {
if (request.readyState == 4) {
if (request.status == 200) {
callback(request.responseText, null);
} else {
callback(null, {
code: request.status,
text: request.statusText
});
}
}
};
request.send(data);
};