UNPKG

angular-ui-router-tabs

Version:

Idiot-proof tab panes with route support using Angular.js + Bootstrap 3 + UI Router.

1,774 lines (1,547 loc) 697 kB
/* * Envjs core-env.1.2.13 * Pure JavaScript Browser Environment * By John Resig <http://ejohn.org/> and the Envjs Team * Copyright 2008-2010 John Resig, under the MIT License */ var Envjs = function(){ var i, name, override = function(){ for(i=0;i<arguments.length;i++){ for ( name in arguments[i] ) { var g = arguments[i].__lookupGetter__(name), s = arguments[i].__lookupSetter__(name); if ( g || s ) { if ( g ) { Envjs.__defineGetter__(name, g); } if ( s ) { Envjs.__defineSetter__(name, s); } } else { Envjs[name] = arguments[i][name]; } } } }; if(arguments.length === 1 && typeof(arguments[0]) == 'string'){ window.location = arguments[0]; }else if (arguments.length === 1 && typeof(arguments[0]) == "object"){ override(arguments[0]); }else if(arguments.length === 2 && typeof(arguments[0]) == 'string'){ override(arguments[1]); window.location = arguments[0]; } return; }, __this__ = this; //eg "Mozilla" Envjs.appCodeName = "Envjs"; //eg "Gecko/20070309 Firefox/2.0.0.3" Envjs.appName = "Resig/20070309 PilotFish/1.2.13"; Envjs.version = "1.6";//? Envjs.revision = ''; /* * Envjs core-env.1.2.13 * Pure JavaScript Browser Environment * By John Resig <http://ejohn.org/> and the Envjs Team * Copyright 2008-2010 John Resig, under the MIT License */ //CLOSURE_START (function(){ /** * @author john resig */ // Helper method for extending one object with another. function __extend__(a,b) { for ( var i in b ) { var g = b.__lookupGetter__(i), s = b.__lookupSetter__(i); if ( g || s ) { if ( g ) { a.__defineGetter__(i, g); } if ( s ) { a.__defineSetter__(i, s); } } else { a[i] = b[i]; } } return a; } /** * Writes message to system out * @param {String} message */ Envjs.log = function(message){}; /** * Constants providing enumerated levels for logging in modules */ Envjs.DEBUG = 1; Envjs.INFO = 2; Envjs.WARN = 3; Envjs.ERROR = 3; Envjs.NONE = 3; /** * Writes error info out to console * @param {Error} e */ Envjs.lineSource = function(e){}; /** * TODO: used in ./event/eventtarget.js * @param {Object} event */ Envjs.defaultEventBehaviors = {}; /** * describes which script src values will trigger Envjs to load * the script like a browser would */ Envjs.scriptTypes = { "text/javascript" :false, "text/envjs" :true }; /** * will be called when loading a script throws an error * @param {Object} script * @param {Object} e */ Envjs.onScriptLoadError = function(script, e){ console.log('error loading script %s %s', script, e); }; /** * load and execute script tag text content * @param {Object} script */ Envjs.loadInlineScript = function(script){ var tmpFile; tmpFile = Envjs.writeToTempFile(script.text, 'js') ; load(tmpFile); }; /** * Should evaluate script in some context * @param {Object} context * @param {Object} source * @param {Object} name */ Envjs.eval = function(context, source, name){}; /** * Executes a script tag * @param {Object} script * @param {Object} parser */ Envjs.loadLocalScript = function(script){ //console.log("loading script %s", script); var types, src, i, base, filename, xhr; if(script.type){ types = script.type.split(";"); for(i=0;i<types.length;i++){ if(Envjs.scriptTypes[types[i]]){ //ok this script type is allowed break; } if(i+1 == types.length){ //console.log('wont load script type %s', script.type); return false; } } } try{ //console.log('handling inline scripts'); if(!script.src.length){ Envjs.loadInlineScript(script); return true; } }catch(e){ //Envjs.error("Error loading script.", e); Envjs.onScriptLoadError(script, e); return false; } //console.log("loading allowed external script %s", script.src); //lets you register a function to execute //before the script is loaded if(Envjs.beforeScriptLoad){ for(src in Envjs.beforeScriptLoad){ if(script.src.match(src)){ Envjs.beforeScriptLoad[src](script); } } } base = "" + script.ownerDocument.location; //filename = Envjs.uri(script.src.match(/([^\?#]*)/)[1], base ); //console.log('loading script from base %s', base); filename = Envjs.uri(script.src, base); try { xhr = new XMLHttpRequest(); xhr.open("GET", filename, false/*syncronous*/); //console.log("loading external script %s", filename); xhr.onreadystatechange = function(){ //console.log("readyState %s", xhr.readyState); if(xhr.readyState === 4){ Envjs.eval( script.ownerDocument.ownerWindow, xhr.responseText, filename ); } }; xhr.send(null, false); } catch(e) { console.log("could not load script %s \n %s", filename, e ); Envjs.onScriptLoadError(script, e); return false; } //lets you register a function to execute //after the script is loaded if(Envjs.afterScriptLoad){ for(src in Envjs.afterScriptLoad){ if(script.src.match(src)){ Envjs.afterScriptLoad[src](script); } } } return true; }; /** * An 'image' was requested by the document. * * - During inital parse of a <link> * - Via an innerHTML parse of a <link> * - A modificiation of the 'src' attribute of an Image/HTMLImageElement * * NOTE: this is optional API. If this doesn't exist then the default * 'loaded' event occurs. * * @param node {Object} the <img> node * @param node the src value * @return 'true' to indicate the 'load' succeed, false otherwise */ Envjs.loadImage = function(node, src) { return true; }; /** * A 'link' was requested by the document. Typically this occurs when: * - During inital parse of a <link> * - Via an innerHTML parse of a <link> * - A modificiation of the 'href' attribute on a <link> node in the tree * * @param node {Object} is the link node in question * @param href {String} is the href. * * Return 'true' to indicate that the 'load' was successful, or false * otherwise. The appropriate event is then triggered. * * NOTE: this is optional API. If this doesn't exist then the default * 'loaded' event occurs */ Envjs.loadLink = function(node, href) { return true; }; (function(){ /* * cookie handling * Private internal helper class used to save/retreive cookies */ /** * Specifies the location of the cookie file */ Envjs.cookieFile = function(){ return 'file://'+Envjs.homedir+'/.cookies'; }; /** * saves cookies to a local file * @param {Object} htmldoc */ Envjs.saveCookies = function(){ var cookiejson = JSON.stringify(Envjs.cookies.peristent,null,'\t'); //console.log('persisting cookies %s', cookiejson); Envjs.writeToFile(cookiejson, Envjs.cookieFile()); }; /** * loads cookies from a local file * @param {Object} htmldoc */ Envjs.loadCookies = function(){ var cookiejson, js; try{ cookiejson = Envjs.readFromFile(Envjs.cookieFile()) js = JSON.parse(cookiejson, null, '\t'); }catch(e){ //console.log('failed to load cookies %s', e); js = {}; } return js; }; Envjs.cookies = { persistent:{ //domain - key on domain name { //path - key on path { //name - key on name { //value : cookie value //other cookie properties //} //} //} //expire - provides a timestamp for expiring the cookie //cookie - the cookie! }, temporary:{//transient is a reserved word :( //like above } }; var __cookies__; //HTMLDocument cookie Envjs.setCookie = function(url, cookie){ var i, index, name, value, properties = {}, attr, attrs; url = Envjs.urlsplit(url); if(cookie) attrs = cookie.split(";"); else return; //for now the strategy is to simply create a json object //and post it to a file in the .cookies.js file. I hate parsing //dates so I decided not to implement support for 'expires' //(which is deprecated) and instead focus on the easier 'max-age' //(which succeeds 'expires') cookie = {};//keyword properties of the cookie cookie['domain'] = url.hostname; cookie['path'] = url.path||'/'; for(i=0;i<attrs.length;i++){ index = attrs[i].indexOf("="); if(index > -1){ name = __trim__(attrs[i].slice(0,index)); value = __trim__(attrs[i].slice(index+1)); if(name=='max-age'){ //we'll have to when to check these //and garbage collect expired cookies cookie[name] = parseInt(value, 10); } else if( name == 'domain' ){ if(__domainValid__(url, value)){ cookie['domain'] = value; } } else if( name == 'path' ){ //not sure of any special logic for path cookie['path'] = value; } else { //its not a cookie keyword so store it in our array of properties //and we'll serialize individually in a moment properties[name] = value; } }else{ if( attrs[i] == 'secure' ){ cookie[attrs[i]] = true; } } } if(!('max-age' in cookie)){ //it's a transient cookie so it only lasts as long as //the window.location remains the same (ie in-memory cookie) __mergeCookie__(Envjs.cookies.temporary, cookie, properties); }else{ //the cookie is persistent __mergeCookie__(Envjs.cookies.persistent, cookie, properties); Envjs.saveCookies(); } }; function __domainValid__(url, value){ var i, domainParts = url.hostname.split('.').reverse(), newDomainParts = value.split('.').reverse(); if(newDomainParts.length > 1){ for(i=0;i<newDomainParts.length;i++){ if(!(newDomainParts[i] == domainParts[i])){ return false; } } return true; } return false; }; Envjs.getCookies = function(url){ //The cookies that are returned must belong to the same domain //and be at or below the current window.location.path. Also //we must check to see if the cookie was set to 'secure' in which //case we must check our current location.protocol to make sure it's //https: var persisted; url = Envjs.urlsplit(url); if(!__cookies__){ try{ __cookies__ = true; try{ persisted = Envjs.loadCookies(); }catch(e){ //fail gracefully //console.log('%s', e); } if(persisted){ __extend__(Envjs.cookies.persistent, persisted); } //console.log('set cookies for doc %s', doc.baseURI); }catch(e){ console.log('cookies not loaded %s', e) }; } var temporary = __cookieString__(Envjs.cookies.temporary, url), persistent = __cookieString__(Envjs.cookies.persistent, url); //console.log('temporary cookies: %s', temporary); //console.log('persistent cookies: %s', persistent); return temporary + persistent; }; function __cookieString__(cookies, url) { var cookieString = "", domain, path, name, i=0; for (domain in cookies) { // check if the cookie is in the current domain (if domain is set) // console.log('cookie domain %s', domain); if (domain == "" || domain == url.hostname) { for (path in cookies[domain]) { // console.log('cookie domain path %s', path); // make sure path is at or below the window location path if (path == "/" || url.path.indexOf(path) > -1) { for (name in cookies[domain][path]) { // console.log('cookie domain path name %s', name); cookieString += ((i++ > 0)?'; ':'') + name + "=" + cookies[domain][path][name].value; } } } } } return cookieString; }; function __mergeCookie__(target, cookie, properties){ var name, now; if(!target[cookie.domain]){ target[cookie.domain] = {}; } if(!target[cookie.domain][cookie.path]){ target[cookie.domain][cookie.path] = {}; } for(name in properties){ now = new Date().getTime(); target[cookie.domain][cookie.path][name] = { "value":properties[name], "secure":cookie.secure, "max-age":cookie['max-age'], "date-created":now, "expiration":(cookie['max-age']===0) ? 0 : now + cookie['max-age'] }; //console.log('cookie is %o',target[cookie.domain][cookie.path][name]); } }; })();//end cookies /* http://www.JSON.org/json2.js 2008-07-15 Public Domain. NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. See http://www.JSON.org/js.html This code should be minified before deployment. See http://javascript.crockford.com/jsmin.html USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO NOT CONTROL. */ try{ JSON; }catch(e){ JSON = function () { function f(n) { // Format integers to have at least two digits. return n < 10 ? '0' + n : n; } Date.prototype.toJSON = function (key) { return this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z'; }; String.prototype.toJSON = function (key) { return String(this); }; Number.prototype.toJSON = Boolean.prototype.toJSON = function (key) { return this.valueOf(); }; var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, escapeable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, gap, indent, meta = { // table of character substitutions '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\' }, rep; function quote(string) { escapeable.lastIndex = 0; return escapeable.test(string) ? '"' + string.replace(escapeable, function (a) { var c = meta[a]; if (typeof c === 'string') { return c; } return '\\u' + ('0000' + (+(a.charCodeAt(0))).toString(16)).slice(-4); }) + '"' : '"' + string + '"'; } function str(key, holder) { var i, // The loop counter. k, // The member key. v, // The member value. length, mind = gap, partial, value = holder[key]; if (value && typeof value === 'object' && typeof value.toJSON === 'function') { value = value.toJSON(key); } if (typeof rep === 'function') { value = rep.call(holder, key, value); } switch (typeof value) { case 'string': return quote(value); case 'number': return isFinite(value) ? String(value) : 'null'; case 'boolean': case 'null': return String(value); case 'object': if (!value) { return 'null'; } gap += indent; partial = []; if (typeof value.length === 'number' && !(value.propertyIsEnumerable('length'))) { length = value.length; for (i = 0; i < length; i += 1) { partial[i] = str(i, value) || 'null'; } v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']'; gap = mind; return v; } if (rep && typeof rep === 'object') { length = rep.length; for (i = 0; i < length; i += 1) { k = rep[i]; if (typeof k === 'string') { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } else { for (k in value) { if (Object.hasOwnProperty.call(value, k)) { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}'; gap = mind; return v; } } return { stringify: function (value, replacer, space) { var i; gap = ''; indent = ''; if (typeof space === 'number') { for (i = 0; i < space; i += 1) { indent += ' '; } } else if (typeof space === 'string') { indent = space; } rep = replacer; if (replacer && typeof replacer !== 'function' && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) { throw new Error('JSON.stringify'); } return str('', {'': value}); }, parse: function (text, reviver) { var j; function walk(holder, key) { var k, v, value = holder[key]; if (value && typeof value === 'object') { for (k in value) { if (Object.hasOwnProperty.call(value, k)) { v = walk(value, k); if (v !== undefined) { value[k] = v; } else { delete value[k]; } } } } return reviver.call(holder, key, value); } cx.lastIndex = 0; if (cx.test(text)) { text = text.replace(cx, function (a) { return '\\u' + ('0000' + (+(a.charCodeAt(0))).toString(16)).slice(-4); }); } if (/^[\],:{}\s]*$/. test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { j = eval('(' + text + ')'); return typeof reviver === 'function' ? walk({'': j}, '') : j; } throw new SyntaxError('JSON.parse'); } }; }(); } /** * synchronizes thread modifications * @param {Function} fn */ Envjs.sync = function(fn){}; /** * sleep thread for specified duration * @param {Object} millseconds */ Envjs.sleep = function(millseconds){}; /** * Interval to wait on event loop when nothing is happening */ Envjs.WAIT_INTERVAL = 20;//milliseconds /* * Copyright (c) 2010 Nick Galbreath * http://code.google.com/p/stringencoders/source/browse/#svn/trunk/javascript * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ /* * url processing in the spirit of python's urlparse module * see `pydoc urlparse` or * http://docs.python.org/library/urlparse.html * * urlsplit: break apart a URL into components * urlunsplit: reconsistute a URL from componets * urljoin: join an absolute and another URL * urldefrag: remove the fragment from a URL * * Take a look at the tests in urlparse-test.html * * On URL Normalization: * * urlsplit only does minor normalization the components Only scheme * and hostname are lowercased urljoin does a bit more, normalizing * paths with "." and "..". * urlnormalize adds additional normalization * * * removes default port numbers * http://abc.com:80/ -> http://abc.com/, etc * * normalizes path * http://abc.com -> http://abc.com/ * and other "." and ".." cleanups * * if file, remove query and fragment * * It does not do: * * normalizes escaped hex values * http://abc.com/%7efoo -> http://abc.com/%7Efoo * * normalize '+' <--> '%20' * * Differences with Python * * The javascript urlsplit returns a normal object with the following * properties: scheme, netloc, hostname, port, path, query, fragment. * All properties are read-write. * * In python, the resulting object is not a dict, but a specialized, * read-only, and has alternative tuple interface (e.g. obj[0] == * obj.scheme). It's not clear why such a simple function requires * a unique datastructure. * * urlunsplit in javascript takes an duck-typed object, * { scheme: 'http', netloc: 'abc.com', ...} * while in * python it takes a list-like object. * ['http', 'abc.com'... ] * * For all functions, the javascript version use * hostname+port if netloc is missing. In python * hostname+port were always ignored. * * Similar functionality in different languages: * * http://php.net/manual/en/function.parse-url.php * returns assocative array but cannot handle relative URL * * TODO: test allowfragments more * TODO: test netloc missing, but hostname present */ var urlparse = {}; // Unlike to be useful standalone // // NORMALIZE PATH with "../" and "./" // http://en.wikipedia.org/wiki/URL_normalization // http://tools.ietf.org/html/rfc3986#section-5.2.3 // urlparse.normalizepath = function(path) { if (!path || path === '/') { return '/'; } var parts = path.split('/'); var newparts = []; // make sure path always starts with '/' if (parts[0]) { newparts.push(''); } for (var i = 0; i < parts.length; ++i) { if (parts[i] === '..') { if (newparts.length > 1) { newparts.pop(); } else { newparts.push(parts[i]); } } else if (parts[i] != '.') { newparts.push(parts[i]); } } path = newparts.join('/'); if (!path) { path = '/'; } return path; }; // // Does many of the normalizations that the stock // python urlsplit/urlunsplit/urljoin neglects // // Doesn't do hex-escape normalization on path or query // %7e -> %7E // Nor, '+' <--> %20 translation // urlparse.urlnormalize = function(url) { var parts = urlparse.urlsplit(url); switch (parts.scheme) { case 'file': // files can't have query strings // and we don't bother with fragments parts.query = ''; parts.fragment = ''; break; case 'http': case 'https': // remove default port if ((parts.scheme === 'http' && parts.port == 80) || (parts.scheme === 'https' && parts.port == 443)) { parts.port = null; // hostname is already lower case parts.netloc = parts.hostname; } break; default: // if we don't have specific normalizations for this // scheme, return the original url unmolested return url; } // for [file|http|https]. Not sure about other schemes parts.path = urlparse.normalizepath(parts.path); return urlparse.urlunsplit(parts); }; urlparse.urldefrag = function(url) { var idx = url.indexOf('#'); if (idx == -1) { return [ url, '' ]; } else { return [ url.substr(0,idx), url.substr(idx+1) ]; } }; urlparse.urlsplit = function(url, default_scheme, allow_fragments) { var leftover; if (typeof allow_fragments === 'undefined') { allow_fragments = true; } // scheme (optional), host, port var fullurl = /^([A-Za-z]+)?(:?\/\/)([0-9.\-A-Za-z]*)(?::(\d+))?(.*)$/; // path, query, fragment var parse_leftovers = /([^?#]*)?(?:\?([^#]*))?(?:#(.*))?$/; var o = {}; var parts = url.match(fullurl); if (parts) { o.scheme = parts[1] || default_scheme || ''; o.hostname = parts[3].toLowerCase() || ''; o.port = parseInt(parts[4],10) || ''; // Probably should grab the netloc from regexp // and then parse again for hostname/port o.netloc = parts[3]; if (parts[4]) { o.netloc += ':' + parts[4]; } leftover = parts[5]; } else { o.scheme = default_scheme || ''; o.netloc = ''; o.hostname = ''; leftover = url; } o.scheme = o.scheme.toLowerCase(); parts = leftover.match(parse_leftovers); o.path = parts[1] || ''; o.query = parts[2] || ''; if (allow_fragments) { o.fragment = parts[3] || ''; } else { o.fragment = ''; } return o; }; urlparse.urlunsplit = function(o) { var s = ''; if (o.scheme) { s += o.scheme + '://'; } if (o.netloc) { if (s == '') { s += '//'; } s += o.netloc; } else if (o.hostname) { // extension. Python only uses netloc if (s == '') { s += '//'; } s += o.hostname; if (o.port) { s += ':' + o.port; } } if (o.path) { s += o.path; } if (o.query) { s += '?' + o.query; } if (o.fragment) { s += '#' + o.fragment; } return s; }; urlparse.urljoin = function(base, url, allow_fragments) { if (typeof allow_fragments === 'undefined') { allow_fragments = true; } var url_parts = urlparse.urlsplit(url); // if url parts has a scheme (i.e. absolute) // then nothing to do if (url_parts.scheme) { if (! allow_fragments) { return url; } else { return urlparse.urldefrag(url)[0]; } } var base_parts = urlparse.urlsplit(base); // copy base, only if not present if (!base_parts.scheme) { base_parts.scheme = url_parts.scheme; } // copy netloc, only if not present if (!base_parts.netloc || !base_parts.hostname) { base_parts.netloc = url_parts.netloc; base_parts.hostname = url_parts.hostname; base_parts.port = url_parts.port; } // paths if (url_parts.path.length > 0) { if (url_parts.path.charAt(0) == '/') { base_parts.path = url_parts.path; } else { // relative path.. get rid of "current filename" and // replace. Same as var parts = // base_parts.path.split('/'); parts[parts.length-1] = // url_parts.path; base_parts.path = parts.join('/'); var idx = base_parts.path.lastIndexOf('/'); if (idx == -1) { base_parts.path = url_parts.path; } else { base_parts.path = base_parts.path.substr(0,idx) + '/' + url_parts.path; } } } // clean up path base_parts.path = urlparse.normalizepath(base_parts.path); // copy query string base_parts.query = url_parts.query; // copy fragments if (allow_fragments) { base_parts.fragment = url_parts.fragment; } else { base_parts.fragment = ''; } return urlparse.urlunsplit(base_parts); }; /** * getcwd - named after posix call of same name (see 'man 2 getcwd') * */ Envjs.getcwd = function() { return '.'; }; /** * resolves location relative to doc location * * @param {Object} path Relative or absolute URL * @param {Object} base (semi-optional) The base url used in resolving "path" above */ Envjs.uri = function(path, base) { //console.log('constructing uri from path %s and base %s', path, base); // Semi-common trick is to make an iframe with src='javascript:false' // (or some equivalent). By returning '', the load is skipped if (path.indexOf('javascript') === 0) { return ''; } // if path is absolute, then just normalize and return if (path.match('^[a-zA-Z]+://')) { return urlparse.urlnormalize(path); } // interesting special case, a few very large websites use // '//foo/bar/' to mean 'http://foo/bar' if (path.match('^//')) { path = 'http:' + path; } // if base not passed in, try to get it from document // Ideally I would like the caller to pass in document.baseURI to // make this more self-sufficient and testable if (!base && document) { base = document.baseURI; } // about:blank doesn't count if (base === 'about:blank'){ base = ''; } // if base is still empty, then we are in QA mode loading local // files. Get current working directory if (!base) { base = 'file://' + Envjs.getcwd() + '/'; } // handles all cases if path is abosulte or relative to base // 3rd arg is "false" --> remove fragments var newurl = urlparse.urlnormalize(urlparse.urljoin(base, path, false)); return newurl; }; /** * Used in the XMLHttpRquest implementation to run a * request in a seperate thread * @param {Object} fn */ Envjs.runAsync = function(fn){}; /** * Used to write to a local file * @param {Object} text * @param {Object} url */ Envjs.writeToFile = function(text, url){}; /** * Used to write to a local file * @param {Object} text * @param {Object} suffix */ Envjs.writeToTempFile = function(text, suffix){}; /** * Used to read the contents of a local file * @param {Object} url */ Envjs.readFromFile = function(url){}; /** * Used to delete a local file * @param {Object} url */ Envjs.deleteFile = function(url){}; /** * establishes connection and calls responsehandler * @param {Object} xhr * @param {Object} responseHandler * @param {Object} data */ Envjs.connection = function(xhr, responseHandler, data){}; __extend__(Envjs, urlparse); /** * Makes an object window-like by proxying object accessors * @param {Object} scope * @param {Object} parent */ Envjs.proxy = function(scope, parent, aliasList){}; Envjs.javaEnabled = false; Envjs.homedir = ''; Envjs.tmpdir = ''; Envjs.os_name = ''; Envjs.os_arch = ''; Envjs.os_version = ''; Envjs.lang = ''; Envjs.platform = ''; /** * * @param {Object} frameElement * @param {Object} url */ Envjs.loadFrame = function(frame, url){ try { if(frame.contentWindow){ //mark for garbage collection frame.contentWindow = null; } //create a new scope for the window proxy //platforms will need to override this function //to make sure the scope is global-like frame.contentWindow = (function(){return this;})(); new Window(frame.contentWindow, window); //I dont think frames load asynchronously in firefox //and I think the tests have verified this but for //some reason I'm less than confident... Are there cases? frame.contentDocument = frame.contentWindow.document; frame.contentDocument.async = false; if(url){ //console.log('envjs.loadFrame async %s', frame.contentDocument.async); frame.contentWindow.location = url; } } catch(e) { console.log("failed to load frame content: from %s %s", url, e); } }; // The following are in rhino/window.js // TODO: Envjs.unloadFrame // TODO: Envjs.proxy /** * @author john resig & the envjs team * @uri http://www.envjs.com/ * @copyright 2008-2010 * @license MIT */ //CLOSURE_END }()); /* * Envjs rhino-env.1.2.13 * Pure JavaScript Browser Environment * By John Resig <http://ejohn.org/> and the Envjs Team * Copyright 2008-2010 John Resig, under the MIT License */ var __context__ = Packages.org.mozilla.javascript.Context.getCurrentContext(); Envjs.platform = "Rhino"; Envjs.revision = "1.7.0.rc2"; /* * Envjs rhino-env.1.2.13 * Pure JavaScript Browser Environment * By John Resig <http://ejohn.org/> and the Envjs Team * Copyright 2008-2010 John Resig, under the MIT License */ //CLOSURE_START (function(){ /** * @author john resig */ // Helper method for extending one object with another. function __extend__(a,b) { for ( var i in b ) { var g = b.__lookupGetter__(i), s = b.__lookupSetter__(i); if ( g || s ) { if ( g ) { a.__defineGetter__(i, g); } if ( s ) { a.__defineSetter__(i, s); } } else { a[i] = b[i]; } } return a; } /** * Writes message to system out. * * Some sites redefine 'print' as in 'window.print', so instead of * printing to stdout, you are popping open a new window, which might * call print, etc, etc,etc This can cause infinite loops and can * exhausing all memory. * * By defining this upfront now, Envjs.log will always call the native 'print' * function * * @param {Object} message */ Envjs.log = print; Envjs.lineSource = function(e){ return e&&e.rhinoException?e.rhinoException.lineSource():"(line ?)"; }; /** * load and execute script tag text content * @param {Object} script */ Envjs.loadInlineScript = function(script){ if(script.ownerDocument.ownerWindow){ Envjs.eval( script.ownerDocument.ownerWindow, script.text, 'eval('+script.text.substring(0,16)+'...):'+new Date().getTime() ); }else{ Envjs.eval( __this__, script.text, 'eval('+script.text.substring(0,16)+'...):'+new Date().getTime() ); } //console.log('evaluated at scope %s \n%s', // script.ownerDocument.ownerWindow.guid, script.text); }; Envjs.eval = function(context, source, name){ __context__.evaluateString( context, source, name, 0, null ); }; //Temporary patch for parser module Packages.org.mozilla.javascript.Context. getCurrentContext().setOptimizationLevel(-1); /** * Rhino provides a very succinct 'sync' * @param {Function} fn */ try{ Envjs.sync = sync; Envjs.spawn = spawn; } catch(e){ //sync unavailable on AppEngine Envjs.sync = function(fn){ //console.log('Threadless platform, sync is safe'); return fn; }; Envjs.spawn = function(fn){ //console.log('Threadless platform, spawn shares main thread.'); return fn(); }; } /** * sleep thread for specified duration * @param {Object} millseconds */ Envjs.sleep = function(millseconds){ try{ java.lang.Thread.currentThread().sleep(millseconds); }catch(e){ console.log('Threadless platform, cannot sleep.'); } }; /** * provides callback hook for when the system exits */ Envjs.onExit = function(callback){ var rhino = Packages.org.mozilla.javascript, contextFactory = __context__.getFactory(), listener = new rhino.ContextFactory.Listener({ contextReleased: function(context){ if(context === __context__) console.log('context released', context); contextFactory.removeListener(this); if(callback) callback(); } }); contextFactory.addListener(listener); }; /** * Get 'Current Working Directory' */ Envjs.getcwd = function() { return java.lang.System.getProperty('user.dir'); } /** * * @param {Object} fn * @param {Object} onInterupt */ Envjs.runAsync = function(fn, onInterupt){ ////Envjs.debug("running async"); var running = true, run; try{ run = Envjs.sync(function(){ fn(); Envjs.wait(); }); Envjs.spawn(run); }catch(e){ console.log("error while running async operation", e); try{if(onInterrupt)onInterrupt(e)}catch(ee){}; } }; /** * Used to write to a local file * @param {Object} text * @param {Object} url */ Envjs.writeToFile = function(text, url){ //Envjs.debug("writing text to url : " + url); var out = new java.io.FileWriter( new java.io.File( new java.net.URI(url.toString()))); out.write( text, 0, text.length ); out.flush(); out.close(); }; /** * Used to write to a local file * @param {Object} text * @param {Object} suffix */ Envjs.writeToTempFile = function(text, suffix){ //Envjs.debug("writing text to temp url : " + suffix); // Create temp file. var temp = java.io.File.createTempFile("envjs-tmp", suffix); // Delete temp file when program exits. temp.deleteOnExit(); // Write to temp file var out = new java.io.FileWriter(temp); out.write(text, 0, text.length); out.close(); return temp.getAbsolutePath().toString()+''; }; /** * Used to read the contents of a local file * @param {Object} url */ Envjs.readFromFile = function( url ){ var fileReader = new java.io.FileReader( new java.io.File( new java.net.URI( url ))); var stringwriter = new java.io.StringWriter(), buffer = java.lang.reflect.Array.newInstance(java.lang.Character.TYPE, 1024), length; while ((length = fileReader.read(buffer, 0, 1024)) != -1) { stringwriter.write(buffer, 0, length); } stringwriter.close(); return stringwriter.toString()+""; }; /** * Used to delete a local file * @param {Object} url */ Envjs.deleteFile = function(url){ var file = new java.io.File( new java.net.URI( url ) ); file["delete"](); }; /** * establishes connection and calls responsehandler * @param {Object} xhr * @param {Object} responseHandler * @param {Object} data */ Envjs.connection = function(xhr, responseHandler, data){ var url = java.net.URL(xhr.url), connection, header, outstream, buffer, length, binary = false, name, value, contentEncoding, instream, responseXML, i; if ( /^file\:/.test(url) ) { try{ if ( "PUT" == xhr.method || "POST" == xhr.method ) { data = data || "" ; Envjs.writeToFile(data, url); xhr.readyState = 4; //could be improved, I just cant recall the correct http codes xhr.status = 200; xhr.statusText = ""; } else if ( xhr.method == "DELETE" ) { Envjs.deleteFile(url); xhr.readyState = 4; //could be improved, I just cant recall the correct http codes xhr.status = 200; xhr.statusText = ""; } else { connection = url.openConnection(); connection.connect(); //try to add some canned headers that make sense try{ if(xhr.url.match(/html$/)){ xhr.responseHeaders["Content-Type"] = 'text/html'; }else if(xhr.url.match(/.xml$/)){ xhr.responseHeaders["Content-Type"] = 'text/xml'; }else if(xhr.url.match(/.js$/)){ xhr.responseHeaders["Content-Type"] = 'text/javascript'; }else if(xhr.url.match(/.json$/)){ xhr.responseHeaders["Content-Type"] = 'application/json'; }else{ xhr.responseHeaders["Content-Type"] = 'text/plain'; } //xhr.responseHeaders['Last-Modified'] = connection.getLastModified(); //xhr.responseHeaders['Content-Length'] = headerValue+''; //xhr.responseHeaders['Date'] = new Date()+'';*/ }catch(e){ console.log('failed to load response headers',e); } } }catch(e){ console.log('failed to open file %s %s', url, e); connection = null; xhr.readyState = 4; xhr.statusText = "Local File Protocol Error"; xhr.responseText = "<html><head/><body><p>"+ e+ "</p></body></html>"; } } else { connection = url.openConnection(); connection.setRequestMethod( xhr.method ); // Add headers to Java connection for (header in xhr.headers){ connection.addRequestProperty(header+'', xhr.headers[header]+''); } //write data to output stream if required if(data){ if(data instanceof Document){ if ( xhr.method == "PUT" || xhr.method == "POST" ) { connection.setDoOutput(true); outstream = connection.getOutputStream(), xml = (new XMLSerializer()).serializeToString(data); buffer = new java.lang.String(xml).getBytes('UTF-8'); outstream.write(buffer, 0, buffer.length); outstream.close(); } }else if(data.length&&data.length>0){ if ( xhr.method == "PUT" || xhr.method == "POST" ) { connection.setDoOutput(true); outstream = connection.getOutputStream(); buffer = new java.lang.String(data).getBytes('UTF-8'); outstream.write(buffer, 0, buffer.length); outstream.close(); } } connection.connect(); }else{ connection.connect(); } } if(connection){ try{ length = connection.getHeaderFields().size(); // Stick the response headers into responseHeaders for (i = 0; i < length; i++) { name = connection.getHeaderFieldKey(i); value = connection.getHeaderField(i); if (name) xhr.responseHeaders[name+''] = value+''; } }catch(e){ console.log('failed to load response headers \n%s',e); } xhr.readyState = 4; xhr.status = parseInt(connection.responseCode,10) || undefined; xhr.statusText = connection.responseMessage || ""; contentEncoding = connection.getContentEncoding() || "utf-8"; instream = null; responseXML = null; try{ //console.log('contentEncoding %s', contentEncoding); if( contentEncoding.equalsIgnoreCase("gzip") || contentEncoding.equalsIgnoreCase("decompress")){ //zipped content binary = true; outstream = new java.io.ByteArrayOutputStream(); buffer = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, 1024); instream = new java.util.zip.GZIPInputStream(connection.getInputStream()) }else{ //this is a text file outstream = new java.io.StringWriter(); buffer = java.lang.reflect.Array.newInstance(java.lang.Character.TYPE, 1024); instream = new java.io.InputStreamReader(connection.getInputStream()); } }catch(e){ if (connection.getResponseCode() == 404){ console.log('failed to open connection stream \n %s %s', e.toString(), e); }else{ console.log('failed to open connection stream \n %s %s', e.toString(), e); } instream = connection.getErrorStream(); } while ((length = instream.read(buffer, 0, 1024)) != -1) { outstream.write(buffer, 0, length); } outstream.close(); instream.close(); if(binary){ xhr.responseText = new String(outstream.toByteArray(), 'UTF-8') + ''; }else{ xhr.responseText = outstream.toString() + ''; } } if(responseHandler){ //Envjs.debug('calling ajax response handler'); responseHandler(); } }; //Since we're running in rhino I guess we can safely assume //java is 'enabled'. I'm sure this requires more thought //than I've given it here Envjs.javaEnabled = true; Envjs.homedir = java.lang.System.getProperty("user.home"); Envjs.tmpdir = java.lang.System.getProperty("java.io.tmpdir"); Envjs.os_name = java.lang.System.getProperty("os.name"); Envjs.os_arch = java.lang.System.getProperty("os.arch"); Envjs.os_version = java.lang.System.getProperty("os.version"); Envjs.lang = java.lang.System.getProperty("user.lang"); /** * * @param {Object} frameElement * @param {Object} url */ Envjs.loadFrame = function(frame, url){ try { if(frame.contentWindow){ //mark for garbage collection frame.contentWindow = null; } //create a new scope for the window proxy frame.contentWindow = Envjs.proxy(); new Window(frame.contentWindow, window); //I dont think frames load asynchronously in firefox //and I think the tests have verified this but for //some reason I'm less than confident... Are there cases? frame.contentDocument = frame.contentWindow.document; frame.contentDocument.async = false; if(url){ //console.log('envjs.loadFrame async %s', frame.contentDocument.async); frame.contentWindow.location = url; } } catch(e) { console.log("failed to load frame content: from %s %s", url, e); } }; /** * unloadFrame * @param {Object} frame */ Envjs.unloadFrame = function(frame){ var all, length, i; try{ //TODO: probably self-referencing structures within a document tree //preventing it from being entirely garbage collected once orphaned. //Should have code to walk tree and break all links between contained //objects. frame.contentDocument = null; if(frame.contentWindow){ frame.contentWindow.close(); } gc(); }catch(e){ console.log(e); } }; /** * Makes an object window-like by proxying object accessors * @param {Object} scope * @param {Object} parent */ Envjs.proxy = function(scope, parent) { try{ if(scope+'' == '[object global]'){ return scope }else{ return __context__.initStandardObjects(); } }catch(e){ console.log('failed to init standard objects %s %s \n%s', scope, parent, e); } }; /** * @author john resig & the envjs team * @uri http://www.envjs.com/ * @copyright 2008-2010 * @license MIT */ //CLOSURE_END }()); /** * @author envjs team */ var Console, console; /* * Envjs console.1.2.13 * Pure JavaScript Browser Environment * By John Resig <http://ejohn.org/> and the Envjs Team * Copyright 2008-2010 John Resig, under the MIT License */ //CLOSURE_START (function(){ /** * @author envjs team * borrowed 99%-ish with love from firebug-lite * * http://wiki.commonjs.org/wiki/Console */ Console = function(module){ var $level, $logger, $null = function(){}; if(Envjs[module] && Env