/* * 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 . */ ( function () { var TDP; /** * A simple popup dialog that can be opened and closed and can contain some HTML. * Due to the way tipsy works, there can be only one TipsyDialog and/or tipsy tooltip on the same element. * * @class mw.mmv.ui.TipsyDialog * @extends mw.mmv.ui.Element * @constructor * @param {jQuery} $anchor the element to which the popup is anchored. * @param {Object} options takes any tipsy option - see * https://github.com/jaz303/tipsy/blob/master/docs/src/index.html.erb#L298 */ function TipsyDialog( $anchor, options ) { mw.mmv.ui.Element.call( this, null ); // tipsy does the element construction so we don't need a container /** @property {jQuery} $anchor - */ this.$anchor = $anchor; /** @property {Object} options - */ this.options = $.extend( {}, this.defaultOptions, options ); /** @property {boolean} dirty Track whether tipsy settings changed and need to be reinitialized. */ this.dirty = false; /** @property {string|null} contentTitle Title of the dialog (optional) */ this.contentTitle = null; /** @property {string|null} contentBody Contents of the dialog */ this.contentBody = null; /** * @property {Function} closeProxy Proxied close function to be used as an event handler, so it can be * identified for removal. */ this.closeProxy = this.maybeCloseOnClick.bind( this ); } OO.inheritClass( TipsyDialog, mw.mmv.ui.Element ); TDP = TipsyDialog.prototype; /** * @property {Object} defaultOptions Tipsy defaults - see * https://github.com/jaz303/tipsy/blob/master/docs/src/index.html.erb#L298 */ TDP.defaultOptions = { // tipsy options trigger: 'manual', html: true, fade: false, offset: 0, gravity: 'sw' }; /** * @property {number} extraOffset offset adjustment to correct for the larger margins and tip size * compared to the standard tipsy style */ TDP.extraOffset = 10; /** * @private * @return {boolean} */ TDP.isInitialized = function () { return !!this.$anchor.tipsy( true ); }; /** * Returns the preprocessed version of an options object: * - directions are flipped on RTL documents * - standard classnames are applied * - HTML content is generated * The original object is not changed. * * @private * @param {Object} originalOptions * @return {Object} Preprocessed options */ TDP.getPreprocessedOptions = function ( originalOptions ) { var options = $.extend( {}, originalOptions ); if ( options.className ) { options.className += ' mw-mmv-tipsy-dialog'; } else { options.className = ' mw-mmv-tipsy-dialog'; } options.gravity = this.correctEW( options.gravity ); options.offset += this.extraOffset; options.fallback = this.generateContent( this.contentTitle, this.contentBody ); return options; }; /** * @private */ TDP.init = function () { var options; if ( !this.isInitialized() || this.dirty ) { options = this.getPreprocessedOptions( this.options ); this.$anchor.tipsy( options ); // add click handler to close the popup when clicking on X or outside // off is to make sure we won't end up with more then one - init() can be called multiple times this.$anchor.find( '.mw-mmv-tipsy-dialog-disable' ).add( document ) .off( 'click.mmv-tipsy-dialog', this.closeProxy ) .on( 'click.mmv-tipsy-dialog', this.closeProxy ); this.dirty = false; } }; /** * Open the dialog */ TDP.open = function () { this.init(); this.$anchor.tipsy( 'enable' ).tipsy( 'show' ); }; /** * Close the dialog */ TDP.close = function () { if ( this.isInitialized() ) { this.$anchor.tipsy( 'hide' ).tipsy( 'disable' ); } }; /** * Return the main popup element. * * @return {jQuery|null} */ TDP.getPopup = function () { var tipsyData = this.$anchor.tipsy( true ); return tipsyData ? tipsyData.$tip : null; }; /** * Set dialog contents * * @param {string|null} title title of the dialog (plain text; escaping will be handled by TipsyDialog) * @param {string|null} body content of the dialog (HTML; no escaping) */ TDP.setContent = function ( title, body ) { this.contentTitle = title; this.contentBody = body; this.dirty = true; }; /** * @private * @param {string} [title] * @param {string} [body] * @return {string} */ TDP.generateContent = function ( title, body ) { body = body || ''; if ( title ) { body = '
' + mw.html.escape( title ) + '
' + body; } return '
' + body; }; /** * Click handler to be set on the document. * * @private * @param {jQuery.Event} event */ TDP.maybeCloseOnClick = function ( event ) { var $clickTarget = $( event.target ); if ( $clickTarget.closest( this.getPopup() ).length === 0 || // click was outside the dialog $clickTarget.closest( '.mw-mmv-tipsy-dialog-disable' ).length > 0 // click was on the close icon ) { this.close(); } }; mw.mmv.ui.TipsyDialog = TipsyDialog; }() );