Jforrester has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/155476

Change subject: Update OOjs to v1.0.12
......................................................................

Update OOjs to v1.0.12

Release notes:
 https://git.wikimedia.org/blob/oojs%2Fcore.git/v1.0.12/History.md

Change-Id: I5542d1cf5aad4d4fd78a04f6bea7a27cbabf055a
---
M .docs/eg-iframe.html
M build/modules.json
M demos/trigger/index.html
M demos/ve/desktop-dist.html
M demos/ve/desktop.html
M demos/ve/eventLogger.html
M demos/ve/eventSequencer.html
M demos/ve/mobile-dist.html
M demos/ve/mobile.html
R lib/oojs/oojs.jquery.js
M tests/index.html
11 files changed, 156 insertions(+), 149 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor 
refs/changes/76/155476/1

diff --git a/.docs/eg-iframe.html b/.docs/eg-iframe.html
index 449c622..99b6fe6 100644
--- a/.docs/eg-iframe.html
+++ b/.docs/eg-iframe.html
@@ -66,7 +66,7 @@
                <script src="../lib/jquery/jquery.js"></script>
 
                <!-- oojs -->
-               <script src="../lib/oojs/oojs.js"></script>
+               <script src="../lib/oojs/oojs.jquery.js"></script>
 
                <!-- oojs-ui -->
                <script src="../lib/oojs-ui/oojs-ui.js"></script>
diff --git a/build/modules.json b/build/modules.json
index 390b3fa..6fc2921 100644
--- a/build/modules.json
+++ b/build/modules.json
@@ -23,7 +23,7 @@
        },
        "oojs": {
                "scripts": [
-                       "lib/oojs/oojs.js"
+                       "lib/oojs/oojs.jquery.js"
                ]
        },
        "oojs-ui": {
diff --git a/demos/trigger/index.html b/demos/trigger/index.html
index 81c97d1..22bf238 100644
--- a/demos/trigger/index.html
+++ b/demos/trigger/index.html
@@ -97,7 +97,7 @@
                        </tr>
                </table>
                <script src="../../lib/jquery/jquery.js"></script>
-               <script src="../../lib/oojs/oojs.js"></script>
+               <script src="../../lib/oojs/oojs.jquery.js"></script>
                <script src="../../lib/unicodejs/unicodejs.js"></script>
                <script src="../../src/ve.js"></script>
                <script src="../../src/ui/ve.ui.js"></script>
diff --git a/demos/ve/desktop-dist.html b/demos/ve/desktop-dist.html
index aefe3b7..3a2e730 100644
--- a/demos/ve/desktop-dist.html
+++ b/demos/ve/desktop-dist.html
@@ -42,7 +42,7 @@
                <script src="../../lib/jquery/jquery.js"></script>
 
                <!-- oojs -->
-               <script src="../../lib/oojs/oojs.js"></script>
+               <script src="../../lib/oojs/oojs.jquery.js"></script>
 
                <!-- oojs-ui -->
                <script src="../../lib/oojs-ui/oojs-ui.js"></script>
diff --git a/demos/ve/desktop.html b/demos/ve/desktop.html
index 6bdeda6..7500f92 100644
--- a/demos/ve/desktop.html
+++ b/demos/ve/desktop.html
@@ -77,7 +77,7 @@
                <script src="../../lib/jquery/jquery.js"></script>
 
                <!-- oojs -->
-               <script src="../../lib/oojs/oojs.js"></script>
+               <script src="../../lib/oojs/oojs.jquery.js"></script>
 
                <!-- oojs-ui -->
                <script src="../../lib/oojs-ui/oojs-ui.js"></script>
diff --git a/demos/ve/eventLogger.html b/demos/ve/eventLogger.html
index f1dd46a..4e213b2 100644
--- a/demos/ve/eventLogger.html
+++ b/demos/ve/eventLogger.html
@@ -51,7 +51,7 @@
                <textarea id="ve-demo-log"></textarea>
 
                <script src="../../lib/jquery/jquery.js"></script>
-               <script src="../../lib/oojs/oojs.js"></script>
+               <script src="../../lib/oojs/oojs.jquery.js"></script>
                <script src="../../lib/rangy/rangy-core-1.3.js"></script>
                <script src="../../lib/rangy/rangy-position-1.3.js"></script>
                <script src="../../lib/unicodejs/unicodejs.js"></script>
diff --git a/demos/ve/eventSequencer.html b/demos/ve/eventSequencer.html
index 0c8eceb..607d593 100644
--- a/demos/ve/eventSequencer.html
+++ b/demos/ve/eventSequencer.html
@@ -9,7 +9,7 @@
                        }
                </style>
                <script src="../../lib/jquery/jquery.js"></script>
-               <script src="../../lib/oojs/oojs.js"></script>
+               <script src="../../lib/oojs/oojs.jquery.js"></script>
                <script src="../../lib/unicodejs/unicodejs.js"></script>
                <script src="../../src/ve.js"></script>
                <script src="../../src/ve.EventSequencer.js"></script>
diff --git a/demos/ve/mobile-dist.html b/demos/ve/mobile-dist.html
index 744c205..b4a4fba 100644
--- a/demos/ve/mobile-dist.html
+++ b/demos/ve/mobile-dist.html
@@ -42,7 +42,7 @@
                <script src="../../lib/jquery/jquery.js"></script>
 
                <!-- oojs -->
-               <script src="../../lib/oojs/oojs.js"></script>
+               <script src="../../lib/oojs/oojs.jquery.js"></script>
 
                <!-- oojs-ui -->
                <script src="../../lib/oojs-ui/oojs-ui.js"></script>
diff --git a/demos/ve/mobile.html b/demos/ve/mobile.html
index 1104f70..2f97a4a 100644
--- a/demos/ve/mobile.html
+++ b/demos/ve/mobile.html
@@ -78,7 +78,7 @@
                <script src="../../lib/jquery/jquery.js"></script>
 
                <!-- oojs -->
-               <script src="../../lib/oojs/oojs.js"></script>
+               <script src="../../lib/oojs/oojs.jquery.js"></script>
 
                <!-- oojs-ui -->
                <script src="../../lib/oojs-ui/oojs-ui.js"></script>
diff --git a/lib/oojs/oojs.js b/lib/oojs/oojs.jquery.js
similarity index 78%
rename from lib/oojs/oojs.js
rename to lib/oojs/oojs.jquery.js
index e684cb8..71f2f55 100644
--- a/lib/oojs/oojs.js
+++ b/lib/oojs/oojs.jquery.js
@@ -1,12 +1,12 @@
 /*!
- * OOjs v1.0.11
+ * OOjs v1.0.12 optimised for jQuery
  * https://www.mediawiki.org/wiki/OOjs
  *
  * Copyright 2011-2014 OOjs Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2014-07-23T20:15:47Z
+ * Date: 2014-08-20T22:33:41Z
  */
 ( function ( global ) {
 
@@ -222,8 +222,10 @@
  * the other. An asymmetrical test may also be performed, which checks only 
that properties in the
  * first object are present in the second object, but not the inverse.
  *
- * @param {Object} a First object to compare
- * @param {Object} b Second object to compare
+ * If either a or b is null or undefined it will be treated as an empty object.
+ *
+ * @param {Object|undefined} a First object to compare
+ * @param {Object|undefined} b Second object to compare
  * @param {boolean} [asymmetrical] Whether to check only that b contains 
values from a
  * @return {boolean} If the objects contain the same values as each other
  */
@@ -233,6 +235,9 @@
        if ( a === b ) {
                return true;
        }
+
+       a = a || {};
+       b = b || {};
 
        for ( k in a ) {
                if ( !hasOwn.call( a, k ) ) {
@@ -261,41 +266,46 @@
  * Copies are deep, and will either be an object or an array depending on 
`source`.
  *
  * @param {Object} source Object to copy
- * @param {Function} [callback] Applied to leaf values before they added to 
the clone
+ * @param {Function} [leafCallback] Applied to leaf values after they are 
cloned but before they are added to the clone
+ * @param {Function} [nodeCallback] Applied to all values before they are 
cloned.  If the nodeCallback returns a value other than undefined, the returned 
value is used instead of attempting to clone.
  * @return {Object} Copy of source object
  */
-oo.copy = function ( source, callback ) {
-       var key, sourceValue, sourceType, destination;
+oo.copy = function ( source, leafCallback, nodeCallback ) {
+       var key, destination;
 
-       if ( typeof source.clone === 'function' ) {
-               return source.clone();
-       }
-
-       destination = Array.isArray( source ) ? new Array( source.length ) : {};
-
-       for ( key in source ) {
-               sourceValue = source[key];
-               sourceType = typeof sourceValue;
-               if ( Array.isArray( sourceValue ) ) {
-                       // Array
-                       destination[key] = oo.copy( sourceValue, callback );
-               } else if ( sourceValue && typeof sourceValue.clone === 
'function' ) {
-                       // Duck type object with custom clone method
-                       destination[key] = callback ?
-                               callback( sourceValue.clone() ) : 
sourceValue.clone();
-               } else if ( sourceValue && typeof sourceValue.cloneNode === 
'function' ) {
-                       // DOM Node
-                       destination[key] = callback ?
-                               callback( sourceValue.cloneNode( true ) ) : 
sourceValue.cloneNode( true );
-               } else if ( oo.isPlainObject( sourceValue ) ) {
-                       // Plain objects
-                       destination[key] = oo.copy( sourceValue, callback );
-               } else {
-                       // Non-plain objects (incl. functions) and primitive 
values
-                       destination[key] = callback ? callback( sourceValue ) : 
sourceValue;
+       if ( nodeCallback ) {
+               // Extensibility: check before attempting to clone source.
+               destination = nodeCallback( source );
+               if ( destination !== undefined ) {
+                       return destination;
                }
        }
 
+       if ( Array.isArray( source ) ) {
+               // Array (fall through)
+               destination = new Array( source.length );
+       } else if ( source && typeof source.clone === 'function' ) {
+               // Duck type object with custom clone method
+               return leafCallback ? leafCallback( source.clone() ) : 
source.clone();
+       } else if ( source && typeof source.cloneNode === 'function' ) {
+               // DOM Node
+               return leafCallback ?
+                       leafCallback( source.cloneNode( true ) ) :
+                       source.cloneNode( true );
+       } else if ( oo.isPlainObject( source ) ) {
+               // Plain objects (fall through)
+               destination = {};
+       } else {
+               // Non-plain objects (incl. functions) and primitive values
+               return leafCallback ? leafCallback( source ) : source;
+       }
+
+       // source is an array or a plain object
+       for ( key in source ) {
+               destination[key] = oo.copy( source[key], leafCallback, 
nodeCallback );
+       }
+
+       // This is an internal node, so we don't apply the leafCallback.
        return destination;
 };
 
@@ -444,38 +454,9 @@
        return simpleArrayCombine( a, b, false );
 };
 
-/*global hasOwn, toString */
+/*global $ */
 
-/**
- * Assert whether a value is a plain object or not.
- *
- * @param {Mixed} obj
- * @return {boolean}
- */
-oo.isPlainObject = function ( obj ) {
-       /*jshint eqnull:true, eqeqeq:false */
-
-       // Any object or value whose internal [[Class]] property is not 
"[object Object]"
-       // Support IE8: Explicitly filter out DOM nodes
-       // Support IE8: Explicitly filter out Window object (needs loose 
comparison)
-       if ( !obj || toString.call( obj ) !== '[object Object]' || obj.nodeType 
|| ( obj != null && obj == obj.window ) ) {
-               return false;
-       }
-
-       // The try/catch suppresses exceptions thrown when attempting to access
-       // the "constructor" property of certain host objects suich as 
window.location
-       // in Firefox < 20 (https://bugzilla.mozilla.org/814622)
-       try {
-               if ( obj.constructor &&
-                               !hasOwn.call( obj.constructor.prototype, 
'isPrototypeOf' ) ) {
-                       return false;
-               }
-       } catch ( e ) {
-               return false;
-       }
-
-       return true;
-};
+oo.isPlainObject = $.isPlainObject;
 
 /*global hasOwn */
 
@@ -495,29 +476,28 @@
        this.bindings = {};
 };
 
+oo.initClass( oo.EventEmitter );
+
 /* Methods */
 
 /**
  * Add a listener to events of a specific event.
  *
+ * The listener can be a function or the string name of a method; if the 
latter, then the
+ * name lookup happens at the time the listener is called.
+ *
  * @param {string} event Type of event to listen to
- * @param {Function} callback Function to call when event occurs
+ * @param {Function|string} method Function or method name to call when event 
occurs
  * @param {Array} [args] Arguments to pass to listener, will be prepended to 
emitted arguments
- * @param {Object} [context=null] Object to use as context for callback 
function or call method on
- * @throws {Error} Listener argument is not a function or method name
+ * @param {Object} [context=null] Context object for function or method call
+ * @throws {Error} Listener argument is not a function or a valid method name
  * @chainable
  */
-oo.EventEmitter.prototype.on = function ( event, callback, args, context ) {
+oo.EventEmitter.prototype.on = function ( event, method, args, context ) {
        var bindings;
 
-       // Validate callback
-       if ( typeof callback !== 'function' ) {
-               throw new Error( 'Invalid callback. Function or method name 
expected.' );
-       }
-       // Fallback to null context
-       if ( arguments.length < 4 ) {
-               context = null;
-       }
+       this.constructor.static.validateMethod( method, context );
+
        if ( hasOwn.call( this.bindings, event ) ) {
                bindings = this.bindings[event];
        } else {
@@ -526,9 +506,9 @@
        }
        // Add binding
        bindings.push( {
-               callback: callback,
+               method: method,
                args: args,
-               context: context
+               context: ( arguments.length < 4 ) ? null : context
        } );
        return this;
 };
@@ -553,41 +533,45 @@
  * Remove a specific listener from a specific event.
  *
  * @param {string} event Type of event to remove listener from
- * @param {Function} [callback] Listener to remove, omit to remove all
- * @param {Object} [context=null] Object used context for callback function or 
method
+ * @param {Function|string} [method] Listener to remove. Must be in the same 
form as was passed
+ * to "on". Omit to remove all listeners.
+ * @param {Object} [context=null] Context object function or method call
  * @chainable
- * @throws {Error} Listener argument is not a function
+ * @throws {Error} Listener argument is not a function or a valid method name
  */
-oo.EventEmitter.prototype.off = function ( event, callback, context ) {
+oo.EventEmitter.prototype.off = function ( event, method, context ) {
        var i, bindings;
 
        if ( arguments.length === 1 ) {
                // Remove all bindings for event
                delete this.bindings[event];
-       } else {
-               if ( typeof callback !== 'function' ) {
-                       throw new Error( 'Invalid callback. Function expected.' 
);
+               return this;
+       }
+
+       this.constructor.static.validateMethod( method, context );
+
+       if ( !( event in this.bindings ) || !this.bindings[event].length ) {
+               // No matching bindings
+               return this;
+       }
+
+       // Default to null context
+       if ( arguments.length < 3 ) {
+               context = null;
+       }
+
+       // Remove matching handlers
+       bindings = this.bindings[event];
+       i = bindings.length;
+       while ( i-- ) {
+               if ( bindings[i].method === method && bindings[i].context === 
context ) {
+                       bindings.splice( i, 1 );
                }
-               if ( !( event in this.bindings ) || 
!this.bindings[event].length ) {
-                       // No matching bindings
-                       return this;
-               }
-               // Fallback to null context
-               if ( arguments.length < 3 ) {
-                       context = null;
-               }
-               // Remove matching handlers
-               bindings = this.bindings[event];
-               i = bindings.length;
-               while ( i-- ) {
-                       if ( bindings[i].callback === callback && 
bindings[i].context === context ) {
-                               bindings.splice( i, 1 );
-                       }
-               }
-               // Cleanup if now empty
-               if ( bindings.length === 0 ) {
-                       delete this.bindings[event];
-               }
+       }
+
+       // Cleanup if now empty
+       if ( bindings.length === 0 ) {
+               delete this.bindings[event];
        }
        return this;
 };
@@ -603,7 +587,7 @@
  * @return {boolean} If event was handled by at least one listener
  */
 oo.EventEmitter.prototype.emit = function ( event ) {
-       var i, len, binding, bindings, args;
+       var i, len, binding, bindings, args, method;
 
        if ( event in this.bindings ) {
                // Slicing ensures that we don't get tripped up by event 
handlers that add/remove bindings
@@ -611,7 +595,13 @@
                args = Array.prototype.slice.call( arguments, 1 );
                for ( i = 0, len = bindings.length; i < len; i++ ) {
                        binding = bindings[i];
-                       binding.callback.apply(
+                       if ( typeof binding.method === 'string' ) {
+                               // Lookup method by name (late binding)
+                               method = binding.context[ binding.method ];
+                       } else {
+                               method = binding.method;
+                       }
+                       method.apply(
                                binding.context,
                                binding.args ? binding.args.concat( args ) : 
args
                        );
@@ -632,7 +622,7 @@
  * @chainable
  */
 oo.EventEmitter.prototype.connect = function ( context, methods ) {
-       var method, callback, args, event;
+       var method, args, event;
 
        for ( event in methods ) {
                method = methods[event];
@@ -643,19 +633,8 @@
                } else {
                        args = [];
                }
-               // Allow callback to be a method name
-               if ( typeof method === 'string' ) {
-                       // Validate method
-                       if ( !context[method] || typeof context[method] !== 
'function' ) {
-                               throw new Error( 'Method not found: ' + method 
);
-                       }
-                       // Resolve to function
-                       callback = context[method];
-               } else {
-                       callback = method;
-               }
                // Add binding
-               this.on.apply( this, [ event, callback, args, context ] );
+               this.on( event, method, args, context );
        }
        return this;
 };
@@ -665,27 +644,17 @@
  *
  * @param {Object} context Object to disconnect methods from
  * @param 
{Object.<string,string>|Object.<string,Function>|Object.<string,Array>} 
[methods] List of
- * event bindings keyed by event name containing either method names or 
functions
+ * event bindings keyed by event name. Values can be either method names or 
functions, but must be
+ * consistent with those used in the corresponding call to "connect".
  * @chainable
  */
 oo.EventEmitter.prototype.disconnect = function ( context, methods ) {
-       var i, method, callback, event, bindings;
+       var i, event, bindings;
 
        if ( methods ) {
                // Remove specific connections to the context
                for ( event in methods ) {
-                       method = methods[event];
-                       if ( typeof method === 'string' ) {
-                               // Validate method
-                               if ( !context[method] || typeof context[method] 
!== 'function' ) {
-                                       throw new Error( 'Method not found: ' + 
method );
-                               }
-                               // Resolve to function
-                               callback = context[method];
-                       } else {
-                               callback = method;
-                       }
-                       this.off( event, callback, context );
+                       this.off( event, methods[event], context );
                }
        } else {
                // Remove all connections to the context
@@ -696,7 +665,7 @@
                                // bindings[i] may have been removed by the 
previous step's
                                // this.off so check it still exists
                                if ( bindings[i] && bindings[i].context === 
context ) {
-                                       this.off( event, bindings[i].callback, 
context );
+                                       this.off( event, bindings[i].method, 
context );
                                }
                        }
                }
@@ -704,6 +673,42 @@
 
        return this;
 };
+
+/**
+ * Validate a function or method call in a context
+ *
+ * For a method name, check that it names a function in the context object
+ *
+ * @static
+ * @param {Function|string} method Function or method name
+ * @param {Mixed} context The context of the call
+ * @throws {Error} A method name is given but there is no context
+ * @throws {Error} In the context object, no property exists with the given 
name
+ * @throws {Error} In the context object, the named property is not a function
+ */
+oo.EventEmitter.static.validateMethod = function ( method, context ) {
+       // Validate method and context
+       if ( typeof method === 'string' ) {
+               // Validate method
+               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.
+                       throw new Error( 'Property "' + method + '" is not a 
function' );
+               }
+       } else if ( typeof method !== 'function' ) {
+               throw new Error( 'Invalid callback. Function or method name 
expected.' );
+       }
+};
+
+/*global hasOwn */
 
 /**
  * @class OO.Registry
@@ -766,7 +771,9 @@
  * @return {Mixed|undefined} Data associated with symbolic name
  */
 oo.Registry.prototype.lookup = function ( name ) {
-       return this.registry[name];
+       if ( hasOwn.call( this.registry, name ) ) {
+               return this.registry[name];
+       }
 };
 
 /**
@@ -831,12 +838,12 @@
  * @throws {Error} Unknown object name
  */
 oo.Factory.prototype.create = function ( name ) {
-       var args, obj, constructor;
+       var args, obj,
+               constructor = this.lookup( name );
 
-       if ( !this.registry.hasOwnProperty( name ) ) {
+       if ( !constructor ) {
                throw new Error( 'No class registered by that name: ' + name );
        }
-       constructor = this.registry[name];
 
        // Convert arguments to array and shift the first argument (name) off
        args = Array.prototype.slice.call( arguments, 1 );
diff --git a/tests/index.html b/tests/index.html
index 3af3dbe..01c0114 100644
--- a/tests/index.html
+++ b/tests/index.html
@@ -26,7 +26,7 @@
                <script src="../lib/jquery/jquery.js"></script>
 
                <!-- oojs -->
-               <script src="../lib/oojs/oojs.js"></script>
+               <script src="../lib/oojs/oojs.jquery.js"></script>
 
                <!-- oojs-ui -->
                <script src="../lib/oojs-ui/oojs-ui.js"></script>

-- 
To view, visit https://gerrit.wikimedia.org/r/155476
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I5542d1cf5aad4d4fd78a04f6bea7a27cbabf055a
Gerrit-PatchSet: 1
Gerrit-Project: VisualEditor/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Jforrester <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to