Created
February 16, 2010 22:18
-
-
Save erichocean/306005 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* @license | |
========================================================================== | |
SproutCore Costello -- Property Observing Library | |
Copyright ©2006-2009, Sprout Systems, Inc. and contributors. | |
Portions copyright ©2008-2009 Apple Inc. All rights reserved. | |
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. | |
For more information about SproutCore, visit http://www.sproutcore.com | |
========================================================================== | |
@license */ | |
var sys = require("sys"); | |
var exports = exports || {}; | |
var SC = SC || exports; | |
var SproutCore = SproutCore || SC; | |
var YES = true, NO = false; | |
var sc_require = sc_require || function() { }; | |
var sc_resource = sc_resource || function sc_resource() {}; | |
// set up console | |
SC.console = { | |
message: function(type, what) { | |
sys.puts(type + ": " + sys.inspect(what)); | |
}, | |
log: function(what){ | |
this.message("LOG", what); | |
}, | |
info: function(what){ | |
this.message("INFO", what); | |
}, | |
error: function(what){ | |
this.message("ERROR", what); | |
}, | |
warn: function(what){ | |
this.message("WARN", what); | |
} | |
}; | |
SC.root = GLOBAL; | |
SC.mixin = function() { | |
var e = arguments[0] || {}; | |
var a = 1; | |
var d = arguments.length; | |
var b; | |
if (d === 1) { | |
e = this || {}; | |
a = 0 | |
} | |
for (; a < d; a++) { | |
if (! (b = arguments[a])) { | |
continue | |
} | |
for (var c in b) { | |
if (!b.hasOwnProperty(c)) { | |
continue | |
} | |
var f = b[c]; | |
if (e === f) { | |
continue | |
} | |
if (f !== undefined) { | |
e[c] = f | |
} | |
} | |
} | |
return e | |
}; | |
SC.supplement = function() { | |
var e = arguments[0] || {}; | |
var a = 1; | |
var d = arguments.length; | |
var b; | |
if (d === 1) { | |
e = this || {}; | |
a = 0 | |
} | |
for (; a < d; a++) { | |
if (! (b = arguments[a])) { | |
continue | |
} | |
for (var c in b) { | |
if (!b.hasOwnProperty(c)) { | |
continue | |
} | |
var f = e[c]; | |
var g = b[c]; | |
if (e === g) { | |
continue | |
} | |
if (g !== undefined && f === undefined) { | |
e[c] = g | |
} | |
} | |
} | |
return e | |
}; | |
SC.extend = SC.mixin; | |
SC.mixin({ | |
T_ERROR: "error", | |
T_OBJECT: "object", | |
T_NULL: "null", | |
T_CLASS: "class", | |
T_HASH: "hash", | |
T_FUNCTION: "function", | |
T_UNDEFINED: "undefined", | |
T_NUMBER: "number", | |
T_BOOL: "boolean", | |
T_ARRAY: "array", | |
T_STRING: "string", | |
typeOf: function(b) { | |
if (b === undefined) { | |
return SC.T_UNDEFINED | |
} | |
if (b === null) { | |
return SC.T_NULL | |
} | |
var a = typeof(b); | |
if (a == "object") { | |
if (b instanceof Array) { | |
a = SC.T_ARRAY | |
} else { | |
if (b instanceof Function) { | |
a = b.isClass ? SC.T_CLASS: SC.T_FUNCTION | |
} else { | |
if (SC.Error && (b instanceof SC.Error)) { | |
a = SC.T_ERROR | |
} else { | |
if (b.isObject === true) { | |
a = SC.T_OBJECT | |
} else { | |
a = SC.T_HASH | |
} | |
} | |
} | |
} | |
} else { | |
if (a === SC.T_FUNCTION) { | |
a = (b.isClass) ? SC.T_CLASS: SC.T_FUNCTION | |
} | |
} | |
return a | |
}, | |
none: function(a) { | |
return a === null || a === undefined | |
}, | |
empty: function(a) { | |
return a === null || a === undefined || a === "" | |
}, | |
isArray: function(c) { | |
if (c && c.objectAt) { | |
return YES | |
} | |
var a = (c ? c.length: null), | |
b = SC.typeOf(c); | |
return ! (SC.none(a) || (b === SC.T_FUNCTION) || (b === SC.T_STRING) || c.setInterval) | |
}, | |
makeArray: function(a) { | |
return SC.isArray(a) ? a: SC.A(a) | |
}, | |
A: function(c) { | |
if (SC.none(c)) { | |
return [] | |
} | |
if (c.slice instanceof Function) { | |
if (typeof(c) === "string") { | |
return [c] | |
} else { | |
return c.slice() | |
} | |
} | |
if (c.toArray) { | |
return c.toArray() | |
} | |
if (!SC.isArray(c)) { | |
return [c] | |
} | |
var b = [], | |
a = c.length; | |
while (--a >= 0) { | |
b[a] = c[a] | |
} | |
return b | |
}, | |
guidKey: "_sc_guid_" + new Date().getTime(), | |
_nextGUID: 0, | |
_numberGuids: [], | |
_stringGuids: {}, | |
_keyCache: {}, | |
guidFor: function(b) { | |
if (b === undefined) { | |
return "(undefined)" | |
} | |
if (b === null) { | |
return "(null)" | |
} | |
if (b === Object) { | |
return "(Object)" | |
} | |
if (b === Array) { | |
return "(Array)" | |
} | |
var a = this.guidKey; | |
if (b[a]) { | |
return b[a] | |
} | |
switch (typeof b) { | |
case SC.T_NUMBER: | |
return (this._numberGuids[b] = this._numberGuids[b] || ("nu" + b)); | |
case SC.T_STRING: | |
return (this._stringGuids[b] = this._stringGuids[b] || ("st" + b)); | |
case SC.T_BOOL: | |
return (b) ? "(true)": "(false)"; | |
default: | |
return SC.generateGuid(b) | |
} | |
}, | |
keyFor: function(d, c) { | |
var b, | |
a = this._keyCache[d]; | |
if (!a) { | |
a = this._keyCache[d] = {} | |
} | |
b = a[c]; | |
if (!b) { | |
b = a[c] = d + "_" + c | |
} | |
return b | |
}, | |
generateGuid: function(b) { | |
var a = ("sc" + (this._nextGUID++)); | |
if (b) { | |
b[this.guidKey] = a | |
} | |
return a | |
}, | |
hashFor: function(a) { | |
return (a && a.hash && (typeof a.hash === SC.T_FUNCTION)) ? a.hash() : this.guidFor(a) | |
}, | |
isEqual: function(d, c) { | |
if (d === null) { | |
return c === null | |
} else { | |
if (d === undefined) { | |
return c === undefined | |
} else { | |
return this.hashFor(d) === this.hashFor(c) | |
} | |
} | |
}, | |
compare: function(h, g) { | |
var f = SC.typeOf(h); | |
var d = SC.typeOf(g); | |
var j = SC.ORDER_DEFINITION.indexOf(f); | |
var b = SC.ORDER_DEFINITION.indexOf(d); | |
if (j < b) { | |
return - 1 | |
} | |
if (j > b) { | |
return 1 | |
} | |
switch (f) { | |
case SC.T_BOOL: | |
case SC.T_NUMBER: | |
if (h < g) { | |
return - 1 | |
} | |
if (h > g) { | |
return 1 | |
} | |
return 0; | |
case SC.T_STRING: | |
if (h.localeCompare(g) < 0) { | |
return - 1 | |
} | |
if (h.localeCompare(g) > 0) { | |
return 1 | |
} | |
return 0; | |
case SC.T_ARRAY: | |
var c = Math.min(h.length, g.length); | |
var a = 0; | |
var e = 0; | |
while (a === 0 && e < c) { | |
a = arguments.callee(h[e], g[e]); | |
if (a !== 0) { | |
return a | |
} | |
e++ | |
} | |
if (h.length < g.length) { | |
return - 1 | |
} | |
if (h.length > g.length) { | |
return 1 | |
} | |
return 0; | |
case SC.T_OBJECT: | |
if (h.constructor.isComparable === YES) { | |
return h.constructor.compare(h, g) | |
} | |
return 0; | |
default: | |
return 0 | |
} | |
}, | |
K: function() { | |
return this | |
}, | |
EMPTY_ARRAY: [], | |
EMPTY_HASH: {}, | |
EMPTY_RANGE: { | |
start: 0, | |
length: 0 | |
}, | |
beget: function(c) { | |
if (SC.none(c)) { | |
return null | |
} | |
var a = SC.K; | |
a.prototype = c; | |
var b = new a(); | |
a.prototype = null; | |
if (SC.typeOf(c.didBeget) === SC.T_FUNCTION) { | |
b = c.didBeget(b) | |
} | |
return b | |
}, | |
copy: function(b) { | |
var a = b; | |
if (b && b.isCopyable) { | |
return b.copy() | |
} | |
switch (SC.typeOf(b)) { | |
case SC.T_ARRAY: | |
if (b.clone && SC.typeOf(b.clone) === SC.T_FUNCTION) { | |
a = b.clone() | |
} else { | |
a = b.slice() | |
} | |
break; | |
case SC.T_HASH: | |
case SC.T_OBJECT: | |
if (b.clone && SC.typeOf(b.clone) === SC.T_FUNCTION) { | |
a = b.clone() | |
} else { | |
a = {}; | |
for (var c in b) { | |
a[c] = b[c] | |
} | |
} | |
} | |
return a | |
}, | |
merge: function() { | |
var c = {}, | |
b = arguments.length, | |
a; | |
for (a = 0; a < b; a++) { | |
SC.mixin(c, arguments[a]) | |
} | |
return c | |
}, | |
keys: function(c) { | |
var a = []; | |
for (var b in c) { | |
a.push(b) | |
} | |
return a | |
}, | |
inspect: function(d) { | |
var a, | |
b = []; | |
for (var c in d) { | |
a = d[c]; | |
if (a === "toString") { | |
continue | |
} | |
if (SC.typeOf(a) === SC.T_FUNCTION) { | |
a = "function() { ... }" | |
} | |
b.push(c + ": " + a) | |
} | |
return "{" + b.join(" , ") + "}" | |
}, | |
tupleForPropertyPath: function(e, a) { | |
if (SC.typeOf(e) === SC.T_ARRAY) { | |
return e | |
} | |
var c; | |
var b = e.indexOf("*"); | |
if (b < 0) { | |
b = e.lastIndexOf(".") | |
} | |
c = (b >= 0) ? e.slice(b + 1) : e; | |
var d = this.objectForPropertyPath(e, a, b); | |
return (d && c) ? [d, c] : null | |
}, | |
objectForPropertyPath: function(f, c, d) { | |
var g, | |
b, | |
e, | |
a; | |
if (!c) { | |
c = SC.root | |
} | |
if (SC.typeOf(f) === SC.T_STRING) { | |
if (d === undefined) { | |
d = f.length | |
} | |
g = 0; | |
while ((c) && (g < d)) { | |
b = f.indexOf(".", g); | |
if ((b < 0) || (b > d)) { | |
b = d | |
} | |
e = f.slice(g, b); | |
c = c.get ? c.get(e) : c[e]; | |
g = b + 1 | |
} | |
if (g < d) { | |
c = undefined | |
} | |
} else { | |
g = 0; | |
a = f.length; | |
e = null; | |
while ((g < a) && c) { | |
e = f[g++]; | |
if (e) { | |
c = (c.get) ? c.get(e) : c[e] | |
} | |
} | |
if (g < a) { | |
c = undefined | |
} | |
} | |
return c | |
}, | |
STRINGS: {}, | |
stringsFor: function(b, a) { | |
SC.mixin(SC.STRINGS, a); | |
return this | |
} | |
}); | |
SC.clone = SC.copy; | |
SC.$A = SC.A; | |
SC.didLoad = SC.K; | |
SC.ORDER_DEFINITION = [SC.T_ERROR, SC.T_UNDEFINED, SC.T_NULL, SC.T_BOOL, SC.T_NUMBER, SC.T_STRING, SC.T_ARRAY, SC.T_HASH, SC.T_OBJECT, SC.T_FUNCTION, SC.T_CLASS]; | |
SC.mixin(Function.prototype, { | |
property: function() { | |
this.dependentKeys = SC.$A(arguments); | |
var a = SC.guidFor(this); | |
this.cacheKey = "__cache__" + a; | |
this.lastSetValueKey = "__lastValue__" + a; | |
this.isProperty = YES; | |
return this | |
}, | |
cacheable: function(a) { | |
this.isProperty = YES; | |
if (!this.dependentKeys) { | |
this.dependentKeys = [] | |
} | |
this.isCacheable = (a === undefined) ? YES: a; | |
return this | |
}, | |
idempotent: function(a) { | |
this.isProperty = YES; | |
if (!this.dependentKeys) { | |
this.dependentKeys = [] | |
} | |
this.isVolatile = (a === undefined) ? YES: a; | |
return this | |
}, | |
observes: function(a) { | |
var e = arguments.length, | |
b = null, | |
d = null; | |
while (--e >= 0) { | |
var c = arguments[e]; | |
if ((c.indexOf(".") < 0) && (c.indexOf("*") < 0)) { | |
if (!b) { | |
b = this.localPropertyPaths = [] | |
} | |
b.push(c) | |
} else { | |
if (!d) { | |
d = this.propertyPaths = [] | |
} | |
d.push(c) | |
} | |
} | |
return this | |
} | |
}); | |
String.prototype.fmt = function() { | |
var b = arguments; | |
var a = 0; | |
return this.replace(/%@([0-9]+)?/g, | |
function(c, d) { | |
d = (d) ? parseInt(d, 0) - 1: a++; | |
c = b[d]; | |
return ((c === null) ? "(null)": (c === undefined) ? "": c).toString() | |
}) | |
}; | |
String.prototype.loc = function() { | |
var a = SC.STRINGS[this] || this; | |
return a.fmt.apply(a, arguments) | |
}; | |
String.prototype.w = function() { | |
var c = [], | |
d = this.split(" "), | |
b = d.length; | |
for (var a = 0; a < b; ++a) { | |
var e = d[a]; | |
if (e.length !== 0) { | |
c.push(e) | |
} | |
} | |
return c | |
}; | |
SC.ObserverSet = { | |
targets: 0, | |
_membersCacheIsValid: NO, | |
add: function(d, f, b) { | |
var c = (d) ? SC.guidFor(d) : "__this__"; | |
var a = this[c]; | |
if (!a) { | |
a = this[c] = SC.CoreSet.create(); | |
a.target = d; | |
a.isTargetSet = YES; | |
this.targets++ | |
} | |
a.add(f); | |
if (b !== undefined) { | |
var e = a.contexts; | |
if (!b) { | |
e = {} | |
} | |
e[SC.guidFor(f)] = b | |
} | |
this._membersCacheIsValid = NO | |
}, | |
remove: function(c, d) { | |
var b = (c) ? SC.guidFor(c) : "__this__"; | |
var a = this[b]; | |
if (!a) { | |
return NO | |
} | |
a.remove(d); | |
if (a.length <= 0) { | |
a.target = null; | |
a.isTargetSet = NO; | |
a.contexts = null; | |
delete this[b]; | |
this.targets-- | |
} else { | |
if (a.contexts) { | |
delete a.contexts[SC.guidFor(d)] | |
} | |
} | |
this._membersCacheIsValid = NO; | |
return YES | |
}, | |
invokeMethods: function() { | |
for (var b in this) { | |
if (!this.hasOwnProperty(b)) { | |
continue | |
} | |
var c = this[b]; | |
if (c && c.isTargetSet) { | |
var a = c.length; | |
var d = c.target; | |
while (--a >= 0) { | |
c[a].call(d) | |
} | |
} | |
} | |
}, | |
getMembers: function() { | |
if (this._membersCacheIsValid) { | |
return this._members | |
} | |
if (!this._members) { | |
this._members = [] | |
} else { | |
this._members.length = 0 | |
} | |
var b = this._members; | |
for (var c in this) { | |
if (!this.hasOwnProperty(c)) { | |
continue | |
} | |
var d = this[c]; | |
if (d && d.isTargetSet) { | |
var a = d.length; | |
var e = d.target; | |
var g = d.contexts; | |
if (g) { | |
while (--a >= 0) { | |
var f = d[a]; | |
b.push([e, f, g[SC.guidFor(f)]]) | |
} | |
} else { | |
while (--a >= 0) { | |
b.push([e, d[a]]) | |
} | |
} | |
} | |
} | |
this._membersCacheIsValid = YES; | |
return b | |
}, | |
clone: function() { | |
var b, | |
d, | |
c, | |
a = SC.ObserverSet.create(); | |
for (c in this) { | |
if (!this.hasOwnProperty(c)) { | |
continue | |
} | |
b = this[c]; | |
if (b && b.isTargetSet) { | |
d = b.clone(); | |
d.target = b.target; | |
if (b.contexts) { | |
d.contexts = SC.clone(b.contexts) | |
} | |
a[c] = d | |
} | |
} | |
a.targets = this.targets; | |
a._membersCacheIsValid = NO; | |
return a | |
}, | |
create: function() { | |
return SC.beget(this) | |
} | |
}; | |
SC.ObserverSet.slice = SC.ObserverSet.clone; | |
sc_require("private/observer_set"); | |
SC.LOG_OBSERVERS = NO; | |
SC.Observable = { | |
isObservable: YES, | |
automaticallyNotifiesObserversFor: function(a) { | |
return YES | |
}, | |
get: function(c) { | |
var b = this[c], | |
a; | |
if (b === undefined) { | |
return this.unknownProperty(c) | |
} else { | |
if (b && b.isProperty) { | |
if (b.isCacheable) { | |
a = this._kvo_cache; | |
if (!a) { | |
a = this._kvo_cache = {} | |
} | |
return (a[b.cacheKey] !== undefined) ? a[b.cacheKey] : (a[b.cacheKey] = b.call(this, c)) | |
} else { | |
return b.call(this, c) | |
} | |
} else { | |
return b | |
} | |
} | |
}, | |
set: function(h, f) { | |
var b = this[h], | |
i = this.automaticallyNotifiesObserversFor(h), | |
e = f, | |
c, | |
a, | |
g, | |
d; | |
if (this._kvo_cacheable && (a = this._kvo_cache)) { | |
c = this._kvo_cachedep; | |
if (!c || (c = c[h]) === undefined) { | |
c = this._kvo_computeCachedDependentsFor(h) | |
} | |
if (c) { | |
g = c.length; | |
while (--g >= 0) { | |
d = c[g]; | |
a[d.cacheKey] = a[d.lastSetValueKey] = undefined | |
} | |
} | |
} | |
if (b && b.isProperty) { | |
a = this._kvo_cache; | |
if (b.isVolatile || !a || (a[b.lastSetValueKey] !== f)) { | |
if (!a) { | |
a = this._kvo_cache = {} | |
} | |
a[b.lastSetValueKey] = f; | |
if (i) { | |
this.propertyWillChange(h) | |
} | |
e = b.call(this, h, f); | |
if (b.isCacheable) { | |
a[b.cacheKey] = e | |
} | |
if (i) { | |
this.propertyDidChange(h, e, YES) | |
} | |
} | |
} else { | |
if (b === undefined) { | |
if (i) { | |
this.propertyWillChange(h) | |
} | |
this.unknownProperty(h, f); | |
if (i) { | |
this.propertyDidChange(h, e) | |
} | |
} else { | |
if (this[h] !== f) { | |
if (i) { | |
this.propertyWillChange(h) | |
} | |
e = this[h] = f; | |
if (i) { | |
this.propertyDidChange(h, e) | |
} | |
} | |
} | |
} | |
return this | |
}, | |
unknownProperty: function(a, b) { | |
if (! (b === undefined)) { | |
this[a] = b | |
} | |
return b | |
}, | |
beginPropertyChanges: function() { | |
this._kvo_changeLevel = (this._kvo_changeLevel || 0) + 1; | |
return this | |
}, | |
endPropertyChanges: function() { | |
this._kvo_changeLevel = (this._kvo_changeLevel || 1) - 1; | |
var b = this._kvo_changeLevel, | |
a = this._kvo_changes; | |
if ((b <= 0) && a && (a.length > 0) && !SC.Observers.isObservingSuspended) { | |
this._notifyPropertyObservers() | |
} | |
return this | |
}, | |
propertyWillChange: function(a) { | |
return this | |
}, | |
propertyDidChange: function(l, j, c) { | |
this._kvo_revision = (this._kvo_revision || 0) + 1; | |
var b = this._kvo_changeLevel || 0, | |
g, | |
k, | |
h, | |
a, | |
d, | |
f = SC.LOG_OBSERVERS && !(this.LOG_OBSERVING === NO); | |
if (this._kvo_cacheable && (a = this._kvo_cache)) { | |
if (!c) { | |
d = this[l]; | |
if (d && d.isProperty) { | |
a[d.cacheKey] = a[d.lastSetValueKey] = undefined | |
} | |
} | |
g = this._kvo_cachedep; | |
if (!g || (g = g[l]) === undefined) { | |
g = this._kvo_computeCachedDependentsFor(l) | |
} | |
if (g) { | |
k = g.length; | |
while (--k >= 0) { | |
h = g[k]; | |
a[h.cacheKey] = a[h.lastSetValueKey] = undefined | |
} | |
} | |
} | |
var e = SC.Observers.isObservingSuspended; | |
if ((b > 0) || e) { | |
var i = this._kvo_changes; | |
if (!i) { | |
i = this._kvo_changes = SC.CoreSet.create() | |
} | |
i.add(l); | |
if (e) { | |
if (f) { | |
console.log("%@%@: will not notify observers because observing is suspended".fmt(SC.KVO_SPACES, this)) | |
} | |
SC.Observers.objectHasPendingChanges(this) | |
} | |
} else { | |
this._notifyPropertyObservers(l) | |
} | |
return this | |
}, | |
registerDependentKey: function(h, c) { | |
var e = this._kvo_dependents, | |
b = this[h], | |
i, | |
g, | |
a, | |
f, | |
d; | |
if (SC.typeOf(c) === SC.T_ARRAY) { | |
i = c; | |
a = 0 | |
} else { | |
i = arguments; | |
a = 1 | |
} | |
g = i.length; | |
if (!e) { | |
this._kvo_dependents = e = {} | |
} | |
while (--g >= a) { | |
f = i[g]; | |
d = e[f]; | |
if (!d) { | |
d = e[f] = [] | |
} | |
d.push(h) | |
} | |
}, | |
_kvo_addCachedDependents: function(b, f, h, c) { | |
var a = f.length, | |
e, | |
d, | |
g; | |
while (--a >= 0) { | |
d = f[a]; | |
c.add(d); | |
e = this[d]; | |
if (e && (e instanceof Function) && e.isProperty) { | |
if (e.isCacheable) { | |
b.push(e) | |
} | |
if ((g = h[d]) && g.length > 0) { | |
this._kvo_addCachedDependents(b, g, h, c) | |
} | |
} | |
} | |
}, | |
_kvo_computeCachedDependentsFor: function(c) { | |
var d = this._kvo_cachedep, | |
f = this._kvo_dependents, | |
e = f ? f[c] : null, | |
a, | |
b; | |
if (!d) { | |
d = this._kvo_cachedep = {} | |
} | |
if (!e || e.length === 0) { | |
return d[c] = null | |
} | |
a = d[c] = []; | |
b = SC._TMP_SEEN_SET = (SC._TMP_SEEN_SET || SC.CoreSet.create()); | |
b.add(c); | |
this._kvo_addCachedDependents(a, e, f, b); | |
b.clear(); | |
if (a.length === 0) { | |
a = d[c] = null | |
} | |
return a | |
}, | |
_kvo_for: function(c, b) { | |
var a = this[c]; | |
if (!this._kvo_cloned) { | |
this._kvo_cloned = {} | |
} | |
if (!a) { | |
a = this[c] = (b === undefined) ? [] : b.create(); | |
this._kvo_cloned[c] = YES | |
} else { | |
if (!this._kvo_cloned[c]) { | |
a = this[c] = a.copy(); | |
this._kvo_cloned[c] = YES | |
} | |
} | |
return a | |
}, | |
addObserver: function(c, f, h, b) { | |
var d, | |
a, | |
e, | |
g; | |
if (h === undefined) { | |
h = f; | |
f = this | |
} | |
if (!f) { | |
f = this | |
} | |
if (SC.typeOf(h) === SC.T_STRING) { | |
h = f[h] | |
} | |
if (!h) { | |
throw "You must pass a method to addObserver()" | |
} | |
c = c.toString(); | |
if (c.indexOf(".") >= 0) { | |
a = SC._ChainObserver.createChain(this, c, f, h, b); | |
a.masterTarget = f; | |
a.masterMethod = h; | |
this._kvo_for(SC.keyFor("_kvo_chains", c)).push(a) | |
} else { | |
if ((this[c] === undefined) && (c.indexOf("@") === 0)) { | |
this.get(c) | |
} | |
if (f === this) { | |
f = null | |
} | |
d = SC.keyFor("_kvo_observers", c); | |
this._kvo_for(d, SC.ObserverSet).add(f, h, b); | |
this._kvo_for("_kvo_observed_keys", SC.CoreSet).add(c) | |
} | |
if (this.didAddObserver) { | |
this.didAddObserver(c, f, h) | |
} | |
return this | |
}, | |
removeObserver: function(c, f, h) { | |
var d, | |
e, | |
b, | |
g, | |
a; | |
if (h === undefined) { | |
h = f; | |
f = this | |
} | |
if (!f) { | |
f = this | |
} | |
if (SC.typeOf(h) === SC.T_STRING) { | |
h = f[h] | |
} | |
if (!h) { | |
throw "You must pass a method to addObserver()" | |
} | |
c = c.toString(); | |
if (c.indexOf(".") >= 0) { | |
d = SC.keyFor("_kvo_chains", c); | |
if (e = this[d]) { | |
e = this._kvo_for(d); | |
a = e.length; | |
while (--a >= 0) { | |
b = e[a]; | |
if (b && (b.masterTarget === f) && (b.masterMethod === h)) { | |
e[a] = b.destroyChain() | |
} | |
} | |
} | |
} else { | |
if (f === this) { | |
f = null | |
} | |
d = SC.keyFor("_kvo_observers", c); | |
if (g = this[d]) { | |
g = this._kvo_for(d); | |
g.remove(f, h); | |
if (g.targets <= 0) { | |
this._kvo_for("_kvo_observed_keys", SC.CoreSet).remove(c) | |
} | |
} | |
} | |
if (this.didRemoveObserver) { | |
this.didRemoveObserver(c, f, h) | |
} | |
return this | |
}, | |
hasObserverFor: function(b) { | |
SC.Observers.flush(this); | |
var d = this[SC.keyFor("_kvo_observers", b)], | |
c = this[SC.keyFor("_kvo_local", b)], | |
a; | |
if (c && c.length > 0) { | |
return YES | |
} | |
if (d && d.getMembers().length > 0) { | |
return YES | |
} | |
return NO | |
}, | |
initObservable: function() { | |
if (this._observableInited) { | |
return | |
} | |
this._observableInited = YES; | |
var e, | |
l, | |
j, | |
i, | |
g, | |
d, | |
k; | |
if (l = this._observers) { | |
var f = l.length; | |
for (e = 0; e < f; e++) { | |
j = l[e]; | |
g = this[j]; | |
d = g.propertyPaths; | |
k = (d) ? d.length: 0; | |
for (var b = 0; | |
b < k; b++) { | |
var m = d[b]; | |
var a = m.indexOf("."); | |
if (a < 0) { | |
this.addObserver(m, this, g) | |
} else { | |
if (m.indexOf("*") === 0) { | |
this.addObserver(m.slice(1), this, g) | |
} else { | |
var h = null; | |
if (a === 0) { | |
h = this; | |
m = m.slice(1) | |
} else { | |
if (a === 4 && m.slice(0, 5) === "this.") { | |
h = this; | |
m = m.slice(5) | |
} else { | |
if (a < 0 && m.length === 4 && m === "this") { | |
h = this; | |
m = "" | |
} | |
} | |
} | |
SC.Observers.addObserver(m, this, g, h) | |
} | |
} | |
} | |
} | |
} | |
this.bindings = []; | |
if (l = this._bindings) { | |
for (e = 0; e < l.length; e++) { | |
j = l[e]; | |
i = this[j]; | |
var c = j.slice(0, -7); | |
this[j] = this.bind(c, i) | |
} | |
} | |
if (l = this._properties) { | |
for (e = 0; e < l.length; | |
e++) { | |
j = l[e]; | |
if (i = this[j]) { | |
if (i.isCacheable) { | |
this._kvo_cacheable = YES | |
} | |
if (i.dependentKeys && (i.dependentKeys.length > 0)) { | |
this.registerDependentKey(j, i.dependentKeys) | |
} | |
} | |
} | |
} | |
}, | |
observersForKey: function(a) { | |
var b = this._kvo_for("_kvo_observers", a); | |
return b.getMembers() || [] | |
}, | |
_notifyPropertyObservers: function(t) { | |
if (!this._observableInited) { | |
this.initObservable() | |
} | |
SC.Observers.flush(this); | |
var g = SC.LOG_OBSERVERS && !(this.LOG_OBSERVING === NO); | |
var o, | |
r, | |
m, | |
d, | |
n, | |
l, | |
q; | |
var p, | |
j, | |
a, | |
f, | |
s, | |
c, | |
i, | |
e; | |
var b, | |
h, | |
k; | |
if (g) { | |
h = SC.KVO_SPACES = (SC.KVO_SPACES || "") + " "; | |
console.log('%@%@: notifying observers after change to key "%@"'.fmt(h, this, t)) | |
} | |
d = this["_kvo_observers_*"]; | |
this._kvo_changeLevel = (this._kvo_changeLevel || 0) + 1; | |
while (((r = this._kvo_changes) && (r.length > 0)) || t) { | |
q = ++this.propertyRevision; | |
if (!r) { | |
r = SC.CoreSet.create() | |
} | |
this._kvo_changes = null; | |
if (t === "*") { | |
r.add("*"); | |
r.addEach(this._kvo_for("_kvo_observed_keys", SC.CoreSet)) | |
} else { | |
if (t) { | |
r.add(t) | |
} | |
} | |
if (m = this._kvo_dependents) { | |
for (n = 0; n < r.length; n++) { | |
t = r[n]; | |
l = m[t]; | |
if (l && (i = l.length)) { | |
if (g) { | |
console.log("%@...including dependent keys for %@: %@".fmt(h, t, l)) | |
} | |
k = this._kvo_cache; | |
if (!k) { | |
k = this._kvo_cache = {} | |
} | |
while (--i >= 0) { | |
r.add(t = l[i]); | |
if (e = this[t]) { | |
this[e.cacheKey] = undefined; | |
k[e.cacheKey] = k[e.lastSetValueKey] = undefined | |
} | |
} | |
} | |
} | |
} | |
while (r.length > 0) { | |
t = r.pop(); | |
o = this[SC.keyFor("_kvo_observers", t)]; | |
if (o) { | |
p = o.getMembers(); | |
j = p.length; | |
for (f = 0; f < j; f++) { | |
a = p[f]; | |
if (a[3] === q) { | |
continue | |
} | |
s = a[0] || this; | |
c = a[1]; | |
b = a[2]; | |
a[3] = q; | |
if (g) { | |
console.log('%@...firing observer on %@ for key "%@"'.fmt(h, s, t)) | |
} | |
if (b !== undefined) { | |
c.call(s, this, t, null, b, q) | |
} else { | |
c.call(s, this, t, null, q) | |
} | |
} | |
} | |
p = this[SC.keyFor("_kvo_local", t)]; | |
if (p) { | |
j = p.length; | |
for (f = 0; f < j; f++) { | |
a = p[f]; | |
c = this[a]; | |
if (c) { | |
if (g) { | |
console.log('%@...firing local observer %@.%@ for key "%@"'.fmt(h, this, a, t)) | |
} | |
c.call(this, this, t, null, q) | |
} | |
} | |
} | |
if (d && t !== "*") { | |
p = d.getMembers(); | |
j = p.length; | |
for (f = 0; | |
f < j; f++) { | |
a = p[f]; | |
s = a[0] || this; | |
c = a[1]; | |
b = a[2]; | |
if (g) { | |
console.log('%@...firing * observer on %@ for key "%@"'.fmt(h, s, t)) | |
} | |
if (b !== undefined) { | |
c.call(s, this, t, null, b, q) | |
} else { | |
c.call(s, this, t, null, q) | |
} | |
} | |
} | |
if (this.propertyObserver) { | |
if (g) { | |
console.log('%@...firing %@.propertyObserver for key "%@"'.fmt(h, this, t)) | |
} | |
this.propertyObserver(this, t, null, q) | |
} | |
} | |
if (r) { | |
r.destroy() | |
} | |
t = null | |
} | |
this._kvo_changeLevel = (this._kvo_changeLevel || 1) - 1; | |
if (g) { | |
SC.KVO_SPACES = h.slice(0, -2) | |
} | |
return YES | |
}, | |
bind: function(a, c, e) { | |
var d; | |
if (e !== undefined) { | |
c = [c, e] | |
} | |
var b = SC.typeOf(c); | |
if (b === SC.T_STRING || b === SC.T_ARRAY) { | |
d = this[a + "BindingDefault"] || SC.Binding; | |
d = d.beget().from(c) | |
} else { | |
d = c | |
} | |
d = d.to(a, this).connect(); | |
this.bindings.push(d); | |
return d | |
}, | |
didChangeFor: function(a) { | |
a = SC.hashFor(a); | |
var b = this._kvo_didChange_valueCache; | |
if (!b) { | |
b = this._kvo_didChange_valueCache = {} | |
} | |
var f = this._kvo_didChange_revisionCache; | |
if (!f) { | |
f = this._kvo_didChange_revisionCache = {} | |
} | |
var e = b[a] || {}; | |
var j = f[a] || {}; | |
var d = false; | |
var c = this._kvo_revision || 0; | |
var h = arguments.length; | |
while (--h >= 1) { | |
var i = arguments[h]; | |
if (j[i] != c) { | |
var g = this.get(i); | |
if (e[i] !== g) { | |
d = true; | |
e[i] = g | |
} | |
} | |
j[i] = c | |
} | |
b[a] = e; | |
f[a] = j; | |
return d | |
}, | |
setIfChanged: function(a, b) { | |
return (this.get(a) !== b) ? this.set(a, b) : this | |
}, | |
getPath: function(b) { | |
var a = SC.tupleForPropertyPath(b, this); | |
if (a === null || a[0] === null) { | |
return undefined | |
} | |
return a[0].get(a[1]) | |
}, | |
setPath: function(c, b) { | |
if (c.indexOf(".") >= 0) { | |
var a = SC.tupleForPropertyPath(c, this); | |
if (!a || !a[0]) { | |
return null | |
} | |
a[0].set(a[1], b) | |
} else { | |
this.set(c, b) | |
} | |
return this | |
}, | |
setPathIfChanged: function(c, b) { | |
if (c.indexOf(".") >= 0) { | |
var a = SC.tupleForPropertyPath(c, this); | |
if (!a || !a[0]) { | |
return null | |
} | |
if (a[0].get(a[1]) !== b) { | |
a[0].set(a[1], b) | |
} | |
} else { | |
this.setIfChanged(c, b) | |
} | |
return this | |
}, | |
getEach: function() { | |
var c = SC.A(arguments); | |
var b = []; | |
for (var a = 0; a < c.length; | |
a++) { | |
b[b.length] = this.getPath(c[a]) | |
} | |
return b | |
}, | |
incrementProperty: function(a) { | |
this.set(a, (this.get(a) || 0) + 1); | |
return this.get(a) | |
}, | |
decrementProperty: function(a) { | |
this.set(a, (this.get(a) || 0) - 1); | |
return this.get(a) | |
}, | |
toggleProperty: function(a, b, c) { | |
if (b === undefined) { | |
b = true | |
} | |
if (c === undefined) { | |
c = false | |
} | |
b = (this.get(a) == b) ? c: b; | |
this.set(a, b); | |
return this.get(a) | |
}, | |
notifyPropertyChange: function(a, b) { | |
this.propertyWillChange(a); | |
this.propertyDidChange(a, b); | |
return this | |
}, | |
allPropertiesDidChange: function() { | |
this._kvo_cache = null; | |
this._notifyPropertyObservers("*"); | |
return this | |
}, | |
addProbe: function(a) { | |
this.addObserver(a, SC.logChange) | |
}, | |
removeProbe: function(a) { | |
this.removeObserver(a, SC.logChange) | |
}, | |
logProperty: function() { | |
var b = SC.$A(arguments); | |
for (var a = 0; a < b.length; a++) { | |
var c = b[a]; | |
console.log("%@:%@: ".fmt(SC.guidFor(this), c), this.get(c)) | |
} | |
}, | |
propertyRevision: 1 | |
}; | |
SC.logChange = function logChange(c, a, b) { | |
console.log("CHANGE: %@[%@] => %@".fmt(c, a, c.get(a))) | |
}; | |
SC.mixin(Array.prototype, SC.Observable); | |
SC.Enumerator = function(a) { | |
this.enumerable = a; | |
this.reset(); | |
return this | |
}; | |
SC.Enumerator.prototype = { | |
nextObject: function() { | |
var c = this._index; | |
var a = this._length; | |
if (c >= a) { | |
return undefined | |
} | |
var b = this.enumerable.nextObject(c, this._previousObject, this._context); | |
this._previousObject = b; | |
this._index = c + 1; | |
if (c >= a) { | |
this._context = SC.Enumerator._pushContext(this._context) | |
} | |
return b | |
}, | |
reset: function() { | |
var b = this.enumerable; | |
if (!b) { | |
throw SC.$error("Enumerator has been destroyed") | |
} | |
this._length = b.get ? b.get("length") : b.length; | |
var a = this._length; | |
this._index = 0; | |
this._previousObject = null; | |
this._context = (a > 0) ? SC.Enumerator._popContext() : null | |
}, | |
destroy: function() { | |
this.enumerable = this._length = this._index = this._previousObject = this._context = null | |
} | |
}; | |
SC.Enumerator.create = function(a) { | |
return new SC.Enumerator(a) | |
}; | |
SC.Enumerator._popContext = function() { | |
var a = this._contextCache ? this._contextCache.pop() : null; | |
return a || {} | |
}; | |
SC.Enumerator._pushContext = function(b) { | |
this._contextCache = this._contextCache || []; | |
var a = this._contextCache; | |
a.push(b); | |
return null | |
}; | |
sc_require("core"); | |
sc_require("system/enumerator"); | |
SC.Enumerable = { | |
isEnumerable: YES, | |
nextObject: function(a, c, b) { | |
return this.objectAt ? this.objectAt(a) : this[a] | |
}, | |
firstObject: function() { | |
if (this.get("length") === 0) { | |
return undefined | |
} | |
if (this.objectAt) { | |
return this.objectAt(0) | |
} | |
var b = SC.Enumerator._popContext(), | |
a; | |
a = this.nextObject(0, null, b); | |
b = SC.Enumerator._pushContext(b); | |
return a | |
}.property(), | |
enumerator: function() { | |
return SC.Enumerator.create(this) | |
}, | |
forEach: function(g, f) { | |
if (typeof g !== "function") { | |
throw new TypeError() | |
} | |
var b = this.get ? this.get("length") : this.length; | |
if (f === undefined) { | |
f = null | |
} | |
var e = null; | |
var c = SC.Enumerator._popContext(); | |
for (var a = 0; a < b; a++) { | |
var d = this.nextObject(a, e, c); | |
g.call(f, d, a, this); | |
e = d | |
} | |
e = null; | |
c = SC.Enumerator._pushContext(c); | |
return this | |
}, | |
getEach: function(a) { | |
return this.map(function(b) { | |
return b ? (b.get ? b.get(a) : b[a]) : null | |
}, | |
this) | |
}, | |
setEach: function(a, b) { | |
this.forEach(function(c) { | |
if (c) { | |
if (c.set) { | |
c.set(a, b) | |
} else { | |
c[a] = b | |
} | |
} | |
}, | |
this); | |
return this | |
}, | |
map: function(h, g) { | |
if (typeof h !== "function") { | |
throw new TypeError() | |
} | |
var b = this.get ? this.get("length") : this.length; | |
if (g === undefined) { | |
g = null | |
} | |
var c = []; | |
var f = null; | |
var d = SC.Enumerator._popContext(); | |
for (var a = 0; a < b; a++) { | |
var e = this.nextObject(a, f, d); | |
c[a] = h.call(g, e, a, this); | |
f = e | |
} | |
f = null; | |
d = SC.Enumerator._pushContext(d); | |
return c | |
}, | |
mapProperty: function(a) { | |
return this.map(function(b) { | |
return b ? (b.get ? b.get(a) : b[a]) : null | |
}) | |
}, | |
filter: function(h, g) { | |
if (typeof h !== "function") { | |
throw new TypeError() | |
} | |
var b = this.get ? this.get("length") : this.length; | |
if (g === undefined) { | |
g = null | |
} | |
var c = []; | |
var f = null; | |
var d = SC.Enumerator._popContext(); | |
for (var a = 0; | |
a < b; a++) { | |
var e = this.nextObject(a, f, d); | |
if (h.call(g, e, a, this)) { | |
c.push(e) | |
} | |
f = e | |
} | |
f = null; | |
d = SC.Enumerator._pushContext(d); | |
return c | |
}, | |
sortProperty: function(b) { | |
var c = (typeof b === SC.T_STRING) ? arguments: b, | |
a = c.length, | |
d; | |
if (this instanceof Array) { | |
d = this | |
} else { | |
d = []; | |
this.forEach(function(e) { | |
d.push(e) | |
}) | |
} | |
if (!d) { | |
return [] | |
} | |
return d.sort(function(g, f) { | |
var e, | |
i, | |
k, | |
j, | |
h = 0; | |
for (e = 0; h === 0 && e < a; e++) { | |
i = c[e]; | |
k = g ? (g.get ? g.get(i) : g[i]) : null; | |
j = f ? (f.get ? f.get(i) : f[i]) : null; | |
h = SC.compare(k, j) | |
} | |
return h | |
}) | |
}, | |
filterProperty: function(j, f) { | |
var d = this.get ? this.get("length") : this.length; | |
var e = []; | |
var i = null; | |
var b = SC.Enumerator._popContext(); | |
for (var g = 0; g < d; g++) { | |
var c = this.nextObject(g, i, b); | |
var h = c ? (c.get ? c.get(j) : c[j]) : null; | |
var a = (f === undefined) ? !!h: SC.isEqual(h, f); | |
if (a) { | |
e.push(c) | |
} | |
i = c | |
} | |
i = null; | |
b = SC.Enumerator._pushContext(b); | |
return e | |
}, | |
find: function(h, d) { | |
if (typeof h !== "function") { | |
throw new TypeError() | |
} | |
var c = this.get ? this.get("length") : this.length; | |
if (d === undefined) { | |
d = null | |
} | |
var g = null, | |
b, | |
i = NO, | |
e = null; | |
var a = SC.Enumerator._popContext(); | |
for (var f = 0; f < c && !i; f++) { | |
b = this.nextObject(f, g, a); | |
if (i = h.call(d, b, f, this)) { | |
e = b | |
} | |
g = b | |
} | |
b = g = null; | |
a = SC.Enumerator._pushContext(a); | |
return e | |
}, | |
findProperty: function(i, f) { | |
var c = this.get ? this.get("length") : this.length; | |
var j = NO, | |
d = null, | |
h = null, | |
b, | |
g; | |
var a = SC.Enumerator._popContext(); | |
for (var e = 0; e < c && !j; e++) { | |
b = this.nextObject(e, h, a); | |
g = b ? (b.get ? b.get(i) : b[i]) : null; | |
j = (f === undefined) ? !!g: SC.isEqual(g, f); | |
if (j) { | |
d = b | |
} | |
h = b | |
} | |
h = b = null; | |
a = SC.Enumerator._pushContext(a); | |
return d | |
}, | |
every: function(h, g) { | |
if (typeof h !== "function") { | |
throw new TypeError() | |
} | |
var b = this.get ? this.get("length") : this.length; | |
if (g === undefined) { | |
g = null | |
} | |
var c = YES; | |
var f = null; | |
var d = SC.Enumerator._popContext(); | |
for (var a = 0; c && (a < b); a++) { | |
var e = this.nextObject(a, f, d); | |
if (!h.call(g, e, a, this)) { | |
c = NO | |
} | |
f = e | |
} | |
f = null; | |
d = SC.Enumerator._pushContext(d); | |
return c | |
}, | |
everyProperty: function(i, e) { | |
var c = this.get ? this.get("length") : this.length; | |
var d = YES; | |
var h = null; | |
var a = SC.Enumerator._popContext(); | |
for (var f = 0; d && (f < c); f++) { | |
var b = this.nextObject(f, h, a); | |
var g = b ? (b.get ? b.get(i) : b[i]) : null; | |
d = (e === undefined) ? !!g: SC.isEqual(g, e); | |
h = b | |
} | |
h = null; | |
a = SC.Enumerator._pushContext(a); | |
return d | |
}, | |
some: function(h, g) { | |
if (typeof h !== "function") { | |
throw new TypeError() | |
} | |
var b = this.get ? this.get("length") : this.length; | |
if (g === undefined) { | |
g = null | |
} | |
var c = NO; | |
var f = null; | |
var d = SC.Enumerator._popContext(); | |
for (var a = 0; (!c) && (a < b); a++) { | |
var e = this.nextObject(a, f, d); | |
if (h.call(g, e, a, this)) { | |
c = YES | |
} | |
f = e | |
} | |
f = null; | |
d = SC.Enumerator._pushContext(d); | |
return c | |
}, | |
someProperty: function(i, e) { | |
var c = this.get ? this.get("length") : this.length; | |
var d = NO; | |
var h = null; | |
var a = SC.Enumerator._popContext(); | |
for (var f = 0; ! d && (f < c); f++) { | |
var b = this.nextObject(f, h, a); | |
var g = b ? (b.get ? b.get(i) : b[i]) : null; | |
d = (e === undefined) ? !!g: SC.isEqual(g, e); | |
h = b | |
} | |
h = null; | |
a = SC.Enumerator._pushContext(a); | |
return d | |
}, | |
reduce: function(g, h, i) { | |
if (typeof g !== "function") { | |
throw new TypeError() | |
} | |
var c = this.get ? this.get("length") : this.length; | |
if (c === 0 && h === undefined) { | |
throw new TypeError() | |
} | |
var d = h; | |
var f = null; | |
var a = SC.Enumerator._popContext(); | |
for (var e = 0; e < c; e++) { | |
var b = this.nextObject(e, f, a); | |
if (b !== null) { | |
if (d === undefined) { | |
d = b | |
} else { | |
d = g.call(null, d, b, e, this, i) | |
} | |
} | |
f = b | |
} | |
f = null; | |
a = SC.Enumerator._pushContext(a); | |
if (d === undefined) { | |
throw new TypeError() | |
} | |
return d | |
}, | |
invoke: function(h) { | |
var e = this.get ? this.get("length") : this.length; | |
if (e <= 0) { | |
return [] | |
} | |
var i; | |
var g = []; | |
var c = arguments.length; | |
if (c > 1) { | |
for (i = 1; i < c; i++) { | |
g.push(arguments[i]) | |
} | |
} | |
var f = []; | |
var j = null; | |
var b = SC.Enumerator._popContext(); | |
for (i = 0; i < e; i++) { | |
var d = this.nextObject(i, j, b); | |
var a = d ? d[h] : null; | |
if (a) { | |
f[i] = a.apply(d, g) | |
} | |
j = d | |
} | |
j = null; | |
b = SC.Enumerator._pushContext(b); | |
return f | |
}, | |
invokeWhile: function(d, i) { | |
var f = this.get ? this.get("length") : this.length; | |
if (f <= 0) { | |
return null | |
} | |
var j; | |
var h = []; | |
var c = arguments.length; | |
if (c > 2) { | |
for (j = 2; j < c; j++) { | |
h.push(arguments[j]) | |
} | |
} | |
var g = d; | |
var k = null; | |
var b = SC.Enumerator._popContext(); | |
for (j = 0; (g === d) && (j < f); j++) { | |
var e = this.nextObject(j, k, b); | |
var a = e ? e[i] : null; | |
if (a) { | |
g = a.apply(e, h) | |
} | |
k = e | |
} | |
k = null; | |
b = SC.Enumerator._pushContext(b); | |
return g | |
}, | |
toArray: function() { | |
var a = []; | |
this.forEach(function(b) { | |
a.push(b) | |
}, | |
this); | |
return a | |
} | |
}; | |
SC._buildReducerFor = function(a, b) { | |
return function(d, e) { | |
var f = this[a]; | |
if (SC.typeOf(f) !== SC.T_FUNCTION) { | |
return this.unknownProperty ? this.unknownProperty(d, e) : null | |
} else { | |
var c = SC.Enumerable.reduce.call(this, f, null, b); | |
return c | |
} | |
}.property("[]") | |
}; | |
SC.Reducers = { | |
"[]": function(a, b) { | |
return this | |
}.property(), | |
enumerableContentDidChange: function(b, a) { | |
this.notifyPropertyChange("[]"); | |
return this | |
}, | |
reducedProperty: function(i, g, f) { | |
if (!i || i.charAt(0) !== "@") { | |
return undefined | |
} | |
var d = i.match(/^@([^(]*)(\(([^)]*)\))?$/); | |
if (!d || d.length < 2) { | |
return undefined | |
} | |
var h = d[1]; | |
var j = d[3]; | |
h = "reduce" + h.slice(0, 1).toUpperCase() + h.slice(1); | |
var a = this[h]; | |
if (SC.typeOf(a) !== SC.T_FUNCTION) { | |
return undefined | |
} | |
if (f === NO) { | |
return SC.Enumerable.reduce.call(this, a, null, j) | |
} | |
var c = SC._buildReducerFor(h, j); | |
var b = this.constructor.prototype; | |
if (b) { | |
b[i] = c; | |
var e = b._properties || []; | |
e.push(i); | |
b._properties = e; | |
this.registerDependentKey(i, "[]") | |
} | |
return SC.Enumerable.reduce.call(this, a, null, j) | |
}, | |
reduceMax: function(a, d, b, f, c) { | |
if (c && d) { | |
d = d.get ? d.get(c) : d[c] | |
} | |
if (a === null) { | |
return d | |
} | |
return (d > a) ? d: a | |
}, | |
reduceMaxObject: function(b, f, c, g, d) { | |
var a = b, | |
h = f; | |
if (d) { | |
if (f) { | |
h = f.get ? f.get(d) : f[d] | |
} | |
if (b) { | |
a = b.get ? b.get(d) : b[d] | |
} | |
} | |
if (a === null) { | |
return f | |
} | |
return (h > a) ? f: b | |
}, | |
reduceMin: function(a, d, b, f, c) { | |
if (c && d) { | |
d = d.get ? d.get(c) : d[c] | |
} | |
if (a === null) { | |
return d | |
} | |
return (d < a) ? d: a | |
}, | |
reduceMinObject: function(b, f, c, g, d) { | |
var a = b, | |
h = f; | |
if (d) { | |
if (f) { | |
h = f.get ? f.get(d) : f[d] | |
} | |
if (b) { | |
a = b.get ? b.get(d) : b[d] | |
} | |
} | |
if (a === null) { | |
return f | |
} | |
return (h < a) ? f: b | |
}, | |
reduceAverage: function(b, g, d, h, f) { | |
if (f && g) { | |
g = g.get ? g.get(f) : g[f] | |
} | |
var c = (b || 0) + g; | |
var a = h.get ? h.get("length") : h.length; | |
if (d >= a - 1) { | |
c = c / a | |
} | |
return c | |
}, | |
reduceSum: function(a, d, b, f, c) { | |
if (c && d) { | |
d = d.get ? d.get(c) : d[c] | |
} | |
return (a === null) ? d: a + d | |
} | |
}; | |
SC.mixin(SC.Enumerable, SC.Reducers); | |
SC.mixin(Array.prototype, SC.Reducers); | |
Array.prototype.isEnumerable = YES; (function() { | |
var a = { | |
nextObject: SC.Enumerable.nextObject, | |
enumerator: SC.Enumerable.enumerator, | |
firstObject: SC.Enumerable.firstObject, | |
sortProperty: SC.Enumerable.sortProperty, | |
mapProperty: function(g) { | |
var e = this.length; | |
var f = []; | |
for (var d = 0; d < e; d++) { | |
var h = this[d]; | |
f[d] = h ? (h.get ? h.get(g) : h[g]) : null | |
} | |
return f | |
}, | |
filterProperty: function(h, j) { | |
var f = this.length; | |
var g = []; | |
for (var e = 0; e < f; e++) { | |
var i = this[e]; | |
var k = i ? (i.get ? i.get(h) : i[h]) : null; | |
var d = (j === undefined) ? !!k: SC.isEqual(k, j); | |
if (d) { | |
g.push(i) | |
} | |
} | |
return g | |
}, | |
find: function(j, i) { | |
if (typeof j !== "function") { | |
throw new TypeError() | |
} | |
var e = this.length; | |
if (i === undefined) { | |
i = null | |
} | |
var g, | |
f = null, | |
h = NO; | |
for (var d = 0; d < e && !h; d++) { | |
g = this[d]; | |
if (h = j.call(i, g, d, this)) { | |
f = g | |
} | |
} | |
g = null; | |
return f | |
}, | |
findProperty: function(g, j) { | |
var e = this.length; | |
var h, | |
k, | |
i = NO, | |
f = null; | |
for (var d = 0; d < e && !i; d++) { | |
k = (h = this[d]) ? (h.get ? h.get(g) : h[g]) : null; | |
i = (j === undefined) ? !!k: SC.isEqual(k, j); | |
if (i) { | |
f = h | |
} | |
} | |
h = null; | |
return f | |
}, | |
everyProperty: function(g, i) { | |
var e = this.length; | |
var f = YES; | |
for (var d = 0; f && (d < e); d++) { | |
var h = this[d]; | |
var j = h ? (h.get ? h.get(g) : h[g]) : null; | |
f = (i === undefined) ? !!j: SC.isEqual(j, i) | |
} | |
return f | |
}, | |
someProperty: function(g, i) { | |
var e = this.length; | |
var f = NO; | |
for (var d = 0; ! f && (d < e); | |
d++) { | |
var h = this[d]; | |
var j = h ? (h.get ? h.get(g) : h[g]) : null; | |
f = (i === undefined) ? !!j: SC.isEqual(j, i) | |
} | |
return f | |
}, | |
invoke: function(f) { | |
var e = this.length; | |
if (e <= 0) { | |
return [] | |
} | |
var d; | |
var h = []; | |
var j = arguments.length; | |
if (j > 1) { | |
for (d = 1; d < j; d++) { | |
h.push(arguments[d]) | |
} | |
} | |
var g = []; | |
for (d = 0; | |
d < e; d++) { | |
var i = this[d]; | |
var k = i ? i[f] : null; | |
if (k) { | |
g[d] = k.apply(i, h) | |
} | |
} | |
return g | |
}, | |
invokeWhile: function(f, k) { | |
var h = this.length; | |
if (h <= 0) { | |
return null | |
} | |
var l; | |
var j = []; | |
var e = arguments.length; | |
if (e > 2) { | |
for (l = 2; l < e; l++) { | |
j.push(arguments[l]) | |
} | |
} | |
var i = f; | |
for (l = 0; (i === f) && (l < h); l++) { | |
var g = this[l]; | |
var d = g ? g[k] : null; | |
if (d) { | |
i = d.apply(g, j) | |
} | |
} | |
return i | |
}, | |
toArray: function() { | |
var e = this.length; | |
if (e <= 0) { | |
return [] | |
} | |
var f = []; | |
for (var d = 0; | |
d < e; d++) { | |
var g = this[d]; | |
f.push(g) | |
} | |
return f | |
}, | |
getEach: function(g) { | |
var f = []; | |
var e = this.length; | |
for (var d = 0; d < e; d++) { | |
var h = this[d]; | |
f[d] = h ? (h.get ? h.get(g) : h[g]) : null | |
} | |
return f | |
}, | |
setEach: function(f, g) { | |
var e = this.length; | |
for (var d = 0; d < e; d++) { | |
var h = this[d]; | |
if (h) { | |
if (h.set) { | |
h.set(f, g) | |
} else { | |
h[f] = g | |
} | |
} | |
} | |
return this | |
} | |
}; | |
var c = { | |
forEach: function(h, g) { | |
if (typeof h !== "function") { | |
throw new TypeError() | |
} | |
var e = this.length; | |
if (g === undefined) { | |
g = null | |
} | |
for (var d = 0; d < e; d++) { | |
var f = this[d]; | |
h.call(g, f, d, this) | |
} | |
return this | |
}, | |
map: function(i, h) { | |
if (typeof i !== "function") { | |
throw new TypeError() | |
} | |
var e = this.length; | |
if (h === undefined) { | |
h = null | |
} | |
var f = []; | |
for (var d = 0; d < e; d++) { | |
var g = this[d]; | |
f[d] = i.call(h, g, d, this) | |
} | |
return f | |
}, | |
filter: function(i, h) { | |
if (typeof i !== "function") { | |
throw new TypeError() | |
} | |
var e = this.length; | |
if (h === undefined) { | |
h = null | |
} | |
var f = []; | |
for (var d = 0; d < e; d++) { | |
var g = this[d]; | |
if (i.call(h, g, d, this)) { | |
f.push(g) | |
} | |
} | |
return f | |
}, | |
every: function(i, h) { | |
if (typeof i !== "function") { | |
throw new TypeError() | |
} | |
var e = this.length; | |
if (h === undefined) { | |
h = null | |
} | |
var f = YES; | |
for (var d = 0; f && (d < e); d++) { | |
var g = this[d]; | |
if (!i.call(h, g, d, this)) { | |
f = NO | |
} | |
} | |
return f | |
}, | |
some: function(i, h) { | |
if (typeof i !== "function") { | |
throw new TypeError() | |
} | |
var e = this.length; | |
if (h === undefined) { | |
h = null | |
} | |
var f = NO; | |
for (var d = 0; (!f) && (d < e); d++) { | |
var g = this[d]; | |
if (i.call(h, g, d, this)) { | |
f = YES | |
} | |
} | |
return f | |
}, | |
reduce: function(j, f, i) { | |
if (typeof j !== "function") { | |
throw new TypeError() | |
} | |
var e = this.length; | |
if (e === 0 && f === undefined) { | |
throw new TypeError() | |
} | |
var g = f; | |
for (var d = 0; | |
d < e; d++) { | |
var h = this[d]; | |
if (h !== null) { | |
if (g === undefined) { | |
g = h | |
} else { | |
g = j.call(null, g, h, d, this, i) | |
} | |
} | |
} | |
if (g === undefined) { | |
throw new TypeError() | |
} | |
return g | |
} | |
}; | |
for (var b in c) { | |
if (!c.hasOwnProperty(b)) { | |
continue | |
} | |
if (!Array.prototype[b] || ((typeof Prototype === "object") && Prototype.Version.match(/^1\.6/))) { | |
Array.prototype[b] = c[b] | |
} | |
} | |
SC.mixin(Array.prototype, a) | |
})(); | |
SC.RangeObserver = { | |
isRangeObserver: YES, | |
toString: function() { | |
var a = this.indexes ? this.indexes.toString() : "SC.IndexSet<..>"; | |
return a.replace("IndexSet", "RangeObserver(%@)".fmt(SC.guidFor(this))) | |
}, | |
create: function(d, f, e, g, c, a) { | |
var b = SC.beget(this); | |
b.source = d; | |
b.indexes = f ? f.frozenCopy() : null; | |
b.target = e; | |
b.method = g; | |
b.context = c; | |
b.isDeep = a || NO; | |
b.beginObserving(); | |
return b | |
}, | |
extend: function(e) { | |
var d = SC.beget(this), | |
c = arguments, | |
b = c.length, | |
a; | |
for (a = 0; a < b; a++) { | |
SC.mixin(d, c[a]) | |
} | |
return d | |
}, | |
destroy: function(a) { | |
this.endObserving(); | |
return this | |
}, | |
update: function(a, b) { | |
if (this.indexes && this.indexes.isEqual(b)) { | |
return this | |
} | |
this.indexes = b ? b.frozenCopy() : null; | |
this.endObserving().beginObserving(); | |
return this | |
}, | |
beginObserving: function() { | |
if (!this.isDeep) { | |
return this | |
} | |
var b = this.observing; | |
if (!b) { | |
b = this.observing = SC.CoreSet.create() | |
} | |
var a = this._beginObservingForEach; | |
if (!a) { | |
a = this._beginObservingForEach = function(c) { | |
var d = this.source.objectAt(c); | |
if (d && d.addObserver) { | |
b.push(d); | |
d._kvo_needsRangeObserver = YES | |
} | |
} | |
} | |
this.indexes.forEach(a, this); | |
this.isObserving = NO; | |
SC.Observers.addPendingRangeObserver(this); | |
return this | |
}, | |
setupPending: function(a) { | |
var d = this.observing; | |
if (this.isObserving || !d || (d.get("length") === 0)) { | |
return YES | |
} | |
if (d.contains(a)) { | |
this.isObserving = YES; | |
var b = this._setupPendingForEach; | |
if (!b) { | |
var c = this.source, | |
e = this.objectPropertyDidChange; | |
b = this._setupPendingForEach = function(f) { | |
var i = this.source.objectAt(f), | |
g = SC.guidFor(i), | |
h; | |
if (i && i.addObserver) { | |
d.push(i); | |
i.addObserver("*", this, e); | |
h = this[g]; | |
if (h === undefined || h === null) { | |
this[g] = f | |
} else { | |
if (h.isIndexSet) { | |
h.add(f) | |
} else { | |
h = this[g] = SC.IndexSet.create(h).add(f) | |
} | |
} | |
} | |
} | |
} | |
this.indexes.forEach(b, this); | |
return YES | |
} else { | |
return NO | |
} | |
}, | |
endObserving: function() { | |
if (!this.isDeep) { | |
return this | |
} | |
var e = this.observing; | |
if (this.isObserving) { | |
var b = this.objectPropertyDidChange, | |
c = this.source, | |
a, | |
f, | |
d; | |
if (e) { | |
f = e.length; | |
for (a = 0; a < f; a++) { | |
d = e[a]; | |
d.removeObserver("*", this, b); | |
this[SC.guidFor(d)] = null | |
} | |
e.length = 0 | |
} | |
this.isObserving = NO | |
} | |
if (e) { | |
e.clear() | |
} | |
return this | |
}, | |
rangeDidChange: function(b) { | |
var a = this.indexes; | |
if (!b || !a || a.intersects(b)) { | |
this.endObserving(); | |
this.method.call(this.target, this.source, null, "[]", b, this.context); | |
this.beginObserving() | |
} | |
return this | |
}, | |
objectPropertyDidChange: function(d, f, g, a) { | |
var e = this.context, | |
h = this.method, | |
c = SC.guidFor(d), | |
b = this[c]; | |
if (b && !b.isIndexSet) { | |
b = this[c] = SC.IndexSet.create(b).freeze() | |
} | |
if (e) { | |
h.call(this.target, this.source, d, f, b, e, a) | |
} else { | |
h.call(this.target, this.source, d, f, b, a) | |
} | |
} | |
}; | |
sc_require("mixins/observable"); | |
sc_require("mixins/enumerable"); | |
sc_require("system/range_observer"); | |
SC.OUT_OF_RANGE_EXCEPTION = "Index out of range"; | |
SC.Array = { | |
isSCArray: YES, | |
replace: function(a, c, b) { | |
throw "replace() must be implemented to support SC.Array" | |
}, | |
objectAt: function(a) { | |
if (a < 0) { | |
return undefined | |
} | |
if (a >= this.get("length")) { | |
return undefined | |
} | |
return this.get(a) | |
}, | |
"[]": function(a, b) { | |
if (b !== undefined) { | |
this.replace(0, this.get("length"), b) | |
} | |
return this | |
}.property(), | |
insertAt: function(a, b) { | |
if (a > this.get("length")) { | |
throw SC.OUT_OF_RANGE_EXCEPTION | |
} | |
this.replace(a, 0, [b]); | |
return this | |
}, | |
removeAt: function(d, a) { | |
var c = 0, | |
b = []; | |
if (typeof d === SC.T_NUMBER) { | |
if ((d < 0) || (d >= this.get("length"))) { | |
throw SC.OUT_OF_RANGE_EXCEPTION | |
} | |
if (a === undefined) { | |
this.replace(d, 1, b); | |
return this | |
} else { | |
d = SC.IndexSet.create(d, a) | |
} | |
} | |
this.beginPropertyChanges(); | |
d.forEachRange(function(f, e) { | |
f -= c; | |
c += e; | |
this.replace(f, e, b) | |
}, | |
this); | |
this.endPropertyChanges(); | |
return this | |
}, | |
removeObject: function(b) { | |
var c = this.get("length") || 0; | |
while (--c >= 0) { | |
var a = this.objectAt(c); | |
if (a == b) { | |
this.removeAt(c) | |
} | |
} | |
return this | |
}, | |
removeObjects: function(a) { | |
this.beginPropertyChanges(); | |
a.forEach(function(b) { | |
this.removeObject(b) | |
}, | |
this); | |
this.endPropertyChanges(); | |
return this | |
}, | |
pushObject: function(a) { | |
this.insertAt(this.get("length"), a); | |
return a | |
}, | |
pushObjects: function(a) { | |
this.beginPropertyChanges(); | |
a.forEach(function(b) { | |
this.pushObject(b) | |
}, | |
this); | |
this.endPropertyChanges(); | |
return this | |
}, | |
popObject: function() { | |
var a = this.get("length"); | |
if (a === 0) { | |
return null | |
} | |
var b = this.objectAt(a - 1); | |
this.removeAt(a - 1); | |
return b | |
}, | |
shiftObject: function() { | |
if (this.get("length") === 0) { | |
return null | |
} | |
var a = this.objectAt(0); | |
this.removeAt(0); | |
return a | |
}, | |
unshiftObject: function(a) { | |
this.insertAt(0, a); | |
return a | |
}, | |
unshiftObjects: function(a) { | |
this.beginPropertyChanges(); | |
a.forEach(function(b) { | |
this.unshiftObject(b) | |
}, | |
this); | |
this.endPropertyChanges(); | |
return this | |
}, | |
isEqual: function(a) { | |
if (!a) { | |
return false | |
} | |
if (a == this) { | |
return true | |
} | |
var b = a.get("length"); | |
if (b != this.get("length")) { | |
return false | |
} | |
while (--b >= 0) { | |
if (!SC.isEqual(a.objectAt(b), this.objectAt(b))) { | |
return false | |
} | |
} | |
return true | |
}, | |
compact: function() { | |
return this.without(null) | |
}, | |
without: function(b) { | |
if (this.indexOf(b) < 0) { | |
return this | |
} | |
var a = []; | |
this.forEach(function(c) { | |
if (c !== b) { | |
a[a.length] = c | |
} | |
}); | |
return a | |
}, | |
uniq: function() { | |
var a = []; | |
this.forEach(function(b) { | |
if (a.indexOf(b) < 0) { | |
a[a.length] = b | |
} | |
}); | |
return a | |
}, | |
rangeObserverClass: SC.RangeObserver, | |
addRangeObserver: function(d, f, h, e) { | |
var a = this._array_rangeObservers; | |
if (!a) { | |
a = this._array_rangeObservers = SC.CoreSet.create() | |
} | |
if (this._array_oldLength === undefined) { | |
this._array_oldLength = this.get("length") | |
} | |
var g = this.rangeObserverClass; | |
var b = NO; | |
var c = g.create(this, d, f, h, e, b); | |
a.add(c); | |
if (!this._array_isNotifyingRangeObservers) { | |
this._array_isNotifyingRangeObservers = YES; | |
this.addObserver("[]", this, this._array_notifyRangeObservers) | |
} | |
return c | |
}, | |
updateRangeObserver: function(b, a) { | |
return b.update(this, a) | |
}, | |
removeRangeObserver: function(c) { | |
var b = c.destroy(this); | |
var a = this._array_rangeObservers; | |
if (a) { | |
a.remove(c) | |
} | |
return b | |
}, | |
enumerableContentDidChange: function(h, g, f) { | |
var a = this._array_rangeObservers, | |
d = this._array_oldLength, | |
e, | |
c, | |
b; | |
this.beginPropertyChanges(); | |
this.notifyPropertyChange("length"); | |
if (a && a.length > 0) { | |
if (d === undefined) { | |
d = 0 | |
} | |
this._array_oldLength = e = this.get("length"); | |
if (h === undefined) { | |
h = 0 | |
} | |
if (f === undefined) { | |
f = e - d | |
} | |
if (f !== 0 || g === undefined) { | |
c = e - h; | |
if (f < 0) { | |
c -= f | |
} | |
} else { | |
c = g | |
} | |
b = this._array_rangeChanges; | |
if (!b) { | |
b = this._array_rangeChanges = SC.IndexSet.create() | |
} | |
b.add(h, c) | |
} | |
this.notifyPropertyChange("[]"); | |
this.endPropertyChanges(); | |
return this | |
}, | |
_array_notifyRangeObservers: function() { | |
var c = this._array_rangeObservers, | |
d = this._array_rangeChanges, | |
b = c ? c.length: 0, | |
a, | |
e; | |
if (b > 0 && d && d.length > 0) { | |
for (a = 0; a < b; a++) { | |
c[a].rangeDidChange(d) | |
} | |
d.clear() | |
} | |
} | |
}; | |
SC.mixin(Array.prototype, SC.Array); | |
SC.Array = SC.mixin({}, | |
SC.Enumerable, SC.Array); | |
SC.Array.slice = function(b, d) { | |
var a = []; | |
var c = this.get("length"); | |
if (SC.none(b)) { | |
b = 0 | |
} | |
if (SC.none(d) || (d > c)) { | |
d = c | |
} | |
while (b < d) { | |
a[a.length] = this.objectAt(b++) | |
} | |
return a | |
}; | |
SC.Array.indexOf = function(d, c) { | |
var b, | |
a = this.get("length"); | |
if (c === undefined) { | |
c = 0 | |
} else { | |
c = (c < 0) ? Math.ceil(c) : Math.floor(c) | |
} | |
if (c < 0) { | |
c += a | |
} | |
for (b = c; b < a; b++) { | |
if (this.objectAt(b) === d) { | |
return b | |
} | |
} | |
return - 1 | |
}; | |
if (!Array.prototype.indexOf) { | |
Array.prototype.indexOf = SC.Array.indexOf | |
} | |
SC.Array.lastIndexOf = function(d, c) { | |
var b, | |
a = this.get("length"); | |
if (c === undefined) { | |
c = a - 1 | |
} else { | |
c = (c < 0) ? Math.ceil(c) : Math.floor(c) | |
} | |
if (c < 0) { | |
c += a | |
} | |
for (b = c; b >= 0; b--) { | |
if (this.objectAt(b) === d) { | |
return b | |
} | |
} | |
return - 1 | |
}; | |
if (!Array.prototype.lastIndexOf) { | |
Array.prototype.lastIndexOf = SC.Array.lastIndexOf | |
} (function() { | |
SC.mixin(Array.prototype, { | |
replace: function(d, g, f) { | |
if (this.isFrozen) { | |
throw SC.FROZEN_ERROR | |
} | |
if (!f || f.length === 0) { | |
this.splice(d, g) | |
} else { | |
var e = [d, g].concat(f); | |
this.splice.apply(this, e) | |
} | |
var c = f ? (f.get ? f.get("length") : f.length) : 0; | |
this.enumerableContentDidChange(d, g, c - g); | |
return this | |
}, | |
unknownProperty: function(d, e) { | |
var c = this.reducedProperty(d, e); | |
if ((e !== undefined) && c === undefined) { | |
c = this[d] = e | |
} | |
return c | |
} | |
}); | |
var b = Array.prototype.indexOf; | |
if (!b || (b === SC.Array.indexOf)) { | |
Array.prototype.indexOf = function(f, e) { | |
var d, | |
c = this.length; | |
if (e === undefined) { | |
e = 0 | |
} else { | |
e = (e < 0) ? Math.ceil(e) : Math.floor(e) | |
} | |
if (e < 0) { | |
e += c | |
} | |
for (d = e; | |
d < c; d++) { | |
if (this[d] === f) { | |
return d | |
} | |
} | |
return - 1 | |
} | |
} | |
var a = Array.prototype.lastIndexOf; | |
if (!a || (a === SC.Array.lastIndexOf)) { | |
Array.prototype.lastIndexOf = function(f, e) { | |
var d, | |
c = this.length; | |
if (e === undefined) { | |
e = c - 1 | |
} else { | |
e = (e < 0) ? Math.ceil(e) : Math.floor(e) | |
} | |
if (e < 0) { | |
e += c | |
} | |
for (d = e; | |
d >= 0; d--) { | |
if (this[d] === f) { | |
return d | |
} | |
} | |
return - 1 | |
} | |
} | |
})(); | |
SC.Comparable = { | |
isComparable: YES, | |
compare: function(d, c) { | |
throw "%@.compare() is not implemented".fmt(this.toString()) | |
} | |
}; | |
SC.Copyable = { | |
isCopyable: YES, | |
copy: function() { | |
throw "%@.copy() is not implemented" | |
}, | |
frozenCopy: function() { | |
var a = this.get ? this.get("isFrozen") : this.isFrozen; | |
if (a === YES) { | |
return this | |
} else { | |
if (a === undefined) { | |
throw "%@ does not support freezing".fmt(this) | |
} else { | |
return this.copy().freeze() | |
} | |
} | |
} | |
}; | |
SC.mixin(Array.prototype, SC.Copyable); | |
Array.prototype.copy = Array.prototype.slice; | |
SC.DelegateSupport = { | |
delegateFor: function(c) { | |
var b = 1, | |
a = arguments.length, | |
d; | |
while (b < a) { | |
d = arguments[b]; | |
if (d && d[c] !== undefined) { | |
return d | |
} | |
b++ | |
} | |
return (this[c] !== undefined) ? this: null | |
}, | |
invokeDelegateMethod: function(c, a, b) { | |
b = SC.A(arguments); | |
b = b.slice(2, b.length); | |
if (!c || !c[a]) { | |
c = this | |
} | |
var d = c[a]; | |
return d ? d.apply(c, b) : null | |
}, | |
getDelegateProperty: function(d, e) { | |
var b = 1, | |
a = arguments.length, | |
c; | |
while (b < a) { | |
c = arguments[b++]; | |
if (c && c[d] !== undefined) { | |
return c.get ? c.get(d) : c[d] | |
} | |
} | |
return (this[d] !== undefined) ? this.get(d) : undefined | |
} | |
}; | |
SC.FROZEN_ERROR = new Error("Cannot modify a frozen object"); | |
SC.Freezable = { | |
isFreezable: YES, | |
isFrozen: NO, | |
freeze: function() { | |
if (this.set) { | |
this.set("isFrozen", YES) | |
} else { | |
this.isFrozen = YES | |
} | |
return this | |
} | |
}; | |
SC.mixin(Array.prototype, SC.Freezable); | |
sc_require("mixins/enumerable"); | |
sc_require("mixins/observable"); | |
sc_require("mixins/freezable"); | |
sc_require("mixins/copyable"); | |
SC.Set = SC.mixin({}, | |
SC.Enumerable, SC.Observable, SC.Freezable, { | |
create: function(b) { | |
var c, | |
a, | |
d = SC.Set._pool, | |
e = this.isObservable; | |
if (!e && b === undefined && d.length > 0) { | |
c = d.pop() | |
} else { | |
c = SC.beget(this); | |
if (e) { | |
c.initObservable() | |
} | |
if (b && b.isEnumerable && b.get("length") > 0) { | |
c.isObservable = NO; | |
if (b.isSCArray) { | |
a = b.get ? b.get("length") : b.length; | |
while (--a >= 0) { | |
c.add(b.objectAt(a)) | |
} | |
} else { | |
if (b.isSet) { | |
a = b.length; | |
while (--a >= 0) { | |
c.add(b[a]) | |
} | |
} else { | |
b.forEach(function(f) { | |
c.add(f) | |
}, | |
this) | |
} | |
} | |
c.isObservable = e | |
} | |
} | |
return c | |
}, | |
isSet: YES, | |
length: 0, | |
firstObject: function() { | |
return (this.length > 0) ? this[0] : undefined | |
}.property(), | |
clear: function() { | |
if (this.isFrozen) { | |
throw SC.FROZEN_ERROR | |
} | |
this.length = 0; | |
return this | |
}, | |
contains: function(b) { | |
if (b === null) { | |
return NO | |
} | |
var a = this[SC.hashFor(b)]; | |
return (!SC.none(a) && (a < this.length) && (this[a] === b)) | |
}, | |
isEqual: function(a) { | |
if (!a || !a.isSet || (a.get("length") !== this.get("length"))) { | |
return NO | |
} | |
var b = this.get("length"); | |
while (--b >= 0) { | |
if (!a.contains(this[b])) { | |
return NO | |
} | |
} | |
return YES | |
}, | |
add: function(d) { | |
if (this.isFrozen) { | |
throw SC.FROZEN_ERROR | |
} | |
if (d === null || d === undefined) { | |
return this | |
} | |
var c = SC.hashFor(d); | |
var b = this[c]; | |
var a = this.length; | |
if ((b === null || b === undefined) || (b >= a) || (this[b] !== d)) { | |
this[a] = d; | |
this[c] = a; | |
this.length = a + 1 | |
} | |
if (this.isObservable) { | |
this.enumerableContentDidChange() | |
} | |
return this | |
}, | |
addEach: function(c) { | |
if (this.isFrozen) { | |
throw SC.FROZEN_ERROR | |
} | |
if (!c || !c.isEnumerable) { | |
throw "%@.addEach must pass enumerable".fmt(this) | |
} | |
var a, | |
b = this.isObservable; | |
if (b) { | |
this.beginPropertyChanges() | |
} | |
if (c.isSCArray) { | |
a = c.get("length"); | |
while (--a >= 0) { | |
this.add(c.objectAt(a)) | |
} | |
} else { | |
if (c.isSet) { | |
a = c.length; | |
while (--a >= 0) { | |
this.add(c[a]) | |
} | |
} else { | |
c.forEach(function(d) { | |
this.add(d) | |
}, | |
this) | |
} | |
} | |
if (b) { | |
this.endPropertyChanges() | |
} | |
return this | |
}, | |
remove: function(d) { | |
if (this.isFrozen) { | |
throw SC.FROZEN_ERROR | |
} | |
if (SC.none(d)) { | |
return this | |
} | |
var c = SC.hashFor(d); | |
var b = this[c]; | |
var a = this.length; | |
if (SC.none(b) || (b >= a) || (this[b] !== d)) { | |
return this | |
} | |
delete this[c]; | |
if (b < (a - 1)) { | |
d = this[b] = this[a - 1]; | |
this[SC.hashFor(d)] = b | |
} | |
this.length = a - 1; | |
if (this.isObservable) { | |
this.enumerableContentDidChange() | |
} | |
return this | |
}, | |
pop: function() { | |
if (this.isFrozen) { | |
throw SC.FROZEN_ERROR | |
} | |
var a = (this.length > 0) ? this[this.length - 1] : null; | |
if (a) { | |
this.remove(a) | |
} | |
return a | |
}, | |
removeEach: function(c) { | |
if (this.isFrozen) { | |
throw SC.FROZEN_ERROR | |
} | |
if (!c || !c.isEnumerable) { | |
throw "%@.addEach must pass enumerable".fmt(this) | |
} | |
var a, | |
b = this.isObservable; | |
if (b) { | |
this.beginPropertyChanges() | |
} | |
if (c.isSCArray) { | |
a = c.get("length"); | |
while (--a >= 0) { | |
this.remove(c.objectAt(a)) | |
} | |
} else { | |
if (c.isSet) { | |
a = c.length; | |
while (--a >= 0) { | |
this.remove(c[a]) | |
} | |
} else { | |
c.forEach(function(d) { | |
this.remove(d) | |
}, | |
this) | |
} | |
} | |
if (b) { | |
this.endPropertyChanges() | |
} | |
return this | |
}, | |
copy: function() { | |
return this.constructor.create(this) | |
}, | |
destroy: function() { | |
this.isFrozen = NO; | |
if (!this.isObservable) { | |
SC.Set._pool.push(this.clear()) | |
} | |
return this | |
}, | |
forEach: function(c, d) { | |
var b = this.length; | |
if (!d) { | |
d = this | |
} | |
for (var a = 0; a < b; | |
a++) { | |
c.call(d, this[a], a, this) | |
} | |
return this | |
}, | |
toString: function() { | |
var b = this.length, | |
a, | |
c = []; | |
for (a = 0; a < b; a++) { | |
c[a] = this[a] | |
} | |
return "SC.Set<%@>".fmt(c.join(",")) | |
}, | |
_pool: [], | |
isObservable: YES | |
}); | |
SC.Set.constructor = SC.Set; | |
SC.Set.clone = SC.Set.copy; | |
SC.Set.push = SC.Set.unshift = SC.Set.add; | |
SC.Set.shift = SC.Set.pop; | |
SC.Set.addObject = SC.Set.add; | |
SC.Set.removeObject = SC.Set.remove; | |
SC.Set._pool = []; | |
SC.CoreSet = SC.beget(SC.Set); | |
SC.CoreSet.isObservable = NO; | |
SC.CoreSet.constructor = SC.CoreSet; | |
sc_require("core"); | |
sc_require("mixins/observable"); | |
sc_require("mixins/array"); | |
sc_require("system/set"); | |
SC.BENCHMARK_OBJECTS = NO; | |
SC._object_extend = function _object_extend(g, f) { | |
if (!f) { | |
throw "SC.Object.extend expects a non-null value. Did you forget to 'sc_require' something? Or were you passing a Protocol to extend() as if it were a mixin?" | |
} | |
g._kvo_cloned = null; | |
var w, | |
m, | |
s, | |
e, | |
h = g.concatenatedProperties, | |
k = SC.K; | |
var c, | |
b; | |
m = (h) ? h.length: 0; | |
var a = (m > 0) ? {}: null; | |
while (--m >= 0) { | |
w = h[m]; | |
c = g[w]; | |
b = f[w]; | |
if (c) { | |
if (! (c instanceof Array)) { | |
c = SC.$A(c) | |
} | |
a[w] = (b) ? c.concat(b) : b | |
} else { | |
if (! (b instanceof Array)) { | |
b = SC.$A(b) | |
} | |
a[w] = b | |
} | |
} | |
var v = g._bindings, | |
l = NO; | |
var t = g._observers, | |
u = NO; | |
var i = g._properties, | |
d = NO; | |
var p, | |
j, | |
n; | |
var r = g.outlets, | |
q = NO; | |
if (f.outlets) { | |
r = (r || SC.EMPTY_ARRAY).concat(f.outlets); | |
q = YES | |
} | |
for (w in f) { | |
if (w === "_kvo_cloned") { | |
continue | |
} | |
if (!f.hasOwnProperty(w)) { | |
continue | |
} | |
var o = (a.hasOwnProperty(w) ? a[w] : null) || f[w]; | |
if (w.slice( - 7) === "Binding") { | |
if (!l) { | |
v = (v || SC.EMPTY_ARRAY).slice(); | |
l = YES | |
} | |
if (v === null) { | |
v = (g._bindings || SC.EMPTY_ARRAY).slice() | |
} | |
v[v.length] = w | |
} else { | |
if (o && (o instanceof Function)) { | |
if (!o.superclass && (o !== (e = g[w]))) { | |
o.superclass = o.base = e || k | |
} | |
if (o.propertyPaths) { | |
if (!u) { | |
t = (t || SC.EMPTY_ARRAY).slice(); | |
u = YES | |
} | |
t[t.length] = w | |
} else { | |
if (p = o.localPropertyPaths) { | |
j = p.length; | |
while (--j >= 0) { | |
n = g._kvo_for(SC.keyFor("_kvo_local", p[j]), SC.Set); | |
n.add(w); | |
g._kvo_for("_kvo_observed_keys", SC.CoreSet).add(p[j]) | |
} | |
} else { | |
if (o.dependentKeys) { | |
if (!d) { | |
i = (i || SC.EMPTY_ARRAY).slice(); | |
d = YES | |
} | |
i[i.length] = w | |
} else { | |
if (o.autoconfiguredOutlet) { | |
if (!q) { | |
r = (r || SC.EMPTY_ARRAY).slice(); | |
q = YES | |
} | |
r[r.length] = w | |
} | |
} | |
} | |
} | |
} | |
} | |
g[w] = o | |
} | |
if (f.hasOwnProperty("toString")) { | |
w = "toString"; | |
o = (a.hasOwnProperty(w) ? a[w] : null) || f[w]; | |
if (!o.superclass && (o !== (e = g[w]))) { | |
o.superclass = o.base = e || k | |
} | |
g[w] = o | |
} | |
g._bindings = v || []; | |
g._observers = t || []; | |
g._properties = i || []; | |
g.outlets = r || []; | |
return g | |
}; | |
SC.Object = function(a) { | |
return this._object_init(a) | |
}; | |
SC.mixin(SC.Object, { | |
mixin: function(b) { | |
var a = arguments.length, | |
c; | |
for (c = 0; c < a; c++) { | |
SC.mixin(this, arguments[c]) | |
} | |
return this | |
}, | |
superclass: null, | |
extend: function(e) { | |
var d = SC.BENCHMARK_OBJECTS; | |
if (d) { | |
SC.Benchmark.start("SC.Object.extend") | |
} | |
var g, | |
c = function(h) { | |
return this._object_init(h) | |
}; | |
for (g in this) { | |
if (!this.hasOwnProperty(g)) { | |
continue | |
} | |
c[g] = this[g] | |
} | |
if (this.hasOwnProperty("toString")) { | |
c.toString = this.toString | |
} | |
c.superclass = this; | |
SC.generateGuid(c); | |
c.subclasses = SC.Set.create(); | |
this.subclasses.add(c); | |
var f = (c.prototype = SC.beget(this.prototype)); | |
var b, | |
a = arguments.length; | |
for (b = 0; b < a; b++) { | |
SC._object_extend(f, arguments[b]) | |
} | |
f.constructor = c; | |
if (d) { | |
SC.Benchmark.end("SC.Object.extend") | |
} | |
return c | |
}, | |
create: function(a) { | |
var b = this; | |
return new b(arguments) | |
}, | |
isClass: YES, | |
subclasses: SC.Set.create(), | |
toString: function() { | |
return SC._object_className(this) | |
}, | |
subclassOf: function(b) { | |
if (this === b) { | |
return NO | |
} | |
var a = this; | |
while (a = a.superclass) { | |
if (a === b) { | |
return YES | |
} | |
} | |
return NO | |
}, | |
hasSubclass: function(a) { | |
return (a && a.subclassOf) ? a.subclassOf(this) : NO | |
}, | |
kindOf: function(a) { | |
return (this === a) || this.subclassOf(a) | |
} | |
}); | |
SC.Object.prototype = { | |
_kvo_enabled: YES, | |
_object_init: function(c) { | |
var b, | |
a = (c) ? c.length: 0; | |
for (b = 0; b < a; b++) { | |
SC._object_extend(this, c[b]) | |
} | |
SC.generateGuid(this); | |
this.init(); | |
var d = this.initMixin; | |
a = (d) ? d.length: 0; | |
for (b = 0; b < a; b++) { | |
d[b].call(this) | |
} | |
return this | |
}, | |
mixin: function() { | |
var b, | |
a = arguments.length; | |
for (b = 0; b < a; b++) { | |
SC.mixin(this, arguments[b]) | |
} | |
for (b = 0; b < a; b++) { | |
var c = arguments[b].initMixin; | |
if (c) { | |
c.call(this) | |
} | |
} | |
return this | |
}, | |
init: function() { | |
this.initObservable(); | |
return this | |
}, | |
isDestroyed: NO, | |
destroy: function() { | |
if (this.get("isDestroyed")) { | |
return this | |
} | |
this.set("isDestroyed", YES); | |
var b, | |
c = this.destroyMixin, | |
a = (c) ? c.length: 0; | |
for (b = 0; b < a; b++) { | |
c[b].call(this) | |
} | |
return this | |
}, | |
isObject: true, | |
respondsTo: function(a) { | |
return !! (SC.typeOf(this[a]) === SC.T_FUNCTION) | |
}, | |
tryToPerform: function(b, c, a) { | |
return this.respondsTo(b) && (this[b](c, a) !== NO) | |
}, | |
superclass: function(b) { | |
var a = arguments.callee.caller; | |
if (!a) { | |
throw "superclass cannot determine the caller method" | |
} | |
return a.superclass ? a.superclass.apply(this, arguments) : null | |
}, | |
instanceOf: function(a) { | |
return this.constructor === a | |
}, | |
kindOf: function(a) { | |
return this.constructor.kindOf(a) | |
}, | |
toString: function() { | |
if (!this._object_toString) { | |
var a = SC._object_className(this.constructor); | |
var b = "%@:%@".fmt(a, SC.guidFor(this)); | |
if (a) { | |
this._object_toString = b | |
} else { | |
return b | |
} | |
} | |
return this._object_toString | |
}, | |
awake: function(a) { | |
this.outlets.forEach(function(b) { | |
this.get(b) | |
}, | |
this); | |
this.bindings.invoke("sync") | |
}, | |
invokeOnce: function(a) { | |
SC.RunLoop.currentRunLoop.invokeOnce(this, a); | |
return this | |
}, | |
invokeLast: function(a) { | |
SC.RunLoop.currentRunLoop.invokeLast(this, a); | |
return this | |
}, | |
concatenatedProperties: ["concatenatedProperties", "initMixin", "destroyMixin"] | |
}; | |
SC.Object.prototype.constructor = SC.Object; | |
SC.mixin(SC.Object.prototype, SC.Observable); | |
function findClassNames() { | |
if (SC._object_foundObjectClassNames) { | |
return | |
} | |
SC._object_foundObjectClassNames = true; | |
var b = []; | |
var a = function(c, d, g) { | |
g--; | |
if (b.indexOf(d) >= 0) { | |
return | |
} | |
b.push(d); | |
for (var e in d) { | |
if (e == "__scope__") { | |
continue | |
} | |
if (e == "superclass") { | |
continue | |
} | |
if (!e.match(/^[A-Z0-9]/)) { | |
continue | |
} | |
var h = (c) ? [c, e].join(".") : e; | |
var f = d[e]; | |
switch (SC.typeOf(f)) { | |
case SC.T_CLASS: | |
if (!f._object_className) { | |
f._object_className = h | |
} | |
if (g >= 0) { | |
a(h, f, g) | |
} | |
break; | |
case SC.T_OBJECT: | |
if (g >= 0) { | |
a(h, f, g) | |
} | |
break; | |
case SC.T_HASH: | |
if (((c) || (h === "SC")) && (g >= 0)) { | |
a(h, f, g) | |
} | |
break; | |
default: | |
break | |
} | |
} | |
}; | |
a(null, SC.root, 2) //eh... | |
} | |
SC.instanceOf = function(a, b) { | |
return !! (a && a.constructor === b) | |
}; | |
SC.kindOf = function(a, b) { | |
if (a && !a.isClass) { | |
a = a.constructor | |
} | |
return !! (a && a.kindOf && a.kindOf(b)) | |
}; | |
SC._object_className = function(b) { | |
if (!SC.isReady) { | |
return "" | |
} | |
if (!b._object_className) { | |
findClassNames() | |
} | |
if (b._object_className) { | |
return b._object_className | |
} | |
var a = b; | |
while (a && !a._object_className) { | |
a = a.superclass | |
} | |
return (a && a._object_className) ? a._object_className: "Anonymous" | |
}; | |
sc_require("system/object"); | |
SC._ChainObserver = function(a) { | |
this.property = a | |
}; | |
SC._ChainObserver.createChain = function(d, j, f, a, b) { | |
var c = j.split("."), | |
h = new SC._ChainObserver(c[0]), | |
g = h, | |
e = c.length; | |
for (var i = 1; i < e; i++) { | |
g = g.next = new SC._ChainObserver(c[i]) | |
} | |
h.objectDidChange(d); | |
g.target = f; | |
g.method = a; | |
g.context = b; | |
return h | |
}; | |
SC._ChainObserver.prototype = { | |
isChainObserver: true, | |
object: null, | |
property: null, | |
next: null, | |
target: null, | |
method: null, | |
objectDidChange: function(a) { | |
if (a === this.object) { | |
return | |
} | |
if (this.object && this.object.removeObserver) { | |
this.object.removeObserver(this.property, this, this.propertyDidChange) | |
} | |
this.object = a; | |
if (this.object && this.object.addObserver) { | |
this.object.addObserver(this.property, this, this.propertyDidChange) | |
} | |
this.propertyDidChange() | |
}, | |
propertyDidChange: function() { | |
var b = this.object; | |
var e = this.property; | |
var d = (b && b.get) ? b.get(e) : null; | |
if (this.next) { | |
this.next.objectDidChange(d) | |
} | |
var f = this.target, | |
g = this.method, | |
c = this.context; | |
if (f && g) { | |
var a = b ? b.propertyRevision: null; | |
if (c) { | |
g.call(f, b, e, d, c, a) | |
} else { | |
g.call(f, b, e, d, a) | |
} | |
} | |
}, | |
destroyChain: function() { | |
var a = this.object; | |
if (a && a.removeObserver) { | |
a.removeObserver(this.property, this, this.propertyDidChange) | |
} | |
if (this.next) { | |
this.next.destroyChain() | |
} | |
this.next = this.target = this.method = this.object = this.context = null; | |
return null | |
} | |
}; | |
sc_require("mixins/observable"); | |
sc_require("system/set"); | |
SC.Observers = { | |
queue: [], | |
addObserver: function(c, d, e, b) { | |
var a; | |
if (SC.typeOf(c) === SC.T_STRING) { | |
a = SC.tupleForPropertyPath(c, b) | |
} else { | |
a = c | |
} | |
if (a) { | |
a[0].addObserver(a[1], d, e) | |
} else { | |
this.queue.push([c, d, e, b]) | |
} | |
}, | |
removeObserver: function(f, g, h, d) { | |
var c, | |
b, | |
a, | |
e; | |
a = SC.tupleForPropertyPath(f, d); | |
if (a) { | |
a[0].removeObserver(a[1], g, h) | |
} | |
c = this.queue.length; | |
b = this.queue; | |
while (--c >= 0) { | |
e = b[c]; | |
if ((e[0] === f) && (e[1] === g) && (e[2] == h) && (e[3] === d)) { | |
b[c] = null | |
} | |
} | |
}, | |
addPendingRangeObserver: function(a) { | |
var b = this.rangeObservers; | |
if (!b) { | |
b = this.rangeObservers = SC.CoreSet.create() | |
} | |
b.add(a); | |
return this | |
}, | |
_TMP_OUT: [], | |
flush: function(a) { | |
var e = this.queue; | |
if (e && e.length > 0) { | |
var h = (this.queue = []); | |
var i = e.length; | |
while (--i >= 0) { | |
var j = e[i]; | |
if (!j) { | |
continue | |
} | |
var f = SC.tupleForPropertyPath(j[0], j[3]); | |
if (f) { | |
f[0].addObserver(f[1], j[1], j[2]) | |
} else { | |
h.push(j) | |
} | |
} | |
} | |
if (a._kvo_needsRangeObserver) { | |
var g = this.rangeObservers, | |
d = g ? g.get("length") : 0, | |
b = this._TMP_OUT, | |
c; | |
for (i = 0; i < d; i++) { | |
c = g[i]; | |
if (c.setupPending(a)) { | |
b.push(c) | |
} | |
} | |
if (b.length > 0) { | |
g.removeEach(b) | |
} | |
b.length = 0; | |
a._kvo_needsRangeObserver = NO | |
} | |
}, | |
isObservingSuspended: 0, | |
_pending: SC.CoreSet.create(), | |
objectHasPendingChanges: function(a) { | |
this._pending.add(a) | |
}, | |
suspendPropertyObserving: function() { | |
this.isObservingSuspended++ | |
}, | |
resumePropertyObserving: function() { | |
var c; | |
if (--this.isObservingSuspended <= 0) { | |
c = this._pending; | |
this._pending = SC.CoreSet.create(); | |
var b, | |
a = c.length; | |
for (b = 0; b < a; b++) { | |
c[b]._notifyPropertyObservers() | |
} | |
c.clear(); | |
c = null | |
} | |
} | |
}; | |
sc_require("system/object"); | |
SC.LOG_BINDINGS = NO; | |
SC.BENCHMARK_BINDING_NOTIFICATIONS = NO; | |
SC.BENCHMARK_BINDING_SETUP = NO; | |
SC.MULTIPLE_PLACEHOLDER = "@@MULT@@"; | |
SC.NULL_PLACEHOLDER = "@@NULL@@"; | |
SC.EMPTY_PLACEHOLDER = "@@EMPTY@@"; | |
SC.Binding = { | |
beget: function(b) { | |
var a = SC.beget(this); | |
a.parentBinding = this; | |
if (b !== undefined) { | |
a = a.from(b) | |
} | |
return a | |
}, | |
builder: function() { | |
var b = this; | |
var a = function(c) { | |
return b.beget().from(c) | |
}; | |
a.beget = function() { | |
return b.beget() | |
}; | |
return a | |
}, | |
from: function(b, a) { | |
if (!b) { | |
return this | |
} | |
var c = (this === SC.Binding) ? this.beget() : this; | |
c._fromPropertyPath = b; | |
c._fromRoot = a; | |
c._fromTuple = null; | |
return c | |
}, | |
to: function(b, a) { | |
var c = (this === SC.Binding) ? this.beget() : this; | |
c._toPropertyPath = b; | |
c._toRoot = a; | |
c._toTuple = null; | |
return c | |
}, | |
connect: function() { | |
if (this.isConnected) { | |
return this | |
} | |
this.isConnected = YES; | |
this._connectionPending = YES; | |
this._syncOnConnect = YES; | |
SC.Binding._connectQueue.add(this); | |
return this | |
}, | |
_connect: function() { | |
if (!this._connectionPending) { | |
return | |
} | |
this._connectionPending = NO; | |
var c, | |
a; | |
var b = SC.BENCHMARK_BINDING_SETUP; | |
if (b) { | |
SC.Benchmark.start("SC.Binding.connect()") | |
} | |
c = this._fromPropertyPath; | |
a = this._fromRoot; | |
if (SC.typeOf(c) === SC.T_STRING) { | |
if (c.indexOf(".") === 0) { | |
c = c.slice(1); | |
if (!a) { | |
a = this._toRoot | |
} | |
} else { | |
if (c.indexOf("*") === 0) { | |
c = [this._fromRoot || this._toRoot, c.slice(1)]; | |
a = null | |
} | |
} | |
} | |
SC.Observers.addObserver(c, this, this.fromPropertyDidChange, a); | |
if (!this._oneWay) { | |
c = this._toPropertyPath; | |
a = this._toRoot; | |
SC.Observers.addObserver(c, this, this.toPropertyDidChange, a) | |
} | |
if (b) { | |
SC.Benchmark.end("SC.Binding.connect()") | |
} | |
if (this._syncOnConnect) { | |
this._syncOnConnect = NO; | |
if (b) { | |
SC.Benchmark.start("SC.Binding.connect().sync") | |
} | |
this.sync(); | |
if (b) { | |
SC.Benchmark.end("SC.Binding.connect().sync") | |
} | |
} | |
}, | |
disconnect: function() { | |
if (!this.isConnected) { | |
return this | |
} | |
if (this._connectionPending) { | |
this._connectionPending = NO | |
} else { | |
SC.Observers.removeObserver(this._fromPropertyPath, this, this.fromPropertyDidChange, this._fromRoot); | |
if (!this._oneWay) { | |
SC.Observers.removeObserver(this._toPropertyPath, this, this.toPropertyDidChange, this._toRoot) | |
} | |
} | |
this.isConnected = NO; | |
return this | |
}, | |
fromPropertyDidChange: function(c, b) { | |
var a = c ? c.get(b) : null; | |
if (a !== this._bindingValue) { | |
this._setBindingValue(c, b); | |
this._changePending = YES; | |
SC.Binding._changeQueue.add(this) | |
} | |
}, | |
toPropertyDidChange: function(c, b) { | |
if (this._oneWay) { | |
return | |
} | |
var a = c.get(b); | |
if (a !== this._transformedBindingValue) { | |
this._setBindingValue(c, b); | |
this._changePending = YES; | |
SC.Binding._changeQueue.add(this) | |
} | |
}, | |
_setBindingValue: function(b, a) { | |
this._bindingSource = b; | |
this._bindingKey = a | |
}, | |
_computeBindingValue: function() { | |
var g = this._bindingSource, | |
e = this._bindingKey, | |
c; | |
if (!g) { | |
return | |
} | |
this._bindingValue = c = g.getPath(e); | |
var f = this._transforms; | |
if (f) { | |
var b = f.length; | |
for (var a = 0; a < b; a++) { | |
var d = f[a]; | |
c = d(c, this) | |
} | |
} | |
if (this._noError && SC.typeOf(c) === SC.T_ERROR) { | |
c = null | |
} | |
this._transformedBindingValue = c | |
}, | |
_connectQueue: SC.CoreSet.create(), | |
_alternateConnectQueue: SC.CoreSet.create(), | |
_changeQueue: SC.CoreSet.create(), | |
_alternateChangeQueue: SC.CoreSet.create(), | |
_changePending: NO, | |
flushPendingChanges: function() { | |
if (this._isFlushing) { | |
return NO | |
} | |
this._isFlushing = YES; | |
SC.Observers.suspendPropertyObserving(); | |
var b = NO; | |
var c = SC.LOG_BINDINGS; | |
var a, | |
d; | |
while ((a = this._connectQueue).length > 0) { | |
this._connectQueue = this._alternateConnectQueue; | |
this._alternateConnectQueue = a; | |
while (d = a.pop()) { | |
d._connect() | |
} | |
} | |
while ((a = this._changeQueue).length > 0) { | |
if (c) { | |
console.log("Begin: Trigger changed bindings") | |
} | |
b = YES; | |
this._changeQueue = this._alternateChangeQueue; | |
this._alternateChangeQueue = a; | |
while (d = a.pop()) { | |
d.applyBindingValue() | |
} | |
if (c) { | |
console.log("End: Trigger changed bindings") | |
} | |
} | |
this._isFlushing = NO; | |
SC.Observers.resumePropertyObserving(); | |
return b | |
}, | |
applyBindingValue: function() { | |
this._changePending = NO; | |
this._computeBindingTargets(); | |
this._computeBindingValue(); | |
var a = this._bindingValue; | |
var b = this._transformedBindingValue; | |
var c = SC.BENCHMARK_BINDING_NOTIFICATIONS; | |
var d = SC.LOG_BINDINGS; | |
if (!this._oneWay && this._fromTarget) { | |
if (d) { | |
console.log("%@: %@ -> %@".fmt(this, a, b)) | |
} | |
if (c) { | |
SC.Benchmark.start(this.toString() + "->") | |
} | |
this._fromTarget.setPathIfChanged(this._fromPropertyKey, a); | |
if (c) { | |
SC.Benchmark.end(this.toString() + "->") | |
} | |
} | |
if (this._toTarget) { | |
if (d) { | |
console.log("%@: %@ <- %@".fmt(this, a, b)) | |
} | |
if (c) { | |
SC.Benchmark.start(this.toString() + "<-") | |
} | |
this._toTarget.setPathIfChanged(this._toPropertyKey, b); | |
if (c) { | |
SC.Benchmark.start(this.toString() + "<-") | |
} | |
} | |
}, | |
sync: function() { | |
if (!this.isConnected) { | |
return this | |
} | |
if (this._connectionPending) { | |
this._syncOnConnect = YES | |
} else { | |
this._computeBindingTargets(); | |
var c = this._fromTarget; | |
var b = this._fromPropertyKey; | |
if (!c || !b) { | |
return this | |
} | |
var a = c.getPath(b); | |
if (a !== this._bindingValue) { | |
this._setBindingValue(c, b); | |
this._changePending = YES; | |
SC.Binding._changeQueue.add(this) | |
} | |
} | |
return this | |
}, | |
_syncOnConnect: NO, | |
_computeBindingTargets: function() { | |
if (!this._fromTarget) { | |
var c, | |
b, | |
a; | |
c = this._fromPropertyPath; | |
b = this._fromRoot; | |
if (SC.typeOf(c) === SC.T_STRING) { | |
if (c.indexOf(".") === 0) { | |
c = c.slice(1); | |
if (!b) { | |
b = this._toRoot | |
} | |
} else { | |
if (c.indexOf("*") === 0) { | |
c = [b || this._toRoot, c.slice(1)]; | |
b = null | |
} | |
} | |
} | |
a = SC.tupleForPropertyPath(c, b); | |
if (a) { | |
this._fromTarget = a[0]; | |
this._fromPropertyKey = a[1] | |
} | |
} | |
if (!this._toTarget) { | |
c = this._toPropertyPath; | |
b = this._toRoot; | |
a = SC.tupleForPropertyPath(c, b); | |
if (a) { | |
this._toTarget = a[0]; | |
this._toPropertyKey = a[1] | |
} | |
} | |
}, | |
oneWay: function(c, a) { | |
if ((a === undefined) && (SC.typeOf(c) === SC.T_BOOL)) { | |
a = c; | |
c = null | |
} | |
var b = this.from(c); | |
if (b === SC.Binding) { | |
b = b.beget() | |
} | |
b._oneWay = (a === undefined) ? YES: a; | |
return b | |
}, | |
transform: function(b) { | |
var c = (this === SC.Binding) ? this.beget() : this; | |
var a = c._transforms; | |
if (a && (a === c.parentBinding._transform)) { | |
a = c._transforms = a.slice() | |
} | |
if (!a) { | |
a = c._transforms = [] | |
} | |
a.push(b); | |
return c | |
}, | |
resetTransforms: function() { | |
var a = (this === SC.Binding) ? this.beget() : this; | |
a._transforms = null; | |
return a | |
}, | |
noError: function(c, a) { | |
if ((a === undefined) && (SC.typeOf(c) === SC.T_BOOL)) { | |
a = c; | |
c = null | |
} | |
var b = this.from(c); | |
if (b === SC.Binding) { | |
b = b.beget() | |
} | |
b._noError = (a === undefined) ? YES: a; | |
return b | |
}, | |
single: function(b, a) { | |
if (a === undefined) { | |
a = SC.MULTIPLE_PLACEHOLDER | |
} | |
return this.from(b).transform(function(e, d) { | |
if (e && e.isEnumerable) { | |
var c = e.get("length"); | |
e = (c > 1) ? a: (c <= 0) ? null: e.firstObject() | |
} | |
return e | |
}) | |
}, | |
notEmpty: function(b, a) { | |
if (a === undefined) { | |
a = SC.EMPTY_PLACEHOLDER | |
} | |
return this.from(b).transform(function(d, c) { | |
if (SC.none(d) || (d === "") || (SC.isArray(d) && d.length === 0)) { | |
d = a | |
} | |
return d | |
}) | |
}, | |
notNull: function(b, a) { | |
if (a === undefined) { | |
a = SC.EMPTY_PLACEHOLDER | |
} | |
return this.from(b).transform(function(d, c) { | |
if (SC.none(d)) { | |
d = a | |
} | |
return d | |
}) | |
}, | |
multiple: function(a) { | |
return this.from(a).transform(function(b) { | |
if (!SC.isArray(b)) { | |
b = (b == null) ? [] : [b] | |
} | |
return b | |
}) | |
}, | |
bool: function(a) { | |
return this.from(a).transform(function(b) { | |
var c = SC.typeOf(b); | |
if (c === SC.T_ERROR) { | |
return b | |
} | |
return (c == SC.T_ARRAY) ? (b.length > 0) : (b === "") ? NO: !!b | |
}) | |
}, | |
not: function(a) { | |
return this.from(a).transform(function(b) { | |
var c = SC.typeOf(b); | |
if (c === SC.T_ERROR) { | |
return b | |
} | |
return ! ((c == SC.T_ARRAY) ? (b.length > 0) : (b === "") ? NO: !!b) | |
}) | |
}, | |
isNull: function(a) { | |
return this.from(a).transform(function(b) { | |
var c = SC.typeOf(b); | |
return (c === SC.T_ERROR) ? b: SC.none(b) | |
}) | |
}, | |
toString: function() { | |
var c = this._fromRoot ? "<%@>:%@".fmt(this._fromRoot, this._fromPropertyPath) : this._fromPropertyPath; | |
var b = this._toRoot ? "<%@>:%@".fmt(this._toRoot, this._toPropertyPath) : this._toPropertyPath; | |
var a = this._oneWay ? "[oneWay]": ""; | |
return "SC.Binding%@(%@ -> %@)%@".fmt(SC.guidFor(this), c, b, a) | |
} | |
}; | |
SC.binding = function(b, a) { | |
return SC.Binding.from(b, a) | |
}; | |
SC.Cookie = SC.Object.extend({ | |
name: null, | |
value: "", | |
expires: null, | |
path: null, | |
domain: null, | |
secure: NO, | |
isCookie: YES, | |
destroy: function() { | |
this.set("expires", -1); | |
this.write(); | |
arguments.callee.base.apply(this, arguments) | |
}, | |
write: function() { | |
var b = this.get("name"), | |
i = this.get("value"), | |
c = this.get("expires"), | |
k = this.get("path"), | |
e = this.get("domain"), | |
a = this.get("secure"); | |
var h = ""; | |
if (c && (SC.typeOf(c) === SC.T_NUMBER || (SC.DateTime && c.get && c.get("milliseconds")) || SC.typeOf(c.toUTCString) === SC.T_FUNCTION)) { | |
var d; | |
if (SC.typeOf(c) === SC.T_NUMBER) { | |
d = new Date(); | |
d.setTime(d.getTime() + (c * 24 * 60 * 60 * 1000)) | |
} else { | |
if (SC.DateTime && c.get && c.get("milliseconds")) { | |
d = new Date(c.get("milliseconds")) | |
} else { | |
if (SC.typeOf(c.toUTCString) === SC.T_FUNCTION) { | |
d = c | |
} | |
} | |
} | |
if (d) { | |
h = "; expires=" + d.toUTCString() | |
} | |
} | |
var j = k ? "; path=" + k: ""; | |
var g = e ? "; domain=" + e: ""; | |
var f = a ? "; secure": ""; | |
document.cookie = [b, "=", encodeURIComponent(i), h, j, g, f].join(""); | |
return this | |
} | |
}); | |
SC.Cookie.mixin({ | |
find: function(a) { | |
if (document.cookie && document.cookie != "") { | |
var d = document.cookie.split(";"); | |
for (var c = 0; c < d.length; c++) { | |
var b = String(d[c]).trim(); | |
if (b.substring(0, a.length + 1) === (a + "=")) { | |
return SC.Cookie.create({ | |
name: a, | |
value: decodeURIComponent(b.substring(a.length + 1)) | |
}) | |
} | |
} | |
} | |
return null | |
} | |
}); | |
SC.Error = SC.Object.extend({ | |
code: -1, | |
message: "", | |
errorValue: null, | |
errorObject: function() { | |
return this | |
}.property().cacheable(), | |
label: null, | |
toString: function() { | |
return "SC.Error:%@:%@ (%@)".fmt(SC.guidFor(this), this.get("message"), this.get("code")) | |
}, | |
isError: YES | |
}); | |
SC.Error.desc = function(d, a, e, c) { | |
var b = { | |
message: d | |
}; | |
if (a !== undefined) { | |
b.label = a | |
} | |
if (c !== undefined) { | |
b.code = c | |
} | |
if (e !== undefined) { | |
b.errorValue = e | |
} | |
return this.create(b) | |
}; | |
SC.$error = function(b, a, d, e) { | |
return SC.Error.desc(b, a, d, e) | |
}; | |
SC.ok = function(a) { | |
return (a !== false) && !(a && a.isError) | |
}; | |
SC.$ok = SC.ok; | |
SC.val = function(a) { | |
if (a && a.isError) { | |
return a.get ? a.get("errorValue") : null | |
} else { | |
return a | |
} | |
}; | |
SC.$val = SC.val; | |
SC.Error.HAS_MULTIPLE_VALUES = -100; | |
sc_require("mixins/enumerable"); | |
sc_require("mixins/observable"); | |
sc_require("mixins/freezable"); | |
sc_require("mixins/copyable"); | |
SC.IndexSet = SC.mixin({}, | |
SC.Enumerable, SC.Observable, SC.Freezable, SC.Copyable, { | |
_sc_sliceContent: function(e) { | |
if (e.length < 1000) { | |
return e.slice() | |
} | |
var d = 0, | |
a = [], | |
b = e[0]; | |
while (b !== 0) { | |
a[d] = b; | |
d = (b < 0) ? (0 - b) : b; | |
b = e[d] | |
} | |
a[d] = 0; | |
this._hint(0, d, a); | |
return a | |
}, | |
create: function(c, b) { | |
var a = SC.beget(this); | |
a.initObservable(); | |
if (c && c.isIndexSet) { | |
a._content = this._sc_sliceContent(c._content); | |
a.max = c.max; | |
a.length = c.length; | |
a.source = c.source | |
} else { | |
a._content = [0]; | |
if (c !== undefined) { | |
a.add(c, b) | |
} | |
} | |
return a | |
}, | |
isIndexSet: YES, | |
HINT_SIZE: 256, | |
length: 0, | |
max: 0, | |
min: function() { | |
var a = this._content, | |
b = a[0]; | |
return (b === 0) ? -1: (b > 0) ? 0: Math.abs(b) | |
}.property("[]").cacheable(), | |
firstObject: function() { | |
return (this.get("length") > 0) ? this.get("min") : undefined | |
}.property(), | |
rangeStartForIndex: function(c) { | |
var f = this._content, | |
a = this.get("max"), | |
b, | |
e, | |
d; | |
if (c >= a) { | |
return a | |
} | |
if (Math.abs(f[c]) > c) { | |
return c | |
} | |
d = c - (c % SC.IndexSet.HINT_SIZE); | |
b = f[d]; | |
if (b < 0 || b > c) { | |
b = d | |
} | |
e = Math.abs(f[b]); | |
while (e < c) { | |
b = e; | |
e = Math.abs(f[b]) | |
} | |
return b | |
}, | |
isEqual: function(c) { | |
if (c === this) { | |
return YES | |
} | |
if (!c || !c.isIndexSet || (c.max !== this.max) || (c.length !== this.length)) { | |
return NO | |
} | |
var e = this._content, | |
b = c._content, | |
d = 0, | |
a = e[d]; | |
do { | |
if (b[d] !== a) { | |
return NO | |
} | |
d = Math.abs(a); | |
a = e[d] | |
} | |
while (d !== 0); | |
return YES | |
}, | |
indexBefore: function(b) { | |
if (b === 0) { | |
return - 1 | |
} | |
b--; | |
var c = this._content, | |
a = this.get("max"), | |
d = this.rangeStartForIndex(b); | |
if (!c) { | |
return null | |
} | |
while ((d === a) || (c[d] < 0)) { | |
if (d === 0) { | |
return - 1 | |
} | |
b = d - 1; | |
d = this.rangeStartForIndex(b) | |
} | |
return b | |
}, | |
indexAfter: function(b) { | |
var d = this._content, | |
a = this.get("max"), | |
e, | |
c; | |
if (!d || (b >= a)) { | |
return - 1 | |
} | |
b++; | |
e = this.rangeStartForIndex(b); | |
c = d[e]; | |
while (c < 0) { | |
if (c === 0) { | |
return - 1 | |
} | |
b = e = Math.abs(c); | |
c = d[e] | |
} | |
return b | |
}, | |
contains: function(g, c) { | |
var b, | |
f, | |
a, | |
e, | |
d; | |
if (c === undefined) { | |
if (g === null || g === undefined) { | |
return NO | |
} | |
if (typeof g === SC.T_NUMBER) { | |
c = 1 | |
} else { | |
if (g && g.isIndexSet) { | |
if (g === this) { | |
return YES | |
} | |
b = g._content; | |
f = 0; | |
a = b[f]; | |
while (a !== 0) { | |
if ((a > 0) && !this.contains(f, a - f)) { | |
return NO | |
} | |
f = Math.abs(a); | |
a = b[f] | |
} | |
return YES | |
} else { | |
c = g.length; | |
g = g.start | |
} | |
} | |
} | |
e = this.rangeStartForIndex(g); | |
d = this._content[e]; | |
return (d > 0) && (e <= g) && (d >= (g + c)) | |
}, | |
intersects: function(f, c) { | |
var b, | |
e, | |
a, | |
d; | |
if (c === undefined) { | |
if (typeof f === SC.T_NUMBER) { | |
c = 1 | |
} else { | |
if (f && f.isIndexSet) { | |
if (f === this) { | |
return YES | |
} | |
b = f._content; | |
e = 0; | |
a = b[e]; | |
while (a !== 0) { | |
if ((a > 0) && this.intersects(e, a - e)) { | |
return YES | |
} | |
e = Math.abs(a); | |
a = b[e] | |
} | |
return NO | |
} else { | |
c = f.length; | |
f = f.start | |
} | |
} | |
} | |
e = this.rangeStartForIndex(f); | |
b = this._content; | |
a = b[e]; | |
d = f + c; | |
while (e < d) { | |
if (a === 0) { | |
return NO | |
} | |
if ((a > 0) && (a > f)) { | |
return YES | |
} | |
e = Math.abs(a); | |
a = b[e] | |
} | |
return NO | |
}, | |
without: function(b, a) { | |
if (b === this) { | |
return SC.IndexSet.create() | |
} | |
return this.clone().remove(b, a) | |
}, | |
replace: function(c, a) { | |
if (a === undefined) { | |
if (typeof c === SC.T_NUMBER) { | |
a = 1 | |
} else { | |
if (c && c.isIndexSet) { | |
this._content = this._sc_sliceContent(c._content); | |
this.beginPropertyChanges().set("max", c.max).set("length", c.length).set("source", c.source).enumerableContentDidChange().endPropertyChanges(); | |
return this | |
} else { | |
a = c.length; | |
c = c.start | |
} | |
} | |
} | |
var b = this.length; | |
this._content.length = 1; | |
this._content[0] = 0; | |
this.length = this.max = 0; | |
return this.add(c, a) | |
}, | |
add: function(a, b) { | |
if (this.isFrozen) { | |
throw SC.FROZEN_ERROR | |
} | |
var e, | |
i, | |
d; | |
if (a && a.isIndexSet) { | |
e = a._content; | |
if (!e) { | |
return this | |
} | |
i = 0; | |
d = e[0]; | |
while (d !== 0) { | |
if (d > 0) { | |
this.add(i, d - i) | |
} | |
i = d < 0 ? 0 - d: d; | |
d = e[i] | |
} | |
return this | |
} else { | |
if (b === undefined) { | |
if (a === null || a === undefined) { | |
return this | |
} else { | |
if (typeof a === SC.T_NUMBER) { | |
b = 1 | |
} else { | |
b = a.length; | |
a = a.start | |
} | |
} | |
} else { | |
if (b === null) { | |
b = 1 | |
} | |
} | |
} | |
if (b <= 0) { | |
return this | |
} | |
var f = this.get("max"), | |
c = f, | |
h, | |
g; | |
e = this._content; | |
if (a === f) { | |
if (a > 0) { | |
i = this.rangeStartForIndex(a - 1); | |
d = e[i]; | |
if (d > 0) { | |
delete e[f]; | |
e[i] = f = a + b; | |
a = i | |
} else { | |
e[f] = f = a + b | |
} | |
} else { | |
e[a] = f = b | |
} | |
e[f] = 0; | |
this.set("max", f); | |
this.set("length", this.length + b); | |
b = f - a | |
} else { | |
if (a > f) { | |
e[f] = 0 - a; | |
e[a] = a + b; | |
e[a + b] = 0; | |
this.set("max", a + b); | |
this.set("length", this.length + b); | |
b = a + b - f; | |
a = f | |
} else { | |
i = this.rangeStartForIndex(a); | |
d = e[i]; | |
f = a + b; | |
h = 0; | |
if ((a > 0) && (i === a) && (d <= 0)) { | |
i = this.rangeStartForIndex(a - 1); | |
d = e[i] | |
} | |
if (d < 0) { | |
e[i] = 0 - a; | |
if (Math.abs(d) > f) { | |
e[a] = 0 - f; | |
e[f] = d | |
} else { | |
e[a] = d | |
} | |
} else { | |
a = i; | |
if (d > f) { | |
f = d | |
} | |
} | |
i = a; | |
while (i < f) { | |
g = e[i]; | |
if (g === 0) { | |
e[f] = 0; | |
d = f; | |
h += f - i | |
} else { | |
d = Math.abs(g); | |
if (d > f) { | |
e[f] = g; | |
d = f | |
} | |
if (g < 0) { | |
h += d - i | |
} | |
} | |
delete e[i]; | |
i = d | |
} | |
if ((i = e[f]) > 0) { | |
delete e[f]; | |
f = i | |
} | |
e[a] = f; | |
if (f > c) { | |
this.set("max", f) | |
} | |
this.set("length", this.get("length") + h); | |
b = f - a | |
} | |
} | |
this._hint(a, b); | |
if (h !== 0) { | |
this.enumerableContentDidChange() | |
} | |
return this | |
}, | |
remove: function(a, b) { | |
if (this.isFrozen) { | |
throw SC.FROZEN_ERROR | |
} | |
if (b === undefined) { | |
if (a === null || a === undefined) { | |
return this | |
} else { | |
if (typeof a === SC.T_NUMBER) { | |
b = 1 | |
} else { | |
if (a.isIndexSet) { | |
a.forEachRange(this.remove, this); | |
return this | |
} else { | |
b = a.length; | |
a = a.start | |
} | |
} | |
} | |
} | |
if (b <= 0) { | |
return this | |
} | |
var f = this.get("max"), | |
c = f, | |
e = this._content, | |
j, | |
d, | |
i, | |
g, | |
h; | |
if (a >= f) { | |
return this | |
} | |
j = this.rangeStartForIndex(a); | |
d = e[j]; | |
h = a + b; | |
i = 0; | |
if ((a > 0) && (j === a) && (d > 0)) { | |
j = this.rangeStartForIndex(a - 1); | |
d = e[j] | |
} | |
if (d > 0) { | |
e[j] = a; | |
if (d > h) { | |
e[a] = h; | |
e[h] = d | |
} else { | |
e[a] = d | |
} | |
} else { | |
a = j; | |
d = Math.abs(d); | |
if (d > h) { | |
h = d | |
} | |
} | |
j = a; | |
while (j < h) { | |
g = e[j]; | |
if (g === 0) { | |
e[h] = 0; | |
d = h | |
} else { | |
d = Math.abs(g); | |
if (d > h) { | |
e[h] = g; | |
d = h | |
} | |
if (g > 0) { | |
i += d - j | |
} | |
} | |
delete e[j]; | |
j = d | |
} | |
if ((j = e[h]) < 0) { | |
delete e[h]; | |
h = Math.abs(j) | |
} | |
if (e[h] === 0) { | |
delete e[h]; | |
e[a] = 0; | |
this.set("max", a) | |
} else { | |
e[a] = 0 - h | |
} | |
this.set("length", this.get("length") - i); | |
b = h - a; | |
this._hint(a, b); | |
if (i !== 0) { | |
this.enumerableContentDidChange() | |
} | |
return this | |
}, | |
_hint: function(g, d, c) { | |
if (c === undefined) { | |
c = this._content | |
} | |
var b = SC.IndexSet.HINT_SIZE, | |
a = Math.abs(c[g]), | |
f = g - (g % b) + b, | |
e = g + d; | |
while (f < e) { | |
while ((a !== 0) && (a <= f)) { | |
g = a; | |
a = Math.abs(c[g]) | |
} | |
if (a === 0) { | |
delete c[f] | |
} else { | |
if (f !== g) { | |
c[f] = g | |
} | |
} | |
f += b | |
} | |
}, | |
clear: function() { | |
if (this.isFrozen) { | |
throw SC.FROZEN_ERROR | |
} | |
var a = this.length; | |
this._content.length = 1; | |
this._content[0] = 0; | |
this.set("length", 0).set("max", 0); | |
if (a > 0) { | |
this.enumerableContentDidChange() | |
} | |
}, | |
addEach: function(b) { | |
if (this.isFrozen) { | |
throw SC.FROZEN_ERROR | |
} | |
this.beginPropertyChanges(); | |
var a = b.get("length"); | |
if (b.isSCArray) { | |
while (--a >= 0) { | |
this.add(b.objectAt(a)) | |
} | |
} else { | |
if (b.isEnumerable) { | |
b.forEach(function(c) { | |
this.add(c) | |
}, | |
this) | |
} | |
} | |
this.endPropertyChanges(); | |
return this | |
}, | |
removeEach: function(b) { | |
if (this.isFrozen) { | |
throw SC.FROZEN_ERROR | |
} | |
this.beginPropertyChanges(); | |
var a = b.get("length"); | |
if (b.isSCArray) { | |
while (--a >= 0) { | |
this.remove(b.objectAt(a)) | |
} | |
} else { | |
if (b.isEnumerable) { | |
b.forEach(function(c) { | |
this.remove(c) | |
}, | |
this) | |
} | |
} | |
this.endPropertyChanges(); | |
return this | |
}, | |
clone: function() { | |
return SC.IndexSet.create(this) | |
}, | |
inspect: function() { | |
var e = this._content, | |
b = e.length, | |
a = 0, | |
c = [], | |
d; | |
for (a = 0; a < b; a++) { | |
d = e[a]; | |
if (d !== undefined) { | |
c.push("%@:%@".fmt(a, d)) | |
} | |
} | |
return "SC.IndexSet<%@>".fmt(c.join(" , ")) | |
}, | |
forEachRange: function(f, d) { | |
var b = this._content, | |
e = 0, | |
a = b[e], | |
c = this.source; | |
if (d === undefined) { | |
d = null | |
} | |
while (a !== 0) { | |
if (a > 0) { | |
f.call(d, e, a - e, this, c) | |
} | |
e = Math.abs(a); | |
a = b[e] | |
} | |
return this | |
}, | |
forEachIn: function(b, c, j, f) { | |
var g = this._content, | |
i = 0, | |
h = 0, | |
d = b + c, | |
a = this.source, | |
e = g[i]; | |
if (f === undefined) { | |
f = null | |
} | |
while (e !== 0) { | |
if (i < b) { | |
i = b | |
} | |
while ((i < e) && (i < d)) { | |
j.call(f, i++, h++, this, a) | |
} | |
if (i >= d) { | |
i = e = 0 | |
} else { | |
i = Math.abs(e); | |
e = g[i] | |
} | |
} | |
return this | |
}, | |
lengthIn: function(g, d) { | |
var a = 0; | |
if (d === undefined) { | |
if (g === null || g === undefined) { | |
return 0 | |
} else { | |
if (typeof g === SC.T_NUMBER) { | |
d = 1 | |
} else { | |
if (g.isIndexSet) { | |
g.forEachRange(function(i, h) { | |
a += this.lengthIn(i, h) | |
}, | |
this); | |
return a | |
} else { | |
d = g.length; | |
g = g.start | |
} | |
} | |
} | |
} | |
if (this.get("length") === 0) { | |
return 0 | |
} | |
var c = this._content, | |
f = 0, | |
b = c[f], | |
e = g + d; | |
while (f < e && b !== 0) { | |
if (b > 0) { | |
a += (b > e) ? e - f: b - f | |
} | |
f = Math.abs(b); | |
b = c[f] | |
} | |
return a | |
}, | |
source: null, | |
indexOf: function(d, c) { | |
var f = this.source; | |
if (!f) { | |
throw "%@.indexOf() requires source".fmt(this) | |
} | |
var b = f.get("length"), | |
e = this._content, | |
g = e[0] < 0 ? Math.abs(e[0]) : 0, | |
a; | |
while (g >= 0 && g < b) { | |
a = f.indexOf(d, g); | |
if (a < 0) { | |
return - 1 | |
} | |
if (this.contains(a)) { | |
return a | |
} | |
g = a + 1 | |
} | |
return - 1 | |
}, | |
lastIndexOf: function(d, c) { | |
var e = this.source; | |
if (!e) { | |
throw "%@.lastIndexOf() requires source".fmt(this) | |
} | |
var b = e.get("length"), | |
f = this.max - 1, | |
a; | |
if (f >= b) { | |
f = b - 1 | |
} | |
while (f >= 0) { | |
a = e.lastIndexOf(d, f); | |
if (a < 0) { | |
return - 1 | |
} | |
if (this.contains(a)) { | |
return a | |
} | |
f = a + 1 | |
} | |
return - 1 | |
}, | |
forEachObject: function(g, e) { | |
var d = this.source; | |
if (!d) { | |
throw "%@.forEachObject() requires source".fmt(this) | |
} | |
var c = this._content, | |
f = 0, | |
a = 0, | |
b = c[f]; | |
if (e === undefined) { | |
e = null | |
} | |
while (b !== 0) { | |
while (f < b) { | |
g.call(e, d.objectAt(f), f, d, this); | |
f++ | |
} | |
f = Math.abs(b); | |
b = c[f] | |
} | |
return this | |
}, | |
addObject: function(c, d) { | |
var e = this.source; | |
if (!e) { | |
throw "%@.addObject() requires source".fmt(this) | |
} | |
var b = e.get("length"), | |
f = 0, | |
a; | |
while (f >= 0 && f < b) { | |
a = e.indexOf(c, f); | |
if (a >= 0) { | |
this.add(a); | |
if (d) { | |
return this | |
} | |
f = a++ | |
} else { | |
return this | |
} | |
} | |
return this | |
}, | |
addObjects: function(b, a) { | |
b.forEach(function(c) { | |
this.addObject(c, a) | |
}, | |
this); | |
return this | |
}, | |
removeObject: function(c, d) { | |
var e = this.source; | |
if (!e) { | |
throw "%@.removeObject() requires source".fmt(this) | |
} | |
var b = e.get("length"), | |
f = 0, | |
a; | |
while (f >= 0 && f < b) { | |
a = e.indexOf(c, f); | |
if (a >= 0) { | |
this.remove(a); | |
if (d) { | |
return this | |
} | |
f = a + 1 | |
} else { | |
return this | |
} | |
} | |
return this | |
}, | |
removeObjects: function(b, a) { | |
b.forEach(function(c) { | |
this.removeObject(c, a) | |
}, | |
this); | |
return this | |
}, | |
LOG_OBSERVING: NO, | |
forEach: function(g, e) { | |
var c = this._content, | |
f = 0, | |
a = 0, | |
d = this.source, | |
b = c[f]; | |
if (e === undefined) { | |
e = null | |
} | |
while (b !== 0) { | |
while (f < b) { | |
g.call(e, f++, a++, this, d) | |
} | |
f = Math.abs(b); | |
b = c[f] | |
} | |
return this | |
}, | |
nextObject: function(f, b, c) { | |
var e = this._content, | |
d = c.next, | |
a = this.get("max"); | |
if (b === null) { | |
b = d = 0 | |
} else { | |
if (b >= a) { | |
delete c.next; | |
return null | |
} else { | |
b++ | |
} | |
} | |
if (b === d) { | |
do { | |
b = Math.abs(d); | |
d = e[b] | |
} | |
while (d < 0); | |
c.next = d | |
} | |
return b | |
}, | |
toString: function() { | |
var a = []; | |
this.forEachRange(function(c, b) { | |
a.push(b === 1 ? c: "%@..%@".fmt(c, c + b - 1)) | |
}, | |
this); | |
return "SC.IndexSet<%@>".fmt(a.join(",")) | |
}, | |
max: 0 | |
}); | |
SC.IndexSet.slice = SC.IndexSet.copy = SC.IndexSet.clone; | |
SC.IndexSet.EMPTY = SC.IndexSet.create().freeze(); | |
SC.LOGGER_LOG_DELIMITER = ", "; | |
SC.LOGGER_LOG_ERROR = "ERROR: "; | |
SC.LOGGER_LOG_INFO = "INFO: "; | |
SC.LOGGER_LOG_WARN = "WARNING: "; | |
SC.Logger = SC.Object.create({ | |
exists: function() { | |
return typeof(this.get("reporter")) !== "undefined" && this.get("reporter") != null | |
}.property("reporter").cacheable(), | |
fallBackOnAlert: NO, | |
fallBackOnLog: YES, | |
format: YES, | |
reporter: SC.console, | |
log: function() { | |
var a = this.get("reporter"); | |
if (this.get("exists") && typeof(a.log) === "function") { | |
if (this.get("format")) { | |
a.log(this._argumentsToString.apply(this, arguments)) | |
} else { | |
a.log.apply(a, arguments) | |
} | |
return true | |
} else { | |
if (this.fallBackOnAlert) { | |
var b = this.get("format") ? this._argumentsToString.apply(this, arguments) : arguments; | |
if (this.get("exists") && typeof(a.alert) === "function") { | |
a.alert(b) | |
} else { | |
alert(b) | |
} | |
return true | |
} | |
} | |
return false | |
}, | |
dir: function() { | |
var a = this.get("reporter"); | |
if (this.get("exists") && typeof(a.dir) === "function") { | |
a.dir.apply(a, arguments); | |
return true | |
} | |
return (this.fallBackOnLog) ? this.log.apply(this, arguments) : false | |
}, | |
dirxml: function() { | |
var a = this.get("reporter"); | |
if (this.get("exists") && typeof(a.dirxml) === "function") { | |
a.dirxml.apply(a, arguments); | |
return true | |
} | |
return (this.fallBackOnLog) ? this.log.apply(this, arguments) : false | |
}, | |
error: function() { | |
var c = this.get("reporter"); | |
if (this.get("exists") && typeof(c.error) === "function") { | |
c.error.apply(c, arguments); | |
return true | |
} else { | |
if (this.fallBackOnLog) { | |
var b = this._argumentsToArray(arguments); | |
if (typeof(b.unshift) === "function") { | |
b.unshift(SC.LOGGER_LOG_ERROR) | |
} | |
return this.log.apply(this, b) | |
} | |
} | |
return false | |
}, | |
group: function(b) { | |
var a = this.get("reporter"); | |
if (this.get("exists") && typeof(a.group) === "function") { | |
a.group(b); | |
return true | |
} | |
return false | |
}, | |
groupEnd: function() { | |
var a = this.get("reporter"); | |
if (this.get("exists") && typeof(a.groupEnd) === "function") { | |
a.groupEnd(); | |
return true | |
} | |
return false | |
}, | |
info: function() { | |
var c = this.get("reporter"); | |
if (this.get("exists") && typeof(c.info) === "function") { | |
c.info.apply(c, arguments); | |
return true | |
} else { | |
if (this.fallBackOnLog) { | |
var b = this._argumentsToArray(arguments); | |
if (typeof(b.unshift) === "function") { | |
b.unshift(SC.LOGGER_LOG_INFO) | |
} | |
return this.log.apply(this, b) | |
} | |
} | |
return false | |
}, | |
profile: function() { | |
var a = this.get("reporter"); | |
if (this.get("exists") && typeof(a.profile) === "function") { | |
a.profile(); | |
return true | |
} | |
return false | |
}, | |
profileEnd: function() { | |
var a = this.get("reporter"); | |
if (this.get("exists") && typeof(a.profileEnd) === "function") { | |
a.profileEnd(); | |
return true | |
} | |
return false | |
}, | |
time: function(b) { | |
var a = this.get("reporter"); | |
if (this.get("exists") && typeof(a.time) === "function") { | |
a.time(b); | |
return true | |
} | |
return false | |
}, | |
timeEnd: function(b) { | |
var a = this.get("reporter"); | |
if (this.get("exists") && typeof(a.timeEnd) === "function") { | |
a.timeEnd(b); | |
return true | |
} | |
return false | |
}, | |
trace: function() { | |
var a = this.get("reporter"); | |
if (this.get("exists") && typeof(a.trace) === "function") { | |
a.trace(); | |
return true | |
} | |
return false | |
}, | |
warn: function() { | |
var c = this.get("reporter"); | |
if (this.get("exists") && typeof(c.warn) === "function") { | |
c.warn.apply(c, arguments); | |
return true | |
} else { | |
if (this.fallBackOnLog) { | |
var b = this._argumentsToArray(arguments); | |
if (typeof(b.unshift) === "function") { | |
b.unshift(SC.LOGGER_LOG_WARN) | |
} | |
return this.log.apply(this, b) | |
} | |
} | |
return false | |
}, | |
_argumentsToArray: function(d) { | |
if (!d) { | |
return [] | |
} | |
var b = []; | |
for (var c = 0; c < d.length; c++) { | |
b[c] = d[c] | |
} | |
return b | |
}, | |
_argumentsToString: function() { | |
var b = ""; | |
for (var a = 0; a < arguments.length - 1; a++) { | |
b += arguments[a] + SC.LOGGER_LOG_DELIMITER | |
} | |
b += arguments[arguments.length - 1]; | |
return b | |
} | |
}); | |
sc_require("private/observer_set"); | |
SC.RunLoop = SC.Object.extend({ | |
beginRunLoop: function() { | |
this._start = new Date().getTime(); | |
if (SC.LOG_BINDINGS || SC.LOG_OBSERVERS) { | |
console.log("-- SC.RunLoop.beginRunLoop at %@".fmt(this._start)) | |
} | |
return this | |
}, | |
endRunLoop: function() { | |
var a; | |
if (SC.LOG_BINDINGS || SC.LOG_OBSERVERS) { | |
console.log("-- SC.RunLoop.endRunLoop ~ flushing application queues") | |
} | |
do { | |
a = this.flushApplicationQueues(); | |
if (!a) { | |
a = this._flushinvokeLastQueue() | |
} | |
} | |
while (a); | |
this._start = null; | |
if (SC.LOG_BINDINGS || SC.LOG_OBSERVERS) { | |
console.log("-- SC.RunLoop.endRunLoop ~ End") | |
} | |
return this | |
}, | |
invokeOnce: function(a, b) { | |
if (b === undefined) { | |
b = a; | |
a = this | |
} | |
if (SC.typeOf(b) === SC.T_STRING) { | |
b = a[b] | |
} | |
if (!this._invokeQueue) { | |
this._invokeQueue = SC.ObserverSet.create() | |
} | |
this._invokeQueue.add(a, b); | |
return this | |
}, | |
invokeLast: function(a, b) { | |
if (b === undefined) { | |
b = a; | |
a = this | |
} | |
if (SC.typeOf(b) === SC.T_STRING) { | |
b = a[b] | |
} | |
if (!this._invokeLastQueue) { | |
this._invokeLastQueue = SC.ObserverSet.create() | |
} | |
this._invokeLastQueue.add(a, b); | |
return this | |
}, | |
flushApplicationQueues: function() { | |
var b = NO; | |
var a = this._invokeQueue; | |
if (a && a.targets > 0) { | |
this._invokeQueue = null; | |
b = YES; | |
a.invokeMethods() | |
} | |
return SC.Binding.flushPendingChanges() || b | |
}, | |
_flushinvokeLastQueue: function() { | |
var a = this._invokeLastQueue, | |
b = NO; | |
if (a && a.targets > 0) { | |
this._invokeLastQueue = null; | |
b = YES; | |
if (b) { | |
a.invokeMethods() | |
} | |
} | |
return b | |
} | |
}); | |
SC.RunLoop.currentRunLoop = null; | |
SC.RunLoop.runLoopClass = SC.RunLoop; | |
SC.RunLoop.begin = function() { | |
var a = this.currentRunLoop; | |
if (!a) { | |
a = this.currentRunLoop = this.runLoopClass.create() | |
} | |
a.beginRunLoop(); | |
return this | |
}; | |
SC.RunLoop.end = function() { | |
var a = this.currentRunLoop; | |
if (!a) { | |
throw "SC.RunLoop.end() called outside of a runloop!" | |
} | |
a.endRunLoop(); | |
return this | |
}; | |
SC.run = function(b, a) { | |
SC.RunLoop.begin(); | |
b.call(a); | |
SC.RunLoop.end() | |
}; | |
sc_require("system/object"); | |
sc_require("mixins/enumerable"); | |
sc_require("mixins/copyable"); | |
sc_require("mixins/freezable"); | |
SC.SelectionSet = SC.Object.extend(SC.Enumerable, SC.Freezable, SC.Copyable, { | |
isSelectionSet: YES, | |
length: function() { | |
var a = 0, | |
b = this._sets, | |
c = this._objects; | |
if (c) { | |
a += c.get("length") | |
} | |
if (b) { | |
b.forEach(function(d) { | |
a += d.get("length") | |
}) | |
} | |
return a | |
}.property().cacheable(), | |
sources: function() { | |
var c = [], | |
d = this._sets, | |
b = d ? d.length: 0, | |
a, | |
f, | |
e; | |
for (a = 0; a < b; a++) { | |
f = d[a]; | |
if (f && f.get("length") > 0 && f.source) { | |
c.push(f.source) | |
} | |
} | |
return c | |
}.property().cacheable(), | |
indexSetForSource: function(e) { | |
if (!e || !e.isSCArray) { | |
return null | |
} | |
var b = this._indexSetCache, | |
d = this._objects, | |
c, | |
a; | |
if (!b) { | |
b = this._indexSetCache = {} | |
} | |
c = b[SC.guidFor(e)]; | |
if (c && c._sourceRevision && (c._sourceRevision !== e.propertyRevision)) { | |
c = null | |
} | |
if (!c) { | |
c = this._indexSetForSource(e, NO); | |
if (c && c.get("length") === 0) { | |
c = null | |
} | |
if (d) { | |
if (c) { | |
c = c.copy() | |
} | |
d.forEach(function(f) { | |
if ((a = e.indexOf(f)) >= 0) { | |
if (!c) { | |
c = SC.IndexSet.create() | |
} | |
c.add(a) | |
} | |
}, | |
this) | |
} | |
if (c) { | |
c = b[SC.guidFor(e)] = c.frozenCopy(); | |
c._sourceRevision = e.propertyRevision | |
} | |
} | |
return c | |
}, | |
_indexSetForSource: function(f, g) { | |
if (g === undefined) { | |
g = YES | |
} | |
var d = SC.guidFor(f), | |
c = this[d], | |
e = this._sets, | |
a = e ? e.length: 0, | |
b = null; | |
if (c >= a) { | |
c = null | |
} | |
if (SC.none(c)) { | |
if (g && !this.isFrozen) { | |
this.propertyWillChange("sources"); | |
if (!e) { | |
e = this._sets = [] | |
} | |
b = e[a] = SC.IndexSet.create(); | |
b.source = f; | |
this[d] = a; | |
this.propertyDidChange("sources") | |
} | |
} else { | |
b = e ? e[c] : null | |
} | |
return b | |
}, | |
add: function(a, b, d) { | |
if (this.isFrozen) { | |
throw SC.FROZEN_ERROR | |
} | |
var g, | |
f, | |
j, | |
i, | |
c, | |
e, | |
h, | |
k; | |
if (b === undefined && d === undefined) { | |
if (!a) { | |
throw "Must pass params to SC.SelectionSet.add()" | |
} | |
if (a.isIndexSet) { | |
return this.add(a.source, a) | |
} | |
if (a.isSelectionSet) { | |
g = a._sets; | |
k = a._objects; | |
f = g ? g.length: 0; | |
this.beginPropertyChanges(); | |
for (j = 0; j < f; j++) { | |
i = g[j]; | |
if (i && i.get("length") > 0) { | |
this.add(i.source, i) | |
} | |
} | |
if (k) { | |
this.addObjects(k) | |
} | |
this.endPropertyChanges(); | |
return this | |
} | |
} | |
i = this._indexSetForSource(a, YES); | |
c = this.get("length"); | |
h = i.get("length"); | |
e = c - h; | |
i.add(b, d); | |
this._indexSetCache = null; | |
e += i.get("length"); | |
if (e !== c) { | |
this.propertyDidChange("length"); | |
this.enumerableContentDidChange(); | |
if (h === 0) { | |
this.notifyPropertyChange("sources") | |
} | |
} | |
return this | |
}, | |
remove: function(a, b, d) { | |
if (this.isFrozen) { | |
throw SC.FROZEN_ERROR | |
} | |
var g, | |
f, | |
j, | |
i, | |
c, | |
e, | |
h, | |
k; | |
if (b === undefined && d === undefined) { | |
if (!a) { | |
throw "Must pass params to SC.SelectionSet.remove()" | |
} | |
if (a.isIndexSet) { | |
return this.remove(a.source, a) | |
} | |
if (a.isSelectionSet) { | |
g = a._sets; | |
k = a._objects; | |
f = g ? g.length: 0; | |
this.beginPropertyChanges(); | |
for (j = 0; j < f; j++) { | |
i = g[j]; | |
if (i && i.get("length") > 0) { | |
this.remove(i.source, i) | |
} | |
} | |
if (k) { | |
this.removeObjects(k) | |
} | |
this.endPropertyChanges(); | |
return this | |
} | |
} | |
i = this._indexSetForSource(a, YES); | |
c = this.get("length"); | |
e = c - i.get("length"); | |
if (i && (k = this._objects)) { | |
if (d !== undefined) { | |
b = SC.IndexSet.create(b, d); | |
d = undefined | |
} | |
k.forEach(function(l) { | |
j = a.indexOf(l); | |
if (b.contains(j)) { | |
k.remove(l); | |
e-- | |
} | |
}, | |
this) | |
} | |
i.remove(b, d); | |
h = i.get("length"); | |
e += h; | |
this._indexSetCache = null; | |
if (e !== c) { | |
this.propertyDidChange("length"); | |
this.enumerableContentDidChange(); | |
if (h === 0) { | |
this.notifyPropertyChange("sources") | |
} | |
} | |
return this | |
}, | |
contains: function(b, d, a) { | |
if (d === undefined && a === undefined) { | |
return this.containsObject(b) | |
} | |
var c = this.indexSetForSource(b); | |
if (!c) { | |
return NO | |
} | |
return c.contains(d, a) | |
}, | |
intersects: function(b, d, a) { | |
var c = this.indexSetForSource(b, NO); | |
if (!c) { | |
return NO | |
} | |
return c.intersects(d, a) | |
}, | |
_TMP_ARY: [], | |
addObject: function(b) { | |
var c = this._TMP_ARY, | |
a; | |
c[0] = b; | |
a = this.addObjects(c); | |
c.length = 0; | |
return a | |
}, | |
addObjects: function(a) { | |
var d = this._objects, | |
b, | |
c; | |
if (!d) { | |
d = this._objects = SC.CoreSet.create() | |
} | |
b = d.get("length"); | |
d.addEach(a); | |
c = d.get("length"); | |
this._indexSetCache = null; | |
if (c !== b) { | |
this.propertyDidChange("length"); | |
this.enumerableContentDidChange() | |
} | |
return this | |
}, | |
removeObject: function(b) { | |
var c = this._TMP_ARY, | |
a; | |
c[0] = b; | |
a = this.removeObjects(c); | |
c.length = 0; | |
return a | |
}, | |
removeObjects: function(b) { | |
var e = this._objects, | |
c, | |
d, | |
a; | |
if (!e) { | |
return this | |
} | |
c = e.get("length"); | |
e.removeEach(b); | |
d = e.get("length"); | |
if (a = this._sets) { | |
a.forEach(function(f) { | |
c += f.get("length"); | |
f.removeObjects(b); | |
d += f.get("length") | |
}, | |
this) | |
} | |
this._indexSetCache = null; | |
if (d !== c) { | |
this.propertyDidChange("length"); | |
this.enumerableContentDidChange() | |
} | |
return this | |
}, | |
containsObject: function(c) { | |
var e = this._objects; | |
if (e && e.contains(c)) { | |
return YES | |
} | |
var d = this._sets, | |
b = d ? d.length: 0, | |
a, | |
f; | |
for (a = 0; a < b; a++) { | |
f = d[a]; | |
if (f && f.indexOf(c) >= 0) { | |
return YES | |
} | |
} | |
return NO | |
}, | |
constrain: function(d) { | |
var e, | |
b, | |
a, | |
c; | |
this.beginPropertyChanges(); | |
this.get("sources").forEach(function(f) { | |
if (f === d) { | |
return | |
} | |
var g = this._indexSetForSource(d, NO); | |
if (g) { | |
this.remove(d, g) | |
} | |
}, | |
this); | |
e = this._indexSetForSource(d, NO); | |
if (e && ((a = e.get("max")) > (b = d.get("length")))) { | |
this.remove(d, b, a - b) | |
} | |
if (c = this._objects) { | |
c.forEach(function(f) { | |
if (d.indexOf(f) < 0) { | |
this.removeObject(f) | |
} | |
}, | |
this) | |
} | |
this.endPropertyChanges(); | |
return this | |
}, | |
isEqual: function(g) { | |
var f, | |
d, | |
b, | |
a, | |
c, | |
e; | |
if (!g || !g.isSelectionSet) { | |
return NO | |
} | |
if (g === this) { | |
return YES | |
} | |
if ((this._sets === g._sets) && (this._objects === g._objects)) { | |
return YES | |
} | |
if (this.get("length") !== g.get("length")) { | |
return NO | |
} | |
f = this._objects; | |
d = g._objects; | |
if (f || d) { | |
if ((f ? f.get("length") : 0) !== (d ? d.get("length") : 0)) { | |
return NO | |
} | |
if (f && !f.isEqual(d)) { | |
return NO | |
} | |
} | |
c = this.get("sources"); | |
a = c.get("length"); | |
for (b = 0; b < a; b++) { | |
e = c.objectAt(b); | |
f = this._indexSetForSource(e, NO); | |
d = this._indexSetForSource(e, NO); | |
if ( !! d !== !!f) { | |
return NO | |
} | |
if (f && !f.isEqual(d)) { | |
return NO | |
} | |
} | |
return YES | |
}, | |
clear: function() { | |
if (this.isFrozen) { | |
throw SC.FROZEN_ERROR | |
} | |
if (this._sets) { | |
this._sets.length = 0 | |
} | |
if (this._objects) { | |
this._objects = null | |
} | |
this._indexSetCache = null; | |
this.propertyDidChange("length"); | |
this.enumerableContentDidChange(); | |
this.notifyPropertyChange("sources"); | |
return this | |
}, | |
copy: function() { | |
var c = this.constructor.create(), | |
d = this._sets, | |
b = d ? d.length: 0, | |
a, | |
e; | |
if (d && b > 0) { | |
d = c._sets = d.slice(); | |
for (a = 0; a < b; a++) { | |
if (! (e = d[a])) { | |
continue | |
} | |
e = d[a] = e.copy(); | |
c[SC.guidFor(e.source)] = a | |
} | |
} | |
if (this._objects) { | |
c._objects = this._objects.copy() | |
} | |
return c | |
}, | |
freeze: function() { | |
if (this.isFrozen) { | |
return this | |
} | |
var a = this._sets, | |
b = a ? a.length: 0, | |
c; | |
while (--b >= 0) { | |
if (c = a[b]) { | |
c.freeze() | |
} | |
} | |
if (this._objects) { | |
this._objects.freeze() | |
} | |
return arguments.callee.base.apply(this, arguments) | |
}, | |
toString: function() { | |
var a = this._sets || []; | |
a = a.map(function(b) { | |
return b.toString().replace("SC.IndexSet", SC.guidFor(b.source)) | |
}, | |
this); | |
if (this._objects) { | |
a.push(this._objects.toString()) | |
} | |
return "SC.SelectionSet:%@<%@>".fmt(SC.guidFor(this), a.join(",")) | |
}, | |
firstObject: function() { | |
var b = this._sets, | |
c = this._objects; | |
if (b && b.get("length") > 0) { | |
var e = b ? b[0] : null, | |
d = e ? e.source: null, | |
a = e ? e.firstObject() : -1; | |
if (d && a >= 0) { | |
return d.objectAt(a) | |
} | |
} | |
return c ? c.firstObject() : undefined | |
}.property(), | |
nextObject: function(c, e, b) { | |
var d, | |
a; | |
if (c === 0) { | |
d = b.objects = []; | |
this.forEach(function(f) { | |
d.push(f) | |
}, | |
this); | |
b.max = d.length | |
} | |
d = b.objects; | |
a = d[c]; | |
if (c + 1 >= b.max) { | |
b.objects = b.max = null | |
} | |
return a | |
}, | |
forEach: function(g, e) { | |
var c = this._sets, | |
d = this._objects, | |
b = c ? c.length: 0, | |
f, | |
a; | |
for (a = 0; a < b; a++) { | |
f = c[a]; | |
if (f) { | |
f.forEachObject(g, e) | |
} | |
} | |
if (d) { | |
d.forEach(g, e) | |
} | |
return this | |
} | |
}); | |
SC.SelectionSet.prototype.clone = SC.SelectionSet.prototype.copy; | |
SC.SelectionSet.EMPTY = SC.SelectionSet.create().freeze(); | |
sc_require("mixins/enumerable"); | |
sc_require("mixins/array"); | |
sc_require("mixins/observable"); | |
sc_require("mixins/delegate_support"); | |
SC.SparseArray = SC.Object.extend(SC.Observable, SC.Enumerable, SC.Array, SC.DelegateSupport, { | |
_requestingLength: 0, | |
_requestingIndex: 0, | |
length: function() { | |
var a = this.delegate; | |
if (a && SC.none(this._length) && a.sparseArrayDidRequestLength) { | |
this._requestingLength++; | |
a.sparseArrayDidRequestLength(this); | |
this._requestingLength-- | |
} | |
return this._length || 0 | |
}.property().cacheable(), | |
provideLength: function(a) { | |
if (SC.none(a)) { | |
this._sa_content = null | |
} | |
if (a !== this._length) { | |
this._length = a; | |
if (this._requestingLength <= 0) { | |
this.enumerableContentDidChange() | |
} | |
} | |
return this | |
}, | |
rangeWindowSize: 1, | |
requestedRangeIndex: [], | |
objectAt: function(a) { | |
var c = this._sa_content, | |
b; | |
if (!c) { | |
c = this._sa_content = [] | |
} | |
if ((b = c[a]) === undefined) { | |
this.requestIndex(a); | |
b = c[a] | |
} | |
return b | |
}, | |
definedIndexes: function(d) { | |
var c = SC.IndexSet.create(), | |
e = this._sa_content, | |
b, | |
a; | |
if (!e) { | |
return c.freeze() | |
} | |
if (d) { | |
d.forEach(function(f) { | |
if (e[f] !== undefined) { | |
c.add(f) | |
} | |
}) | |
} else { | |
a = e.length; | |
for (b = 0; b < a; b++) { | |
if (e[b] !== undefined) { | |
c.add(b) | |
} | |
} | |
} | |
return c.freeze() | |
}, | |
_TMP_RANGE: {}, | |
requestIndex: function(b) { | |
var c = this.delegate; | |
if (!c) { | |
return this | |
} | |
var a = this.get("rangeWindowSize"), | |
e = b; | |
if (a > 1) { | |
e = e - Math.floor(e % a) | |
} | |
if (a < 1) { | |
a = 1 | |
} | |
this._requestingIndex++; | |
if (c.sparseArrayDidRequestRange) { | |
var d = this._TMP_RANGE; | |
if (this.wasRangeRequested(e) === -1) { | |
d.start = e; | |
d.length = a; | |
c.sparseArrayDidRequestRange(this, d); | |
this.requestedRangeIndex.push(e) | |
} | |
} else { | |
if (c.sparseArrayDidRequestIndex) { | |
while (--a >= 0) { | |
c.sparseArrayDidRequestIndex(this, e + a) | |
} | |
} | |
} | |
this._requestingIndex--; | |
return this | |
}, | |
wasRangeRequested: function(c) { | |
var b, | |
a; | |
for (b = 0, a = this.requestedRangeIndex.length; | |
b < a; b++) { | |
if (this.requestedRangeIndex[b] === c) { | |
return b | |
} | |
} | |
return - 1 | |
}, | |
rangeRequestCompleted: function(b) { | |
var a = this.wasRangeRequested(b); | |
if (a >= 0) { | |
this.requestedRangeIndex.removeAt(a, 1); | |
return YES | |
} | |
return NO | |
}, | |
provideObjectsInRange: function(b, e) { | |
var c = this._sa_content; | |
if (!c) { | |
c = this._sa_content = [] | |
} | |
var d = b.start, | |
a = b.length; | |
while (--a >= 0) { | |
c[d + a] = e[a] | |
} | |
if (this._requestingIndex <= 0) { | |
this.enumerableContentDidChange() | |
} | |
return this | |
}, | |
_TMP_PROVIDE_ARRAY: [], | |
_TMP_PROVIDE_RANGE: { | |
length: 1 | |
}, | |
provideObjectAtIndex: function(c, b) { | |
var d = this._TMP_PROVIDE_ARRAY, | |
a = this._TMP_PROVIDE_RANGE; | |
d[0] = b; | |
a.start = c; | |
return this.provideObjectsInRange(a, d) | |
}, | |
objectsDidChangeInRange: function(a) { | |
var b = this._sa_content; | |
if (b) { | |
if (a.start === 0 && SC.maxRange(a) >= b.length) { | |
this._sa_content = null | |
} else { | |
var d = a.start, | |
c = Math.min(d + a.length, b.length); | |
while (--c >= d) { | |
b[c] = undefined | |
} | |
} | |
} | |
this.enumerableContentDidChange(a); | |
return this | |
}, | |
indexOf: function(c) { | |
var a = this.delegate; | |
if (a && a.sparseArrayDidRequestIndexOf) { | |
return a.sparseArrayDidRequestIndexOf(this, c) | |
} else { | |
var b = this._sa_content; | |
if (!b) { | |
b = this._sa_content = [] | |
} | |
return b.indexOf(c) | |
} | |
}, | |
replace: function(b, g, e) { | |
e = e || []; | |
var c = this.delegate; | |
if (c) { | |
if (!c.sparseArrayShouldReplace || !c.sparseArrayShouldReplace(this, b, g, e)) { | |
return this | |
} | |
} | |
var d = this._sa_content; | |
if (!d) { | |
d = this._sa_content = [] | |
} | |
d.replace(b, g, e); | |
var a = e ? (e.get ? e.get("length") : e.length) : 0; | |
var f = a - g; | |
if (!SC.none(this._length)) { | |
this.propertyWillChange("length"); | |
this._length += f; | |
this.propertyDidChange("length") | |
} | |
this.enumerableContentDidChange(b, g, f); | |
return this | |
}, | |
reset: function() { | |
this._sa_content = null; | |
this._length = null; | |
this.enumerableContentDidChange(); | |
this.invokeDelegateMethod(this.delegate, "sparseArrayDidReset", this); | |
return this | |
} | |
}); | |
SC.SparseArray.array = function(a) { | |
return this.create({ | |
_length: a || 0 | |
}) | |
}; | |
if ((typeof SC !== "undefined") && SC && SC.bundleDidLoad) { | |
SC.bundleDidLoad("sproutcore/runtime") | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment