mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-03 19:45:44 -05:00
261 lines
6.9 KiB
JavaScript
261 lines
6.9 KiB
JavaScript
/**
|
|
* Bootstrap JavaScript Library
|
|
* (c) 2006 - 2011 Juerg Lehni, http://lehni.org/
|
|
*
|
|
* Bootstrap is released under the MIT license
|
|
* http://bootstrapjs.org/
|
|
*
|
|
* Inspirations:
|
|
* http://dean.edwards.name/weblog/2006/03/base/
|
|
* http://dev.helma.org/Wiki/JavaScript+Inheritance+Sugar/
|
|
* http://prototypejs.org/
|
|
* http://mootools.net/
|
|
*/
|
|
|
|
var Base = this.Base = new function() {
|
|
var fix = !this.__proto__,
|
|
hidden = /^(statics|generics|preserve|beans|enumerable|prototype|__proto__|toString|valueOf)$/,
|
|
proto = Object.prototype,
|
|
has = fix
|
|
? function(name) {
|
|
return name != '__proto__' && this.hasOwnProperty(name);
|
|
}
|
|
: proto.hasOwnProperty,
|
|
toString = proto.toString,
|
|
isArray = Array.isArray = Array.isArray || function(obj) {
|
|
return toString.call(obj) === '[object Array]';
|
|
},
|
|
proto = Array.prototype,
|
|
slice = proto.slice,
|
|
forEach = proto.forEach = proto.forEach || function(iter, bind) {
|
|
for (var i = 0, l = this.length; i < l; i++)
|
|
iter.call(bind, this[i], i, this);
|
|
},
|
|
forIn = function(iter, bind) {
|
|
for (var i in this)
|
|
if (has.call(this, i))
|
|
iter.call(bind, this[i], i, this);
|
|
},
|
|
_define = Object.defineProperty,
|
|
_describe = Object.getOwnPropertyDescriptor;
|
|
|
|
function define(obj, name, desc) {
|
|
if (_define) {
|
|
try {
|
|
delete obj[name];
|
|
return _define(obj, name, desc);
|
|
} catch (e) {}
|
|
}
|
|
if ((desc.get || desc.set) && obj.__defineGetter__) {
|
|
desc.get && obj.__defineGetter__(name, desc.get);
|
|
desc.set && obj.__defineSetter__(name, desc.set);
|
|
} else {
|
|
obj[name] = desc.value;
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
function describe(obj, name) {
|
|
if (_describe) {
|
|
try {
|
|
return _describe(obj, name);
|
|
} catch (e) {}
|
|
}
|
|
var get = obj.__lookupGetter__ && obj.__lookupGetter__(name);
|
|
return get
|
|
? { get: get, set: obj.__lookupSetter__(name), enumerable: true,
|
|
configurable: true }
|
|
: has.call(obj, name)
|
|
? { value: obj[name], enumerable: true, configurable: true,
|
|
writable: true }
|
|
: null;
|
|
}
|
|
|
|
function inject(dest, src, enumerable, base, preserve, generics) {
|
|
var beans, bean;
|
|
|
|
function field(name, val, dontCheck, generics) {
|
|
var val = val || (val = describe(src, name))
|
|
&& (val.get ? val : val.value),
|
|
func = typeof val == 'function', res = val,
|
|
prev = preserve || func
|
|
? (val && val.get ? name in dest : dest[name]) : null;
|
|
if (generics && func && (!preserve || !generics[name])) {
|
|
generics[name] = function(bind) {
|
|
return bind && dest[name].apply(bind,
|
|
slice.call(arguments, 1));
|
|
}
|
|
}
|
|
if ((dontCheck || val !== undefined && has.call(src, name))
|
|
&& (!preserve || !prev)) {
|
|
if (func) {
|
|
if (prev && /\bthis\.base\b/.test(val)) {
|
|
var fromBase = base && base[name] == prev;
|
|
res = function() {
|
|
var tmp = describe(this, 'base');
|
|
define(this, 'base', { value: fromBase
|
|
? base[name] : prev, configurable: true });
|
|
try {
|
|
return val.apply(this, arguments);
|
|
} finally {
|
|
tmp ? define(this, 'base', tmp)
|
|
: delete this.base;
|
|
}
|
|
};
|
|
// Make wrapping closure pretend to be the original
|
|
// function on inspection
|
|
res.toString = function() {
|
|
return val.toString();
|
|
}
|
|
res.valueOf = function() {
|
|
return val.valueOf();
|
|
}
|
|
}
|
|
if (beans && (bean = name.match(/^(get|is)(([A-Z])(.*))$/)))
|
|
beans.push([ bean[3].toLowerCase() + bean[4], bean[2] ]);
|
|
}
|
|
if (!res || func || !res.get && !res.set)
|
|
res = { value: res, writable: true };
|
|
if ((describe(dest, name)
|
|
|| { configurable: true }).configurable) {
|
|
res.configurable = true;
|
|
res.enumerable = enumerable;
|
|
}
|
|
define(dest, name, res);
|
|
}
|
|
}
|
|
if (src) {
|
|
beans = src.beans && [];
|
|
for (var name in src)
|
|
if (has.call(src, name) && !hidden.test(name))
|
|
field(name, null, true, generics);
|
|
field('toString');
|
|
field('valueOf');
|
|
for (var i = 0, l = beans && beans.length; i < l; i++)
|
|
try {
|
|
var bean = beans[i], part = bean[1];
|
|
field(bean[0], {
|
|
get: dest['get' + part] || dest['is' + part],
|
|
set: dest['set' + part]
|
|
}, true);
|
|
} catch (e) {}
|
|
}
|
|
return dest;
|
|
}
|
|
|
|
function extend(obj) {
|
|
function ctor(dont) {
|
|
if (fix) define(this, '__proto__', { value: obj });
|
|
if (this.initialize && dont !== ctor.dont)
|
|
return this.initialize.apply(this, arguments);
|
|
}
|
|
ctor.prototype = obj;
|
|
ctor.toString = function() {
|
|
return (this.prototype.initialize || function() {}).toString();
|
|
}
|
|
return ctor;
|
|
}
|
|
|
|
function iterator(iter) {
|
|
return !iter
|
|
? function(val) { return val }
|
|
: typeof iter != 'function'
|
|
? function(val) { return val == iter }
|
|
: iter;
|
|
}
|
|
|
|
function each(iter, bind, asArray) {
|
|
try {
|
|
(asArray || asArray == undefined && isArray(this) ? forEach : forIn)
|
|
.call(this, iterator(iter), bind = bind || this);
|
|
} catch (e) {
|
|
if (e !== Base.stop) throw e;
|
|
}
|
|
return bind;
|
|
}
|
|
|
|
function clone(obj) {
|
|
return each.call(obj, function(val, i) {
|
|
this[i] = val;
|
|
}, new obj.constructor());
|
|
}
|
|
|
|
// Inject into new ctor object that's passed to inject(), and then returned
|
|
return inject(function() {}, {
|
|
inject: function(src) {
|
|
if (src) {
|
|
var proto = this.prototype,
|
|
base = proto.__proto__ && proto.__proto__.constructor,
|
|
statics = src.statics == true ? src : src.statics;
|
|
if (statics != src)
|
|
inject(proto, src, src.enumerable, base && base.prototype,
|
|
src.preserve, src.generics && this);
|
|
inject(this, statics, true, base, src.preserve);
|
|
}
|
|
for (var i = 1, l = arguments.length; i < l; i++)
|
|
this.inject(arguments[i]);
|
|
return this;
|
|
},
|
|
|
|
extend: function(src) {
|
|
var proto = new this(this.dont), ctor = extend(proto);
|
|
define(proto, 'constructor',
|
|
{ value: ctor, writable: true, configurable: true });
|
|
ctor.dont = {};
|
|
inject(ctor, this, true);
|
|
return arguments.length ? this.inject.apply(ctor, arguments) : ctor;
|
|
}
|
|
// Pass true for enumerable, so inject() and extend() can be passed on
|
|
// to subclasses of Base through Base.inject() / extend().
|
|
}, true).inject({
|
|
has: has,
|
|
each: each,
|
|
|
|
inject: function() {
|
|
for (var i = 0, l = arguments.length; i < l; i++)
|
|
inject(this, arguments[i]);
|
|
return this;
|
|
},
|
|
|
|
extend: function() {
|
|
var res = new (extend(this));
|
|
return res.inject.apply(res, arguments);
|
|
},
|
|
|
|
clone: function() {
|
|
return clone(this);
|
|
},
|
|
|
|
statics: {
|
|
clone: clone,
|
|
define: define,
|
|
describe: describe,
|
|
iterator: iterator,
|
|
|
|
has: function(obj, name) {
|
|
return has.call(obj, name);
|
|
},
|
|
|
|
each: function(obj, iter, bind) {
|
|
return each.call(obj, iter, bind);
|
|
},
|
|
|
|
type: function(obj) {
|
|
return (obj || obj === 0) && (obj._type || typeof obj) || null;
|
|
},
|
|
|
|
check: function(obj) {
|
|
return !!(obj || obj === 0);
|
|
},
|
|
|
|
pick: function() {
|
|
for (var i = 0, l = arguments.length; i < l; i++)
|
|
if (arguments[i] !== undefined)
|
|
return arguments[i];
|
|
return null;
|
|
},
|
|
|
|
stop: {}
|
|
}
|
|
});
|
|
}
|