Load oojs-ui on demand when "use this file" is clicked

Change-Id: Ia3b6b91c7ff0cb223f5f312eb901726fb6adcf35
Mingle: https://wikimedia.mingle.thoughtworks.com/projects/multimedia/cards/426
This commit is contained in:
Gilles Dubuc 2014-04-11 16:05:58 +02:00
parent 0d9c3aa545
commit eb6386bb5b
5 changed files with 107 additions and 33 deletions

View file

@ -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',
),
),

View file

@ -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',

View file

@ -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 ) );

View file

@ -34,13 +34,6 @@
this.$reuseDialog = $( '<div>' )
.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 = $( '<div>' )
.addClass( 'mw-mmv-reuse-down-arrow' )
.appendTo( this.$reuseDialog );
@ -54,8 +47,6 @@
* @property {Object.<string, mw.mmv.ui.Element>} 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 ]
};
}
};
/**

View file

@ -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.' );