jenkins-bot has submitted this change and it was merged.

Change subject: Introduce Class
......................................................................


Introduce Class

Make our inheritance model more consistent. This is mostly copy and
paste + making sure that child classes call parent's constructor.

Change-Id: Ifd38f20ab08cbb311adfef5c53e6707cf1789410
---
M includes/Resources.php
R javascripts/common/Class.js
M javascripts/common/Overlay.js
M javascripts/common/eventemitter.js
M javascripts/common/mf-api.js
M javascripts/common/mf-view.js
M javascripts/common/uploads/PhotoUploader.js
M javascripts/common/uploads/PhotoUploaderPreview.js
M javascripts/modules/editor/EditorOverlay.js
M javascripts/specials/overlays/CarouselOverlay.js
M javascripts/specials/uploads.js
M javascripts/views/page.js
A tests/javascripts/common/test_Class.js
D tests/javascripts/common/test_mf-oop.js
14 files changed, 329 insertions(+), 321 deletions(-)

Approvals:
  Jdlrobson: Verified; Looks good to me, approved
  jenkins-bot: Verified



diff --git a/includes/Resources.php b/includes/Resources.php
index 32c093e..b21e598 100644
--- a/includes/Resources.php
+++ b/includes/Resources.php
@@ -158,6 +158,7 @@
                ),
                'scripts' => array(
                        'javascripts/externals/hogan.js',
+                       'javascripts/common/Class.js',
                        'javascripts/common/eventemitter.js',
                        'javascripts/common/Router.js',
                        'javascripts/common/mf-application.js',
@@ -396,7 +397,6 @@
                        'mediawiki.jqueryMsg',
                ),
                'scripts' => array(
-                       'javascripts/common/mf-oop.js',
                        'javascripts/common/mf-api.js',
                        'javascripts/common/mf-view.js',
                        'javascripts/common/Drawer.js',
diff --git a/javascripts/common/mf-oop.js b/javascripts/common/Class.js
similarity index 87%
rename from javascripts/common/mf-oop.js
rename to javascripts/common/Class.js
index d3c3bb7..cc5e604 100644
--- a/javascripts/common/mf-oop.js
+++ b/javascripts/common/Class.js
@@ -40,8 +40,12 @@
                return Child;
        }
 
-       M.define( 'oop', {
-               extend: extend
-       } );
+       function Class() {
+               this.initialize.apply( this, arguments );
+       }
+       Class.prototype.initialize = function() {};
+       Class.extend = extend;
+
+       M.define( 'Class', Class );
 
 }( mw.mobileFrontend ) );
diff --git a/javascripts/common/Overlay.js b/javascripts/common/Overlay.js
index c076ded..808261b 100644
--- a/javascripts/common/Overlay.js
+++ b/javascripts/common/Overlay.js
@@ -12,7 +12,7 @@
                closeOnBack: false,
                initialize: function( options ) {
                        var self = this;
-                       this._super( options );
+                       options = options || {};
                        this.parent = options.parent;
                        this.isOpened = false;
 
@@ -28,6 +28,8 @@
                        if ( this.closeOnBack ) {
                                hideOnRoute();
                        }
+
+                       this._super( options );
                },
                postRender: function() {
                        var self = this;
diff --git a/javascripts/common/eventemitter.js 
b/javascripts/common/eventemitter.js
index 33226b6..4a6afd7 100644
--- a/javascripts/common/eventemitter.js
+++ b/javascripts/common/eventemitter.js
@@ -1,5 +1,7 @@
 ( function( M, $ ) {
 
+       var Class = M.require( 'Class' ), EventEmitter;
+
        function callbackProxy( callback ) {
                return function() {
                        var args = Array.prototype.slice.call( arguments, 1 );
@@ -7,44 +9,44 @@
                };
        }
 
-       function EventEmitter() {}
+       EventEmitter = Class.extend( {
+               /**
+                * Bind a callback to the event.
+                *
+                * @param {string} event Event name.
+                * @param {Function} callback Callback to be bound.
+                */
+               on: function( event, callback ) {
+                       $( this ).on( event, callbackProxy( callback ) );
+                       return this;
+               },
 
-       /**
-        * Bind a callback to the event.
-        *
-        * @param {string} event Event name.
-        * @param {Function} callback Callback to be bound.
-        */
-       EventEmitter.prototype.on = function( event, callback ) {
-               $( this ).on( event, callbackProxy( callback ) );
-               return this;
-       };
+               /**
+                * Bind a callback to the event and run it only once.
+                *
+                * @param {string} event Event name.
+                * @param {Function} callback Callback to be bound.
+                */
+               one: function( event, callback ) {
+                       $( this ).one( event, callbackProxy( callback ) );
+                       return this;
+               },
 
-       /**
-        * Bind a callback to the event and run it only once.
-        *
-        * @param {string} event Event name.
-        * @param {Function} callback Callback to be bound.
-        */
-       EventEmitter.prototype.one = function( event, callback ) {
-               $( this ).one( event, callbackProxy( callback ) );
-               return this;
-       };
-
-       /**
-        * Emit an event. This causes all bound callbacks to be run.
-        *
-        * @param {string} event Event name.
-        * @param {*} [arguments] Optional arguments to be passed to callbacks.
-        */
-       EventEmitter.prototype.emit = function( event /* , arg1, arg2, ... */ ) 
{
-               var args = Array.prototype.slice.call( arguments, 1 );
-               // use .triggerHandler() for emitting events to avoid 
accidentally
-               // invoking object's functions, e.g. don't call obj.something() 
when
-               // doing obj.emit( 'something' )
-               $( this ).triggerHandler( event, args );
-               return this;
-       };
+               /**
+                * Emit an event. This causes all bound callbacks to be run.
+                *
+                * @param {string} event Event name.
+                * @param {*} [arguments] Optional arguments to be passed to 
callbacks.
+                */
+               emit: function( event /* , arg1, arg2, ... */ ) {
+                       var args = Array.prototype.slice.call( arguments, 1 );
+                       // use .triggerHandler() for emitting events to avoid 
accidentally
+                       // invoking object's functions, e.g. don't call 
obj.something() when
+                       // doing obj.emit( 'something' )
+                       $( this ).triggerHandler( event, args );
+                       return this;
+               }
+       } );
 
        M.define( 'eventemitter', EventEmitter );
 
diff --git a/javascripts/common/mf-api.js b/javascripts/common/mf-api.js
index 2c255c8..2d885c6 100644
--- a/javascripts/common/mf-api.js
+++ b/javascripts/common/mf-api.js
@@ -1,8 +1,7 @@
 ( function( M, $ ) {
 
-       var oop = M.require( 'oop' ),
-               EventEmitter = M.require( 'eventemitter' ),
-               api;
+       var EventEmitter = M.require( 'eventemitter' ),
+               Api, api;
 
        // TODO: this might be dangerous and cause conflicts with other code
        // should we move it to Api#ajax?
@@ -14,153 +13,148 @@
                }
        } );
 
-       function Api( options ) {
-               this.requests = [];
-               this.tokenCache = {};
-               this.initialize( options );
-       }
+       Api = EventEmitter.extend( {
+               /**
+                * Constructor, if you override it, use _super().
+                *
+                * @param {Object} options Object passed to the constructor.
+                */
+               initialize: function() {
+                       this.requests = [];
+                       this.tokenCache = {};
+               },
 
-       Api.prototype = new EventEmitter();
+               /**
+                * A wrapper for $.ajax() to be used when calling server APIs.
+                * Preprocesses data argument in the following way:
+                * - removes boolean values equal to false
+                * - concatenates Array values with '|'
+                *
+                * @example
+                * <code>
+                * ajax( { a: false, b: [1, 2, 3] }, { type: 'post' } );
+                * // is equal to
+                * $.ajax( {
+                *     type: 'post',
+                *     data: { b: '1|2|3' }
+                * } );
+                * </code>
+                *
+                * @param {Object} data Data to be preprocessed and added to 
options
+                * @param {Object} options Parameters passed to $.ajax()
+                * @return {jQuery.Deferred} Object returned by $.ajax()
+                */
+               ajax: function( data, options ) {
+                       var key, request;
+                       options = $.extend( {}, options );
 
-       // FIXME: make Api and View inherit from an abstract Class object
-       /**
-        * Constructor that can be overriden.
-        *
-        * @param {Object} options Object passed to the constructor.
-        */
-       Api.prototype.initialize = function() {};
-
-       /**
-        * A wrapper for $.ajax() to be used when calling server APIs.
-        * Preprocesses data argument in the following way:
-        * - removes boolean values equal to false
-        * - concatenates Array values with '|'
-        *
-        * @example
-        * <code>
-        * ajax( { a: false, b: [1, 2, 3] }, { type: 'post' } );
-        * // is equal to
-        * $.ajax( {
-        *     type: 'post',
-        *     data: { b: '1|2|3' }
-        * } );
-        * </code>
-        *
-        * @param {Object} data Data to be preprocessed and added to options
-        * @param {Object} options Parameters passed to $.ajax()
-        * @return {jQuery.Deferred} Object returned by $.ajax()
-        */
-       Api.prototype.ajax = function( data, options ) {
-               var key, request;
-               options = $.extend( {}, options );
-
-               if (
-                       typeof data !== 'string' &&
-                       ( typeof FormData === 'undefined' || !( data instanceof 
FormData ) )
-               ) {
-                       for ( key in data ) {
-                               if ( data[key] === false ) {
-                                       delete data[key];
-                               } else if ( $.isArray( data[key] ) ) {
-                                       data[key] = data[key].join( '|' );
-                               }
-                       }
-               }
-               options.data = data;
-
-               // FIXME: uncomment when 
https://bugzilla.wikimedia.org/show_bug.cgi?id=44921 is resolved
-               /*
-               options.xhr = function() {
-                       var xhr = $.ajaxSettings.xhr();
-                       if ( xhr.upload ) {
-                               // need to bind this event before we open the 
connection (see note at
-                               // 
https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest#Monitoring_progress)
-                               xhr.upload.addEventListener( 'progress', 
function( ev ) {
-                                       if ( ev.lengthComputable ) {
-                                               self.emit( 'progress', request, 
ev.loaded / ev.total );
+                       if (
+                               typeof data !== 'string' &&
+                                       ( typeof FormData === 'undefined' || !( 
data instanceof FormData ) )
+                       ) {
+                               for ( key in data ) {
+                                       if ( data[key] === false ) {
+                                               delete data[key];
+                                       } else if ( $.isArray( data[key] ) ) {
+                                               data[key] = data[key].join( '|' 
);
                                        }
-                               } );
-                       }
-                       return xhr;
-               };
-               */
-
-               request = $.ajax( options );
-               this.requests.push( request );
-               return request;
-       };
-
-       /**
-        * A wrapper for $.ajax() to be used when calling server APIs.
-        * Sends a GET request. See ajax() for details.
-        *
-        * @param {Object} data Data to be preprocessed and added to options
-        * @param {Object} options Parameters passed to $.ajax()
-        * @return {jQuery.Deferred} Object returned by $.ajax()
-        */
-       Api.prototype.get = function( data, options ) {
-               options = $.extend( {}, options, { type: 'GET' } );
-               return this.ajax( data, options );
-       };
-
-       /**
-        * A wrapper for $.ajax() to be used when calling server APIs.
-        * Sends a POST request. See ajax() for details.
-        *
-        * @param {Object} data Data to be preprocessed and added to options
-        * @param {Object} options Parameters passed to $.ajax()
-        * @return {jQuery.Deferred} Object returned by $.ajax()
-        */
-       Api.prototype.post = function( data, options ) {
-               options = $.extend( {}, options, { type: 'POST' } );
-               return this.ajax( data, options );
-       };
-
-       /**
-        * Abort all unfinished requests issued by this Api object.
-        */
-       Api.prototype.abort = function() {
-               this.requests.forEach( function( request ) {
-                       request.abort();
-               } );
-       };
-
-       /**
-        * Retrieves a token for a given endpoint
-        *
-        * @param {String} tokenType: Name of the type of token needed e.g. 
edit, upload - defaults to edit
-        * @param {String} endpoint: Optional alternative host to query via CORS
-        * @param {String} caToken: Optional additional CentralAuth token to be
-        * sent with the request. This is needed for requests to external wikis
-        * where the user is not logged in. caToken is for single use only.
-        * @return {jQuery.Deferred} Object returned by $.ajax(), callback will 
be passed
-        *   the token string, false if the user is anon or undefined where not 
available or a warning is set
-        */
-       Api.prototype.getToken = function( tokenType, endpoint, caToken ) {
-               var data, d = $.Deferred(), isCacheable;
-
-               tokenType = tokenType || 'edit';
-               isCacheable = tokenType !== 'centralauth';
-
-               if ( !this.tokenCache[ endpoint ] ) {
-                       this.tokenCache[ endpoint ] = {};
-               }
-               if ( !M.isLoggedIn() ) {
-                       return d.reject( 'Token requested when not logged in.' 
);
-               } else if ( isCacheable && this.tokenCache[ endpoint 
].hasOwnProperty( tokenType ) ) {
-                       return this.tokenCache[ endpoint ][ tokenType ];
-               } else {
-                       data = {
-                               action: 'tokens',
-                               type: tokenType
-                       };
-                       if ( endpoint ) {
-                               data.origin = M.getOrigin();
-                               if ( caToken ) {
-                                       data.centralauthtoken = caToken;
                                }
                        }
-                       this.ajax( data, {
+                       options.data = data;
+
+                       // FIXME: uncomment when 
https://bugzilla.wikimedia.org/show_bug.cgi?id=44921 is resolved
+                       /*
+                       options.xhr = function() {
+                               var xhr = $.ajaxSettings.xhr();
+                               if ( xhr.upload ) {
+                                       // need to bind this event before we 
open the connection (see note at
+                                       // 
https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest#Monitoring_progress)
+                                       xhr.upload.addEventListener( 
'progress', function( ev ) {
+                                               if ( ev.lengthComputable ) {
+                                                       self.emit( 'progress', 
request, ev.loaded / ev.total );
+                                               }
+                                       } );
+                               }
+                               return xhr;
+                       };
+                       */
+
+                       request = $.ajax( options );
+                       this.requests.push( request );
+                       return request;
+               },
+
+               /**
+                * A wrapper for $.ajax() to be used when calling server APIs.
+                * Sends a GET request. See ajax() for details.
+                *
+                * @param {Object} data Data to be preprocessed and added to 
options
+                * @param {Object} options Parameters passed to $.ajax()
+                * @return {jQuery.Deferred} Object returned by $.ajax()
+                */
+               get: function( data, options ) {
+                       options = $.extend( {}, options, { type: 'GET' } );
+                       return this.ajax( data, options );
+               },
+
+               /**
+                * A wrapper for $.ajax() to be used when calling server APIs.
+                * Sends a POST request. See ajax() for details.
+                *
+                * @param {Object} data Data to be preprocessed and added to 
options
+                * @param {Object} options Parameters passed to $.ajax()
+                * @return {jQuery.Deferred} Object returned by $.ajax()
+                */
+               post: function( data, options ) {
+                       options = $.extend( {}, options, { type: 'POST' } );
+                       return this.ajax( data, options );
+               },
+
+               /**
+                * Abort all unfinished requests issued by this Api object.
+                */
+               abort: function() {
+                       this.requests.forEach( function( request ) {
+                               request.abort();
+                       } );
+               },
+
+               /**
+                * Retrieves a token for a given endpoint
+                *
+                * @param {String} tokenType: Name of the type of token needed 
e.g. edit, upload - defaults to edit
+                * @param {String} endpoint: Optional alternative host to query 
via CORS
+                * @param {String} caToken: Optional additional CentralAuth 
token to be
+                * sent with the request. This is needed for requests to 
external wikis
+                * where the user is not logged in. caToken is for single use 
only.
+                * @return {jQuery.Deferred} Object returned by $.ajax(), 
callback will be passed
+                *   the token string, false if the user is anon or undefined 
where not available or a warning is set
+                */
+               getToken: function( tokenType, endpoint, caToken ) {
+                       var data, d = $.Deferred(), isCacheable;
+
+                       tokenType = tokenType || 'edit';
+                       isCacheable = tokenType !== 'centralauth';
+
+                       if ( !this.tokenCache[ endpoint ] ) {
+                               this.tokenCache[ endpoint ] = {};
+                       }
+                       if ( !M.isLoggedIn() ) {
+                               return d.reject( 'Token requested when not 
logged in.' );
+                       } else if ( isCacheable && this.tokenCache[ endpoint 
].hasOwnProperty( tokenType ) ) {
+                               return this.tokenCache[ endpoint ][ tokenType ];
+                       } else {
+                               data = {
+                                       action: 'tokens',
+                                       type: tokenType
+                               };
+                               if ( endpoint ) {
+                                       data.origin = M.getOrigin();
+                                       if ( caToken ) {
+                                               data.centralauthtoken = caToken;
+                                       }
+                               }
+                               this.ajax( data, {
                                        url: endpoint || M.getApiUrl(),
                                        xhrFields: { withCredentials: true }
                                } ).then( function( tokenData ) {
@@ -176,12 +170,11 @@
                                                d.reject( 'Bad token name.' );
                                        }
                                } );
-                       this.tokenCache[ endpoint ][ tokenType ] = d;
-                       return d;
+                               this.tokenCache[ endpoint ][ tokenType ] = d;
+                               return d;
+                       }
                }
-       };
-
-       Api.extend = oop.extend;
+       } );
 
        api = new Api();
        api.Api = Api;
diff --git a/javascripts/common/mf-view.js b/javascripts/common/mf-view.js
index 4b59ff8..7a4ea76 100644
--- a/javascripts/common/mf-view.js
+++ b/javascripts/common/mf-view.js
@@ -1,7 +1,6 @@
 ( function( M, $ ) {
 
-       var oop = M.require( 'oop' ),
-               EventEmitter = M.require( 'eventemitter' );
+       var EventEmitter = M.require( 'eventemitter' ), View;
 
        /**
         * An abstraction over a jQuery element. Should be extended using 
extend().
@@ -48,78 +47,76 @@
         * @param {Object} options Options for the view, containing the el or
         * template data or any other information you want to use in the view.
         */
-       function View( options ) {
-               options = $.extend( {}, this.defaults, options );
-               if ( options.el ) {
-                       this.$el = $( options.el );
-               } else {
-                       this.$el = $( '<' + this.tagName + '>' );
+       View = EventEmitter.extend( {
+               tagName: 'div',
+
+               /**
+                * Constructor, if you override it, use _super().
+                *
+                * @param {Object} options Object passed to the constructor.
+                */
+               initialize: function( options ) {
+                       this._super();
+                       options = $.extend( {}, this.defaults, options );
+                       if ( options.el ) {
+                               this.$el = $( options.el );
+                       } else {
+                               this.$el = $( '<' + this.tagName + '>' );
+                       }
+                       this.$el.addClass( this.className );
+
+                       // TODO: if template compilation is too slow, don't 
compile them on a
+                       // per object basis, but don't worry about it now 
(maybe add cache to
+                       // M.template.compile())
+                       if ( typeof this.template === 'string' ) {
+                               this.template = M.template.compile( 
this.template );
+                       }
+
+                       this.options = options;
+                       this.render( options );
+               },
+
+               /**
+                * Function called before the view is rendered. Can be 
redefined in
+                * objects that extend View.
+                *
+                * @param {Object} options Object passed to the constructor.
+                */
+               preRender: function() {},
+
+               /**
+                * Function called after the view is rendered. Can be redefined 
in
+                * objects that extend View.
+                *
+                * @param {Object} options Object passed to the constructor.
+                */
+               postRender: function() {},
+
+               /**
+                * Fill this.$el with template rendered using data if template 
is set.
+                *
+                * @param {Object} data Template data.
+                */
+               render: function( data ) {
+                       data = data || this.options;
+                       this.preRender( data );
+                       if ( this.template ) {
+                               this.$el.html( this.template.render( data ) );
+                       }
+                       this.postRender( data );
+               },
+
+               /**
+                * Wraps this.$el.find, so that you can search for elements in 
the view's
+                * ($el's) scope.
+                *
+                * @param {string} query A jQuery CSS selector.
+                * @return {jQuery} jQuery object containing results of the 
search.
+                */
+               $: function( query ) {
+                       return this.$el.find( query );
                }
-               this.$el.addClass( this.className );
-
-               // TODO: if template compilation is too slow, don't compile 
them on a
-               // per object basis, but don't worry about it now (maybe add 
cache to
-               // M.template.compile())
-               if ( typeof this.template === 'string' ) {
-                       this.template = M.template.compile( this.template );
-               }
-
-               this.options = options;
-               this.initialize( options );
-               this.render( options );
-       }
-
-       View.prototype = new EventEmitter();
-       View.prototype.tagName = 'div';
-
-       // FIXME: make Api and View inherit from an abstract Class object
-       /**
-        * Constructor that can be overriden.
-        *
-        * @param {Object} options Object passed to the constructor.
-        */
-       View.prototype.initialize = function() {};
-
-       /**
-        * Function called before the view is rendered. Can be redefined in
-        * objects that extend View.
-        *
-        * @param {Object} options Object passed to the constructor.
-        */
-       View.prototype.preRender = function() {};
-
-       /**
-        * Function called after the view is rendered. Can be redefined in
-        * objects that extend View.
-        *
-        * @param {Object} options Object passed to the constructor.
-        */
-       View.prototype.postRender = function() {};
-
-       /**
-        * Fill this.$el with template rendered using data if template is set.
-        *
-        * @param {Object} data Template data.
-        */
-       View.prototype.render = function( data ) {
-               data = data || this.options;
-               this.preRender( data );
-               if ( this.template ) {
-                       this.$el.html( this.template.render( data ) );
-               }
-               this.postRender( data );
-       };
-
-       /**
-        * Wraps this.$el.find, so that you can search for elements in the 
view's
-        * ($el's) scope.
-        *
-        * @param {string} query A jQuery CSS selector.
-        * @return {jQuery} jQuery object containing results of the search.
-        */
-       View.prototype.$ = function( query ) {
-               return this.$el.find( query );
-       };
+       } );
 
        [
                'append',
@@ -138,8 +135,6 @@
                        return this;
                };
        } );
-
-       View.extend = oop.extend;
 
        M.define( 'view', View );
 
diff --git a/javascripts/common/uploads/PhotoUploader.js 
b/javascripts/common/uploads/PhotoUploader.js
index 1232422..b4f252c 100644
--- a/javascripts/common/uploads/PhotoUploader.js
+++ b/javascripts/common/uploads/PhotoUploader.js
@@ -99,6 +99,7 @@
 
                initialize: function( options ) {
                        this.log = getLog( options.funnel );
+                       this._super( options );
                },
 
                postRender: function() {
diff --git a/javascripts/common/uploads/PhotoUploaderPreview.js 
b/javascripts/common/uploads/PhotoUploaderPreview.js
index 293b32a..82ca588 100644
--- a/javascripts/common/uploads/PhotoUploaderPreview.js
+++ b/javascripts/common/uploads/PhotoUploaderPreview.js
@@ -21,6 +21,7 @@
 
                initialize: function( options ) {
                        this.log = options.log;
+                       this._super( options );
                },
 
                postRender: function() {
diff --git a/javascripts/modules/editor/EditorOverlay.js 
b/javascripts/modules/editor/EditorOverlay.js
index a660719..098be85 100644
--- a/javascripts/modules/editor/EditorOverlay.js
+++ b/javascripts/modules/editor/EditorOverlay.js
@@ -41,9 +41,9 @@
                },
 
                initialize: function( options ) {
-                       this._super( options );
                        this.api = new EditorApi( { title: options.title, 
isNew: options.isNew } );
                        this.sectionCount = options.sectionCount;
+                       this._super( options );
                },
 
                postRender: function( options ) {
diff --git a/javascripts/specials/overlays/CarouselOverlay.js 
b/javascripts/specials/overlays/CarouselOverlay.js
index 985433e..ad9b673 100644
--- a/javascripts/specials/overlays/CarouselOverlay.js
+++ b/javascripts/specials/overlays/CarouselOverlay.js
@@ -5,8 +5,8 @@
                        template: '',
                        className: 'overlay-carousel mw-mf-overlay',
                        initialize: function( options ) {
-                               this._super( options );
                                this.carousel = new Carousel( { pages: 
options.pages } );
+                               this._super( options );
                        },
                        postRender: function( options ) {
                                this.$el.empty();
diff --git a/javascripts/specials/uploads.js b/javascripts/specials/uploads.js
index ba6b3a1..de064e7 100644
--- a/javascripts/specials/uploads.js
+++ b/javascripts/specials/uploads.js
@@ -12,6 +12,7 @@
 
        UserGalleryApi = Api.extend( {
                initialize: function() {
+                       this._super();
                        this.limit = 10;
                },
                getPhotos: function() {
@@ -71,6 +72,7 @@
                        this.threshold = 1000;
                        this.loading = false;
                        this.api = new UserGalleryApi();
+                       this._super();
                },
                postRender: function() {
                        this.$end = this.$( '.end' );
diff --git a/javascripts/views/page.js b/javascripts/views/page.js
index 89a3237..3ff065b 100644
--- a/javascripts/views/page.js
+++ b/javascripts/views/page.js
@@ -7,18 +7,18 @@
        Section = View.extend( {
                template: M.template.get( 'section' ),
                defaults: {
-                       hasReferences: false, // flag for references
                        heading: '',
-                       content: '',
-                       index: -1, // index of this section in the given page
-                       id: null
+                       content: ''
                },
                initialize: function( options ) {
                        this.heading = options.heading;
-                       this.index = options.index;
+                       // index of this section in the given page
+                       this.index = options.index || -1;
                        this.content = options.content;
-                       this.hasReferences = options.hasReferences;
-                       this.id = options.id;
+                       // flag for references
+                       this.hasReferences = options.hasReferences || false;
+                       this.id = options.id || null;
+                       this._super( options );
                }
        } );
 
diff --git a/tests/javascripts/common/test_Class.js 
b/tests/javascripts/common/test_Class.js
new file mode 100644
index 0000000..a7ea225
--- /dev/null
+++ b/tests/javascripts/common/test_Class.js
@@ -0,0 +1,54 @@
+( function( M ) {
+
+       var Class = M.require( 'Class' );
+
+       QUnit.module( 'MobileFrontend Class' );
+
+       QUnit.test( '.extend', 5, function( assert ) {
+               var Parent, Child, child;
+
+               Parent = Class.extend( {
+                       parent: function() {
+                               return 'parent';
+                       },
+                       override: function() {
+                               return 'override';
+                       },
+                       callSuper: function() {
+                               return 'super';
+                       }
+               } );
+
+               Child = Parent.extend( {
+                       override: function() {
+                               return 'overriden';
+                       },
+                       child: function() {
+                               return 'child';
+                       },
+                       callSuper: function() {
+                               return this._super() + ' duper';
+                       }
+               } );
+
+               child = new Child();
+               assert.strictEqual( child.parent(), 'parent', 'inherit parent 
properties' );
+               assert.strictEqual( child.override(), 'overriden', 'override 
parent properties' );
+               assert.strictEqual( child.child(), 'child', 'add new 
properties' );
+               assert.strictEqual( child.callSuper(), 'super duper', "call 
parent's functions" );
+               assert.strictEqual( Child.extend, Class.extend, 'make Child 
extendeable' );
+       } );
+
+       QUnit.test( '#initialize', 1, function( assert ) {
+               var Thing, spy = sinon.spy();
+
+               Thing = Class.extend( {
+                       initialize: spy
+               } );
+
+               new Thing( 'abc', 123 );
+
+               assert.ok( spy.calledWith( 'abc', 123 ), 'call #initialize when 
creating new instance' );
+       } );
+
+}( mw.mobileFrontend ) );
diff --git a/tests/javascripts/common/test_mf-oop.js 
b/tests/javascripts/common/test_mf-oop.js
deleted file mode 100644
index 71367ac..0000000
--- a/tests/javascripts/common/test_mf-oop.js
+++ /dev/null
@@ -1,46 +0,0 @@
-( function( M ) {
-
-var oop = M.require( 'oop' );
-
-QUnit.module( 'MobileFrontend oop' );
-
-QUnit.test( '#extend', 5, function() {
-       var Child, child;
-
-       function Parent() {}
-
-       Parent.prototype.parent = function() {
-               return 'parent';
-       };
-
-       Parent.prototype.override = function() {
-               return 'override';
-       };
-
-       Parent.prototype.callSuper = function() {
-               return 'super';
-       };
-
-       Parent.extend = oop.extend;
-
-       Child = Parent.extend( {
-               override: function() {
-                       return 'overriden';
-               },
-               child: function() {
-                       return 'child';
-               },
-               callSuper: function() {
-                       return this._super() + ' duper';
-               }
-       } );
-
-       child = new Child();
-       strictEqual( child.parent(), 'parent', 'inherit parent properties' );
-       strictEqual( child.override(), 'overriden', 'override parent 
properties' );
-       strictEqual( child.child(), 'child', 'add new properties' );
-       strictEqual( child.callSuper(), 'super duper', "call parent's 
functions" );
-       strictEqual( Child.extend, oop.extend, 'make Child extendeable' );
-} );
-
-}( mw.mobileFrontend ) );

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

Gerrit-MessageType: merged
Gerrit-Change-Id: Ifd38f20ab08cbb311adfef5c53e6707cf1789410
Gerrit-PatchSet: 2
Gerrit-Project: mediawiki/extensions/MobileFrontend
Gerrit-Branch: master
Gerrit-Owner: JGonera <[email protected]>
Gerrit-Reviewer: JGonera <[email protected]>
Gerrit-Reviewer: Jdlrobson <[email protected]>
Gerrit-Reviewer: jenkins-bot

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

Reply via email to