' )
.addClass( 'mw-mmv-about-links' )
.append(
this.$mmvAboutLink,
separator,
this.$mmvDiscussLink,
separator,
this.$mmvHelpLink
)
.appendTo( this.$imageMetadata );
};
// *********************************
// ******** Setting methods ********
// *********************************
/**
* Sets the link to the user page where possible
* @param {mw.mmv.model.Repo} repoData
* @param {string} username
* @param {string} gender
*/
MPP.setUserPageLink = function ( repoData, username, gender ) {
var userpage = 'User:' + username,
articlePath = repoData.getArticlePath(),
userlink = articlePath.replace( '$1', userpage );
this.$username
.text(
mw.message( 'multimediaviewer-userpage-link', username, gender ).text()
)
.prop( 'href', userlink );
this.$usernameLi.toggleClass( 'empty', !username );
};
/**
* Sets the file title in the panel
* @param {string} title
*/
MPP.setFileTitle = function ( title ) {
this.title.set( title );
};
/**
* Sets the upload or creation date and time in the panel
* @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' );
};
/**
* Set source and author.
* @param {string} source With unsafe HTML
* @param {string} author With unsafe HTML
* @param {string} filepageUrl URL of the file page (used when other data is not available)
*/
MPP.setCredit = function ( source, author, filepageUrl ) {
// sanitization will be done by TruncatableTextField.set()
if ( author && source ) {
this.creditField.set(
mw.message(
'multimediaviewer-credit',
this.wrapAuthor( author ),
this.wrapSource( source )
).plain()
);
} else if ( author ) {
this.creditField.set( this.wrapAuthor( author ) );
} else if ( source ) {
this.creditField.set( this.wrapSource( source ) );
} else {
this.creditField.set(
$( '
' )
.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 $( '' )
.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
* @return {string} unsafe HTML
*/
MPP.wrapAuthor = function ( author ) {
return $( '' )
.addClass( 'mw-mmv-author' )
.append( $.parseHTML( author ) )
.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;
if ( license ) {
shortName = license.getShortName();
url = license.deedUrl || filePageUrl;
isCc = license.isCc();
} else {
shortName = mw.message( 'multimediaviewer-license-default' ).text();
url = filePageUrl;
isCc = false;
}
this.$license
.text( shortName )
.prop( 'href', url )
.prop( 'target', license && license.deedUrl ? '_blank' : '' );
this.$licenseLi
.toggleClass( 'cc-license', isCc )
.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 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, value ) {
value = 'go away jshint';
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
* @param {mw.mmv.model.User} user
*/
MPP.setImageInfo = function ( image, imageData, repoData, user ) {
var panel = this,
fileTitle = image.filePageTitle;
mw.mmv.attributionLogger.logAttribution( imageData );
this.setFileTitle( fileTitle.getNameText() );
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.setCredit( imageData.source, imageData.author, imageData.descriptionUrl );
this.buttons.set( imageData, repoData );
this.description.set( imageData.description, image.caption );
this.setLicense( imageData.license, imageData.descriptionUrl );
if ( imageData.permission ) {
this.setPermission( imageData.permission );
}
this.setLocationData( imageData );
if ( user ) {
this.setUserPageLink( repoData, imageData.lastUploader, user.gender );
}
};
/**
* Show an error message, in case the data could not be loaded
* @param {string} error
*/
MPP.showError = function ( error ) {
this.$title.addClass( 'error' )
.text( mw.message( 'multimediaviewer-metadata-error', error ).text() );
};
/**
* 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 () {
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();
};
/**
* Calls #revealTruncatedText() or #hideTruncatedText() based on the current state.
*/
MPP.toggleTruncatedText = function () {
if ( this.$container.hasClass( 'mw-mmv-untruncated' ) ) {
this.hideTruncatedText();
} else {
this.revealTruncatedText();
}
};
/**
* Shows truncated text in the title and credit (this also rearranges the layout a bit).
* Opens the panel partially to make sure the revealed text is visible.
* @param {boolean} noScroll if set, do not scroll the panel (because the function was triggered from a
* scroll event in the first place)
*/
MPP.revealTruncatedText = function ( noScroll ) {
if ( this.$container.hasClass( 'mw-mmv-untruncated' ) ) {
// avoid self-triggering via reveal -> scroll -> reveal
return;
}
this.$container.addClass( 'mw-mmv-untruncated' );
this.title.grow();
this.creditField.grow();
if ( this.aboveFoldIsLargerThanNormal() && !noScroll ) {
this.scroller.scrollIntoView( this.description.$imageDescDiv, 500 );
}
};
/**
* Undoes changes made by revealTruncatedText().
*/
MPP.hideTruncatedText = function () {
if ( !this.$container.hasClass( 'mw-mmv-untruncated' ) ) {
// avoid double-triggering
return;
}
this.title.shrink();
this.creditField.shrink();
this.$container.removeClass( 'mw-mmv-untruncated' );
};
/**
* Returns true if the above-fold part of the metadata panel changed size (due to text overflow) after
* calling revealTruncatedText().
*/
MPP.aboveFoldIsLargerThanNormal = function () {
return this.$aboveFold.height() > parseInt( this.$aboveFold.css( 'min-height' ), 10 ) ||
this.$credit.height() > parseInt( this.$aboveFold.css( 'padding-bottom' ), 10 );
};
mw.mmv.ui.MetadataPanel = MetadataPanel;
}( mediaWiki, jQuery, OO ) );