UNPKG

crossbrowdy

Version:

A Multimedia JavaScript framework to create real cross-platform and hybrid game engines, games, emulators, multimedia libraries and apps.

748 lines (647 loc) 18.2 kB
(function (window, document, location, navigator, undefined, name) { "use strict"; function Helper () { var self = this; /** * Variable holding the body element. */ self.body = document.body || document.getElementsByTagName("body")[0]; /** * Variable holding the documents protocol. */ self.protocol = location.protocol || document.protocol; /** * Variable holding the documents domain. */ self.domain = document.domain; /** * Variable holding the Object prototype. */ self.oProto = Object.prototype; /** * Function to check whether the argument is undefined. */ self.isUndefined = function (_arg) { return _arg === undefined; }; /** * Function to check if the browser is IE. */ self.isIE = function () { var result = false; /* jshint ignore:start */ result = new Function("return/*@cc_on!@*/!1")() || ( self.isNumber(document.documentMode) && document.documentMode <= 10 ); /* jshint ignore:end */ return result; }; /** * Function to fix the key of a storage function */ self.fixKey = function (_key) { var forbidden = new RegExp( "[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g" ); return _key.replace(/^d/, "___$&").replace(forbidden, "___"); }; /** * Function to iterate through array. */ self.each = function (_array, _callback) { var length = _array.length; while (length) { length -= 1; if ( !self.isUndefined(_array.key) ) { _callback.call(self, _array.key(length), length); } else { _callback.call(self, _array[length], length); } } }; /** * Function to iterate through object. */ self.forEach = function (_object, _callback) { var key = null; for (key in _object) { if (_object.hasOwnProperty(key)) { _callback.call(self, _object[key], key); } } }; /** * Function to add attributes to element. */ self.attribute = function (_element, _key, _value) { var att; if ( !!_element.setAttribute ) { // Supported by most browsers. _element.setAttribute(_key, _value); } else if ( !!_element.attributes ) { // Another way of applying attributes. _element.attributes[_key] = _value; } else if ( !!_element.createAttribute ) { // Yet another way supported by DOM1 att = document.createAttribute(_key); att.value = _value; _element.setAttributeNode(att); } else { // Last option. _element[_key] = _value; } }; /** * Function to retrieve the swf url based on the src of the script. */ self.swfURL = (function() { var scripts = document.scripts || document.getElementsByTagName("script"), source = scripts[scripts.length-1].src.split("?"), url = null; if (source[1]) { self.each(source[1].split("&"), function (_arg) { var data = _arg.split("="); if (data[0] === "swfURL") { url = decodeURIComponent(data[1].replace(/\+/g, " ")); return url; } }); } return url; })(); /** * Function that emulates the appendChild method. */ self.appendChild = function (_parent, _child) { _parent.insertBefore( _child, _parent.lastChild ? _parent.lastChild.nextSibling : _parent.lastChild ); }; /** * Function to create an element. */ self.element = function (_arg) { return document.createElement(_arg); }; /** * Function that returns an integer in base 10. */ self.toInt = function (_arg) { return parseInt(_arg, 10); }; /** * Function that determines if flash is available. */ self.hasFlash = function () { var flash, description, mimetype = "application/x-shockwave-flash"; try { flash = new ActiveXObject("ShockwaveFlash.ShockwaveFlash"); if ( flash ) { description = flash.GetVariable("$version"); if ( description && _.toInt(description.split(" ")[1].split(",")[0]) >= 9 ) { return true; } } return false; } catch (ignore) { if ( _.isObject(navigator.plugins["Shockwave Flash"]) && !_.isUndefined(navigator.mimeTypes) && !_.isUndefined(navigator.mimeTypes[mimetype]) ) { description = navigator.plugins["Shockwave Flash"].description; if ( navigator.mimeTypes[mimetype].enabledPlugin && !_.isUndefined(description) ) { description = description.replace( /^.*\s+(\S+\s+\S+$)/, "$1" ); if ( _.toInt(description.replace(/^(.*)\..*$/, "$1")) >= 9 ) { return true; } } } return false; } }; /** * Function to check whether the argument is an Object. */ self.isObject = function (_arg) { return _arg === Object(_arg); }; /** * Functions to check the type of a given argument. */ self.each.call(self, [ "String", "Function", "Number" ], function (_type) { self["is" + _type] = function (_arg) { return typeof _arg === _type.toLowerCase() || self.oProto.toString.call(_arg) === "[object " + _type + "]"; }; } ); } Helper.prototype.constructor = Helper; var _ = new Helper(), ready = false, proto; // Inspired by the solution from John Resig // http://ejohn.org/blog/simple-javascript-inheritance/#postcomment function Class(){} Class.extend = function(_values) { var Self = this, superClass = Self.prototype, protoClass = new Self(Class), superMethod = function () { return (function (name, fn) { return function() { var res, temp = this.$super; // Add a new super method that is the same method // but on the super-class this.$super = superClass[name]; res = fn.apply(this, arguments); this.$super = temp; return res; }; }(arguments[0], arguments[1])); }; // Copy the properties over onto the new prototype _.forEach(_values, function (_value, _name) { // Check if we're overwriting an existing function protoClass[_name] = ( _.isFunction(_value) && _.isFunction(superClass[_name]) ) ? superMethod.call(Self, _name, _value) : _value; }); function Persistent () { var self = this; if ( !(self instanceof Persistent) ) { return new Persistent(arguments[0]); } if ( arguments[0] !== Class && self.init ) { self.init.apply(self, arguments); } } Persistent.prototype = protoClass; Persistent.prototype.constructor = Persistent; Persistent.extend = Self.extend; return Persistent; }; var GlobalStorage = Class.extend({ "init" : function () { var self = this; if ( location.hostname === "localhost" ) { self.__storage__ = window.globalStorage["localhost.localdomain"]; } else { self.__storage__ = window.globalStorage[location.hostname]; } self.length = self.__storage__.length; }, "key" : function (_index) { var self = this; return (_index+1 > self.length || _index < 0) ? null : self.__storage__.key(_index); }, "getItem" : function (_key) { var self = this, object = self.__storage__.getItem(_key); if ( _.isObject(object) ) { return object.value; } return object; }, "setItem" : function (_key, _data) { var self = this; self.__storage__.setItem(_key, _data); self.length = self.__storage__.length; }, "removeItem" : function (_key) { var self = this; self.__storage__.removeItem(_key); self.length = self.__storage__.length; }, "clear" : function () { var self = this; _.each(self.__storage__, function (_key) { self.removeItem(_key); }); }, "isLoaded" : function () { return true; } }); GlobalStorage.prototype.constructor = GlobalStorage; window.GlobalStorage = GlobalStorage; var UserDataStorage = Class.extend({ "init" : function () { var self = this, AXO, owner, garbage = function () { window.detachEvent("onunload", garbage); AXO = owner = self.__storage__ = null; /* jshint ignore:start */ if ( _.isFunction(CollectGarbage) ) { CollectGarbage(); } /* jshint ignore:end */ }; try { AXO = new ActiveXObject("htmlfile"); AXO.open(); AXO.write( "<html><head><title>" + name + "</title>" + "<script type=\"text/javascript\">" + "document.domain = '" + _.protocol + "//" + _.domain + "';" + "</script>" + "</head><body></body></html>" ); AXO.close(); owner = AXO.body; self.__storage__ = AXO.createElement("div"); window.attachEvent("unload", garbage); } catch (ignore) { owner = _.body; self.__storage__ = _.element("div"); } _.appendChild(owner, self.__storage__); self.__storage__.style.display = "none"; self.__storage__.addBehavior("#default#userData"); self.__storage__.load(name + "_" + _.domain); self.__attributes__ = self.__storage__.XMLDocument.documentElement.attributes; self.length = self.__attributes__.length; }, "key" : function (_index) { var self = this, result = null; try { result = _index >= self.length ? null : self.__attributes__[_index].name; } catch (ignore) {} return result; }, "getItem" : function (_key) { var self = this; return self.__storage__.getAttribute(_.fixKey(_key)); }, "setItem" : function (_key, _data) { var self = this; try { self.__storage__.setAttribute(_.fixKey(_key), _data); self.__storage__.save(name + "_" + _.domain); self.length = self.__attributes__.length; } catch (e) { throw { "name" : "UserDataQuotaExceeded", "message" : "UserData is out of memory" }; } }, "removeItem" : function (_key) { var self = this; self.__storage__.removeAttribute(_.fixKey(_key)); self.__storage__.save(name + "_" + _.domain); self.length = self.__attributes__.length; }, "clear" : function () { var self = this; _.each(self.__attributes__, function (_attr) { self.removeItem(_attr.name); }); }, "isLoaded" : function () { return true; } }); UserDataStorage.prototype.constructor = UserDataStorage; window.UserDataStorage = UserDataStorage; var FlashStorage = Class.extend({ "init" : function (onerror) { var self = this, owner, url = _.swfURL ? _.swfURL : name + ".swf", timeout = 2000, attrs = "", mimetype = "application/x-shockwave-flash", attributes = { "id" : name, "name" : name, "width" : 1, "height" : 1 }, parameters = { allowScriptAccess : "always", wmode : "transparent", flashvars : "readyFn=window._swfReady" }, swfLoaded = function (_object, _callback, _error) { var cTimer = null, eTimer = null, clear = function () { clearInterval(cTimer); clearTimeout(eTimer); eTimer = cTimer = null; }; cTimer = setInterval(function () { if ( ( _.oProto.hasOwnProperty.call(_object, "PercentLoaded") && _object.PercentLoaded() === 100 ) || ready ) { clear.call(self); _callback.call(self); } }, 10); eTimer = setTimeout(function () { clear.call(self); if ( _.isFunction(_error) ) { _error.call(self); } }, timeout); }, unload = function () { var timer = null; window.detachEvent("onunload", unload); owner.style.display = "none"; timer = setInterval(function () { if (owner.readyState === 4) { clearInterval(timer); _.each(owner, function (_arg) { if ( _.isFunction(_arg) ) { _arg = null; } }); owner.parentNode.removeChild(owner); } }, 10); }; window._swfReady = function (_bool) { ready = _bool; }; try { attributes.classid = "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"; parameters.movie = url; _.forEach(attributes, function (_value, _key) { attrs += _key + "=\"" + _value + "\" "; }); owner = _.element( "<object " + attrs + ">" ); _.forEach(parameters, function (_value, _key) { var param = _.element( "<param name='" + _key + "' value='" + _value + "'>" ); _.appendChild(owner, param); }); window.attachEvent("onunload", unload); } catch (ignore) { if ( !_.isIE() ) { delete attributes.classid; delete parameters.movie; } owner = _.element("object"); _.forEach(parameters, function (_value, _key) { var param = _.element("param"); _.attribute(param, "name", _key); _.attribute(param, "value", _value); _.appendChild(owner, param); }); if ( !_.isIE() ) { _.attribute(owner, "type", mimetype); _.attribute(owner, "data", url); } _.forEach(attributes, function (_value, _key) { _.attribute(owner, _key, _value); }); } _.appendChild(_.body, owner); swfLoaded.call(self, owner, function () { self.__storage__ = document[name] || document.getElementById(name) || document.embeds[name]; self.length = self.__storage__.length(); self.key = function (_index) { return self.__storage__.key(_index); }; self.getItem = function (_key) { return self.__storage__.getItem(_key); }; self.setItem = function (_key, _data) { if ( !self.__storage__.setItem(_key, _data) ) { throw { "name" : "FlashQuotaExceeded", "message" : "FlashStorage is out of memory" }; } self.length = self.__storage__.length(); }; self.removeItem = function (_key) { self.__storage__.removeItem(_key); self.length = self.__storage__.length(); }; self.clear = function () { self.__storage__.clear(); self.length = self.__storage__.length(); }; self.isLoaded = function () { return true; }; }, onerror); }, "isLoaded" : function () { return false; } }); FlashStorage.prototype.constructor = FlashStorage; window.FlashStorage = FlashStorage; var CookieStorage = Class.extend({ "length" : (function () { var count = document.cookie.match(/\=/g); return count && count.length || 0; }()), "key" : function (_index) { var key = window.unescape( document.cookie.replace( /\s*\=(?:.(?!;))*$/, "" ).split(/\s*\=(?:[^;](?!;))*[^;]?;\s*/).sort()[_index] ); return key === "" ? null : key; }, "getItem" : function (_key) { var item = document.cookie.indexOf(_key + "=") === -1 ? "" : window.unescape( document.cookie.replace( new RegExp( "(?:^|.*;\\s*)" + window.escape(_key).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*" ), "$1" ) ); return item === "" ? null : item; }, "setItem" : function (_key, _data) { var self = this, count = 0, cookie = window.escape(_key) + "=" + window.escape(_data) + "; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/"; if (cookie.length > 4093) { throw { name : "CookieQuotaExceeded", message : "CookieStorage is out of memory" }; } document.cookie = cookie; count = document.cookie.match(/\=/g); self.length = count && count.length || 0; }, "removeItem" : function (_key) { var self = this, count = 0; document.cookie = window.escape(_key) + "=" + "; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/"; count = document.cookie.match(/\=/g); self.length = count && count.length || 0; }, "clear" : function () { var self = this; _.each(self, function (_key) { self.removeItem(_key); }); }, "isLoaded" : function () { return true; } }); CookieStorage.prototype.constructor = CookieStorage; window.CookieStorage = CookieStorage; try { window.localStorage.setItem(name, name); window.localStorage.removeItem(name); } catch (ignore) { if ( window.globalStorage ) { proto = GlobalStorage; } else if ( document.documentElement && document.documentElement.addBehavior ) { proto = UserDataStorage; } else if ( _.hasFlash() ) { proto = FlashStorage; } else if ( navigator.cookieEnabled ) { proto = CookieStorage; } var Storage = proto.extend({ "key" : function (_index) { var self = this; if ( _.isNumber(_index) && _index < self.length && _index >= 0 ) { return self.$super(_index); } return null; }, "getItem" : function (_key) { var self = this; if ( _.isString(_key) ) { return self.$super(_key); } return null; }, "setItem" : function (_key, _value) { var self = this, value = _.isString(_value) ? _value : ( !(_value === null || _.isUndefined(_value)) && _.oProto.hasOwnProperty.call(_value, "toString") ? _value.toString() : _.oProto.toString.call(_value)); if ( _.isString(_key) ) { self.$super( _key, value ); } }, "removeItem" : function (_key) { var self = this; if ( _.isString(_key) ) { self.$super(_key); } }, "isLoaded" : function (_callback) { var self = this, timer = null; if ( !_.isFunction(_callback) ) { return; } if ( self.$super() ) { return _callback.call(self); } timer = setInterval(function () { if ( self.$super() ) { clearInterval(timer); timer = null; _callback.call(self); } }, 10); } }); Storage.prototype.constructor = Storage; window.Storage = Storage; window.localStorage = new Storage( function () { window.localStorage = new CookieStorage(); } ); } }(window, window.document, window.location, window.navigator, void(0), "localStorage"));