new file: Files/flashplayer_32_sa.exe new file: favicon.ico new file: globe.gif new file: imgs/download.png new file: imgs/zuck.jpg new file: index.html new file: other.ico new file: script.js new file: site.webmanifest new file: sitemap.html new file: styles/backround.css new file: styles/border.css new file: styles/fonts/Titillium_Web/OFL.txt new file: styles/fonts/Titillium_Web/TitilliumWeb-Black.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-Bold.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-BoldItalic.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-ExtraLight.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-ExtraLightItalic.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-Italic.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-Light.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-LightItalic.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-Regular.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-SemiBold.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-SemiBoldItalic.ttf new file: styles/fonts/webfontkit-20221027-163353/generator_config.txt new file: styles/fonts/webfontkit-20221027-163353/specimen_files/grid_12-825-55-15.css new file: styles/fonts/webfontkit-20221027-163353/specimen_files/specimen_stylesheet.css new file: styles/fonts/webfontkit-20221027-163353/stylesheet.css new file: styles/fonts/webfontkit-20221027-163353/titilliumweb-extralight-demo.html new file: styles/fonts/webfontkit-20221027-163353/titilliumweb-extralight-webfont.woff new file: styles/fonts/webfontkit-20221027-163353/titilliumweb-extralight-webfont.woff2 new file: styles/fonts/webfontkit-20221027-165950/generator_config.txt new file: styles/fonts/webfontkit-20221027-165950/specimen_files/grid_12-825-55-15.css new file: styles/fonts/webfontkit-20221027-165950/specimen_files/specimen_stylesheet.css new file: styles/fonts/webfontkit-20221027-165950/stylesheet.css new file: styles/fonts/webfontkit-20221027-165950/titilliumweb-bold-demo.html new file: styles/fonts/webfontkit-20221027-165950/titilliumweb-bold-webfont.woff new file: styles/fonts/webfontkit-20221027-165950/titilliumweb-bold-webfont.woff2 new file: styles/style.css new file: tools/2048/.gitignore new file: tools/2048/.jshintrc new file: tools/2048/CONTRIBUTING.md new file: tools/2048/LICENSE.txt new file: tools/2048/README.md new file: tools/2048/Rakefile new file: tools/2048/favicon.ico new file: tools/2048/index.html new file: tools/2048/js/animframe_polyfill.js new file: tools/2048/js/application.js new file: tools/2048/js/bind_polyfill.js new file: tools/2048/js/classlist_polyfill.js new file: tools/2048/js/game_manager.js new file: tools/2048/js/grid.js new file: tools/2048/js/html_actuator.js new file: tools/2048/js/keyboard_input_manager.js new file: tools/2048/js/local_storage_manager.js new file: tools/2048/js/tile.js new file: tools/2048/meta/apple-touch-icon.png new file: tools/webretro/cores/neocd_libretro.js new file: tools/webretro/cores/neocd_libretro.wasm new file: tools/webretro/cores/nestopia_libretro.js new file: tools/webretro/cores/nestopia_libretro.wasm new file: tools/webretro/cores/o2em_libretro.js new file: tools/webretro/cores/o2em_libretro.wasm new file: tools/webretro/cores/opera_libretro.js new file: tools/webretro/cores/opera_libretro.wasm
989 lines
35 KiB
JavaScript
989 lines
35 KiB
JavaScript
/**
|
||
* gamecore.js - Copyright 2012 Playcraft Labs, Inc. (see licence.txt)
|
||
* class.js
|
||
* Classes and objects
|
||
*/
|
||
|
||
/**
|
||
* @Class
|
||
* A modified version of class.js to cater to static inheritance and deep object cloning
|
||
* Based almost completely on class.js (Javascript MVC -- Justin Meyer, Brian Moschel, Michael Mayer and others)
|
||
* (http://javascriptmvc.com/contribute.html)
|
||
* Some portions adapted from Prototype JavaScript framework, version 1.6.0.1 (c) 2005-2007 Sam Stephenson
|
||
* <p>
|
||
* Class system for javascript
|
||
* <p>
|
||
* <code>
|
||
* var Fighter = gamecore.Base.extend('Fighter',
|
||
* {
|
||
* // static (this is inherited as well)
|
||
* firingSpeed: 1000
|
||
* },
|
||
* {
|
||
* // instance
|
||
*
|
||
* hp: 0,
|
||
* lastFireTime: 0,
|
||
*
|
||
* init: function(hp)
|
||
* {
|
||
* this.hp = hp;
|
||
* },
|
||
*
|
||
* fire: function()
|
||
* {
|
||
* this._super(); // super methods!
|
||
*
|
||
* // do firing!
|
||
* }
|
||
* });
|
||
*
|
||
* var gunship = new Fighter(100);
|
||
* </code>
|
||
*
|
||
* Introspection:
|
||
* <code>
|
||
* gamecore.Base.extend(‘Fighter.Gunship’);
|
||
* Fighter.Gunship.shortName; // ‘Gunship’
|
||
* Fighter.Gunship.fullName; // ‘Fighter.Gunship’
|
||
* Fighter.Gunship.namespace; // ‘Fighter’
|
||
* </code>
|
||
* <p>
|
||
* Setup method will be called prior to any init -- nice if you want to do things without needing the
|
||
* users to call _super in the init, as well as for normalizing parameters.
|
||
* <code>
|
||
* setup: function()
|
||
* {
|
||
* this.objectId = this.Class.totalObjects++;
|
||
* this.uniqueId = this.Class.fullName + ':' + this.objectId;
|
||
* }
|
||
* </code>
|
||
*/
|
||
|
||
// compatible with jquery classing
|
||
(function ($)
|
||
{
|
||
var regs = {
|
||
undHash: /_|-/,
|
||
colons: /::/,
|
||
words: /([A-Z]+)([A-Z][a-z])/g,
|
||
lowUp: /([a-z\d])([A-Z])/g,
|
||
dash: /([a-z\d])([A-Z])/g,
|
||
replacer: /\{([^\}]+)\}/g,
|
||
dot: /\./
|
||
},
|
||
getNext = function (current, nextPart, add)
|
||
{
|
||
return current[nextPart] || ( add && (current[nextPart] = {}) );
|
||
},
|
||
isContainer = function (current)
|
||
{
|
||
var type = typeof current;
|
||
return type && ( type == 'function' || type == 'object' );
|
||
},
|
||
getObject = function (objectName, roots, add)
|
||
{
|
||
var parts = objectName ? objectName.split(regs.dot) : [],
|
||
length = parts.length,
|
||
currents = $.isArray(roots) ? roots : [roots || window],
|
||
current,
|
||
ret,
|
||
i,
|
||
c = 0,
|
||
type;
|
||
|
||
if (length == 0)
|
||
{
|
||
return currents[0];
|
||
}
|
||
while (current = currents[c++])
|
||
{
|
||
for (i = 0; i < length - 1 && isContainer(current); i++)
|
||
{
|
||
current = getNext(current, parts[i], add);
|
||
}
|
||
if (isContainer(current))
|
||
{
|
||
|
||
ret = getNext(current, parts[i], add);
|
||
|
||
if (ret !== undefined)
|
||
{
|
||
|
||
if (add === false)
|
||
{
|
||
delete current[parts[i]];
|
||
}
|
||
return ret;
|
||
|
||
}
|
||
|
||
}
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @class jQuery.String
|
||
*
|
||
* A collection of useful string helpers.
|
||
*
|
||
*/
|
||
str = $.String = $.extend($.String || {}, {
|
||
/**
|
||
* @function
|
||
* Gets an object from a string.
|
||
* @param {String} name the name of the object to look for
|
||
* @param {Array} [roots] an array of root objects to look for the name
|
||
* @param {Boolean} [add] true to add missing objects to
|
||
* the path. false to remove found properties. undefined to
|
||
* not modify the root object
|
||
*/
|
||
getObject: getObject,
|
||
/**
|
||
* Capitalizes a string
|
||
* @param {String} s the string.
|
||
* @return {String} a string with the first character capitalized.
|
||
*/
|
||
capitalize: function (s, cache)
|
||
{
|
||
return s.charAt(0).toUpperCase() + s.substr(1);
|
||
},
|
||
/**
|
||
* Capitalizes a string from something undercored. Examples:
|
||
* @codestart
|
||
* jQuery.String.camelize("one_two") //-> "oneTwo"
|
||
* "three-four".camelize() //-> threeFour
|
||
* @codeend
|
||
* @param {String} s
|
||
* @return {String} a the camelized string
|
||
*/
|
||
camelize: function (s)
|
||
{
|
||
s = str.classize(s);
|
||
return s.charAt(0).toLowerCase() + s.substr(1);
|
||
},
|
||
/**
|
||
* Like camelize, but the first part is also capitalized
|
||
* @param {String} s
|
||
* @return {String} the classized string
|
||
*/
|
||
classize: function (s, join)
|
||
{
|
||
var parts = s.split(regs.undHash),
|
||
i = 0;
|
||
for (; i < parts.length; i++)
|
||
{
|
||
parts[i] = str.capitalize(parts[i]);
|
||
}
|
||
|
||
return parts.join(join || '');
|
||
},
|
||
/**
|
||
* Like [jQuery.String.classize|classize], but a space separates each 'word'
|
||
* @codestart
|
||
* jQuery.String.niceName("one_two") //-> "One Two"
|
||
* @codeend
|
||
* @param {String} s
|
||
* @return {String} the niceName
|
||
*/
|
||
niceName: function (s)
|
||
{
|
||
return str.classize(s, ' ');
|
||
},
|
||
|
||
/**
|
||
* Underscores a string.
|
||
* @codestart
|
||
* jQuery.String.underscore("OneTwo") //-> "one_two"
|
||
* @codeend
|
||
* @param {String} s
|
||
* @return {String} the underscored string
|
||
*/
|
||
underscore: function (s)
|
||
{
|
||
return s.replace(regs.colons, '/').replace(regs.words, '$1_$2').replace(regs.lowUp, '$1_$2').replace(regs.dash, '_').toLowerCase();
|
||
},
|
||
/**
|
||
* Returns a string with {param} replaced values from data.
|
||
*
|
||
* $.String.sub("foo {bar}",{bar: "far"})
|
||
* //-> "foo far"
|
||
*
|
||
* @param {String} s The string to replace
|
||
* @param {Object} data The data to be used to look for properties. If it's an array, multiple
|
||
* objects can be used.
|
||
* @param {Boolean} [remove] if a match is found, remove the property from the object
|
||
*/
|
||
sub: function (s, data, remove)
|
||
{
|
||
var obs = [];
|
||
obs.push(s.replace(regs.replacer, function (whole, inside)
|
||
{
|
||
//convert inside to type
|
||
var ob = getObject(inside, data, typeof remove == 'boolean' ? !remove : remove),
|
||
type = typeof ob;
|
||
if ((type === 'object' || type === 'function') && type !== null)
|
||
{
|
||
obs.push(ob);
|
||
return "";
|
||
} else
|
||
{
|
||
return "" + ob;
|
||
}
|
||
}));
|
||
return obs.length <= 1 ? obs[0] : obs;
|
||
}
|
||
});
|
||
|
||
})(jQuery);
|
||
(function ($)
|
||
{
|
||
|
||
// if we are initializing a new class
|
||
var initializing = false,
|
||
makeArray = $.makeArray,
|
||
isFunction = $.isFunction,
|
||
isArray = $.isArray,
|
||
extend = $.extend,
|
||
|
||
/**
|
||
*
|
||
*/
|
||
cloneObject = function(object)
|
||
{
|
||
if (!object || typeof(object) != 'object')
|
||
return object;
|
||
|
||
// special case handling of array (deep copy them)
|
||
if (object instanceof Array)
|
||
{
|
||
var clone = [];
|
||
for (var c = 0; c < object.length; c++)
|
||
clone[c] = cloneObject(object[c]);
|
||
return clone;
|
||
}
|
||
else // otherwise, it's a normal object, clone it's properties
|
||
{
|
||
var cloneObj = {};
|
||
for (var prop in object)
|
||
cloneObj[prop] = cloneObject(object[prop]);
|
||
return cloneObj;
|
||
}
|
||
},
|
||
|
||
concatArgs = function (arr, args)
|
||
{
|
||
return arr.concat(makeArray(args));
|
||
},
|
||
// tests if we can get super in .toString()
|
||
fnTest = /xyz/.test(function ()
|
||
{
|
||
xyz;
|
||
}) ? /\b_super\b/ : /.*/,
|
||
// overwrites an object with methods, sets up _super
|
||
// newProps - new properties
|
||
// oldProps - where the old properties might be
|
||
// addTo - what we are adding to
|
||
inheritProps = function (newProps, oldProps, addTo)
|
||
{
|
||
addTo = addTo || newProps
|
||
for (var name in newProps)
|
||
{
|
||
// Check if we're overwriting an existing function
|
||
addTo[name] = isFunction(newProps[name]) &&
|
||
isFunction(oldProps[name]) &&
|
||
fnTest.test(newProps[name]) ? (function (name, fn)
|
||
{
|
||
return function ()
|
||
{
|
||
var tmp = this._super, ret;
|
||
|
||
// Add a new ._super() method that is the same method but on the super-class
|
||
this._super = oldProps[name];
|
||
|
||
// The method only need to be bound temporarily, so we remove it when we're done executing
|
||
ret = fn.apply(this, arguments);
|
||
this._super = tmp;
|
||
return ret;
|
||
};
|
||
})(name, newProps[name]) : newProps[name];
|
||
}
|
||
},
|
||
|
||
|
||
/**
|
||
* @class jQuery.Class
|
||
* @plugin jquery/class
|
||
* @tag core
|
||
* @download dist/jquery/jquery.class.js
|
||
* @test jquery/class/qunit.html
|
||
*
|
||
* Class provides simulated inheritance in JavaScript. Use clss to bridge the gap between
|
||
* jQuery's functional programming style and Object Oriented Programming. It
|
||
* is based off John Resig's [http://ejohn.org/blog/simple-javascript-inheritance/|Simple Class]
|
||
* Inheritance library. Besides prototypal inheritance, it includes a few important features:
|
||
*
|
||
* - Static inheritance
|
||
* - Introspection
|
||
* - Namespaces
|
||
* - Setup and initialization methods
|
||
* - Easy callback function creation
|
||
*
|
||
*
|
||
* ## Static v. Prototype
|
||
*
|
||
* Before learning about Class, it's important to
|
||
* understand the difference between
|
||
* a class's __static__ and __prototype__ properties.
|
||
*
|
||
* //STATIC
|
||
* MyClass.staticProperty //shared property
|
||
*
|
||
* //PROTOTYPE
|
||
* myclass = new MyClass()
|
||
* myclass.prototypeMethod() //instance method
|
||
*
|
||
* A static (or class) property is on the Class constructor
|
||
* function itself
|
||
* and can be thought of being shared by all instances of the
|
||
* Class. Prototype propertes are available only on instances of the Class.
|
||
*
|
||
* ## A Basic Class
|
||
*
|
||
* The following creates a Monster class with a
|
||
* name (for introspection), static, and prototype members.
|
||
* Every time a monster instance is created, the static
|
||
* count is incremented.
|
||
*
|
||
* @codestart
|
||
* $.Class.extend('Monster',
|
||
* /* @static *|
|
||
* {
|
||
* count: 0
|
||
* },
|
||
* /* @prototype *|
|
||
* {
|
||
* init: function( name ) {
|
||
*
|
||
* // saves name on the monster instance
|
||
* this.name = name;
|
||
*
|
||
* // sets the health
|
||
* this.health = 10;
|
||
*
|
||
* // increments count
|
||
* this.Class.count++;
|
||
* },
|
||
* eat: function( smallChildren ){
|
||
* this.health += smallChildren;
|
||
* },
|
||
* fight: function() {
|
||
* this.health -= 2;
|
||
* }
|
||
* });
|
||
*
|
||
* hydra = new Monster('hydra');
|
||
*
|
||
* dragon = new Monster('dragon');
|
||
*
|
||
* hydra.name // -> hydra
|
||
* Monster.count // -> 2
|
||
* Monster.shortName // -> 'Monster'
|
||
*
|
||
* hydra.eat(2); // health = 12
|
||
*
|
||
* dragon.fight(); // health = 8
|
||
*
|
||
* @codeend
|
||
*
|
||
*
|
||
* Notice that the prototype <b>init</b> function is called when a new instance of Monster is created.
|
||
*
|
||
*
|
||
* ## Inheritance
|
||
*
|
||
* When a class is extended, all static and prototype properties are available on the new class.
|
||
* If you overwrite a function, you can call the base class's function by calling
|
||
* <code>this._super</code>. Lets create a SeaMonster class. SeaMonsters are less
|
||
* efficient at eating small children, but more powerful fighters.
|
||
*
|
||
*
|
||
* Monster.extend("SeaMonster",{
|
||
* eat: function( smallChildren ) {
|
||
* this._super(smallChildren / 2);
|
||
* },
|
||
* fight: function() {
|
||
* this.health -= 1;
|
||
* }
|
||
* });
|
||
*
|
||
* lockNess = new SeaMonster('Lock Ness');
|
||
* lockNess.eat(4); //health = 12
|
||
* lockNess.fight(); //health = 11
|
||
*
|
||
* ### Static property inheritance
|
||
*
|
||
* You can also inherit static properties in the same way:
|
||
*
|
||
* $.Class.extend("First",
|
||
* {
|
||
* staticMethod: function() { return 1;}
|
||
* },{})
|
||
*
|
||
* First.extend("Second",{
|
||
* staticMethod: function() { return this._super()+1;}
|
||
* },{})
|
||
*
|
||
* Second.staticMethod() // -> 2
|
||
*
|
||
* ## Namespaces
|
||
*
|
||
* Namespaces are a good idea! We encourage you to namespace all of your code.
|
||
* It makes it possible to drop your code into another app without problems.
|
||
* Making a namespaced class is easy:
|
||
*
|
||
* @codestart
|
||
* $.Class.extend("MyNamespace.MyClass",{},{});
|
||
*
|
||
* new MyNamespace.MyClass()
|
||
* @codeend
|
||
* <h2 id='introspection'>Introspection</h2>
|
||
* Often, it's nice to create classes whose name helps determine functionality. Ruby on
|
||
* Rails's [http://api.rubyonrails.org/classes/ActiveRecord/Base.html|ActiveRecord] ORM class
|
||
* is a great example of this. Unfortunately, JavaScript doesn't have a way of determining
|
||
* an object's name, so the developer must provide a name. Class fixes this by taking a String name for the class.
|
||
* @codestart
|
||
* $.Class.extend("MyOrg.MyClass",{},{})
|
||
* MyOrg.MyClass.shortName //-> 'MyClass'
|
||
* MyOrg.MyClass.fullName //-> 'MyOrg.MyClass'
|
||
* @codeend
|
||
* The fullName (with namespaces) and the shortName (without namespaces) are added to the Class's
|
||
* static properties.
|
||
*
|
||
*
|
||
* <h2>Setup and initialization methods</h2>
|
||
* <p>
|
||
* Class provides static and prototype initialization functions.
|
||
* These come in two flavors - setup and init.
|
||
* Setup is called before init and
|
||
* can be used to 'normalize' init's arguments.
|
||
* </p>
|
||
* <div class='whisper'>PRO TIP: Typically, you don't need setup methods in your classes. Use Init instead.
|
||
* Reserve setup methods for when you need to do complex pre-processing of your class before init is called.
|
||
*
|
||
* </div>
|
||
* @codestart
|
||
* $.Class.extend("MyClass",
|
||
* {
|
||
* setup: function() {} //static setup
|
||
* init: function() {} //static constructor
|
||
* },
|
||
* {
|
||
* setup: function() {} //prototype setup
|
||
* init: function() {} //prototype constructor
|
||
* })
|
||
* @codeend
|
||
*
|
||
* <h3>Setup</h3>
|
||
* <p>Setup functions are called before init functions. Static setup functions are passed
|
||
* the base class followed by arguments passed to the extend function.
|
||
* Prototype static functions are passed the Class constructor function arguments.</p>
|
||
* <p>If a setup function returns an array, that array will be used as the arguments
|
||
* for the following init method. This provides setup functions the ability to normalize
|
||
* arguments passed to the init constructors. They are also excellent places
|
||
* to put setup code you want to almost always run.</p>
|
||
* <p>
|
||
* The following is similar to how [jQuery.Controller.prototype.setup]
|
||
* makes sure init is always called with a jQuery element and merged options
|
||
* even if it is passed a raw
|
||
* HTMLElement and no second parameter.
|
||
* </p>
|
||
* @codestart
|
||
* $.Class.extend("jQuery.Controller",{
|
||
* ...
|
||
* },{
|
||
* setup: function( el, options ) {
|
||
* ...
|
||
* return [$(el),
|
||
* $.extend(true,
|
||
* this.Class.defaults,
|
||
* options || {} ) ]
|
||
* }
|
||
* })
|
||
* @codeend
|
||
* Typically, you won't need to make or overwrite setup functions.
|
||
* <h3>Init</h3>
|
||
*
|
||
* <p>Init functions are called after setup functions.
|
||
* Typically, they receive the same arguments
|
||
* as their preceding setup function. The Foo class's <code>init</code> method
|
||
* gets called in the following example:
|
||
* </p>
|
||
* @codestart
|
||
* $.Class.Extend("Foo", {
|
||
* init: function( arg1, arg2, arg3 ) {
|
||
* this.sum = arg1+arg2+arg3;
|
||
* }
|
||
* })
|
||
* var foo = new Foo(1,2,3);
|
||
* foo.sum //-> 6
|
||
* @codeend
|
||
* <h2>Callbacks</h2>
|
||
* <p>Similar to jQuery's proxy method, Class provides a
|
||
* [jQuery.Class.static.callback callback]
|
||
* function that returns a callback to a method that will always
|
||
* have
|
||
* <code>this</code> set to the class or instance of the class.
|
||
* </p>
|
||
* The following example uses this.callback to make sure
|
||
* <code>this.name</code> is available in <code>show</code>.
|
||
* @codestart
|
||
* $.Class.extend("Todo",{
|
||
* init: function( name ) { this.name = name }
|
||
* get: function() {
|
||
* $.get("/stuff",this.callback('show'))
|
||
* },
|
||
* show: function( txt ) {
|
||
* alert(this.name+txt)
|
||
* }
|
||
* })
|
||
* new Todo("Trash").get()
|
||
* @codeend
|
||
* <p>Callback is available as a static and prototype method.</p>
|
||
*
|
||
* <h2>Typing<h2>
|
||
* Classes are automatically populating with three type related components:
|
||
*
|
||
* _types: a variable that contains an array of types of this class (extends history)
|
||
* _fullTypeName: a string representation of the extends hierarchy
|
||
* isA(string): a function you can call which will return true if the class is of a given type string.
|
||
* <p>
|
||
* Example:
|
||
* <p>
|
||
* Animal.extend('Tiger', {}, {});
|
||
* Tiger._types; // ['Animal', 'Tiger']
|
||
* Tiger._fullTypeName; // 'Animal | Tiger |"
|
||
* Tiger.isA('Animal'); // true
|
||
* </p>
|
||
* @constructor Creating a new instance of an object that has extended jQuery.Class
|
||
* calls the init prototype function and returns a new instance of the class.
|
||
*
|
||
*/
|
||
|
||
clss = $.Class = function ()
|
||
{
|
||
if (arguments.length)
|
||
{
|
||
return clss.extend.apply(clss, arguments);
|
||
}
|
||
};
|
||
|
||
/* @Static*/
|
||
extend(clss, {
|
||
/**
|
||
* @function callback
|
||
* Returns a callback function for a function on this Class.
|
||
* The callback function ensures that 'this' is set appropriately.
|
||
* @codestart
|
||
* $.Class.extend("MyClass",{
|
||
* getData: function() {
|
||
* this.showing = null;
|
||
* $.get("data.json",this.callback('gotData'),'json')
|
||
* },
|
||
* gotData: function( data ) {
|
||
* this.showing = data;
|
||
* }
|
||
* },{});
|
||
* MyClass.showData();
|
||
* @codeend
|
||
* <h2>Currying Arguments</h2>
|
||
* Additional arguments to callback will fill in arguments on the returning function.
|
||
* @codestart
|
||
* $.Class.extend("MyClass",{
|
||
* getData: function( <b>callback</b> ) {
|
||
* $.get("data.json",this.callback('process',<b>callback</b>),'json');
|
||
* },
|
||
* process: function( <b>callback</b>, jsonData ) { //callback is added as first argument
|
||
* jsonData.processed = true;
|
||
* callback(jsonData);
|
||
* }
|
||
* },{});
|
||
* MyClass.getData(showDataFunc)
|
||
* @codeend
|
||
* <h2>Nesting Functions</h2>
|
||
* Callback can take an array of functions to call as the first argument. When the returned callback function
|
||
* is called each function in the array is passed the return value of the prior function. This is often used
|
||
* to eliminate currying initial arguments.
|
||
* @codestart
|
||
* $.Class.extend("MyClass",{
|
||
* getData: function( callback ) {
|
||
* //calls process, then callback with value from process
|
||
* $.get("data.json",this.callback(['process2',callback]),'json')
|
||
* },
|
||
* process2: function( type,jsonData ) {
|
||
* jsonData.processed = true;
|
||
* return [jsonData];
|
||
* }
|
||
* },{});
|
||
* MyClass.getData(showDataFunc);
|
||
* @codeend
|
||
* @param {String|Array} fname If a string, it represents the function to be called.
|
||
* If it is an array, it will call each function in order and pass the return value of the prior function to the
|
||
* next function.
|
||
* @return {Function} the callback function.
|
||
*/
|
||
callback: function (funcs)
|
||
{
|
||
//args that should be curried
|
||
var args = makeArray(arguments),
|
||
self;
|
||
|
||
funcs = args.shift();
|
||
|
||
if (!isArray(funcs))
|
||
{
|
||
funcs = [funcs];
|
||
}
|
||
|
||
self = this;
|
||
|
||
return function class_cb()
|
||
{
|
||
var cur = concatArgs(args, arguments),
|
||
isString,
|
||
length = funcs.length,
|
||
f = 0,
|
||
func;
|
||
|
||
for (; f < length; f++)
|
||
{
|
||
func = funcs[f];
|
||
if (!func)
|
||
continue;
|
||
|
||
isString = typeof func == "string";
|
||
if (isString && self._set_called)
|
||
self.called = func;
|
||
|
||
cur = (isString ? self[func] : func).apply(self, cur || []);
|
||
if (f < length - 1)
|
||
cur = !isArray(cur) || cur._use_call ? [cur] : cur
|
||
}
|
||
return cur;
|
||
}
|
||
},
|
||
/**
|
||
* @function getObject
|
||
* Gets an object from a String.
|
||
* If the object or namespaces the string represent do not
|
||
* exist it will create them.
|
||
* @codestart
|
||
* Foo = {Bar: {Zar: {"Ted"}}}
|
||
* $.Class.getobject("Foo.Bar.Zar") //-> "Ted"
|
||
* @codeend
|
||
* @param {String} objectName the object you want to get
|
||
* @param {Object} [current=window] the object you want to look in.
|
||
* @return {Object} the object you are looking for.
|
||
*/
|
||
getObject: $.String.getObject,
|
||
/**
|
||
* @function newInstance
|
||
* Creates a new instance of the class. This method is useful for creating new instances
|
||
* with arbitrary parameters.
|
||
* <h3>Example</h3>
|
||
* @codestart
|
||
* $.Class.extend("MyClass",{},{})
|
||
* var mc = MyClass.newInstance.apply(null, new Array(parseInt(Math.random()*10,10))
|
||
* @codeend
|
||
* @return {class} instance of the class
|
||
*/
|
||
newInstance: function ()
|
||
{
|
||
var inst = this.rawInstance();
|
||
var args;
|
||
|
||
if (inst.setup)
|
||
args = inst.setup.apply(inst, arguments);
|
||
|
||
// Added by martin@playcraftlabs.com -- fix for deep cloning of properties
|
||
for (var prop in inst.__proto__)
|
||
inst[prop] = cloneObject(inst[prop]);
|
||
|
||
if (inst.init)
|
||
inst.init.apply(inst, isArray(args) ? args : arguments);
|
||
|
||
return inst;
|
||
},
|
||
/**
|
||
* Setup gets called on the inherting class with the base class followed by the
|
||
* inheriting class's raw properties.
|
||
*
|
||
* Setup will deeply extend a static defaults property on the base class with
|
||
* properties on the base class. For example:
|
||
*
|
||
* $.Class("MyBase",{
|
||
* defaults : {
|
||
* foo: 'bar'
|
||
* }
|
||
* },{})
|
||
*
|
||
* MyBase("Inheriting",{
|
||
* defaults : {
|
||
* newProp : 'newVal'
|
||
* }
|
||
* },{}
|
||
*
|
||
* Inheriting.defaults -> {foo: 'bar', 'newProp': 'newVal'}
|
||
*
|
||
* @param {Object} baseClass the base class that is being inherited from
|
||
* @param {String} fullName the name of the new class
|
||
* @param {Object} staticProps the static properties of the new class
|
||
* @param {Object} protoProps the prototype properties of the new class
|
||
*/
|
||
setup: function (baseClass, fullName)
|
||
{
|
||
this.defaults = extend(true, {}, baseClass.defaults, this.defaults);
|
||
if (this._types == undefined) this._types = [];
|
||
this._types.push(this.fullName);
|
||
if (this._fullTypeName == undefined) this._fullTypeName = '|';
|
||
this._fullTypeName += this.fullName + '|';
|
||
return arguments;
|
||
},
|
||
rawInstance: function ()
|
||
{
|
||
initializing = true;
|
||
var inst = new this();
|
||
initializing = false;
|
||
return inst;
|
||
},
|
||
/**
|
||
* Extends a class with new static and prototype functions. There are a variety of ways
|
||
* to use extend:
|
||
* @codestart
|
||
* //with className, static and prototype functions
|
||
* $.Class.extend('Task',{ STATIC },{ PROTOTYPE })
|
||
* //with just classname and prototype functions
|
||
* $.Class.extend('Task',{ PROTOTYPE })
|
||
* //With just a className
|
||
* $.Class.extend('Task')
|
||
* @codeend
|
||
* @param {String} [fullName] the classes name (used for classes w/ introspection)
|
||
* @param {Object} [klass] the new classes static/class functions
|
||
* @param {Object} [proto] the new classes prototype functions
|
||
* @return {jQuery.Class} returns the new class
|
||
*/
|
||
extend: function (fullName, klass, proto)
|
||
{
|
||
// figure out what was passed
|
||
if (typeof fullName != 'string')
|
||
{
|
||
proto = klass;
|
||
klass = fullName;
|
||
fullName = null;
|
||
}
|
||
if (!proto)
|
||
{
|
||
proto = klass;
|
||
klass = null;
|
||
}
|
||
|
||
proto = proto || {};
|
||
var _super_class = this,
|
||
_super = this.prototype,
|
||
name, shortName, namespace, prototype;
|
||
|
||
// append the isA function
|
||
this.isA = function(typeName)
|
||
{
|
||
return this._fullTypeName.indexOf('|'+typeName+'|') != -1;
|
||
};
|
||
|
||
// Instantiate a base class (but only create the instance,
|
||
// don't run the init constructor)
|
||
initializing = true;
|
||
prototype = new this();
|
||
initializing = false;
|
||
// Copy the properties over onto the new prototype
|
||
inheritProps(proto, _super, prototype);
|
||
|
||
// The dummy class constructor
|
||
|
||
function Class()
|
||
{
|
||
// All construction is actually done in the init method
|
||
if (initializing) return;
|
||
|
||
if (this.constructor !== Class && arguments.length)
|
||
{ //we are being called w/o new
|
||
return arguments.callee.extend.apply(arguments.callee, arguments)
|
||
} else
|
||
{ //we are being called w/ new
|
||
// copy objects
|
||
|
||
return this.Class.newInstance.apply(this.Class, arguments)
|
||
}
|
||
}
|
||
|
||
// Copy old stuff onto class
|
||
for (name in this)
|
||
if (this.hasOwnProperty(name))
|
||
Class[name] = cloneObject(this[name]);
|
||
|
||
// copy new props on class
|
||
inheritProps(klass, this, Class);
|
||
|
||
// do namespace stuff
|
||
if (fullName)
|
||
{
|
||
var parts = fullName.split(/\./);
|
||
var shortName = parts.pop();
|
||
|
||
// Martin Wells (playcraft): bug fix. Don't add a namespace object if the class name
|
||
// has no namespace elements (i.e. it's just "MyClass", not "MyProject.MyClass")
|
||
if (parts.length > 0)
|
||
{
|
||
current = clss.getObject(parts.join('.'), window, true),
|
||
namespace = current;
|
||
}
|
||
|
||
current[shortName] = Class;
|
||
}
|
||
|
||
// set things that can't be overwritten
|
||
extend(Class, {
|
||
prototype: prototype,
|
||
namespace: namespace,
|
||
shortName: shortName,
|
||
constructor: Class,
|
||
fullName: fullName
|
||
});
|
||
|
||
//make sure our prototype looks nice
|
||
Class.prototype.Class = Class.prototype.constructor = Class;
|
||
|
||
|
||
/**
|
||
* @attribute fullName
|
||
* The full name of the class, including namespace, provided for introspection purposes.
|
||
* @codestart
|
||
* $.Class.extend("MyOrg.MyClass",{},{})
|
||
* MyOrg.MyClass.shortName //-> 'MyClass'
|
||
* MyOrg.MyClass.fullName //-> 'MyOrg.MyClass'
|
||
* @codeend
|
||
*/
|
||
|
||
var args = Class.setup.apply(Class, concatArgs([_super_class], arguments));
|
||
|
||
if (Class.init)
|
||
{
|
||
Class.init.apply(Class, args || []);
|
||
}
|
||
|
||
/* @Prototype*/
|
||
|
||
return Class;
|
||
/**
|
||
* @function setup
|
||
* If a setup method is provided, it is called when a new
|
||
* instances is created. It gets passed the same arguments that
|
||
* were given to the Class constructor function (<code> new Class( arguments ... )</code>).
|
||
*
|
||
* $.Class("MyClass",
|
||
* {
|
||
* setup: function( val ) {
|
||
* this.val = val;
|
||
* }
|
||
* })
|
||
* var mc = new MyClass("Check Check")
|
||
* mc.val //-> 'Check Check'
|
||
*
|
||
* Setup is called before [jQuery.Class.prototype.init init]. If setup
|
||
* return an array, those arguments will be used for init.
|
||
*
|
||
* $.Class("jQuery.Controller",{
|
||
* setup : function(htmlElement, rawOptions){
|
||
* return [$(htmlElement),
|
||
* $.extend({}, this.Class.defaults, rawOptions )]
|
||
* }
|
||
* })
|
||
*
|
||
* <div class='whisper'>PRO TIP:
|
||
* Setup functions are used to normalize constructor arguments and provide a place for
|
||
* setup code that extending classes don't have to remember to call _super to
|
||
* run.
|
||
* </div>
|
||
*
|
||
* Setup is not defined on $.Class itself, so calling super in inherting classes
|
||
* will break. Don't do the following:
|
||
*
|
||
* $.Class("Thing",{
|
||
* setup : function(){
|
||
* this._super(); // breaks!
|
||
* }
|
||
* })
|
||
*
|
||
* @return {Array|undefined} If an array is return, [jQuery.Class.prototype.init] is
|
||
* called with those arguments; otherwise, the original arguments are used.
|
||
*/
|
||
//break up
|
||
/**
|
||
* @function init
|
||
* If an <code>init</code> method is provided, it gets called when a new instance
|
||
* is created. Init gets called after [jQuery.Class.prototype.setup setup], typically with the
|
||
* same arguments passed to the Class
|
||
* constructor: (<code> new Class( arguments ... )</code>).
|
||
*
|
||
* $.Class("MyClass",
|
||
* {
|
||
* init: function( val ) {
|
||
* this.val = val;
|
||
* }
|
||
* })
|
||
* var mc = new MyClass(1)
|
||
* mc.val //-> 1
|
||
*
|
||
* [jQuery.Class.prototype.setup Setup] is able to modify the arguments passed to init. Read
|
||
* about it there.
|
||
*
|
||
*/
|
||
//Breaks up code
|
||
/**
|
||
* @attribute Class
|
||
* References the static properties of the instance's class.
|
||
* <h3>Quick Example</h3>
|
||
* @codestart
|
||
* // a class with a static classProperty property
|
||
* $.Class.extend("MyClass", {classProperty : true}, {});
|
||
*
|
||
* // a new instance of myClass
|
||
* var mc1 = new MyClass();
|
||
*
|
||
* //
|
||
* mc1.Class.classProperty = false;
|
||
*
|
||
* // creates a new MyClass
|
||
* var mc2 = new mc.Class();
|
||
* @codeend
|
||
* Getting static properties via the Class property, such as it's
|
||
* [jQuery.Class.static.fullName fullName] is very common.
|
||
*/
|
||
}
|
||
|
||
})
|
||
|
||
|
||
clss.prototype.
|
||
/**
|
||
* @function callback
|
||
* Returns a callback function. This does the same thing as and is described better in [jQuery.Class.static.callback].
|
||
* The only difference is this callback works
|
||
* on a instance instead of a class.
|
||
* @param {String|Array} fname If a string, it represents the function to be called.
|
||
* If it is an array, it will call each function in order and pass the return value of the prior function to the
|
||
* next function.
|
||
* @return {Function} the callback function
|
||
*/
|
||
callback = clss.callback;
|
||
|
||
|
||
})(jQuery); |