diff options
Diffstat (limited to 'www/wiki/extensions/MultimediaViewer/resources/mmv/ui/mmv.ui.metadataPanel.js')
-rw-r--r-- | www/wiki/extensions/MultimediaViewer/resources/mmv/ui/mmv.ui.metadataPanel.js | 886 |
1 files changed, 886 insertions, 0 deletions
diff --git a/www/wiki/extensions/MultimediaViewer/resources/mmv/ui/mmv.ui.metadataPanel.js b/www/wiki/extensions/MultimediaViewer/resources/mmv/ui/mmv.ui.metadataPanel.js new file mode 100644 index 00000000..182173fa --- /dev/null +++ b/www/wiki/extensions/MultimediaViewer/resources/mmv/ui/mmv.ui.metadataPanel.js @@ -0,0 +1,886 @@ +/* + * 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 MPP; + + /** + * Represents the metadata panel in the viewer + * + * @class mw.mmv.ui.MetadataPanel + * @extends mw.mmv.ui.Element + * @constructor + * @param {jQuery} $container The container for the panel (.mw-mmv-post-image). + * @param {jQuery} $aboveFold The brighter headline of the metadata panel (.mw-mmv-above-fold). + * Called "aboveFold" for historical reasons, but actually a part of the next sibling of the element + * is also above the fold (bottom of the screen). + * @param {mw.storage} localStorage the localStorage object, for dependency injection + * @param {mw.mmv.Config} config A configuration object. + */ + function MetadataPanel( $container, $aboveFold, localStorage, config ) { + mw.mmv.ui.Element.call( this, $container ); + + this.$aboveFold = $aboveFold; + + /** @property {mw.mmv.Config} config - */ + this.config = config; + + /** @property {mw.mmv.HtmlUtils} htmlUtils - */ + this.htmlUtils = new mw.mmv.HtmlUtils(); + + this.initializeHeader( localStorage ); + this.initializeImageMetadata(); + this.initializeAboutLinks(); + } + oo.inheritClass( MetadataPanel, mw.mmv.ui.Element ); + MPP = MetadataPanel.prototype; + + /** + * Maximum number of restriction icons before default icon is used + * + * @property MAX_RESTRICT + * @static + */ + MetadataPanel.MAX_RESTRICT = 4; + + /** + * FIXME this should be in the jquery.fullscreen plugin. + * + * @return {boolean} + */ + MPP.isFullscreened = function () { + return $( this.$container ).closest( '.jq-fullscreened' ).length > 0; + }; + + MPP.attach = function () { + var panel = this; + + this.scroller.attach(); + this.buttons.attach(); + this.title.attach(); + this.creditField.attach(); + + this.$title + .add( this.$authorAndSource ) + .add( this.title.$ellipsis ) + .add( this.creditField.$ellipsis ) + .each( function () { + $( this ).tipsy( 'enable' ); + } ) + .on( 'click.mmv-mp', function ( e ) { + var clickTargetIsLink = $( e.target ).is( 'a' ), + clickTargetIsTruncated = !!$( e.target ).closest( '.mw-mmv-ttf-truncated' ).length, + someTextIsExpanded = !!$( e.target ).closest( '.mw-mmv-untruncated' ).length; + + if ( + !clickTargetIsLink && // don't interfere with clicks on links in the text + clickTargetIsTruncated && // don't expand when non-truncated text is clicked + !someTextIsExpanded // ignore clicks if text is already expanded + ) { + if ( panel.isFullscreened() ) { + panel.revealTruncatedText(); + } else { + panel.scroller.toggle( 'up' ); + } + } + } ); + + $( this.$container ).on( 'mmv-metadata-open.mmv-mp mmv-metadata-reveal-truncated-text.mmv-mp', function () { + panel.revealTruncatedText(); + } ).on( 'mmv-metadata-close.mmv-mp', function () { + panel.hideTruncatedText(); + } ).on( 'mouseleave.mmv-mp', function () { + var duration; + + if ( panel.isFullscreened() ) { + duration = parseFloat( panel.$container.css( 'transition-duration' ) ) * 1000 || 0; + panel.panelShrinkTimeout = setTimeout( function () { + panel.hideTruncatedText(); + }, duration ); + } + } ).on( 'mouseenter.mmv-mp', function () { + clearTimeout( panel.panelShrinkTimeout ); + } ).on( 'mmv-permission-grow.mmv-mp', function () { + panel.$permissionLink + .text( mw.message( 'multimediaviewer-permission-link-hide' ).text() ); + } ).on( 'mmv-permission-shrink.mmv-mp', function () { + panel.$permissionLink + .text( mw.message( 'multimediaviewer-permission-link' ).text() ); + } ); + + this.handleEvent( 'jq-fullscreen-change.lip', function () { + panel.hideTruncatedText(); + } ); + }; + + MPP.unattach = function () { + this.scroller.freezeHeight(); + + this.$title + .add( this.title.$ellipsis ) + .add( this.$authorAndSource ) + .add( this.creditField.$ellipsis ) + .each( function () { + $( this ).tipsy( 'hide' ).tipsy( 'disable' ); + } ) + .off( 'click.mmv-mp' ); + + $( this.$container ).off( '.mmv-mp' ); + + this.scroller.unattach(); + this.buttons.unattach(); + this.clearEvents(); + }; + + MPP.empty = function () { + this.scroller.freezeHeight(); + this.scroller.empty(); + + this.buttons.empty(); + + this.description.empty(); + this.permission.empty(); + + this.$title.removeClass( 'error' ); + this.title.empty(); + this.creditField.empty(); + + this.$license.empty().prop( 'href', '#' ); + this.$licenseLi.addClass( 'empty' ); + this.$permissionLink.hide(); + this.$restrictions.children().hide(); + + this.$filename.empty(); + this.$filenamePrefix.empty(); + this.$filenameLi.addClass( 'empty' ); + + this.$datetime.empty(); + this.$datetimeLi.addClass( 'empty' ); + + this.$location.empty(); + this.$locationLi.addClass( 'empty' ); + + this.progressBar.empty(); + + this.$container.removeClass( 'mw-mmv-untruncated' ); + }; + + /* Initialization methods */ + + /** + * Initializes the header, which contains the title, credit, and license elements. + * + * @param {mw.storage} localStorage the localStorage object, for dependency injection + */ + MPP.initializeHeader = function ( localStorage ) { + this.progressBar = new mw.mmv.ui.ProgressBar( this.$aboveFold ); + + this.scroller = new mw.mmv.ui.MetadataPanelScroller( this.$container, this.$aboveFold, + localStorage ); + + this.$titleDiv = $( '<div>' ) + .addClass( 'mw-mmv-title-contain' ) + .appendTo( this.$aboveFold ); + + this.$container.append( this.$aboveFold ); + + this.initializeButtons(); // float, needs to be on top + this.initializeTitle(); + }; + + /** + * Initializes the title elements. + */ + MPP.initializeTitle = function () { + this.$titlePara = $( '<p>' ) + .addClass( 'mw-mmv-title-para' ) + .appendTo( this.$aboveFold ); + + this.$title = $( '<span>' ) + .addClass( 'mw-mmv-title' ); + + this.title = new mw.mmv.ui.TruncatableTextField( this.$titlePara, this.$title, { + styles: [ 'mw-mmv-title-small', 'mw-mmv-title-smaller' ] + } ); + this.title.setTitle( + mw.message( 'multimediaviewer-title-popup-text' ), + mw.message( 'multimediaviewer-title-popup-text-more' ) + ); + + this.$title.add( this.title.$ellipsis ).tipsy( { + delayIn: mw.config.get( 'wgMultimediaViewer' ).tooltipDelay, + gravity: this.correctEW( 'sw' ) + } ); + }; + + MPP.initializeButtons = function () { + this.buttons = new mw.mmv.ui.StripeButtons( this.$titleDiv ); + }; + + /** + * Initializes the main body of metadata elements. + */ + MPP.initializeImageMetadata = function () { + this.$container.addClass( 'mw-mmv-ttf-ellipsis-container' ); + + this.$imageMetadata = $( '<div>' ) + .addClass( 'mw-mmv-image-metadata' ) + .appendTo( this.$container ); + + this.$imageMetadataLeft = $( '<div>' ) + .addClass( 'mw-mmv-image-metadata-column mw-mmv-image-metadata-desc-column' ) + .appendTo( this.$imageMetadata ); + + this.$imageMetadataRight = $( '<div>' ) + .addClass( 'mw-mmv-image-metadata-column mw-mmv-image-metadata-links-column' ) + .appendTo( this.$imageMetadata ); + + this.initializeCredit(); + this.description = new mw.mmv.ui.Description( this.$imageMetadataLeft ); + this.permission = new mw.mmv.ui.Permission( this.$imageMetadataLeft, this.scroller ); + this.initializeImageLinks(); + }; + + /** + * Initializes the credit elements. + */ + MPP.initializeCredit = function () { + this.$credit = $( '<p>' ) + .addClass( 'mw-mmv-credit empty' ) + .appendTo( this.$imageMetadataLeft ) + .on( 'click.mmv-mp', '.mw-mmv-credit-fallback', function () { + mw.mmv.actionLogger.log( 'author-page' ); + } ); + + // we need an inline container for tipsy, otherwise it would be centered weirdly + this.$authorAndSource = $( '<span>' ) + .addClass( 'mw-mmv-source-author' ) + .on( 'click', '.mw-mmv-author a', function () { + mw.mmv.actionLogger.log( 'author-page' ); + } ) + .on( 'click', '.mw-mmv-source a', function () { + mw.mmv.actionLogger.log( 'source-page' ); + } ); + + this.creditField = new mw.mmv.ui.TruncatableTextField( + this.$credit, + this.$authorAndSource, + { styles: [] } + ); + + this.creditField.setTitle( + mw.message( 'multimediaviewer-credit-popup-text' ), + mw.message( 'multimediaviewer-credit-popup-text-more' ) + ); + + this.$authorAndSource.add( this.creditField.$ellipsis ).tipsy( { + delayIn: mw.config.get( 'wgMultimediaViewer' ).tooltipDelay, + gravity: this.correctEW( 'sw' ) + } ); + }; + + /** + * Initializes the list of image metadata on the right side of the panel. + */ + MPP.initializeImageLinks = function () { + this.$imageLinkDiv = $( '<div>' ) + .addClass( 'mw-mmv-image-links-div' ) + .appendTo( this.$imageMetadataRight ); + + this.$imageLinks = $( '<ul>' ) + .addClass( 'mw-mmv-image-links' ) + .appendTo( this.$imageLinkDiv ); + + this.initializeLicense(); + this.initializeFilename(); + this.initializeDatetime(); + this.initializeLocation(); + }; + + /** + * Initializes the license elements. + */ + MPP.initializeLicense = function () { + var panel = this; + + this.$licenseLi = $( '<li>' ) + .addClass( 'mw-mmv-license-li empty' ) + .appendTo( this.$imageLinks ); + + this.$license = $( '<a>' ) + .addClass( 'mw-mmv-license' ) + .prop( 'href', '#' ) + .appendTo( this.$licenseLi ) + .on( 'click', function () { + mw.mmv.actionLogger.log( 'license-page' ); + } ); + + this.$restrictions = $( '<span>' ) + .addClass( 'mw-mmv-restrictions' ) + .appendTo( this.$licenseLi ); + + this.$permissionLink = $( '<span>' ) + .addClass( 'mw-mmv-permission-link mw-mmv-label' ) + .text( mw.message( 'multimediaviewer-permission-link' ).text() ) + .appendTo( this.$licenseLi ) + .hide() + .on( 'click', function () { + if ( panel.permission.isFullSize() ) { + panel.permission.shrink(); + } else { + panel.permission.grow(); + panel.scroller.toggle( 'up' ); + } + return false; + } ); + }; + + /** + * Initializes the filename element. + */ + MPP.initializeFilename = function () { + this.$filenameLi = $( '<li>' ) + .addClass( 'mw-mmv-filename-li empty' ) + .appendTo( this.$imageLinks ); + + this.$filenamePrefix = $( '<span>' ) + .addClass( 'mw-mmv-filename-prefix' ) + .appendTo( this.$filenameLi ); + + this.$filename = $( '<span>' ) + .addClass( 'mw-mmv-filename' ) + .appendTo( this.$filenameLi ); + }; + + /** + * Initializes the upload date/time element. + */ + MPP.initializeDatetime = function () { + this.$datetimeLi = $( '<li>' ) + .addClass( 'mw-mmv-datetime-li empty' ) + .appendTo( this.$imageLinks ); + + this.$datetime = $( '<span>' ) + .addClass( 'mw-mmv-datetime' ) + .appendTo( this.$datetimeLi ); + }; + + /** + * Initializes the geolocation element. + */ + MPP.initializeLocation = function () { + this.$locationLi = $( '<li>' ) + .addClass( 'mw-mmv-location-li empty' ) + .appendTo( this.$imageLinks ); + + this.$location = $( '<a>' ) + .addClass( 'mw-mmv-location' ) + .appendTo( this.$locationLi ) + .click( function () { mw.mmv.actionLogger.log( 'location-page' ); } ); + }; + + /** + * Initializes two about links at the bottom of the panel. + */ + MPP.initializeAboutLinks = function () { + var separator = ' | '; + + this.$mmvAboutLink = $( '<a>' ) + .prop( 'href', mw.config.get( 'wgMultimediaViewer' ).infoLink ) + .text( mw.message( 'multimediaviewer-about-mmv' ).text() ) + .addClass( 'mw-mmv-about-link' ) + .click( function () { mw.mmv.actionLogger.log( 'about-page' ); } ); + + this.$mmvDiscussLink = $( '<a>' ) + .prop( 'href', mw.config.get( 'wgMultimediaViewer' ).discussionLink ) + .text( mw.message( 'multimediaviewer-discuss-mmv' ).text() ) + .addClass( 'mw-mmv-discuss-link' ) + .click( function () { mw.mmv.actionLogger.log( 'discuss-page' ); } ); + + this.$mmvHelpLink = $( '<a>' ) + .prop( 'href', mw.config.get( 'wgMultimediaViewer' ).helpLink ) + .text( mw.message( 'multimediaviewer-help-mmv' ).text() ) + .addClass( 'mw-mmv-help-link' ) + .click( function () { mw.mmv.actionLogger.log( 'help-page' ); } ); + + this.$mmvAboutLinks = $( '<div>' ) + .addClass( 'mw-mmv-about-links' ) + .append( + this.$mmvAboutLink, + separator, + this.$mmvDiscussLink, + separator, + this.$mmvHelpLink + ) + .appendTo( this.$imageMetadata ); + }; + + /* Setters */ + + /** + * Sets the image title at the top of the metadata panel. + * The title will be the first one available form the options below: + * - the image caption + * - the description from the filepage + * - the filename (without extension) + * + * @param {mw.mmv.LightboxImage} image + * @param {mw.mmv.model.Image} imageData + */ + MPP.setTitle = function ( image, imageData ) { + var title; + + if ( image.caption ) { + title = image.caption; + } else if ( imageData.description ) { + title = imageData.description; + } else { + title = image.filePageTitle.getNameText(); + } + + this.title.set( title ); + }; + + /** + * Sets the upload or creation date and time in the panel + *f + * @param {string} date The formatted date to set. + * @param {boolean} created Whether this is the creation date + */ + MPP.setDateTime = function ( date, created ) { + this.$datetime.text( + mw.message( + 'multimediaviewer-datetime-' + ( created ? 'created' : 'uploaded' ), + date + ).text() + ); + + this.$datetimeLi.removeClass( 'empty' ); + }; + + /** + * Sets the file name in the panel. + * + * @param {string} filename The file name to set, without prefix + */ + MPP.setFileName = function ( filename ) { + this.$filenamePrefix.text( 'File:' ); + this.$filename.text( filename ); + + this.$filenameLi.removeClass( 'empty' ); + }; + + /** + * Set source and author. + * + * @param {string} attribution Custom attribution string + * @param {string} source With unsafe HTML + * @param {string} author With unsafe HTML + * @param {number} authorCount + * @param {string} filepageUrl URL of the file page (used when other data is not available) + */ + MPP.setCredit = function ( attribution, source, author, authorCount, filepageUrl ) { + // sanitization will be done by TruncatableTextField.set() + if ( attribution && ( authorCount <= 1 || !authorCount ) ) { + this.creditField.set( this.wrapAttribution( attribution ) ); + } else if ( author && source ) { + this.creditField.set( + mw.message( + 'multimediaviewer-credit', + this.wrapAuthor( author, authorCount, filepageUrl ), + this.wrapSource( source ) + ).plain() + ); + } else if ( author ) { + this.creditField.set( this.wrapAuthor( author, authorCount, filepageUrl ) ); + } else if ( source ) { + this.creditField.set( this.wrapSource( source ) ); + } else { + this.creditField.set( + $( '<a>' ) + .addClass( 'mw-mmv-credit-fallback' ) + .prop( 'href', filepageUrl ) + .text( mw.message( 'multimediaviewer-credit-fallback' ).plain() ) + ); + } + + this.$credit.removeClass( 'empty' ); + }; + + /** + * Wraps a source string it with MediaViewer styles + * + * @param {string} source Warning - unsafe HTML sometimes goes here + * @return {string} unsafe HTML + */ + MPP.wrapSource = function ( source ) { + return $( '<span>' ) + .addClass( 'mw-mmv-source' ) + .append( $.parseHTML( source ) ) + .get( 0 ).outerHTML; + }; + + /** + * Wraps an author string with MediaViewer styles + * + * @param {string} author Warning - unsafe HTML sometimes goes here + * @param {number} authorCount + * @param {string} filepageUrl URL of the file page (used when some author data is not available) + * @return {string} unsafe HTML + */ + MPP.wrapAuthor = function ( author, authorCount, filepageUrl ) { + var moreText, + $wrapper = $( '<span>' ); + + $wrapper.addClass( 'mw-mmv-author' ); + + if ( authorCount > 1 ) { + moreText = this.htmlUtils.jqueryToHtml( + $( '<a>' ) + .addClass( 'mw-mmv-more-authors' ) + .text( mw.message( 'multimediaviewer-multiple-authors', authorCount - 1 ).text() ) + .attr( 'href', filepageUrl ) + ); + $wrapper.append( mw.message( 'multimediaviewer-multiple-authors-combine', author, moreText ).text() ); + } else { + $wrapper.append( author ); + } + + return $wrapper.get( 0 ).outerHTML; + }; + + /** + * Wraps an attribution string with MediaViewer styles + * + * @param {string} attribution Warning - unsafe HTML sometimes goes here + * @return {string} unsafe HTML + */ + MPP.wrapAttribution = function ( attribution ) { + return $( '<span>' ) + .addClass( 'mw-mmv-author' ) + .addClass( 'mw-mmv-source' ) + .append( $.parseHTML( attribution ) ) + .get( 0 ).outerHTML; + }; + + /** + * Sets the license display in the panel + * + * @param {mw.mmv.model.License|null} license license data (could be missing) + * @param {string} filePageUrl URL of the file description page + */ + MPP.setLicense = function ( license, filePageUrl ) { + var shortName, url, isCc, isPd; + + if ( license ) { + shortName = license.getShortName(); + url = license.deedUrl || filePageUrl; + isCc = license.isCc(); + isPd = license.isPd(); + } else { + shortName = mw.message( 'multimediaviewer-license-default' ).text(); + url = filePageUrl; + isCc = isPd = false; + } + + this.$license + .text( shortName ) + .prop( 'href', url ) + .prop( 'target', license && license.deedUrl ? '_blank' : '' ); + + this.$licenseLi + .toggleClass( 'cc-license', isCc ) + .toggleClass( 'pd-license', isPd ) + .removeClass( 'empty' ); + }; + + /** + * Set an extra permission text which should be displayed. + * + * @param {string} permission + */ + MPP.setPermission = function ( permission ) { + this.$permissionLink.show(); + this.permission.set( permission ); + }; + + /** + * Sets any special restrictions that should be displayed. + * + * @param {string[]} restrictions Array of restrictions + */ + MPP.setRestrictions = function ( restrictions ) { + var panel = this, + restrictionsSet = {}, + showDefault = false, + validRestrictions = 0; + + $.each( restrictions, function ( index, value ) { + if ( !mw.message( 'multimediaviewer-restriction-' + value ).exists() || value === 'default' || index + 1 > MetadataPanel.MAX_RESTRICT ) { + showDefault = true; // If the restriction isn't defined or there are more than MAX_RESTRICT of them, show a generic symbol at the end + return; + } + if ( restrictionsSet[ value ] ) { + return; // Only show one of each symbol + } else { + restrictionsSet[ value ] = true; + } + + panel.$restrictions.append( panel.createRestriction( value ) ); + validRestrictions++; // See how many defined restrictions are added so we know which default i18n msg to use + } ); + + if ( showDefault ) { + if ( validRestrictions ) { + panel.$restrictions.append( panel.createRestriction( 'default-and-others' ) ); + } else { + panel.$restrictions.append( panel.createRestriction( 'default' ) ); + } + } + }; + + /** + * Helper function that generates restriction labels + * + * @param {string} type Restriction type + * @return {jQuery} jQuery object of label + */ + MPP.createRestriction = function ( type ) { + var $label = $( '<span>' ) + .addClass( 'mw-mmv-label mw-mmv-restriction-label' ) + .prop( 'title', mw.message( 'multimediaviewer-restriction-' + type ).text() ) + .tipsy( { + delay: mw.config.get( 'wgMultimediaViewer' ).tooltipDelay, + gravity: this.correctEW( 'se' ) + } ); + + $( '<span>' ) + .addClass( 'mw-mmv-restriction-label-inner mw-mmv-restriction-' + + ( type === 'default-and-others' ? 'default' : type ) ) + .text( mw.message( 'multimediaviewer-restriction-' + type ).text() ) + .appendTo( $label ); + + return $label; + }; + + /** + * Sets location data in the interface. + * + * @param {mw.mmv.model.Image} imageData + */ + MPP.setLocationData = function ( imageData ) { + var latsec, latitude, latmsg, latdeg, latremain, latmin, + longsec, longitude, longmsg, longdeg, longremain, longmin, + language; + + if ( !imageData.hasCoords() ) { + return; + } + + latitude = imageData.latitude >= 0 ? imageData.latitude : imageData.latitude * -1; + latmsg = 'multimediaviewer-geoloc-' + ( imageData.latitude >= 0 ? 'north' : 'south' ); + latdeg = Math.floor( latitude ); + latremain = latitude - latdeg; + latmin = Math.floor( ( latremain ) * 60 ); + + longitude = imageData.longitude >= 0 ? imageData.longitude : imageData.longitude * -1; + longmsg = 'multimediaviewer-geoloc-' + ( imageData.longitude >= 0 ? 'east' : 'west' ); + longdeg = Math.floor( longitude ); + longremain = longitude - longdeg; + longmin = Math.floor( ( longremain ) * 60 ); + + longremain -= longmin / 60; + latremain -= latmin / 60; + latsec = Math.round( latremain * 100 * 60 * 60 ) / 100; + longsec = Math.round( longremain * 100 * 60 * 60 ) / 100; + + this.$location.text( + mw.message( 'multimediaviewer-geolocation', + mw.message( + 'multimediaviewer-geoloc-coords', + + mw.message( + 'multimediaviewer-geoloc-coord', + mw.language.convertNumber( latdeg ), + mw.language.convertNumber( latmin ), + mw.language.convertNumber( latsec ), + mw.message( latmsg ).text() + ).text(), + + mw.message( + 'multimediaviewer-geoloc-coord', + mw.language.convertNumber( longdeg ), + mw.language.convertNumber( longmin ), + mw.language.convertNumber( longsec ), + mw.message( longmsg ).text() + ).text() + ).text() + ).text() + ); + + $.each( mw.language.data, function ( key ) { + language = key; + return false; + } ); + + this.$location.prop( 'href', ( + '//tools.wmflabs.org/geohack/geohack.php?pagename=' + + 'File:' + imageData.title.getMain() + + '¶ms=' + + Math.abs( imageData.latitude ) + ( imageData.latitude >= 0 ? '_N_' : '_S_' ) + + Math.abs( imageData.longitude ) + ( imageData.longitude >= 0 ? '_E_' : '_W_' ) + + '&language=' + language + ) ); + + this.$locationLi.removeClass( 'empty' ); + }; + + /** + * Set all the image information in the panel + * + * @param {mw.mmv.LightboxImage} image + * @param {mw.mmv.model.Image} imageData + * @param {mw.mmv.model.Repo} repoData + */ + MPP.setImageInfo = function ( image, imageData, repoData ) { + var panel = this; + + mw.mmv.attributionLogger.logAttribution( imageData ); + + if ( imageData.creationDateTime ) { + // Use the raw date until moment can try to interpret it + panel.setDateTime( imageData.creationDateTime ); + + this.formatDate( imageData.creationDateTime ).then( function ( formattedDate ) { + panel.setDateTime( formattedDate, true ); + } ); + } else if ( imageData.uploadDateTime ) { + // Use the raw date until moment can try to interpret it + panel.setDateTime( imageData.uploadDateTime ); + + this.formatDate( imageData.uploadDateTime ).then( function ( formattedDate ) { + panel.setDateTime( formattedDate ); + } ); + } + + this.buttons.set( imageData, repoData ); + this.description.set( imageData.description, image.caption ); + + this.setLicense( imageData.license, imageData.descriptionUrl ); + + this.setFileName( imageData.title.getMainText() ); + + // these handle text truncation and should be called when everything that can push text down + // (e.g. floated buttons) has already been laid out + this.setTitle( image, imageData ); + this.setCredit( imageData.attribution, imageData.source, imageData.author, imageData.authorCount, imageData.descriptionUrl ); + + if ( imageData.permission ) { + this.setPermission( imageData.permission ); + } + + if ( imageData.restrictions ) { + this.setRestrictions( imageData.restrictions ); + } + + this.setLocationData( imageData ); + + this.resetTruncatedText(); + this.scroller.unfreezeHeight(); + }; + + /** + * Show an error message, in case the data could not be loaded + * + * @param {string} title image title + * @param {string} error error message + */ + MPP.showError = function ( title, error ) { + this.$credit.text( mw.message( 'multimediaviewer-metadata-error', error ).text() ); + this.$title.html( title ); + }; + + /** + * Transforms a date string into localized, human-readable format. + * Unrecognized strings are returned unchanged. + * + * @param {string} dateString + * @return {jQuery.Deferred} + */ + MPP.formatDate = function ( dateString ) { + var deferred = $.Deferred(), + date; + + mw.loader.using( 'moment', function () { + /* global moment */ + date = moment( dateString ); + + if ( date.isValid() ) { + deferred.resolve( date.format( 'LL' ) ); + } else { + deferred.resolve( dateString ); + } + }, function ( error ) { + deferred.reject( error ); + if ( window.console && window.console.error ) { + window.console.error( 'mw.loader.using error when trying to load moment', error ); + } + } ); + + return deferred.promise(); + }; + + /** + * Shows truncated text in the title and credit (this also rearranges the layout a bit). + */ + MPP.revealTruncatedText = function () { + if ( this.$container.hasClass( 'mw-mmv-untruncated' ) ) { + return; + } + this.$container.addClass( 'mw-mmv-untruncated' ); + this.title.grow(); + this.creditField.grow(); + }; + + /** + * Undoes changes made by revealTruncatedText(). + */ + MPP.hideTruncatedText = function () { + if ( !this.$container.hasClass( 'mw-mmv-untruncated' ) ) { + return; + } + this.title.shrink(); + this.creditField.shrink(); + this.$container.removeClass( 'mw-mmv-untruncated' ); + }; + + /** + * Hide or reveal truncated text based on whether the panel is open. This is normally handled by + * MetadataPanelScroller, but when the panel is reset (e.g. on a prev/next event) sometimes the panel position can change without a panel , such as on a + * prev/next event; in such cases this function has to be called. + */ + MPP.resetTruncatedText = function () { + if ( this.scroller.panelIsOpen() ) { + this.revealTruncatedText(); + } else { + this.hideTruncatedText(); + } + }; + + mw.mmv.ui.MetadataPanel = MetadataPanel; +}( mediaWiki, jQuery, OO ) ); |