diff --git a/MultimediaViewer.php b/MultimediaViewer.php
index 0af11da0d..4404a14b6 100644
--- a/MultimediaViewer.php
+++ b/MultimediaViewer.php
@@ -485,10 +485,6 @@ $wgResourceModules += array(
'dependencies' => array(
'mmv.ui',
'oojs',
- 'oojs-ui',
- 'mmv.ui.reuse.share',
- 'mmv.ui.reuse.embed',
- 'mmv.ui.reuse.download',
),
),
diff --git a/MultimediaViewerHooks.php b/MultimediaViewerHooks.php
index 82b0b7480..45daec769 100644
--- a/MultimediaViewerHooks.php
+++ b/MultimediaViewerHooks.php
@@ -222,6 +222,9 @@ class MultimediaViewerHooks {
'dependencies' => array(
'mmv',
'mmv.bootstrap',
+ 'mmv.ui.reuse.share',
+ 'mmv.ui.reuse.embed',
+ 'mmv.ui.reuse.download',
),
'localBasePath' => __DIR__,
'remoteExtPath' => 'MultimediaViewer',
diff --git a/resources/mmv/mmv.js b/resources/mmv/mmv.js
index e003fcab6..cb5681522 100755
--- a/resources/mmv/mmv.js
+++ b/resources/mmv/mmv.js
@@ -310,6 +310,7 @@
}
viewer.ui.panel.animateMetadataOnce();
+ viewer.preloadDependencies();
} );
this.comingFromHashChange = false;
@@ -706,9 +707,16 @@
/**
* Unregisters all event handlers. Currently only used in tests.
*/
- MMVP.cleanupEventHandlers = function () {
+ MMVP.cleanupEventHandlers = function () {
$( document ).off( 'mmv-close.mmvp mmv-next.mmvp mmv-prev.mmvp mmv-resize.mmvp' );
};
+ /**
+ * Preloads JS and CSS dependencies that aren't needed to display the first image, but could be needed later
+ */
+ MMVP.preloadDependencies = function () {
+ mw.loader.load( [ 'mmv.ui.reuse.share', 'mmv.ui.reuse.embed', 'mmv.ui.reuse.download' ] );
+ };
+
mw.mmv.MultimediaViewer = MultimediaViewer;
}( mediaWiki, jQuery ) );
diff --git a/resources/mmv/ui/mmv.ui.reuse.dialog.js b/resources/mmv/ui/mmv.ui.reuse.dialog.js
index 9d03bec8c..c52693993 100644
--- a/resources/mmv/ui/mmv.ui.reuse.dialog.js
+++ b/resources/mmv/ui/mmv.ui.reuse.dialog.js
@@ -34,13 +34,6 @@
this.$reuseDialog = $( '
' )
.addClass( 'mw-mmv-reuse-dialog' );
- this.reuseTabs = new oo.ui.MenuWidget( {
- classes: [ 'mw-mmv-reuse-tabs' ]
- } );
- // MenuWidget has a nasty tendency to hide itself, maybe we're not using it right?
- this.reuseTabs.hide = $.noop;
- this.reuseTabs.$element.show().appendTo( this.$reuseDialog );
-
this.$downArrow = $( '
' )
.addClass( 'mw-mmv-reuse-down-arrow' )
.appendTo( this.$reuseDialog );
@@ -54,8 +47,6 @@
* @property {Object.} List of tab ui objects.
*/
this.tabs = null;
-
- this.initTabs();
}
oo.inheritClass( Dialog, mw.mmv.ui.Element );
DP = Dialog.prototype;
@@ -64,6 +55,14 @@
DP.initTabs = function () {
var shareTab, embedTab, downloadTab;
+ this.reuseTabs = new oo.ui.MenuWidget( {
+ classes: [ 'mw-mmv-reuse-tabs' ]
+ } );
+
+ // MenuWidget has a nasty tendency to hide itself, maybe we're not using it right?
+ this.reuseTabs.hide = $.noop;
+ this.reuseTabs.$element.show().appendTo( this.$reuseDialog );
+
this.tabs = {
share: new mw.mmv.ui.reuse.Share( this.$reuseDialog ),
download: new mw.mmv.ui.reuse.Download( this.$reuseDialog ),
@@ -86,20 +85,52 @@
// Default to 'share' tab
this.selectedTab = 'share';
this.reuseTabs.selectItem( shareTab );
+
+ if ( this.dependenciesNeedToBeAttached ) {
+ this.attachDependencies();
+ }
+
+ if ( this.tabsSetValues ) {
+ // This is a delayed set() for the elements we've just created on demand
+ this.tabs.share.set.apply( this.tabs.share, this.tabsSetValues.share );
+ this.tabs.download.set.apply( this.tabs.download, this.tabsSetValues.download );
+ this.tabs.embed.set.apply( this.tabs.embed, this.tabsSetValues.embed );
+ this.tabsSetValues = undefined;
+ }
};
/**
* Handles click on link that opens/closes the dialog.
*/
- DP.handleOpenCloseClick = function() {
+ DP.handleOpenCloseClick = function () {
+ var dialog = this,
+ $deferred = $.Deferred();
+
mw.mmv.logger.log( 'use-this-file-link-click' );
- if ( this.isOpen ) {
- this.closeDialog();
+ if ( this.tabs === null ) {
+ // initTabs() needs to have these dependencies loaded in order to run
+ mw.loader.using( [ 'mmv.ui.reuse.share', 'mmv.ui.reuse.embed', 'mmv.ui.reuse.download' ], function () {
+ dialog.initTabs();
+ $deferred.resolve();
+ }, function (error) {
+ $deferred.reject( error );
+ if ( window.console && window.console.error ) {
+ window.console.error( 'mw.loader.using error when trying to load reuse dependencies', error );
+ }
+ } );
} else {
- this.openDialog();
+ $deferred.resolve();
}
+ $deferred.then( function() {
+ if ( dialog.isOpen ) {
+ dialog.closeDialog();
+ } else {
+ dialog.openDialog();
+ }
+ } );
+
return false;
};
@@ -123,31 +154,52 @@
/**
* Registers listeners.
*/
- DP.attach = function() {
- var dialog = this,
- tab;
+ DP.attach = function () {
+ var dialog = this;
this.handleEvent( 'mmv-reuse-open', $.proxy( dialog.handleOpenCloseClick, dialog ) );
- this.reuseTabs.on( 'select', $.proxy( dialog.handleTabSelection, dialog ) );
- for ( tab in this.tabs ) {
- this.tabs[tab].attach();
+ this.attachDependencies();
+ };
+
+ /**
+ * Registrers listeners for dependencies loaded on demand
+ */
+ DP.attachDependencies = function () {
+ var tab, dialog = this;
+
+ if ( this.reuseTabs && this.tabs ) {
+ // This is a delayed attach() for the elements we've just created on demand
+ this.reuseTabs.on( 'select', $.proxy( dialog.handleTabSelection, dialog ) );
+
+ for ( tab in this.tabs ) {
+ this.tabs[tab].attach();
+ }
+
+ this.dependenciesNeedToBeAttached = false;
+ } else {
+ this.dependenciesNeedToBeAttached = true;
}
};
/**
* Clears listeners.
*/
- DP.unattach = function() {
+ DP.unattach = function () {
var tab;
this.constructor['super'].prototype.unattach.call( this );
this.stopListeningToOutsideClick();
- this.reuseTabs.off( 'select' );
- for ( tab in this.tabs ) {
- this.tabs[tab].unattach();
+ if ( this.reuseTabs ) {
+ this.reuseTabs.off( 'select' );
+ }
+
+ if ( this.tabs ) {
+ for ( tab in this.tabs ) {
+ this.tabs[tab].unattach();
+ }
}
};
@@ -159,9 +211,17 @@
* @param {string} caption
*/
DP.set = function ( image, repo, caption) {
- this.tabs.share.set( image );
- this.tabs.download.set( image );
- this.tabs.embed.set( image, repo, caption );
+ if ( this.tabs !== null ) {
+ this.tabs.share.set( image );
+ this.tabs.download.set( image );
+ this.tabs.embed.set( image, repo, caption );
+ } else {
+ this.tabsSetValues = {
+ share : [ image ],
+ download : [ image ],
+ embed : [ image, repo, caption ]
+ };
+ }
};
/**
diff --git a/tests/qunit/mmv/ui/mmv.ui.reuse.dialog.test.js b/tests/qunit/mmv/ui/mmv.ui.reuse.dialog.test.js
index 6bdb4e169..a9fab308e 100644
--- a/tests/qunit/mmv/ui/mmv.ui.reuse.dialog.test.js
+++ b/tests/qunit/mmv/ui/mmv.ui.reuse.dialog.test.js
@@ -23,12 +23,11 @@
QUnit.module( 'mmv.ui.reuse.Dialog', QUnit.newMwEnvironment() );
- QUnit.test( 'Sanity test, object creation and UI construction', 3, function ( assert ) {
+ QUnit.test( 'Sanity test, object creation and UI construction', 2, function ( assert ) {
var reuseDialog = makeReuseDialog();
assert.ok( reuseDialog, 'Reuse UI element is created.' );
assert.strictEqual( reuseDialog.$reuseDialog.length, 1, 'Reuse dialog div created.' );
- assert.ok( reuseDialog.reuseTabs, 'Reuse tabs created.' );
} );
QUnit.test( 'handleOpenCloseClick():', 2, function ( assert ) {
@@ -59,6 +58,8 @@
QUnit.test( 'handleTabSelection():', 4, function ( assert ) {
var reuseDialog = makeReuseDialog();
+ reuseDialog.initTabs();
+
reuseDialog.tabs.share.show = function () {
assert.ok( true, 'Share tab shown.' );
};
@@ -83,6 +84,8 @@
QUnit.test( 'attach()/unattach():', 2, function ( assert ) {
var reuseDialog = makeReuseDialog();
+ reuseDialog.initTabs();
+
reuseDialog.handleOpenCloseClick = function() {
assert.ok( false, 'handleOpenCloseClick should not have been called.' );
};
@@ -126,6 +129,8 @@
var reuseDialog = makeReuseDialog(),
realCloseDialog = reuseDialog.closeDialog;
+ reuseDialog.initTabs();
+
function clickOutsideDialog() {
var event = new $.Event( 'click', { target: reuseDialog.$container[0] } );
reuseDialog.$container.trigger( event );
@@ -200,6 +205,8 @@
},
embedFileInfo = new mw.mmv.model.EmbedFileInfo( title, src, url );
+ reuseDialog.initTabs();
+
reuseDialog.set( image, embedFileInfo );
assert.ok( ! reuseDialog.isOpen, 'Dialog closed by default.' );