mediawiki-extensions-WikiEd.../modules/jquery.wikiEditor.dialogs.js
Schnark 6602d905ee WikiEditor: Move HTML for dialogs to separate files
Move the HTML for the dialogs to separate template files,
using the template mechanism from core.
It is still possible to specify the HTML directly as before,
to be used in gadgets etc.

Change-Id: Ia7ad5aaa9cac429d1c9d706bdf6760e3eda358bc
2015-08-14 13:07:27 +00:00

238 lines
8.1 KiB
JavaScript

/**
* Dialog Module for wikiEditor
*/
( function ( $, mw ) {
$.wikiEditor.modules.dialogs = {
/**
* Compatability map
*/
browsers: {
// Left-to-right languages
ltr: {
msie: [['>=', 7]],
// jQuery UI appears to be broken in FF 2.0 - 2.0.0.4
firefox: [
['>=', 2], ['!=', '2.0'], ['!=', '2.0.0.1'], ['!=', '2.0.0.2'], ['!=', '2.0.0.3'], ['!=', '2.0.0.4']
],
opera: [['>=', 9.6]],
safari: [['>=', 3]],
chrome: [['>=', 3]]
},
// Right-to-left languages
rtl: {
msie: [['>=', 7]],
// jQuery UI appears to be broken in FF 2.0 - 2.0.0.4
firefox: [
['>=', 2], ['!=', '2.0'], ['!=', '2.0.0.1'], ['!=', '2.0.0.2'], ['!=', '2.0.0.3'], ['!=', '2.0.0.4']
],
opera: [['>=', 9.6]],
safari: [['>=', 3]],
chrome: [['>=', 3]]
}
},
/**
* API accessible functions
*/
api: {
addDialog: function ( context, data ) {
$.wikiEditor.modules.dialogs.fn.create( context, data );
},
openDialog: function ( context, module ) {
if ( module in $.wikiEditor.modules.dialogs.modules ) {
var mod = $.wikiEditor.modules.dialogs.modules[module],
$dialog = $( '#' + mod.id );
if ( $dialog.length === 0 ) {
$.wikiEditor.modules.dialogs.fn.reallyCreate( context, mod, module );
$dialog = $( '#' + mod.id );
}
// Workaround for bug in jQuery UI: close button in top right retains focus
$dialog.closest( '.ui-dialog' )
.find( '.ui-dialog-titlebar-close' )
.removeClass( 'ui-state-focus' );
$dialog.dialog( 'open' );
}
},
closeDialog: function ( context, module ) {
if ( module in $.wikiEditor.modules.dialogs.modules ) {
$( '#' + $.wikiEditor.modules.dialogs.modules[module].id ).dialog( 'close' );
}
}
},
/**
* Internally used functions
*/
fn: {
/**
* Creates a dialog module within a wikiEditor
*
* @param {Object} context Context object of editor to create module in
* @param {Object} config Configuration object to create module from
*/
create: function ( context, config ) {
var mod, module, filtered, i, $existingDialog;
// Defer building of modules, unless they require immediate creation
for ( mod in config ) {
module = config[mod];
// Only create the dialog if it's supported, isn't filtered and doesn't exist yet
filtered = false;
if ( typeof module.filters !== 'undefined' ) {
for ( i = 0; i < module.filters.length; i++ ) {
if ( $( module.filters[i] ).length === 0 ) {
filtered = true;
break;
}
}
}
// If the dialog already exists, but for another textarea, simply remove it
$existingDialog = $( '#' + module.id );
if ( $existingDialog.length > 0 && $existingDialog.data( 'context' ).$textarea !== context.$textarea ) {
$existingDialog.remove();
}
// Re-select from the DOM, we might have removed the dialog just now
$existingDialog = $( '#' + module.id );
if ( !filtered && $.wikiEditor.isSupported( module ) && $existingDialog.length === 0 ) {
$.wikiEditor.modules.dialogs.modules[mod] = module;
context.$textarea.trigger( 'wikiEditor-dialogs-setup-' + mod );
// If this dialog requires immediate creation, create it now
if ( typeof module.immediateCreate !== 'undefined' && module.immediateCreate ) {
$.wikiEditor.modules.dialogs.fn.reallyCreate( context, module, mod );
}
}
}
},
/**
* Build the actual dialog. This done on-demand rather than in create()
* @param {Object} context Context object of editor dialog belongs to
* @param {Object} module Dialog module object
* @param {String} name Dialog name (key in $.wikiEditor.modules.dialogs.modules)
*/
reallyCreate: function ( context, module, name ) {
var msg, dialogDiv, $content,
configuration = module.dialog;
// Add some stuff to configuration
configuration.bgiframe = true;
configuration.autoOpen = false;
// By default our dialogs are modal, unless explicitely defined in their specific configuration.
if ( typeof configuration.modal === 'undefined' ) {
configuration.modal = true;
}
configuration.title = $.wikiEditor.autoMsg( module, 'title' );
// Transform messages in keys
// Stupid JS won't let us do stuff like
// foo = { mw.msg( 'bar' ): baz }
configuration.newButtons = {};
for ( msg in configuration.buttons ) {
configuration.newButtons[mw.msg( msg )] = configuration.buttons[msg];
}
configuration.buttons = configuration.newButtons;
if ( module.htmlTemplate ) {
$content = mw.template.get( 'jquery.wikiEditor.dialogs.config', module.htmlTemplate ).render();
} else {
$content = $( $.parseHTML( module.html ) );
}
// Create the dialog <div>
dialogDiv = $( '<div>' )
.attr( 'id', module.id )
.append( $content )
.data( 'context', context )
.appendTo( $( 'body' ) )
.each( module.init )
.dialog( configuration );
// Set tabindexes on buttons added by .dialog()
$.wikiEditor.modules.dialogs.fn.setTabindexes( dialogDiv.closest( '.ui-dialog' )
.find( 'button' ).not( '[tabindex]' ) );
if ( !( 'resizeme' in module ) || module.resizeme ) {
dialogDiv
.bind( 'dialogopen', $.wikiEditor.modules.dialogs.fn.resize )
.find( '.ui-tabs' ).bind( 'tabsshow', function () {
$( this ).closest( '.ui-dialog-content' ).each(
$.wikiEditor.modules.dialogs.fn.resize );
} );
}
dialogDiv.bind( 'dialogclose', function () {
context.fn.restoreSelection();
} );
// Let the outside world know we set up this dialog
context.$textarea.trigger( 'wikiEditor-dialogs-loaded-' + name );
},
/**
* Resize a dialog so its contents fit
*
* Usage: dialog.each( resize ); or dialog.bind( 'blah', resize );
* NOTE: This function assumes $.ui.dialog has already been loaded
*/
resize: function () {
var oldWS, thisWidth, wrapperWidth,
wrapper = $( this ).closest( '.ui-dialog' ),
oldWidth = wrapper.width(),
// Make sure elements don't wrapped so we get an accurate idea of whether they really fit. Also temporarily show
// hidden elements. Work around jQuery bug where <div style="display: inline;"/> inside a dialog is both
// :visible and :hidden
oldHidden = $( this ).find( '*' ).not( ':visible' );
// Save the style attributes of the hidden elements to restore them later. Calling hide() after show() messes up
// for elements hidden with a class
oldHidden.each( function () {
$( this ).data( 'oldstyle', $( this ).attr( 'style' ) );
} );
oldHidden.show();
oldWS = $( this ).css( 'white-space' );
$( this ).css( 'white-space', 'nowrap' );
if ( wrapper.width() <= $( this ).get( 0 ).scrollWidth ) {
thisWidth = $( this ).data( 'thisWidth' ) ? $( this ).data( 'thisWidth' ) : 0;
thisWidth = Math.max( $( this ).get( 0 ).width, thisWidth );
$( this ).width( thisWidth );
$( this ).data( 'thisWidth', thisWidth );
wrapperWidth = $( this ).data( 'wrapperWidth' ) ? $( this ).data( 'wrapperWidth' ) : 0;
wrapperWidth = Math.max( wrapper.get( 0 ).scrollWidth, wrapperWidth );
wrapper.width( wrapperWidth );
$( this ).data( 'wrapperWidth', wrapperWidth );
$( this ).dialog( { 'width': wrapper.width() } );
wrapper.css( 'left', parseInt( wrapper.css( 'left' ), 10 ) - ( wrapper.width() - oldWidth ) / 2 );
}
$( this ).css( 'white-space', oldWS );
oldHidden.each( function () {
$( this ).attr( 'style', $( this ).data( 'oldstyle' ) );
} );
},
/**
* Set the right tabindexes on elements in a dialog
* @param $elements Elements to set tabindexes on. If they already have tabindexes, this function can behave a bit weird
*/
setTabindexes: function ( $elements ) {
// Get the highest tab index
var tabIndex = $( document ).lastTabIndex() + 1;
$elements.each( function () {
$( this ).attr( 'tabindex', tabIndex++ );
} );
}
},
// This stuff is just hanging here, perhaps we could come up with a better home for this stuff
modules: {},
quickDialog: function ( body, settings ) {
$( '<div>' )
.text( body )
.appendTo( $( 'body' ) )
.dialog( $.extend( {
bgiframe: true,
modal: true
}, settings ) )
.dialog( 'open' );
}
};
}( jQuery, mediaWiki ) );