Merge "Add share panel, replace reuse"

This commit is contained in:
jenkins-bot 2014-03-19 14:24:31 +00:00 committed by Gerrit Code Review
commit 548dafc0f3
26 changed files with 1110 additions and 283 deletions

View file

@ -61,11 +61,6 @@ $messages['en'] = array(
'multimediaviewer-permission-link' => 'view terms',
'multimediaviewer-permission-viewmore' => 'View more',
'multimediaviewer-use-file' => 'Use this file',
'multimediaviewer-use-file-owt' => 'Use this file on a wiki page, as a thumbnail',
'multimediaviewer-use-file-own' => 'Use this file on a wiki page, inline',
'multimediaviewer-use-file-offwiki' => 'Use this file on another website',
'multimediaviewer-about-mmv' => 'About Media Viewer',
'multimediaviewer-discuss-mmv' => 'Leave feedback',
@ -83,6 +78,36 @@ $messages['en'] = array(
'multimediaviewer-fileusage-link' => 'View all uses',
'multimediaviewer-fileusage-local-section' => 'On this site',
'multimediaviewer-fileusage-global-section' => 'On other sites',
'multimediaviewer-reuse-link' => 'Use this file',
'multimediaviewer-share-tab' => 'Share',
'multimediaviewer-embed-tab' => 'Embed',
'multimediaviewer-link-to-page' => 'Link to file description page',
'multimediaviewer-link-to-file' => 'Link to original file',
'multimediaviewer-embed-wt' => 'Wikitext',
'multimediaviewer-embed-html' => 'HTML',
// Ridiculously complicated messages for embedding
'multimediaviewer-html-embed-credit-text-tbls' => '"$1" by $2. Licensed under $3 via $4.',
'multimediaviewer-html-embed-credit-text-tls' => '"$1". Licensed under $2 via $3.',
'multimediaviewer-html-embed-credit-text-tbs' => '"$1" by $2. Via $3.',
'multimediaviewer-html-embed-credit-text-tbl' => '"$1" by $2. Licensed under $3.',
'multimediaviewer-html-embed-credit-text-tb' => '"$1" by $2.',
'multimediaviewer-html-embed-credit-text-ts' => '"$1". Via $2.',
'multimediaviewer-html-embed-credit-text-tl' => '"$1". Licensed under $2.',
'multimediaviewer-embed-byline' => 'By $1',
'multimediaviewer-embed-license' => 'Licensed under $1.',
'multimediaviewer-embed-via' => 'Via $1.',
// Embed size choices
'multimediaviewer-default-embed-size' => 'Default thumbnail size',
'multimediaviewer-original-embed-size' => 'Original size - $1 × $2 px',
'multimediaviewer-large-embed-size' => 'Large - $1 × $2 px',
'multimediaviewer-medium-embed-size' => 'Medium - $1 × $2 px',
'multimediaviewer-small-embed-size' => 'Small - $1 × $2 px',
);
/** Message documentation (Message documentation)
@ -160,24 +185,7 @@ They will usually be derived from the HTML output from wikitext on a file descri
'multimediaviewer-permission-link' => 'Text of the link (on top of the metadata box) which shows additional license terms',
'multimediaviewer-permission-viewmore' => 'Text of the link (at the cutoff of the license term preview) which shows additional license terms.
{{Identical|View more}}',
'multimediaviewer-use-file' => 'Link that opens a dialog with options for sharing the file, e.g. onwiki or on another site. Similar to the Commons gadget stockPhoto.',
'multimediaviewer-use-file-owt' => 'Label for input box which has wikitext used to show an image with the thumb option and a helpful caption.
The wikitext is like <code><nowiki>[[filename|thumb|desc]]</nowiki></code>.
Similar to the Commons gadget stockPhoto.
See also:
* {{msg-mw|Multimediaviewer-use-file-own}}',
'multimediaviewer-use-file-own' => 'Label for input box which has wikitext used to show an image inline with a helpful title attribute.
The wikitext is like <code><nowiki>[[filename|desc]]</nowiki></code>.
Similar to the Commons gadget stockPhoto.
See also:
* {{msg-mw|Multimediaviewer-use-file-owt}}',
'multimediaviewer-use-file-offwiki' => 'Label for HTML used to show an image on an external site, with a link back to the wiki. Similar to the Commons gadget stockPhoto.',
'multimediaviewer-about-mmv' => 'Text for a link to a page with more information about Media Viewer software.',
'multimediaviewer-discuss-mmv' => 'Text for a link to a page where the user can discuss the Media Viewer software.
{{Identical|Leave feedback}}',
@ -235,6 +243,76 @@ Followed by {{msg-mw|Multimediaviewer-fileusage-link}} and the list of pages.
See also:
* {{msg-mw|Multimediaviewer-fileusage-local-section}}',
'multimediaviewer-reuse-link' => 'Text of the link on the metadata panel which opens the reuse panel',
'multimediaviewer-share-tab' => 'Tab title text for the file reuse panel - used for the section with shareable URLs.',
'multimediaviewer-embed-tab' => 'Tab title text for the file reuse panel - used for the section with embeddable HTML and wikitext.',
'multimediaviewer-link-to-page' => 'Used as alt-text to describe a URL that goes to a File: page for an image.',
'multimediaviewer-link-to-file' => 'Used as alt-text to describe a URL that goes to an image file.',
'multimediaviewer-embed-wt' => 'Used to represent a choice for embedding a file in a wiki page, as wikitext.',
'multimediaviewer-embed-html' => 'Used to represent a choice for embedding a file in an HTML document, as HTML.',
'multimediaviewer-html-embed-credit-text-tbls' => 'Credit text, used when generating HTML to reuse an image.
Which one of the multimediaviewer-html-embed-credit-text-* messages is used will depend on what information about the image is available.
* $1 - name of the work (typically the filename without an extension)
* $2 - name of the author
* $3 - name of the license
* $4 - name of the website/institution which was the direct source for this image
Each of the parameters could be either plain text or a link.',
'multimediaviewer-html-embed-credit-text-tls' => 'Credit text, used when generating HTML to reuse an image.
Which one of the multimediaviewer-html-embed-credit-text-* messages is used will depend on what information about the image is available.
* $1 - name of the work (typically the filename without an extension)
* $2 - name of the license
* $3 - name of the website/institution which was the direct source for this image
Each of the parameters could be either plain text or a link.',
'multimediaviewer-html-embed-credit-text-tbs' => 'Credit text, used when generating HTML to reuse an image.
Which one of the multimediaviewer-html-embed-credit-text-* messages is used will depend on what information about the image is available.
* $1 - name of the work (typically the filename without an extension)
* $2 - name of the author
* $3 - name of the website/institution which was the direct source for this image
Each of the parameters could be either plain text or a link.',
'multimediaviewer-html-embed-credit-text-tbl' => 'Credit text, used when generating HTML to reuse an image.
Which one of the multimediaviewer-html-embed-credit-text-* messages is used will depend on what information about the image is available.
* $1 - name of the work (typically the filename without an extension)
* $2 - name of the author
* $3 - name of the license
Each of the parameters could be either plain text or a link.',
'multimediaviewer-html-embed-credit-text-tb' => 'Credit text, used when generating HTML to reuse an image.
Which one of the multimediaviewer-html-embed-credit-text-* messages is used will depend on what information about the image is available.
* $1 - name of the work (typically the filename without an extension)
* $2 - name of the author
Each of the parameters could be either plain text or a link.',
'multimediaviewer-html-embed-credit-text-ts' => 'Credit text, used when generating HTML to reuse an image.
Which one of the multimediaviewer-html-embed-credit-text-* messages is used will depend on what information about the image is available.
* $1 - name of the work (typically the filename without an extension)
* $2 - name of the website/institution which was the direct source for this image
Each of the parameters could be either plain text or a link.',
'multimediaviewer-html-embed-credit-text-tl' => 'Credit text, used when generating HTML to reuse an image.
Which one of the multimediaviewer-html-embed-credit-text-* messages is used will depend on what information about the image is available.
* $1 - name of the work (typically the filename without an extension)
* $2 - name of the license
Each of the parameters could be either plain text or a link.',
'multimediaviewer-embed-byline' => 'Byline (author credit) text, used when generating wikitext/HTML to reuse the image. $1 is author name.',
'multimediaviewer-embed-license' => 'License information, used when generating wikitext/HTML to reuse the image. $1 is the license name.',
'multimediaviewer-embed-via' => 'Source information (e. g. "via Flickr"), used when generating wikitext/HTML to reuse the image.
$1 is source (probably a website or institution name)',
'multimediaviewer-default-embed-size' => 'Text of size selector option which will generate wikitext for a thumbnail without explicit size.',
'multimediaviewer-original-embed-size' => 'Text of size selector option which will generate wikitext for a thumbnail with the original (full) size.
* $1 - width in pixels
* $2 - height in pixels',
'multimediaviewer-large-embed-size' => 'Text of size selector option which will generate wikitext for a thumbnail with small size.
* $1 - width in pixels
* $2 - height in pixels',
'multimediaviewer-medium-embed-size' => 'Text of size selector option which will generate wikitext for a thumbnail with medium size.
* $1 - width in pixels
* $2 - height in pixels',
'multimediaviewer-small-embed-size' => 'Text of size selector option which will generate wikitext for a thumbnail with large size.
* $1 - width in pixels
* $2 - height in pixels',
);
/** Arabic (العربية)

View file

@ -316,13 +316,12 @@ call_user_func( function() {
),
'dependencies' => array(
'mediawiki.language',
'mmv.ui',
'mmv.ui.categories',
'mmv.ui.description',
'mmv.ui.fileReuse',
'mmv.ui.fileUsage',
'mmv.ui.permission',
'mmv.ui.reuse.dialog',
'moment',
'oojs',
),
@ -354,18 +353,62 @@ call_user_func( function() {
),
), $moduleInfo( 'mmv/ui' ) );
$wgResourceModules['mmv.ui.fileReuse'] = array_merge( array(
$wgResourceModules['mmv.ui.reuse.dialog'] = array_merge( array(
'scripts' => array(
'mmv.ui.fileReuse.js',
'mmv.ui.reuse.dialog.js',
),
'styles' => array(
'mmv.ui.fileReuse.less',
'mmv.ui.reuse.dialog.less',
),
'dependencies' => array(
'mmv.ui',
'oojs',
'oojs-ui',
'mmv.ui.reuse.share',
),
'messages' => array(
'multimediaviewer-reuse-link',
),
), $moduleInfo( 'mmv/ui' ) );
$wgResourceModules['mmv.ui.reuse.tab'] = array_merge( array(
'scripts' => array(
'mmv.ui.reuse.tab.js',
),
'dependencies' => array(
'mmv.ui',
'oojs',
),
'messages' => array(
'multimediaviewer-reuse-link',
),
), $moduleInfo( 'mmv/ui' ) );
$wgResourceModules['mmv.ui.reuse.share'] = array_merge( array(
'scripts' => array(
'mmv.ui.reuse.share.js',
),
'styles' => array(
'mmv.ui.reuse.share.less',
),
'dependencies' => array(
'mmv.ui.reuse.tab',
'oojs',
'oojs-ui',
),
'messages' => array(
'multimediaviewer-share-tab',
'multimediaviewer-link-to-file',
'multimediaviewer-link-to-page',
),
), $moduleInfo( 'mmv/ui' ) );
@ -438,15 +481,11 @@ call_user_func( function() {
'jquery.hidpi',
'jquery.scrollTo',
'jquery.throttle-debounce',
'jquery.ui.dialog',
'jquery.hidpi',
),
'messages' => array(
'multimediaviewer-file-page',
'multimediaviewer-use-file',
'multimediaviewer-use-file-owt',
'multimediaviewer-use-file-own',
'multimediaviewer-use-file-offwiki',
'multimediaviewer-desc-nil',
),
), $moduleInfo( 'mmv' ) );

View file

@ -145,6 +145,9 @@ class MultimediaViewerHooks {
'tests/qunit/mmv/ui/mmv.ui.fileUsage.test.js',
'tests/qunit/mmv/ui/mmv.ui.metadataPanel.test.js',
'tests/qunit/mmv/ui/mmv.ui.permission.test.js',
'tests/qunit/mmv/ui/mmv.ui.reuse.dialog.test.js',
'tests/qunit/mmv/ui/mmv.ui.reuse.share.test.js',
'tests/qunit/mmv/ui/mmv.ui.reuse.tab.test.js',
'tests/qunit/mmv/mmv.testhelpers.js',
),
'dependencies' => array(

View file

@ -25,6 +25,16 @@
* An HTML <img> element.
*/
/**
* @class OO.ui.MenuItemWidget
* <https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/OO.ui.MenuItemWidget>
*/
/**
* @class OO.ui.MenuWidget
* <https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/OO.ui.MenuWidget>
*/
/**
* @class XMLHttpRequest
* An AJAX request

View file

@ -82,7 +82,6 @@
};
/**
* @method
* Finds the smallest bucket which is large enough to hold the target size
* (i. e. the smallest bucket whose size is equal to or greater than the target).
* If none of the buckets are large enough, returns the largest bucket.
@ -106,7 +105,6 @@
};
/**
* @method
* @protected
* Finds the largest width for an image so that it will still fit into a given bounding box,
* based on the size of a sample (some smaller version of the same image, like the thumbnail
@ -132,7 +130,6 @@
};
/**
* @method
* Finds the largest width for an image so that it will still fit into a given bounding box,
* based on the size of a sample (some smaller version of the same image, like the thumbnail
* shown in the article) which is used to calculate the ratio.

View file

@ -627,7 +627,7 @@
viewer.prevImage();
} ).on( 'mmv-resize.mmvp', function () {
viewer.resize( viewer.ui );
});
} );
};
/**

View file

@ -1,3 +1,5 @@
@import "ui/mmv.mixins";
/**
* Animation helper from core
*/
@ -186,6 +188,10 @@ body.mobile .mw-mlb-controls,
background-color: rgb(0,0,0);
}
.mw-mlb-title-contain {
position: relative;
}
.mw-mlb-license,
.mw-mlb-title-contain {
vertical-align: middle;
@ -380,12 +386,7 @@ body.mw-mlb-lightbox-open #content {
&.pointing-down {
background-position: center top;
transform: rotate(180deg);
-moz-transform: rotate(180deg);
-o-transform: rotate(180deg);
-webkit-transform: rotate(180deg);
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2.0);
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2.0)";
.rotate(180deg);
}
}

View file

@ -31,7 +31,6 @@
oo.inheritClass( UserInfo, mw.mmv.provider.Api );
/**
* @method
* Runs an API GET request to get the user info.
* @param {string} username
* @param {mw.mmv.model.Repo} repoInfo

View file

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -28,3 +28,14 @@
filter: e(%("progid:DXImageTransform.Microsoft.gradient( startColorstr='#00ffffff', endColorstr='#ffffff',GradientType=0 )",
rgbahex(@invisible), rgbahex(@backgroundColor))); // IE6-9
}
.rotate(@degrees: 45deg) {
-webkit-transform: rotate(@degrees);
-moz-transform: rotate(@degrees);
-ms-transform: rotate(@degrees);
-o-transform: rotate(@degrees);
transform: rotate(@degrees);
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=(@degrees / 90.0));
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=(@degrees / 90.0))";
}

View file

@ -164,7 +164,6 @@
};
/**
* @method
* Sets page thumbnail for display if blowupFactor <= MAX_BLOWUP_FACTOR. Otherwise thumb is not set.
* The image gets also blured to avoid pixelation if blowupFactor > BLUR_BLOWUP_FACTOR_THRESHOLD.
* We set SVG files to the maximum screen size available.
@ -267,7 +266,6 @@
};
/**
* @method
* Gets the widths for a given lightbox image.
* @param {mw.mmv.LightboxImage} image
* @returns {mw.mmv.model.ThumbnailWidth}

View file

@ -1,198 +0,0 @@
/*
* This file is part of the MediaWiki extension MultimediaViewer.
*
* MultimediaViewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MultimediaViewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MultimediaViewer. If not, see <http://www.gnu.org/licenses/>.
*/
( function ( mw, $, oo ) {
// Shortcut for prototype later
var FRP;
/**
* Represents the file reuse dialog and link to open it.
* @class mw.mmv.ui.FileReuse
* @extends mw.mmv.ui.Element
*/
function FileReuse( $container ) {
var reuse = this;
mw.mmv.ui.Element.call( this, $container );
this.$useFileLi = $( '<li>' )
.addClass( 'mw-mlb-usefile-li empty' )
.appendTo( this.$container );
this.$useFile = $( '<a>' )
.addClass( 'mw-mlb-usefile' )
.prop( 'href', '#' )
.text( mw.message( 'multimediaviewer-use-file' ).text() )
.click( function () {
mw.mmv.logger.log( 'use-this-file-link-click' );
reuse.openDialog();
return false;
} )
.appendTo( this.$useFileLi );
}
oo.inheritClass( FileReuse, mw.mmv.ui.Element );
FRP = FileReuse.prototype;
/**
* @method
* Saves some data about the image on the $useFile element for later setup.
* @param {mw.Title} title
* @param {string} src The URL for the full-size image
* @param {boolean} isLocal Whether the file is on this wiki or not
*/
FRP.set = function ( title, src, isLocal, author, license ) {
this.$useFile.data( 'title', title );
this.$useFile.data( 'src', src );
this.$useFile.data( 'isLocal', isLocal );
this.$useFile.data( 'author', author );
this.$useFile.data( 'license', license );
this.$useFileLi.removeClass( 'empty' );
};
/**
* @method
* @inheritdoc
*/
FRP.empty = function () {
this.$useFile.data( 'title', null );
this.$useFile.data( 'link', null );
this.$useFile.data( 'src', null );
this.$useFile.data( 'isLocal', null );
this.$useFile.data( 'author', null );
this.$useFile.data( 'license', null );
this.$useFileLi.addClass( 'empty' );
};
/**
* @method
* Opens a dialog with information about file reuse.
*/
FRP.openDialog = function () {
// Only open dialog once
if ( this.$dialog ) {
return false;
}
function selectAllOnEvent() {
this.select();
}
var fileTitle = this.$useFile.data( 'title' ),
filename = fileTitle.getPrefixedText(),
desc = fileTitle.getNameText(),
linkPrefix = this.$useFile.data( 'isLocal' ) ? mw.config.get( 'wgServer' ) : '',
src = this.$useFile.data( 'src' ),
link = this.$useFile.data( 'link' ) || src,
pattern = /^\/[^\/]/,
finalLink = pattern.test(link) ? linkPrefix +link: link,
license = this.$useFile.data( 'license' ) || '',
author = this.$useFile.data( 'author' ) || '',
linkTitle = ( license + ( author ? ' (' + author + ')' : '' ) ).trim(),
owtId = 'mw-mlb-use-file-onwiki-thumb',
ownId = 'mw-mlb-use-file-onwiki-normal',
owId = 'mw-mlb-use-file-offwiki',
reuse = this,
$owtLabel = $( '<label>' )
.prop( 'for', owtId )
.text( mw.message( 'multimediaviewer-use-file-owt' ).text() ),
$owtField = $( '<input>' )
.prop( 'type', 'text' )
.prop( 'id', owtId )
.prop( 'readonly', true )
.focus( selectAllOnEvent )
.val( '[[' + filename + '|thumb|' + desc + ']]' ),
$onWikiThumb = $( '<div>' )
.append( $owtLabel,
$owtField
),
$ownLabel = $( '<label>' )
.prop( 'for', ownId )
.text( mw.message( 'multimediaviewer-use-file-own' ).text() ),
$ownField = $( '<input>' )
.prop( 'type', 'text' )
.prop( 'id', ownId )
.prop( 'readonly', true )
.focus( selectAllOnEvent )
.val( '[[' + filename + '|' + desc + ']]' ),
$onWikiNormal = $( '<div>' )
.append(
$ownLabel,
$ownField
),
$owLabel = $( '<label>' )
.prop( 'for', owId )
.text( mw.message( 'multimediaviewer-use-file-offwiki' ).text() ),
$owField = $( '<input>' )
.prop( 'type', 'text' )
.prop( 'id', owId )
.prop( 'readonly', true )
.focus( selectAllOnEvent )
.val( '<a href="' + finalLink + ( linkTitle ? '" title="' + linkTitle : '' ) + '" ><img src="' + src + '" /></a>' ),
$offWiki = $( '<div>' )
.append(
$owLabel,
$owField
);
this.$dialog = $( '<div>' )
.addClass( 'mw-mlb-use-file-dialog' )
.append(
$onWikiThumb,
$onWikiNormal,
$offWiki
)
.dialog( {
width: 750,
close: function () {
// Delete the dialog object
reuse.$dialog = undefined;
}
} );
$owtField.focus();
return false;
};
/**
* Closes the dialog forcefully
*/
FRP.closeDialog = function () {
if ( this.$dialog ) {
this.$dialog.dialog( 'close' );
}
};
mw.mmv.ui.FileReuse = FileReuse;
}( mediaWiki, jQuery, OO ) );

View file

@ -1,15 +0,0 @@
.mw-mlb-image-links li.mw-mlb-usefile-li:before {
/* @embed */
background-image: url(img/use-ltr.svg) !important;
}
.mw-mlb-use-file-dialog label {
input {
width: 100%;
}
label {
display: block;
font-weight: bold;
}
}

View file

@ -16,6 +16,8 @@
*/
( function ( mw, $ ) {
var EP;
/**
* Represents a UI element.
* @class mw.mmv.ui.Element
@ -30,13 +32,13 @@
/** @property {Object.<string, string[]>} eventsRegistered Events that this element has registered with the DOM. */
this.eventsRegistered = {};
}
EP = Element.prototype;
/**
* @method
* Helper function for whitelisting HTML to only keep links and text. Works in-place.
* @param {jQuery} $el
*/
Element.prototype.whitelistHtml = function ( $el ) {
EP.whitelistHtml = function ( $el ) {
var child, $prev, $child = $el.children().first();
while ( $child && $child.length ) {
@ -64,26 +66,39 @@
};
/**
* @method
* @abstract
* Sets the data for the element.
*/
Element.prototype.set = function () {};
EP.set = function () {};
/**
* @method
* @abstract
* Empties the element.
*/
Element.prototype.empty = function () {};
EP.empty = function () {};
/**
* @abstract
* Registers listeners.
*/
EP.attach = function() {};
/**
* @abstract
* Clears listeners.
*/
EP.unattach = function() {
this.clearEvents();
};
/**
* @method
* Add event handler in a way that will be auto-cleared on lightbox close
* @param {string} name Name of event, like 'keydown'
* @param {Function} handler Callback for the event
*
* TODO: Unit tests
*/
Element.prototype.handleEvent = function ( name, handler ) {
EP.handleEvent = function ( name, handler ) {
if ( this.eventsRegistered[name] === undefined ) {
this.eventsRegistered[name] = [];
}
@ -92,10 +107,11 @@
};
/**
* @method
* Remove all events that have been registered on this element.
*
* TODO: Unit tests
*/
Element.prototype.clearEvents = function () {
EP.clearEvents = function () {
var i, handlers, thisevent,
events = Object.keys( this.eventsRegistered );
@ -109,5 +125,6 @@
};
mw.mmv.ui = {};
mw.mmv.ui.reuse = {};
mw.mmv.ui.Element = Element;
}( mediaWiki, jQuery ) );

View file

@ -29,6 +29,7 @@
*/
function MetadataPanel( $container, $controlBar ) {
mw.mmv.ui.Element.call( this, $container );
this.$controlBar = $controlBar;
/**
@ -57,9 +58,13 @@
$.scrollTo().on( 'scroll.mmvp', $.throttle( 250, function() {
panel.scroll();
} ) );
this.fileReuse.attach();
};
MPP.unattach = function() {
this.fileReuse.unattach();
this.fileReuse.closeDialog();
this.clearEvents();
$.scrollTo().off( 'scroll.mmvp' );
@ -239,7 +244,7 @@
this.initializeDatetime();
this.initializeLocation();
this.fileReuse = new mw.mmv.ui.FileReuse( this.$imageLinks );
this.fileReuse = new mw.mmv.ui.reuse.Dialog( this.$container, this.$titleDiv );
this.categories = new mw.mmv.ui.Categories( this.$imageLinks );
this.fileUsage = new mw.mmv.ui.FileUsage(
@ -440,18 +445,10 @@
/**
* Sets up the file reuse data in the DOM
* @param {mw.Title} title
* @param {string} imageUrl
* @param {boolean} isLocal
* @param {mw.mmv.model.Image} image
*/
MPP.setFileReuseData = function ( title, imageUrl, isLocal ) {
this.fileReuse.set(
title,
imageUrl,
isLocal,
this.$license.data( 'license' ),
this.$author.text()
);
MPP.setFileReuseData = function ( image ) {
this.fileReuse.set( image );
};
/**
@ -628,7 +625,6 @@
fileTitle = image.filePageTitle;
this.setFileTitle( fileTitle.getNameText() );
this.setFileReuseData( fileTitle, imageData.url, repoData.isLocal );
this.setRepoDisplay( repoData.displayName, repoData.favIcon, repoData.isLocal );
this.setFilePageLink( imageData.descriptionUrl );
@ -676,6 +672,9 @@
if ( user ) {
this.setUserPageLink( repoData, imageData.lastUploader, user.gender );
}
// File reuse steals a bunch of information from the DOM, so do it last
this.setFileReuseData( imageData, repoData.displayName, image.caption );
};
/**
@ -741,7 +740,6 @@
};
/**
* @method
* Makes sure that the given element (which must be a descendant of the metadata panel) is
* in view. If it isn't, scrolls the panel smoothly to reveal it.
* @param {HTMLElement|jQuery|string} target

View file

@ -0,0 +1,224 @@
/*
* This file is part of the MediaWiki extension MultimediaViewer.
*
* MultimediaViewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MultimediaViewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MultimediaViewer. If not, see <http://www.gnu.org/licenses/>.
*/
( function ( mw, $, oo ) {
// Shortcut for prototype later
var DP;
/**
* Represents the file reuse dialog and the link to open it.
* @class mw.mmv.ui.reuse.Dialog
* @extends mw.mmv.ui.Element
* @param {jQuery} $container the element to which the dialog will be appended
* @param {jQuery} $linkContainer the element to which the link to open the dialog will be appended
*/
function Dialog( $container, $linkContainer ) {
mw.mmv.ui.Element.call( this, $container );
this.$reuseLink = $( '<span>' )
.addClass( 'mw-mlb-reuse-link empty' )
.text( mw.message( 'multimediaviewer-reuse-link' ).text() );
this.$reuseLink.appendTo( $linkContainer );
this.$reuseDialog = $( '<div>' )
.addClass( 'mw-mlb-reuse-dialog' );
this.reuseTabs = new oo.ui.MenuWidget( {
classes: [ 'mw-mlb-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-mlb-reuse-down-arrow' )
.appendTo( this.$reuseDialog );
this.$reuseDialog.appendTo( this.$container );
/** @property {boolean} Whether or not the dialog is open. */
this.isOpen = false;
/**
* @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;
// FIXME this should happen outside the dialog and the tabs, but we need to improve
DP.initTabs = function () {
var shareTab;
this.tabs = {
share: new mw.mmv.ui.reuse.Share( this.$reuseDialog )
};
shareTab = new oo.ui.MenuItemWidget(
'share', { label: mw.message( 'multimediaviewer-share-tab' ).text() } );
this.reuseTabs.addItems( [
shareTab
] );
// Default to 'share' tab
this.selectedTab = 'share';
this.reuseTabs.selectItem( shareTab );
};
/**
* Handles click on link that opens/closes the dialog.
*/
DP.handleOpenCloseClick = function() {
mw.mmv.logger.log( 'use-this-file-link-click' );
if ( this.isOpen ) {
this.closeDialog();
} else {
this.openDialog();
}
return false;
};
/**
* Handles tab selection.
*/
DP.handleTabSelection = function ( option ) {
var tab;
this.selectedTab = option.getData();
for ( tab in this.tabs ) {
if ( tab === this.selectedTab ) {
this.tabs[tab].show();
} else {
this.tabs[tab].hide();
}
}
};
/**
* Registers listeners.
*/
DP.attach = function() {
var dialog = this,
tab;
this.$reuseLink.on( 'click', $.proxy( dialog.handleOpenCloseClick, dialog ) );
this.reuseTabs.on( 'select', $.proxy( dialog.handleTabSelection, dialog ) );
for ( tab in this.tabs ) {
this.tabs[tab].attach();
}
};
/**
* Clears listeners.
*/
DP.unattach = function() {
var tab;
this.constructor.super.prototype.unattach.call( this );
this.stopListeningToOutsideClick();
this.$reuseLink.off( 'click' );
this.reuseTabs.off( 'select' );
for ( tab in this.tabs ) {
this.tabs[tab].unattach();
}
};
/**
* Sets data needed by contaned tabs and makes dialog launch link visible.
* @param {mw.mmv.model.Image} image
*/
DP.set = function ( image ) {
this.tabs.share.set( image );
this.$reuseLink.removeClass( 'empty' );
};
/**
* @inheritdoc
*/
DP.empty = function () {
this.closeDialog();
for ( var tab in this.tabs ) {
this.tabs[tab].empty();
}
this.$reuseLink.addClass( 'empty' );
};
/**
* Opens a dialog with information about file reuse.
*/
DP.openDialog = function () {
this.startListeningToOutsideClick();
this.$reuseDialog.show();
this.$reuseLink.addClass( 'open' );
this.isOpen = true;
this.tabs[this.selectedTab].show();
};
/**
* Closes the reuse dialog.
*/
DP.closeDialog = function () {
this.stopListeningToOutsideClick();
this.$reuseDialog.hide();
this.$reuseLink.removeClass( 'open' );
this.isOpen = false;
};
/**
* Sets up the event handler which closes the dialog when the user clicks outside.
*/
DP.startListeningToOutsideClick = function () {
var dialog = this;
this.outsideClickHandler = this.outsideClickHandler || function ( e ) {
var $clickTarget = $( e.target );
if ( $clickTarget.closest( dialog.$reuseDialog ).length ) {
return;
}
dialog.closeDialog();
return false;
};
$( document ).on( 'click.mmv', this.outsideClickHandler );
};
/**
* Removes the event handler set up by startListeningToOutsideClick().
*/
DP.stopListeningToOutsideClick = function () {
$( document ).off( 'click.mmv', this.outsideClickHandler );
};
mw.mmv.ui.reuse.Dialog = Dialog;
}( mediaWiki, jQuery, OO ) );

View file

@ -0,0 +1,126 @@
@import "mmv.mixins";
.mw-mlb-reuse-link {
@reuse-link-color: rgb(136, 136, 136);
position: absolute;
right: 0;
bottom: 0;
border-left: 1px solid @reuse-link-color;
padding: 15px;
.unselectable;
font-size: 1.25em;
color: @reuse-link-color;
cursor: pointer;
opacity: 0.8;
transition: opacity 0.25s;
&:before {
display: inline-block;
width: 1em;
height: 1em;
// fix odd position caused by bottom of icon and bottom of SVG not being aligned
position: relative;
top: 0.1em;
/* @embed */
background-image: url(img/use-ltr.svg);
background-size: 1em 1em;
margin-right: 0.25em;
content: ' ';
vertical-align: baseline;
}
&.open {
opacity: 1;
}
}
// not-so-great but quick way of ensuring the reuse link does not get overflowed with text
.mw-mlb-title-contain {
padding-right: 175px;
}
.mw-mlb-reuse-dialog {
@background-color: rgb(255, 255, 255);
@shadow-color: rgb(0, 0, 0);
@border-radius: 3px;
@divider-border-height: 1px;
@dialog-width: 450px;
@dialog-height: 350px;
// positioned relative to the metadata panel
position: absolute;
right: 5px;
top: -1 * (@dialog-height + 5px);
width: @dialog-width;
height: @dialog-height;
background-color: @background-color;
box-shadow: 2px 2px 2px @shadow-color;
.box-round(@border-radius);
.mw-mlb-reuse-tabs {
@divider-color: rgb(204, 204, 204);
position: static;
box-shadow: none;
border-bottom: @divider-border-height solid @divider-color;
.box-round(@border-radius @border-radius 0 0);
.oo-ui-iconedElement-icon.oo-ui-icon-check {
display: none;
}
li {
@tab-border-height: 3px;
@highlighted-tab-color: rgb(225, 243, 255);
@selected-tab-color: rgb(0, 113, 188);
display: inline-block;
padding: 10px 25px;
font-size: 1.2em;
&.oo-ui-optionWidget-highlighted {
border-bottom: (@tab-border-height - @divider-border-height) solid @highlighted-tab-color;
}
&.oo-ui-optionWidget-selected,
&.oo-ui-optionWidget-highlighted.oo-ui-optionWidget-selected {
border-bottom: @tab-border-height solid @selected-tab-color;
}
&:first-child {
.box-round(@border-radius 0 0 0);
}
}
}
.mw-mlb-reuse-pane {
display: none;
padding: 10px;
&.active {
display: block;
}
}
.mw-mlb-reuse-down-arrow {
@arrow-size: 20px;
@arrow-border-color: rgb(170, 170, 170);
@arrow-border-size: 1px;
background-color: @background-color;
width: @arrow-size;
height: @arrow-size;
border-right: @arrow-border-size solid @arrow-border-color;
border-bottom: @arrow-border-size solid @arrow-border-color;
.rotate(45deg);
position: absolute;
right: 60px;
bottom: -1 * ( @arrow-size / 2 );
}
}

View file

@ -0,0 +1,105 @@
/*
* This file is part of the MediaWiki extension MultimediaViewer.
*
* MultimediaViewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MultimediaViewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MultimediaViewer. If not, see <http://www.gnu.org/licenses/>.
*/
( function ( mw, $, oo ) {
// Shortcut for prototype later
var SP;
/**
* Represents the file reuse dialog and link to open it.
* @class mw.mmv.ui.reuse.Share
* @extends mw.mmv.ui.reuse.Tab
* @param {jQuery} $container
*/
function Share( $container ) {
Share.super.call( this, $container );
this.init();
}
oo.inheritClass( Share, mw.mmv.ui.reuse.Tab );
SP = Share.prototype;
SP.init = function () {
this.$pane.addClass( 'mw-mlb-share-pane active' )
.appendTo( this.$container );
this.pageInput = new oo.ui.TextInputWidget( {
classes: [ 'mw-mlb-share-page' ],
readOnly: true
} );
this.$pageLink = $( '<a>' )
.addClass( 'mw-mlb-share-page-link' )
.prop( 'alt', mw.message( 'multimediaviewer-link-to-page' ).text() )
.prop( 'target', '_blank' )
.html( '&nbsp;' )
.appendTo( this.$pane );
this.pageInput.$element.appendTo( this.$pane );
this.$pane.appendTo( this.$container );
};
/**
* Shows the pane.
*/
SP.show = function () {
this.constructor.super.prototype.show.call( this );
this.pageInput.$element.focus();
};
/**
* @inheritdoc
* @param {mw.mmv.model.Image} image
*/
SP.set = function ( image ) {
// FIXME this should be handled by mmv.js to be DRY
var url = image.descriptionUrl + '#mediaviewer/' + image.title.getMainText();
this.pageInput.setValue( url );
this.$pageLink.prop( 'href', url );
};
/**
* @inheritdoc
*/
SP.empty = function () {
this.pageInput.setValue( '' );
this.$pageLink.prop( 'href', null );
};
/**
* @inheritdoc
*/
SP.attach = function() {
var $input = this.pageInput.$element.find( 'input' );
this.pageInput.onDOMEvent( 'focus', $.proxy( this.selectAllOnEvent, $input ) );
this.pageInput.onDOMEvent( 'mousedown click', $.proxy( this.onlyFocus, $input ) );
};
/**
* @inheritdoc
*/
SP.unattach = function() {
this.constructor.super.prototype.unattach.call( this );
this.pageInput.offDOMEvent( 'focus mousedown click' );
};
mw.mmv.ui.reuse.Share = Share;
}( mediaWiki, jQuery, OO ) );

View file

@ -0,0 +1,30 @@
.mw-mlb-share-page {
// override OOJS-UI fixed width
width: auto;
// make sure this is a new block formatting context so that the float shrinks it instead of
// running into it and pushing the input down (there is probably a better way of doing this)
overflow: hidden;
}
.mw-mlb-share-page-link {
float: left;
width: 1.5em;
height: 1.5em;
// position approximately to the middle - probably fragile but couldn't find a better way as the
// height of OOJS-UI input widget has both em and px parts and not possible to calculate exactly
margin: 8px 0;
padding: 0 10px;
/* @embed */
background-image: url(img/link.svg);
background-size: contain;
background-position: center;
background-repeat: no-repeat;
&:hover {
/* @embed */
background-image: url(img/link-hover.svg);
text-decoration: none;
}
}

View file

@ -0,0 +1,73 @@
/*
* This file is part of the MediaWiki extension MediaViewer.
*
* MediaViewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MediaViewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MediaViewer. If not, see <http://www.gnu.org/licenses/>.
*/
( function( mw, $, oo ) {
var TP;
/**
* A tab in a mw.mmv.ui.Pane component
* @class mw.mmv.ui.reuse.Tab
* @extends mw.mmv.ui.Element
* @param {jQuery} $container
* @constructor
*/
function Tab( $container ) {
Tab.super.call( this, $container );
/**
* Container for the tab.
* @property {jQuery}
*/
this.$pane = $( '<div>' ).addClass( 'mw-mlb-reuse-pane' );
}
oo.inheritClass( Tab, mw.mmv.ui.Element );
TP = Tab.prototype;
/**
* Shows the pane.
*/
TP.show = function () {
this.$pane.addClass( 'active' );
};
/**
* Hides the pane.
*/
TP.hide = function () {
this.$pane.removeClass( 'active' );
};
/**
* Makes the entire input/textarea selected when focused.
*/
TP.selectAllOnEvent = function () {
this.select();
};
/**
* Reduces the action of clicks to solely focusing the input/textarea.
* Essentialy disables clicking inside the text to select a portion of it.
*/
TP.onlyFocus = function ( e ) {
this.focus();
e.preventDefault();
return false;
};
mw.mmv.ui.reuse.Tab = Tab;
}( mediaWiki, jQuery, OO ) );

View file

@ -182,4 +182,5 @@
assert.ok( e, 'Exception is thrown when gender parameter is not understood');
}
} );
}( mediaWiki ) );

View file

@ -127,7 +127,10 @@
filePageTitle : mw.Title.newFromText( 'File:' + title + '.jpg' )
},
imageData = {
hasCoords: function() { return false; },
title: image.filePageTitle,
url: 'https://upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg',
descriptionUrl: 'https://commons.wikimedia.org/wiki/File:Foobar.jpg',
hasCoords: function() { return false; }
},
repoData = {
getArticlePath : function() { return 'Foo'; }

View file

@ -0,0 +1,196 @@
/*
* This file is part of the MediaWiki extension MultimediaViewer.
*
* MultimediaViewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MultimediaViewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MultimediaViewer. If not, see <http://www.gnu.org/licenses/>.
*/
( function ( mw, $ ) {
function makeReuseDialog() {
var $fixture = $( '#qunit-fixture' );
return new mw.mmv.ui.reuse.Dialog( $fixture, $( '<div>' ).appendTo( $fixture ) );
}
QUnit.module( 'mmv.ui.reuse.Dialog', QUnit.newMwEnvironment() );
QUnit.test( 'Sanity test, object creation and UI construction', 4, function ( assert ) {
var reuseDialog = makeReuseDialog();
assert.ok( reuseDialog, 'Reuse UI element is created.' );
assert.strictEqual( reuseDialog.$reuseLink.length, 1, 'Reuse link created.' );
assert.strictEqual( reuseDialog.$reuseDialog.length, 1, 'Reuse dialog div created.' );
assert.ok( reuseDialog.reuseTabs, 'Reuse tabs created.' );
} );
QUnit.test( 'handleOpenCloseClick():', 2, function ( assert ) {
var reuseDialog = makeReuseDialog();
reuseDialog.openDialog = function () {
assert.ok( true, 'openDialog called.' );
};
reuseDialog.closeDialog = function () {
assert.ok( false, 'closeDialog should not have been called.' );
};
// Dialog is closed by default, we should open it
reuseDialog.handleOpenCloseClick();
reuseDialog.openDialog = function () {
assert.ok( false, 'openDialog should not have been called.' );
};
reuseDialog.closeDialog = function () {
assert.ok( true, 'closeDialog called.' );
};
reuseDialog.isOpen = true;
// Dialog open now, we should close it.
reuseDialog.handleOpenCloseClick();
} );
QUnit.test( 'attach()/unattach():', 2, function ( assert ) {
var reuseDialog = makeReuseDialog();
reuseDialog.handleOpenCloseClick = function() {
assert.ok( false, 'handleOpenCloseClick should not have been called.' );
};
reuseDialog.handleTabSelection = function() {
assert.ok( false, 'handleTabSelection should not have been called.' );
};
// Triggering action events before attaching should do nothing
reuseDialog.$reuseLink.trigger( 'click' );
reuseDialog.reuseTabs.emit( 'select' );
reuseDialog.handleOpenCloseClick = function() {
assert.ok( true, 'handleOpenCloseClick called.' );
};
reuseDialog.handleTabSelection = function() {
assert.ok( true, 'handleTabSelection called.' );
};
reuseDialog.attach();
// Action events should be handled now
reuseDialog.$reuseLink.trigger( 'click' );
reuseDialog.reuseTabs.emit( 'select' );
// Test the unattach part
reuseDialog.handleOpenCloseClick = function() {
assert.ok( false, 'handleOpenCloseClick should not have been called.' );
};
reuseDialog.handleTabSelection = function() {
assert.ok( false, 'handleTabSelection should not have been called.' );
};
reuseDialog.unattach();
// Triggering action events now that we are unattached should do nothing
reuseDialog.$reuseLink.trigger( 'click' );
reuseDialog.reuseTabs.emit( 'select' );
} );
QUnit.test( 'start/stopListeningToOutsideClick():', 11, function ( assert ) {
var reuseDialog = makeReuseDialog(),
realCloseDialog = reuseDialog.closeDialog;
function clickOutsideDialog() {
var event = new $.Event( 'click', { target: reuseDialog.$container[0] } );
reuseDialog.$container.trigger( event );
return event;
}
function clickInsideDialog() {
var event = new $.Event( 'click', { target: reuseDialog.$reuseDialog[0] } );
reuseDialog.$reuseDialog.trigger( event );
return event;
}
function assertDialogDoesNotCatchClicks() {
var event;
reuseDialog.closeDialog = function() { assert.ok( false, 'Dialog is not affected by click' ); };
event = clickOutsideDialog();
assert.ok( !event.isDefaultPrevented(), 'Dialog does not affect click' );
assert.ok( !event.isPropagationStopped(), 'Dialog does not affect click propagation' );
}
function assertDialogCatchesOutsideClicksOnly() {
var event;
reuseDialog.closeDialog = function() { assert.ok( false, 'Dialog is not affected by inside click' ); };
event = clickInsideDialog();
assert.ok( !event.isDefaultPrevented(), 'Dialog does not affect inside click' );
assert.ok( !event.isPropagationStopped(), 'Dialog does not affect inside click propagation' );
reuseDialog.closeDialog = function() { assert.ok( true, 'Dialog is closed by outside click' ); };
event = clickOutsideDialog();
assert.ok( event.isDefaultPrevented(), 'Dialog catches outside click' );
assert.ok( event.isPropagationStopped(), 'Dialog stops outside click propagation' );
}
assertDialogDoesNotCatchClicks();
reuseDialog.openDialog();
assertDialogCatchesOutsideClicksOnly();
realCloseDialog.call( reuseDialog );
assertDialogDoesNotCatchClicks();
reuseDialog.openDialog();
reuseDialog.unattach();
assertDialogDoesNotCatchClicks();
} );
QUnit.test( 'set()/empty():', 3, function ( assert ) {
var reuseDialog = makeReuseDialog(),
title = mw.Title.newFromText( 'File:Foobar.jpg' ),
src = 'https://upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg',
url = 'https://commons.wikimedia.org/wiki/File:Foobar.jpg',
image = { // fake mw.mmv.model.Image
title: title,
url: src,
descriptionUrl: url,
width: 100,
height: 80
};
assert.ok( reuseDialog.$reuseLink.hasClass( 'empty' ), 'Dialog launch link is empty by default.' );
reuseDialog.set( image );
assert.ok( ! reuseDialog.$reuseLink.hasClass( 'empty' ), 'Dialog launch link is not empty after set().' );
reuseDialog.empty();
assert.ok( reuseDialog.$reuseLink.hasClass( 'empty' ), 'Dialog launch link is empty now.' );
} );
QUnit.test( 'openDialog()/closeDialog():', 3, function ( assert ) {
var reuseDialog = makeReuseDialog(),
title = mw.Title.newFromText( 'File:Foobar.jpg' ),
src = 'https://upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg',
url = 'https://commons.wikimedia.org/wiki/File:Foobar.jpg',
image = { // fake mw.mmv.model.Image
title: title,
url: src,
descriptionUrl: url,
width: 100,
height: 80
};
reuseDialog.set( image );
assert.ok( ! reuseDialog.isOpen, 'Dialog closed by default.' );
reuseDialog.openDialog();
assert.ok( reuseDialog.isOpen, 'Dialog open now.' );
reuseDialog.closeDialog();
assert.ok( ! reuseDialog.isOpen, 'Dialog closed now.' );
} );
}( mediaWiki, jQuery ) );

View file

@ -0,0 +1,88 @@
/*
* This file is part of the MediaWiki extension MultimediaViewer.
*
* MultimediaViewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MultimediaViewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MultimediaViewer. If not, see <http://www.gnu.org/licenses/>.
*/
( function ( mw, $ ) {
function makeShare() {
return new mw.mmv.ui.reuse.Share( $( '#qunit-fixture' ) );
}
QUnit.module( 'mmv.ui.reuse.share', QUnit.newMwEnvironment() );
QUnit.test( 'Sanity test, object creation and UI construction', 4, function ( assert ) {
var share = makeShare();
assert.ok( share, 'Share UI element is created.' );
assert.strictEqual( share.$pane.length, 1, 'Pane div created.' );
assert.ok( share.pageInput, 'Text field created.' );
assert.ok( share.$pageLink, 'Link created.' );
} );
QUnit.test( 'set()/empty():', 3, function ( assert ) {
var share = makeShare(),
image = { // fake mw.mmv.model.Image
title: new mw.Title( 'File:Foobar.jpg' ),
url: 'https://upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg',
};
assert.notStrictEqual( ! share.pageInput.getValue(), '', 'pageInput is empty.' );
share.set( image );
assert.notStrictEqual( share.pageInput.getValue(), '', 'pageInput is not empty.' );
share.empty();
assert.notStrictEqual( ! share.pageInput.getValue(), '', 'pageInput is empty.' );
} );
QUnit.test( 'attach()/unattach():', 1, function ( assert ) {
var share = makeShare(),
image = {
title: new mw.Title( 'File:Foobar.jpg' ),
url: 'https://upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg',
};
share.set( image );
share.selectAllOnEvent = function() {
assert.ok( false, 'selectAllOnEvent should not have been called.' );
};
// Triggering action events before attaching should do nothing
share.pageInput.$element.focus();
share.selectAllOnEvent = function () {
assert.ok( true, 'selectAllOnEvent was called.' );
};
share.attach();
// Action events should be handled now
share.pageInput.$element.focus();
// Test the unattach part
share.selectAllOnEvent = function() {
assert.ok( false, 'selectAllOnEvent should not have been called.' );
};
share.unattach();
// Triggering action events now that we are unattached should do nothing
share.pageInput.$element.focus();
} );
}( mediaWiki, jQuery ) );

View file

@ -0,0 +1,43 @@
/*
* This file is part of the MediaWiki extension MultimediaViewer.
*
* MultimediaViewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MultimediaViewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MultimediaViewer. If not, see <http://www.gnu.org/licenses/>.
*/
( function ( mw, $ ) {
var $fixture = $( '#qunit-fixture' );
function makeReuseTab() {
return new mw.mmv.ui.reuse.Tab( $( '<div>' ).appendTo( $fixture ), $fixture );
}
QUnit.module( 'mmv.ui.reuse.Tab', QUnit.newMwEnvironment() );
QUnit.test( 'Object creation, UI construction and basic funtionality', 5, function ( assert ) {
var reuseTab = makeReuseTab();
assert.ok( reuseTab, 'Reuse UI element is created.' );
assert.strictEqual( reuseTab.$pane.length, 1, 'Pane created.' );
assert.ok( !reuseTab.$pane.hasClass( 'active' ), 'Tab is not active.' );
reuseTab.show();
assert.ok( reuseTab.$pane.hasClass( 'active' ), 'Tab is active.' );
reuseTab.hide();
assert.ok( !reuseTab.$pane.hasClass( 'active' ), 'Tab is not active.' );
} );
}( mediaWiki, jQuery ) );