Phuedx has uploaded a new change for review.

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

Change subject: WIP: Add footer link change listener
......................................................................

WIP: Add footer link change listener

TODO:
* Integration tests.
* Documentation (in doc/change_listener.md).

Change-Id: Ibe6934058327c7f02f7d8092e74a667a5a1c600a
---
M extension.json
M resources/ext.popups/boot.js
A resources/ext.popups/changeListener.js
A resources/ext.popups/footerLinkChangeListener.js
M resources/ext.popups/index.js
A tests/qunit/ext.popups/changeListener.test.js
6 files changed, 190 insertions(+), 2 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Popups 
refs/changes/51/321851/1

diff --git a/extension.json b/extension.json
index a7330c9..1562708 100644
--- a/extension.json
+++ b/extension.json
@@ -64,6 +64,8 @@
                                "resources/ext.popups/processLinks.js",
                                "resources/ext.popups/gateway.js",
                                "resources/ext.popups/reducers.js",
+                               "resources/ext.popups/changeListener.js",
+                               
"resources/ext.popups/footerLinkChangeListener.js",
                                "resources/ext.popups/boot.js"
                        ],
                        "templates": {
diff --git a/resources/ext.popups/boot.js b/resources/ext.popups/boot.js
index 00d770a..a6787d0 100644
--- a/resources/ext.popups/boot.js
+++ b/resources/ext.popups/boot.js
@@ -1,4 +1,4 @@
-( function ( mw, Redux, ReduxThunk ) {
+( function ( mw, Redux, ReduxThunk, $ ) {
        var BLACKLISTED_LINKS = [
                '.extiw',
                '.image',
@@ -22,6 +22,23 @@
                        mw.user,
                        userSettings
                );
+       }
+
+       /**
+        * Subscribes the registered change listeners to the
+        * [store](http://redux.js.org/docs/api/Store.html#store).
+        *
+        * Change listeners are registered by setting a property on
+        * `mw.popups.changeListeners`.
+        *
+        * @param {Store} store
+        */
+       function registerChangeListeners( store ) {
+               $.each( mw.popups.changeListeners, function ( _, 
changeListenerFactory ) {
+                       var changeListener = changeListenerFactory();
+
+                       store.subscribe( mw.popups.createChangeListener( 
changeListener, store ) );
+               } );
        }
 
        /**
@@ -53,6 +70,7 @@
                        ) )
                );
                actions = createBoundActions( store );
+               registerChangeListeners( store );
 
                actions.boot(
                        isUserInCondition(),
@@ -81,4 +99,4 @@
                } );
        } );
 
-}( mediaWiki, Redux, ReduxThunk ) );
+}( mediaWiki, Redux, ReduxThunk, jQuery ) );
diff --git a/resources/ext.popups/changeListener.js 
b/resources/ext.popups/changeListener.js
new file mode 100644
index 0000000..5dcaed4
--- /dev/null
+++ b/resources/ext.popups/changeListener.js
@@ -0,0 +1,44 @@
+( function ( mw ) {
+
+       /**
+        * @typedef {Function} ext.popups.ChangeListener
+        * @param {Object} prevState The previous state
+        * @param {Object} state The current state
+        */
+
+       /**
+        * Creates a change listener, which is bound, **but not subscribed**, 
to the
+        * [store](http://redux.js.org/docs/api/Store.html).
+        *
+        * A change listener is a function that is only invoked when the state 
in the
+        * [store](http://redux.js.org/docs/api/Store.html) changes. N.B. that 
there
+        * may not be a 1:1 correspondence with actions being dispatched to the 
store
+        * and the state in the store changing.
+        *
+        * See 
[Store#subscribe](http://redux.js.org/docs/api/Store.html#subscribe)
+        * for more information about what change listeners may and may not do.
+        *
+        * @param {ext.popups.ChangeListener} callback
+        * @param {Store} store
+        * @return {Function} A function that should be passed to
+        *  
[Store#subscribe]([Store#subscribe](http://redux.js.org/docs/api/Store.html#subscribe)
+        */
+       mw.popups.createChangeListener = function ( callback, store ) {
+               // This function is based on the example in [the documentation 
for
+               // 
Store#subscribe](http://redux.js.org/docs/api/Store.html#subscribe),
+               // which was written by Dan Abramov.
+
+               var state;
+
+               return function () {
+                       var prevState = state;
+
+                       state = store.getState();
+
+                       if ( prevState !== state ) {
+                               callback( prevState, state );
+                       }
+               };
+       };
+
+}( mediaWiki ) );
diff --git a/resources/ext.popups/footerLinkChangeListener.js 
b/resources/ext.popups/footerLinkChangeListener.js
new file mode 100644
index 0000000..c5df9fc
--- /dev/null
+++ b/resources/ext.popups/footerLinkChangeListener.js
@@ -0,0 +1,63 @@
+( function ( mw, $ ) {
+
+       /**
+        * Creates the link element and appends it to the footer element.
+        *
+        * The following elements are considered to be the footer element 
(highest
+        * priority to lowest):
+        *
+        * # `#footer-places`
+        * # `#f-list`
+        * # The parent element of `#footer li`, which is either an `ol` or 
`ul`.
+        *
+        * @return {jQuery} The link element
+        */
+       function createFooterLink() {
+               var $link = $( '<li>' ).append(
+                               $( '<a>' )
+                                       .attr( 'href', '#' )
+                                       .text( mw.message( 
'popups-settings-enable' ).text() )
+                       ),
+                       $footer;
+
+               // As yet, we don't know whether the link should be visible.
+               $link.hide();
+
+               // From 
https://en.wikipedia.org/wiki/MediaWiki:Gadget-ReferenceTooltips.js,
+               // which was written by Yair rand 
<https://en.wikipedia.org/wiki/User:Yair_rand>.
+               $footer = $( '#footer-places, #f-list' );
+
+               if ( $footer.length === 0 ) {
+                       $footer = $( '#footer li' ).parent();
+               }
+
+               $footer.append( $link );
+
+               return $link;
+       }
+
+       /**
+        * Creates the footer link change listener.
+        *
+        * When `state.preview.enabled` is truthy, then the "Enable previews" 
link is
+        * shown in the footer menu; otherwise, the link is hidden.
+        *
+        * @return {Function}
+        */
+       mw.popups.changeListeners.footerLink = function () {
+               var $footerLink;
+
+               return function ( prevState, state ) {
+                       if ( $footerLink === undefined ) {
+                               $footerLink = createFooterLink();
+                       }
+
+                       if ( state.preview.enabled ) {
+                               $footerLink.hide();
+                       } else {
+                               $footerLink.show();
+                       }
+               };
+       };
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/ext.popups/index.js b/resources/ext.popups/index.js
index 378fd81..9e3a872 100644
--- a/resources/ext.popups/index.js
+++ b/resources/ext.popups/index.js
@@ -2,4 +2,15 @@
 
        mw.popups = {};
 
+       /**
+        * Unlike action creators and reducers, change listeners are more 
complex and
+        * won't be defined in just one file. Create the 
`mw.popups.changeListeners`
+        * namespace here to avoid repeating the following:
+        *
+        * ```js
+        * mw.popups.changeListeners = mw.popups.changeListeners || {};
+        * ```
+        */
+       mw.popups.changeListeners = {};
+
 }( mediaWiki ) );
diff --git a/tests/qunit/ext.popups/changeListener.test.js 
b/tests/qunit/ext.popups/changeListener.test.js
new file mode 100644
index 0000000..077fbf3
--- /dev/null
+++ b/tests/qunit/ext.popups/changeListener.test.js
@@ -0,0 +1,50 @@
+( function ( mw ) {
+
+       var stubStore = ( function () {
+               var state;
+
+               return {
+                       getState: function () {
+                               return state;
+                       },
+                       setState: function ( value ) {
+                               state = value;
+                       }
+               };
+       }() );
+
+       QUnit.module( 'ext.popups/changeListener' );
+
+       QUnit.test( 'it should only call the callback when the state has 
changed', function ( assert ) {
+               var spy = this.sandbox.spy(),
+                       changeListener = mw.popups.createChangeListener( spy, 
stubStore );
+
+               assert.expect( 4 );
+
+               stubStore.setState( {} );
+
+               changeListener();
+               changeListener();
+
+               assert.strictEqual( spy.callCount, 1 );
+               assert.ok( spy.calledWith(
+                       undefined, // The initial internal state of the change 
listener.
+                       {}
+               ) );
+
+               stubStore.setState( {
+                       foo: 'bar'
+               } );
+
+               changeListener();
+
+               assert.strictEqual( spy.callCount, 2 );
+               assert.ok( spy.calledWith(
+                       {},
+                       {
+                               foo: 'bar'
+                       }
+               ) );
+       } );
+
+}( mediaWiki ) );

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibe6934058327c7f02f7d8092e74a667a5a1c600a
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Popups
Gerrit-Branch: mpga
Gerrit-Owner: Phuedx <[email protected]>

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

Reply via email to