summaryrefslogtreecommitdiff
path: root/resources/lib/oojs/oojs.jquery.js
diff options
context:
space:
mode:
Diffstat (limited to 'resources/lib/oojs/oojs.jquery.js')
-rw-r--r--resources/lib/oojs/oojs.jquery.js126
1 files changed, 104 insertions, 22 deletions
diff --git a/resources/lib/oojs/oojs.jquery.js b/resources/lib/oojs/oojs.jquery.js
index c62df221..18dc5649 100644
--- a/resources/lib/oojs/oojs.jquery.js
+++ b/resources/lib/oojs/oojs.jquery.js
@@ -1,12 +1,12 @@
/*!
- * OOjs v1.1.1 optimised for jQuery
+ * OOjs v1.1.6 optimised for jQuery
* https://www.mediawiki.org/wiki/OOjs
*
- * Copyright 2011-2014 OOjs Team and other contributors.
+ * Copyright 2011-2015 OOjs Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2014-09-11T00:40:09Z
+ * Date: 2015-03-19T00:42:55Z
*/
( function ( global ) {
@@ -20,6 +20,7 @@ var
* @singleton
*/
oo = {},
+ // Optimisation: Local reference to Object.prototype.hasOwnProperty
hasOwn = oo.hasOwnProperty,
toString = oo.toString;
@@ -159,6 +160,64 @@ oo.mixinClass = function ( targetFn, originFn ) {
/* Object Methods */
/**
+ * Get a deeply nested property of an object using variadic arguments, protecting against
+ * undefined property errors.
+ *
+ * `quux = oo.getProp( obj, 'foo', 'bar', 'baz' );` is equivalent to `quux = obj.foo.bar.baz;`
+ * except that the former protects against JS errors if one of the intermediate properties
+ * is undefined. Instead of throwing an error, this function will return undefined in
+ * that case.
+ *
+ * @param {Object} obj
+ * @param {Mixed...} [keys]
+ * @return obj[arguments[1]][arguments[2]].... or undefined
+ */
+oo.getProp = function ( obj ) {
+ var i,
+ retval = obj;
+ for ( i = 1; i < arguments.length; i++ ) {
+ if ( retval === undefined || retval === null ) {
+ // Trying to access a property of undefined or null causes an error
+ return undefined;
+ }
+ retval = retval[arguments[i]];
+ }
+ return retval;
+};
+
+/**
+ * Set a deeply nested property of an object using variadic arguments, protecting against
+ * undefined property errors.
+ *
+ * `oo.setProp( obj, 'foo', 'bar', 'baz' );` is equivalent to `obj.foo.bar = baz;` except that
+ * the former protects against JS errors if one of the intermediate properties is
+ * undefined. Instead of throwing an error, undefined intermediate properties will be
+ * initialized to an empty object. If an intermediate property is not an object, or if obj itself
+ * is not an object, this function will silently abort.
+ *
+ * @param {Object} obj
+ * @param {Mixed...} [keys]
+ * @param {Mixed} [value]
+ */
+oo.setProp = function ( obj ) {
+ var i,
+ prop = obj;
+ if ( Object( obj ) !== obj ) {
+ return;
+ }
+ for ( i = 1; i < arguments.length - 2; i++ ) {
+ if ( prop[arguments[i]] === undefined ) {
+ prop[arguments[i]] = {};
+ }
+ if ( Object( prop[arguments[i]] ) !== prop[arguments[i]] ) {
+ return;
+ }
+ prop = prop[arguments[i]];
+ }
+ prop[arguments[arguments.length - 2]] = arguments[arguments.length - 1];
+};
+
+/**
* Create a new object that is an instance of the same
* constructor as the input, inherits from the same object
* and contains the same own properties.
@@ -228,7 +287,8 @@ oo.getObjectValues = function ( obj ) {
*
* @param {Object|undefined|null} a First object to compare
* @param {Object|undefined|null} b Second object to compare
- * @param {boolean} [asymmetrical] Whether to check only that b contains values from a
+ * @param {boolean} [asymmetrical] Whether to check only that a's values are equal to b's
+ * (i.e. a is a subset of b)
* @return {boolean} If the objects contain the same values as each other
*/
oo.compare = function ( a, b, asymmetrical ) {
@@ -241,10 +301,16 @@ oo.compare = function ( a, b, asymmetrical ) {
a = a || {};
b = b || {};
+ if ( typeof a.nodeType === 'number' && typeof a.isEqualNode === 'function' ) {
+ return a.isEqualNode( b );
+ }
+
for ( k in a ) {
- if ( !hasOwn.call( a, k ) ) {
- // Support es3-shim: Without this filter, comparing [] to {} will be false in ES3
+ if ( !hasOwn.call( a, k ) || a[k] === undefined || a[k] === b[k] ) {
+ // Support es3-shim: Without the hasOwn filter, comparing [] to {} will be false in ES3
// because the shimmed "forEach" is enumerable and shows up in Array but not Object.
+ // Also ignore undefined values, because there is no conceptual difference between
+ // a key that is absent and a key that is present but whose value is undefined.
continue;
}
@@ -257,7 +323,7 @@ oo.compare = function ( a, b, asymmetrical ) {
( aType === 'string' || aType === 'number' || aType === 'boolean' ) &&
aValue !== bValue
) ||
- ( aValue === Object( aValue ) && !oo.compare( aValue, bValue, asymmetrical ) ) ) {
+ ( aValue === Object( aValue ) && !oo.compare( aValue, bValue, true ) ) ) {
return false;
}
}
@@ -370,6 +436,21 @@ oo.getHash.keySortReplacer = function ( key, val ) {
};
/**
+ * Get the unique values of an array, removing duplicates
+ *
+ * @param {Array} arr Array
+ * @return {Array} Unique values in array
+ */
+oo.unique = function ( arr ) {
+ return arr.reduce( function ( result, current ) {
+ if ( result.indexOf( current ) === -1 ) {
+ result.push( current );
+ }
+ return result;
+ }, [] );
+};
+
+/**
* Compute the union (duplicate-free merge) of a set of arrays.
*
* Arrays values must be convertable to object keys (strings).
@@ -506,11 +587,6 @@ oo.isPlainObject = $.isPlainObject;
if ( context === undefined || context === null ) {
throw new Error( 'Method name "' + method + '" has no context.' );
}
- if ( !( method in context ) ) {
- // Technically the method does not need to exist yet: it could be
- // added before call time. But this probably signals a typo.
- throw new Error( 'Method not found: "' + method + '"' );
- }
if ( typeof context[method] !== 'function' ) {
// Technically the property could be replaced by a function before
// call time. But this probably signals a typo.
@@ -565,11 +641,11 @@ oo.isPlainObject = $.isPlainObject;
*/
oo.EventEmitter.prototype.once = function ( event, listener ) {
var eventEmitter = this,
- listenerWrapper = function () {
- eventEmitter.off( event, listenerWrapper );
- listener.apply( eventEmitter, Array.prototype.slice.call( arguments, 0 ) );
+ wrapper = function () {
+ eventEmitter.off( event, wrapper );
+ return listener.apply( this, arguments );
};
- return this.on( event, listenerWrapper );
+ return this.on( event, wrapper );
};
/**
@@ -593,7 +669,7 @@ oo.isPlainObject = $.isPlainObject;
validateMethod( method, context );
- if ( !( event in this.bindings ) || !this.bindings[event].length ) {
+ if ( !hasOwn.call( this.bindings, event ) || !this.bindings[event].length ) {
// No matching bindings
return this;
}
@@ -630,12 +706,15 @@ oo.isPlainObject = $.isPlainObject;
* @return {boolean} If event was handled by at least one listener
*/
oo.EventEmitter.prototype.emit = function ( event ) {
- var i, len, binding, bindings, args, method;
+ var args = [],
+ i, len, binding, bindings, method;
- if ( event in this.bindings ) {
+ if ( hasOwn.call( this.bindings, event ) ) {
// Slicing ensures that we don't get tripped up by event handlers that add/remove bindings
bindings = this.bindings[event].slice();
- args = Array.prototype.slice.call( arguments, 1 );
+ for ( i = 1, len = arguments.length; i < len; i++ ) {
+ args.push( arguments[i] );
+ }
for ( i = 0, len = bindings.length; i < len; i++ ) {
binding = bindings[i];
if ( typeof binding.method === 'string' ) {
@@ -849,7 +928,8 @@ oo.Factory.prototype.register = function ( constructor ) {
* @throws {Error} Unknown object name
*/
oo.Factory.prototype.create = function ( name ) {
- var args, obj,
+ var obj, i,
+ args = [],
constructor = this.lookup( name );
if ( !constructor ) {
@@ -857,7 +937,9 @@ oo.Factory.prototype.create = function ( name ) {
}
// Convert arguments to array and shift the first argument (name) off
- args = Array.prototype.slice.call( arguments, 1 );
+ for ( i = 1; i < arguments.length; i++ ) {
+ args.push( arguments[i] );
+ }
// We can't use the "new" operator with .apply directly because apply needs a
// context. So instead just do what "new" does: create an object that inherits from