%PDF- %PDF-
Direktori : /www/varak.net/wiki.varak.net/extensions/MultimediaViewer/resources/mmv/ui/ |
Current File : /www/varak.net/wiki.varak.net/extensions/MultimediaViewer/resources/mmv/ui/mmv.ui.metadataPanel.js |
/* * 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.SafeStorage} 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.SafeStorage} 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 ) .on( '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' ) .on( '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' ) .on( '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' ) .on( '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; 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() ); 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=' + encodeURIComponent( mw.config.get( 'wgUserLanguage' ) ) ) ); 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 ) );