'use strict'; /*@ Ox.get Get a remote file # fixme: remote? same-origin-policy? jsonp? (url, callback) -> undefined url Remote URL callback Callback function data The contents of the remote resource @*/ Ox.get = function(url, callback) { var req = new XMLHttpRequest(); req.open('GET', url, true); req.onreadystatechange = function() { if (req.readyState == 4) { if (req.status == 200) { callback(req.responseText); } else { throw new Error( 'Cannot get URL "' + url + '" (Status: ' + req.status + ')' ); } } }; req.send(); }; /*@ Ox.getJSON Get and parse one or more remote JSON files # fixme: remote? same-origin-policy? jsonp? (url, callback) -> undefined url One or more remote URLs callback Callback function data The parsed contents of the remote resource(s) For multiple URLs, keys are file names, values are contents @*/ Ox.getJSON = (function() { function getJSON(url, callback) { Ox.get(url, function(data) { callback(JSON.parse(data)); }); } return function(url, callback) { var urls = Ox.toArray(url), data = {}, i = 0, n = urls.length; urls.forEach(function(url) { getJSON(url, function(data_) { data[url] = data_; ++i == n && callback(n == 1 ? data[url] : data); }); }); }; }()); /*@ Ox.getJSONC Get and parse a remote JSONC file JSONC is JSON with JavaScript line or block comments (url, callback) -> undefined url Remote URL callback Callback function data The parsed contents of the remote resource @*/ Ox.getJSONC = function(url, callback) { Ox.get(url, function(data) { callback(JSON.parse(Ox.minify(data))); }); }; /*@ Ox.loadFile Loads a file (image, script or stylesheet) (file="script.js", callback) -> undefined (file="stylesheet.css", callback) -> undefined (file="image.png", callback) -> undefined file Local path or remote URL callback Callback function image DOM element (if the file is an image) @*/ Ox.loadFile = (function() { // fixme: this doesn't handle errors yet // fixme: rename to getFile? // fixme: what about array of files? var cache = {}; return function (file, callback) { var element, head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement, request, type = file.split('.').pop(), isImage = type != 'css' && type != 'js'; if (!cache[file]) { if (isImage) { element = new Image(); element.onload = addFileToCache; element.src = file; } else { if (!findFileInHead()) { element = document.createElement( type == 'css' ? 'link' : 'script' ); element[type == 'css' ? 'href' : 'src'] = file + '?' + Ox.random(1000000); element.type = type == 'css' ? 'text/css' : 'text/javascript'; if (/MSIE/.test(navigator.userAgent)) { // fixme: find a way to check if css/js have loaded in msie setTimeout(addFileToCache, 2500); } else { if (type == 'css') { element.rel = 'stylesheet'; waitForCSS(); } else { element.onload = addFileToCache; } } head.appendChild(element); } else { addFileToCache(); } } } else { callback(); } function addFileToCache() { if (isImage) { // for an image, save the element itself, // so that it remains in the browser cache cache[file] = element; callback(element); } else { cache[file] = true; callback(); } } function findFileInHead() { return Ox.makeArray( document.getElementsByTagName(type == 'css' ? 'link' : 'script') ).map(function(element) { return element[type == 'css' ? 'href' : 'src'] == file; }).reduce(function(prev, curr) { return prev || curr; }, false); } function waitForCSS() { var error = false; try { element.sheet.cssRule; } catch(e) { error = true; setTimeout(function() { waitForCSS(); }, 25); } !error && addFileToCache(); } }; }()); /*@ Ox.loadFiles Loads multiple files (images, scripts or stylesheets) (files, callback) -> undefined files <[s]|[[s]]> Array of files, or array of arrays of files Multiple files in the same array will be loaded simultaneously, but multiple arrays of files will be loaded in that order. callback Callback function images DOM elements (if any file was an image) Keys are the file names, values are the DOM elements @*/ Ox.loadFiles = (function() { function loadFiles(files, callback) { files = Ox.toArray(files); var i = 0, n = files.length, images = {}; Ox.toArray(files).forEach(function(file) { Ox.loadFile(file, function(image) { if (image) { images[file] = image; } ++i == n && callback(images); }); }); } return function(files, callback) { var i = 0, n = files.length, images = {}; files.forEach(function(file) { loadFiles(file, function(images_) { Ox.extend(images, images_) ++i == n && callback(Ox.len(images) ? images : void 0); }); }); }; }());