/* * JavaScript for WikiEditor Dialogs */ $( document ).ready( function() { /* if ( !$.wikiEditor.isSupported( $.wikiEditor.modules.dialogs ) ) { return; } */ // Replace icons $( '#wpTextbox1' ) .wikiEditor( 'removeFromToolbar', { 'section': 'main', 'group': 'insert', 'tool': 'xlink' } ) .wikiEditor( 'removeFromToolbar', { 'section': 'main', 'group': 'insert', 'tool': 'ilink' } ) .wikiEditor( 'removeFromToolbar', { 'section': 'main', 'group': 'insert', 'tool': 'reference' } ) .wikiEditor( 'removeFromToolbar', { 'section': 'advanced', 'group': 'insert', 'tool': 'table' } ) .wikiEditor( 'addToToolbar', { 'section': 'main', 'group': 'insert', 'tools': { 'link': { 'labelMsg': 'wikieditor-toolbar-tool-link', 'type': 'button', 'icon': 'insert-link.png', 'offset': [2, -1654], 'action': { 'type': 'dialog', 'module': 'insert-link' } }, 'reference': { 'labelMsg': 'wikieditor-toolbar-tool-reference', 'type': 'button', 'icon': 'insert-reference.png', 'offset': [2, -1798], 'action': { 'type': 'dialog', 'module': 'insert-reference' } } } } ) .wikiEditor( 'addToToolbar', { 'section': 'advanced', 'group': 'insert', 'tools': { 'table': { 'labelMsg': 'wikieditor-toolbar-tool-table', 'type': 'button', 'icon': 'insert-table.png', 'offset': [2, -1942], 'action': { 'type': 'dialog', 'module': 'insert-table' } } } } ) .wikiEditor( 'addToToolbar', { 'section': 'advanced', 'groups': { 'search': { 'tools': { 'replace': { 'labelMsg': 'wikieditor-toolbar-tool-replace', 'type': 'button', 'icon': 'search-replace.png', 'offset': [-70, -214], 'action': { 'type': 'dialog', 'module': 'search-and-replace' } } } } } } ); // Add dialogs module $( '#wpTextbox1' ).wikiEditor( 'addModule', { 'dialogs': { 'insert-link': { titleMsg: 'wikieditor-toolbar-tool-link-title', id: 'wikieditor-toolbar-link-dialog', html: '\
\
\ \ \ \
\
\ \ \
\
\
\ \ \
\
\ \ \
\
\
', init: function() { function isExternalLink( s ) { // The following things are considered to be external links: // * Starts a URL protocol // * Starts with www. // All of these are potentially valid titles, and the latter two categories match about 6300 // titles in enwiki's ns0. Out of 6.9M titles, that's 0.09% if ( typeof arguments.callee.regex == 'undefined' ) { // Cache the regex arguments.callee.regex = new RegExp( "^(" + wgUrlProtocols + "|www\\.)", 'i'); } return s.match( arguments.callee.regex ); } // Updates the status indicator above the target link function updateWidget( status ) { $( '#wikieditor-toolbar-link-int-target-status' ).children().hide(); $( '#wikieditor-toolbar-link-int-target' ).parent() .removeClass( 'status-invalid status-external status-notexists status-exists status-loading' ); if ( status ) { $( '#wikieditor-toolbar-link-int-target-status-' + status ).show(); $( '#wikieditor-toolbar-link-int-target' ).parent().addClass( 'status-' + status ); } if ( status == 'invalid' ) { $( '.ui-dialog:visible .ui-dialog-buttonpane button:first' ) .attr( 'disabled', true ) .addClass( 'disabled' ); } else { $( '.ui-dialog:visible .ui-dialog-buttonpane button:first' ) .removeAttr('disabled') .removeClass('disabled'); } } // Updates the UI to show if the page title being inputed by the user exists or not // accepts parameter internal for bypassing external link detection function updateExistence( internal ) { // ensure the internal parameter is a boolean if ( internal != true ) internal = false; // Abort previous request var request = $( '#wikieditor-toolbar-link-int-target-status' ).data( 'request' ); if ( request ) { request.abort(); } var target = $( '#wikieditor-toolbar-link-int-target' ).val(); var cache = $( '#wikieditor-toolbar-link-int-target-status' ).data( 'existencecache' ); if ( cache[target] ) { updateWidget( cache[target] ); return; } if ( target.replace( /^\s+$/,'' ) == '' ) { // Hide the widget when the textbox is empty updateWidget( false ); return; } // If the forced internal paremter was not true, check if the target is an external link if ( !internal && isExternalLink( target ) ) { updateWidget( 'external' ); return; } if ( target.indexOf( '|' ) != -1 ) { // Title contains | , which means it's invalid // but confuses the API. Show invalid and bypass API updateWidget( 'invalid' ); return; } // Show loading spinner while waiting for the API to respond updateWidget( 'loading' ); // Call the API to check page status, saving the request object so it can be aborted if // necessary $( '#wikieditor-toolbar-link-int-target-status' ).data( 'request', $.ajax( { url: wgScriptPath + '/api.php', dataType: 'json', data: { 'action': 'query', 'indexpageids': '', 'titles': target, 'converttitles': '', 'format': 'json' }, success: function( data ) { var status; if ( !data || typeof data.query == 'undefined' ) { // This happens in some weird cases status = false; } else { var page = data.query.pages[data.query.pageids[0]]; status = 'exists'; if ( typeof page.missing != 'undefined' ) status = 'notexists'; else if ( typeof page.invalid != 'undefined' ) status = 'invalid'; } // Cache the status of the link target if the force internal parameter was not // passed if ( !internal ) cache[target] = status; updateWidget( status ); } } ) ); } $( '#wikieditor-toolbar-link-type-int, #wikieditor-toolbar-link-type-ext' ).click( function() { if( $( '#wikieditor-toolbar-link-type-ext' ).is( ':checked' ) ) { // Abort previous request var request = $( '#wikieditor-toolbar-link-int-target-status' ).data( 'request' ); if ( request ) { request.abort(); } updateWidget( 'external' ); } if( $( '#wikieditor-toolbar-link-type-int' ).is( ':checked' ) ) updateExistence( true ); }); // Set labels of tabs based on rel values var msg = mediaWiki.msg; $(this).find( '[rel]' ).each( function() { $(this).text( msg.get( $(this).attr( 'rel' ) ) ); }); // Set tabindexes on form fields $.wikiEditor.modules.dialogs.fn.setTabindexes( $(this).find( 'input' ).not( '[tabindex]' ) ); // Setup the tooltips in the textboxes $( '#wikieditor-toolbar-link-int-target' ) .data( 'tooltip', msg.get( 'wikieditor-toolbar-tool-link-int-target-tooltip' ) ); $( '#wikieditor-toolbar-link-int-text' ) .data( 'tooltip', msg.get( 'wikieditor-toolbar-tool-link-int-text-tooltip' ) ); $( '#wikieditor-toolbar-link-int-target, #wikieditor-toolbar-link-int-text' ) .each( function() { var tooltip = msg.get( $( this ).attr( 'id' ) + '-tooltip' ); if ( $( this ).val() == '' ) $( this ) .addClass( 'wikieditor-toolbar-dialog-hint' ) .val( $( this ).data( 'tooltip' ) ) .data( 'tooltip-mode', true ); } ) .focus( function() { if( $( this ).val() == $( this ).data( 'tooltip' ) ) { $( this ) .val( '' ) .removeClass( 'wikieditor-toolbar-dialog-hint' ) .data( 'tooltip-mode', false ); } }) .bind( 'change', function() { if ( $( this ).val() != $( this ).data( 'tooltip' ) ) { $( this ) .removeClass( 'wikieditor-toolbar-dialog-hint' ) .data( 'tooltip-mode', false ); } }) .bind( 'blur', function() { if ( $( this ).val() == '' ) { $( this ) .addClass( 'wikieditor-toolbar-dialog-hint' ) .val( $( this ).data( 'tooltip' ) ) .data( 'tooltip-mode', true ); } }); // Automatically copy the value of the internal link page title field to the link text field unless the // user has changed the link text field - this is a convenience thing since most link texts are going to // be the the same as the page title - Also change the internal/external radio button accordingly $( '#wikieditor-toolbar-link-int-target' ).bind( 'change keydown paste cut', function() { // $(this).val() is the old value, before the keypress - Defer this until $(this).val() has // been updated setTimeout( function() { if ( isExternalLink( $( '#wikieditor-toolbar-link-int-target' ).val() ) ) { $( '#wikieditor-toolbar-link-type-ext' ).attr( 'checked', 'checked' ); updateWidget( 'external' ); } else { $( '#wikieditor-toolbar-link-type-int' ).attr( 'checked', 'checked' ); updateExistence(); } if ( $( '#wikieditor-toolbar-link-int-text' ).data( 'untouched' ) ) if ( $( '#wikieditor-toolbar-link-int-target' ).val() == $( '#wikieditor-toolbar-link-int-target' ).data( 'tooltip' ) ) { $( '#wikieditor-toolbar-link-int-text' ) .addClass( 'wikieditor-toolbar-dialog-hint' ) .val( $( '#wikieditor-toolbar-link-int-text' ).data( 'tooltip' ) ) .change(); } else { $( '#wikieditor-toolbar-link-int-text' ) .val( $( '#wikieditor-toolbar-link-int-target' ).val() ) .change(); } }, 0 ); }); $( '#wikieditor-toolbar-link-int-text' ).bind( 'change keydown paste cut', function() { var oldVal = $(this).val(); var that = this; setTimeout( function() { if ( $(that).val() != oldVal ) $(that).data( 'untouched', false ); }, 0 ); }); // Add images to the page existence widget, which will be shown mutually exclusively to communicate if // the page exists, does not exist or the title is invalid (like if it contains a | character) var existsMsg = msg.get( 'wikieditor-toolbar-tool-link-int-target-status-exists' ); var notexistsMsg = msg.get( 'wikieditor-toolbar-tool-link-int-target-status-notexists' ); var invalidMsg = msg.get( 'wikieditor-toolbar-tool-link-int-target-status-invalid' ); var externalMsg = msg.get( 'wikieditor-toolbar-tool-link-int-target-status-external' ); var loadingMsg = msg.get( 'wikieditor-toolbar-tool-link-int-target-status-loading' ); $( '#wikieditor-toolbar-link-int-target-status' ) .append( $( '
' ) .attr( 'id', 'wikieditor-toolbar-link-int-target-status-exists' ) .append( existsMsg ) ) .append( $( '
' ) .attr( 'id', 'wikieditor-toolbar-link-int-target-status-notexists' ) .append( notexistsMsg ) ) .append( $( '
' ) .attr( 'id', 'wikieditor-toolbar-link-int-target-status-invalid' ) .append( invalidMsg ) ) .append( $( '
' ) .attr( 'id', 'wikieditor-toolbar-link-int-target-status-external' ) .append( externalMsg ) ) .append( $( '
' ) .attr( 'id', 'wikieditor-toolbar-link-int-target-status-loading' ) .append( $( '' ).attr( { 'src': $.wikiEditor.imgPath + 'dialogs/' + 'loading.gif', 'alt': loadingMsg, 'title': loadingMsg } ) ) ) .data( 'existencecache', {} ) .children().hide(); $( '#wikieditor-toolbar-link-int-target' ) .bind( 'keyup paste cut', function() { // Cancel the running timer if applicable if ( typeof $(this).data( 'timerID' ) != 'undefined' ) { clearTimeout( $(this).data( 'timerID' ) ); } // Delay fetch for a while // FIXME: Make 120 configurable elsewhere var timerID = setTimeout( updateExistence, 120 ); $(this).data( 'timerID', timerID ); } ) .change( function() { // Cancel the running timer if applicable if ( typeof $(this).data( 'timerID' ) != 'undefined' ) { clearTimeout( $(this).data( 'timerID' ) ); } // Fetch right now updateExistence(); } ); // Title suggestions $( '#wikieditor-toolbar-link-int-target' ).data( 'suggcache', {} ).suggestions( { fetch: function( query ) { var that = this; var title = $(this).val(); if ( isExternalLink( title ) || title.indexOf( '|' ) != -1 || title == '') { $(this).suggestions( 'suggestions', [] ); return; } var cache = $(this).data( 'suggcache' ); if ( typeof cache[title] != 'undefined' ) { $(this).suggestions( 'suggestions', cache[title] ); return; } var request = $.ajax( { url: wgScriptPath + '/api.php', data: { 'action': 'opensearch', 'search': title, 'namespace': 0, 'suggest': '', 'format': 'json' }, dataType: 'json', success: function( data ) { cache[title] = data[1]; $(that).suggestions( 'suggestions', data[1] ); } }); $(this).data( 'request', request ); }, cancel: function() { var request = $(this).data( 'request' ); if ( request ) request.abort(); } }); }, dialog: { width: 500, dialogClass: 'wikiEditor-toolbar-dialog', buttons: { 'wikieditor-toolbar-tool-link-insert': function() { function escapeInternalText( s ) { // FIXME: Should this escape [[ too? Seems to work without that return s.replace( /(]{2,})/g, '$1' ); } function escapeExternalTarget( s ) { return s.replace( / /g, '%20' ) .replace( /\[/g, '%5B' ) .replace( /]/g, '%5D' ); } function escapeExternalText( s ) { // FIXME: Should this escape [ too? Seems to work without that return s.replace( /(]+)/g, '$1' ); } var insertText = ''; var whitespace = $( '#wikieditor-toolbar-link-dialog' ).data( 'whitespace' ); var target = $( '#wikieditor-toolbar-link-int-target' ).val(); var text = $( '#wikieditor-toolbar-link-int-text' ).val(); // check if the tooltips were passed as target or text if ( $( '#wikieditor-toolbar-link-int-target' ).data( 'tooltip-mode' ) ) target = ""; if ( $( '#wikieditor-toolbar-link-int-text' ).data( 'tooltip-mode' ) ) text = ""; var msg = mediaWiki.msg; if ( target == '' ) { alert( msg.get( 'wikieditor-toolbar-tool-link-empty' ) ); return; } if ( $.trim( text ) == '' ) { // [[Foo| ]] creates an invisible link // Instead, generate [[Foo|]] text = ''; } if ( $( '#wikieditor-toolbar-link-type-int' ).is( ':checked' ) ) { // FIXME: Exactly how fragile is this? if ( $( '#wikieditor-toolbar-link-int-target-status-invalid' ).is( ':visible' ) ) { // Refuse to add links to invalid titles alert( msg.get( 'wikieditor-toolbar-tool-link-int-invalid' ) ); return; } if ( target == text || !text.length ) insertText = '[[' + target + ']]'; else insertText = '[[' + target + '|' + escapeInternalText( text ) + ']]'; } else { // Prepend http:// if there is no protocol if ( !target.match( /^[a-z]+:\/\/./ ) ) target = 'http://' + target; // Detect if this is really an internal link in disguise var match = target.match( $(this).data( 'articlePathRegex' ) ); if ( match && !$(this).data( 'ignoreLooksInternal' ) ) { var buttons = { }; var that = this; buttons[ msg.get( 'wikieditor-toolbar-tool-link-lookslikeinternal-int' ) ] = function() { $( '#wikieditor-toolbar-link-int-target' ).val( match[1] ).change(); $(this).dialog( 'close' ); }; buttons[ msg.get( 'wikieditor-toolbar-tool-link-lookslikeinternal-ext' ) ] = function() { $(that).data( 'ignoreLooksInternal', true ); $(that).closest( '.ui-dialog' ).find( 'button:first' ).click(); $(that).data( 'ignoreLooksInternal', false ); $(this).dialog( 'close' ); }; $.wikiEditor.modules.dialogs.quickDialog( msg.get( 'wikieditor-toolbar-tool-link-lookslikeinternal', match[1] ), { buttons: buttons } ); return; } var escTarget = escapeExternalTarget( target ); var escText = escapeExternalText( text ); if ( escTarget == escText ) insertText = escTarget; else if ( text == '' ) insertText = '[' + escTarget + ']'; else insertText = '[' + escTarget + ' ' + escText + ']'; } // Preserve whitespace in selection when replacing if ( whitespace ) insertText = whitespace[0] + insertText + whitespace[1]; $(this).dialog( 'close' ); $.wikiEditor.modules.toolbar.fn.doAction( $(this).data( 'context' ), { type: 'replace', options: { pre: insertText } }, $(this) ); // Blank form $( '#wikieditor-toolbar-link-int-target, #wikieditor-toolbar-link-int-text' ).val( '' ); $( '#wikieditor-toolbar-link-type-int, #wikieditor-toolbar-link-type-ext' ) .attr( 'checked', '' ); }, 'wikieditor-toolbar-tool-link-cancel': function() { // Clear any saved selection state var context = $(this).data( 'context' ); context.fn.restoreCursorAndScrollTop(); $(this).dialog( 'close' ); } }, open: function() { // Cache the articlepath regex $(this).data( 'articlePathRegex', new RegExp( '^' + RegExp.escape( wgServer + wgArticlePath ) .replace( /\\\$1/g, '(.*)' ) + '$' ) ); // Pre-fill the text fields based on the current selection var context = $(this).data( 'context' ); // Restore and immediately save selection state, needed for inserting stuff later context.fn.restoreCursorAndScrollTop(); context.fn.saveCursorAndScrollTop(); var selection = context.$textarea.textSelection( 'getSelection' ); $( '#wikieditor-toolbar-link-int-target' ).focus(); // Trigger the change event, so the link status indicator is up to date $( '#wikieditor-toolbar-link-int-target' ).change(); $( '#wikieditor-toolbar-link-dialog' ).data( 'whitespace', [ '', '' ] ); if ( selection != '' ) { var target, text, type; var matches; if ( ( matches = selection.match( /^(\s*)\[\[([^\]\|]+)(\|([^\]\|]*))?\]\](\s*)$/ ) ) ) { // [[foo|bar]] or [[foo]] target = matches[2]; text = ( matches[4] ? matches[4] : matches[2] ); type = 'int'; // Preserve whitespace when replacing $( '#wikieditor-toolbar-link-dialog' ).data( 'whitespace', [ matches[1], matches[5] ] ); } else if ( ( matches = selection.match( /^(\s*)\[([^\] ]+)( ([^\]]+))?\](\s*)$/ ) ) ) { // [http://www.example.com foo] or [http://www.example.com] target = matches[2]; text = ( matches[4] ? matches[4] : '' ); type = 'ext'; // Preserve whitespace when replacing $( '#wikieditor-toolbar-link-dialog' ).data( 'whitespace', [ matches[1], matches[5] ] ); } else { // Trim any leading and trailing whitespace from the selection, // but preserve it when replacing target = text = $.trim( selection ); if ( target.length < selection.length ) { $( '#wikieditor-toolbar-link-dialog' ).data( 'whitespace', [ selection.substr( 0, selection.indexOf( target.charAt( 0 ) ) ), selection.substr( selection.lastIndexOf( target.charAt( target.length - 1 ) ) + 1 ) ] ); } } // Change the value by calling val() doesn't trigger the change event, so let's do that // ourselves if ( typeof text != 'undefined' ) $( '#wikieditor-toolbar-link-int-text' ).val( text ).change(); if ( typeof target != 'undefined' ) $( '#wikieditor-toolbar-link-int-target' ).val( target ).change(); if ( typeof type != 'undefined' ) $( '#wikieditor-toolbar-link-' + type ).attr( 'checked', 'checked' ); } $( '#wikieditor-toolbar-link-int-text' ).data( 'untouched', $( '#wikieditor-toolbar-link-int-text' ).val() == $( '#wikieditor-toolbar-link-int-target' ).val() || $( '#wikieditor-toolbar-link-int-text' ).hasClass( 'wikieditor-toolbar-dialog-hint' ) ); $( '#wikieditor-toolbar-link-int-target' ).suggestions(); //don't overwrite user's text if( selection != '' ){ $( '#wikieditor-toolbar-link-int-text' ).data( 'untouched', false ); } $( '#wikieditor-toolbar-link-int-text, #wikiedit-toolbar-link-int-target' ) .each( function() { if ( $(this).val() == '' ) $(this).parent().find( 'label' ).show(); }); if ( !( $(this).data( 'dialogkeypressset' ) ) ) { $(this).data( 'dialogkeypressset', true ); // Execute the action associated with the first button // when the user presses Enter $(this).closest( '.ui-dialog' ).keypress( function( e ) { if ( ( e.keyCode || e.which ) == 13 ) { var button = $(this).data( 'dialogaction' ) || $(this).find( 'button:first' ); button.click(); e.preventDefault(); } }); // Make tabbing to a button and pressing // Enter do what people expect $(this).closest( '.ui-dialog' ).find( 'button' ).focus( function() { $(this).closest( '.ui-dialog' ).data( 'dialogaction', this ); }); } } } }, 'insert-reference': { titleMsg: 'wikieditor-toolbar-tool-reference-title', id: 'wikieditor-toolbar-reference-dialog', html: '\
\
\
\ \ \
\
\
', init: function() { // Insert translated strings into labels $( this ).find( '[rel]' ).each( function() { $( this ).text( mediaWiki.msg.get( $( this ).attr( 'rel' ) ) ); } ); }, dialog: { dialogClass: 'wikiEditor-toolbar-dialog', width: 590, buttons: { 'wikieditor-toolbar-tool-reference-insert': function() { var insertText = $( '#wikieditor-toolbar-reference-text' ).val(); var whitespace = $( '#wikieditor-toolbar-reference-dialog' ).data( 'whitespace' ); var attributes = $( '#wikieditor-toolbar-reference-dialog' ).data( 'attributes' ); // Close the dialog $( this ).dialog( 'close' ); $.wikiEditor.modules.toolbar.fn.doAction( $( this ).data( 'context' ), { type: 'replace', options: { pre: whitespace[0] + '', peri: insertText, post: '' + whitespace[1] } }, $( this ) ); // Restore form state $( '#wikieditor-toolbar-reference-text' ).val( "" ); }, 'wikieditor-toolbar-tool-reference-cancel': function() { // Clear any saved selection state var context = $( this ).data( 'context' ); context.fn.restoreCursorAndScrollTop(); $( this ).dialog( 'close' ); } }, open: function() { // Pre-fill the text fields based on the current selection var context = $(this).data( 'context' ); // Restore and immediately save selection state, needed for inserting stuff later context.fn.restoreCursorAndScrollTop(); context.fn.saveCursorAndScrollTop(); var selection = context.$textarea.textSelection( 'getSelection' ); // set focus $( '#wikieditor-toolbar-reference-text' ).focus(); $( '#wikieditor-toolbar-reference-dialog' ) .data( 'whitespace', [ '', '' ] ) .data( 'attributes', '' ); if ( selection != '' ) { var matches, text; if ( ( matches = selection.match( /^(\s*)]*)>([^\<]*)<\/ref\>(\s*)$/ ) ) ) { text = matches[3]; // Preserve whitespace when replacing $( '#wikieditor-toolbar-reference-dialog' ) .data( 'whitespace', [ matches[1], matches[4] ] ); $( '#wikieditor-toolbar-reference-dialog' ).data( 'attributes', matches[2] ); } else { text = selection; } $( '#wikieditor-toolbar-reference-text' ).val( text ); } if ( !( $( this ).data( 'dialogkeypressset' ) ) ) { $( this ).data( 'dialogkeypressset', true ); // Execute the action associated with the first button // when the user presses Enter $( this ).closest( '.ui-dialog' ).keypress( function( e ) { if ( ( e.keyCode || e.which ) == 13 ) { var button = $( this ).data( 'dialogaction' ) || $( this ).find( 'button:first' ); button.click(); e.preventDefault(); } } ); // Make tabbing to a button and pressing // Enter do what people expect $( this ).closest( '.ui-dialog' ).find( 'button' ).focus( function() { $( this ).closest( '.ui-dialog' ).data( 'dialogaction', this ); } ); } } } }, 'insert-table': { titleMsg: 'wikieditor-toolbar-tool-table-title', id: 'wikieditor-toolbar-table-dialog', // FIXME: Localize 'x'? html: '\
\
\
\ \ \
\
\ \ \
\
\ \ \
\
\
\
\ \
\
\
\ \
\
\
\
\ \
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \
\
\
', init: function() { $(this).find( '[rel]' ).each( function() { $(this).text( mediaWiki.msg.get( $(this).attr( 'rel' ) ) ); }); // Set tabindexes on form fields $.wikiEditor.modules.dialogs.fn.setTabindexes( $(this).find( 'input' ).not( '[tabindex]' ) ); $( '#wikieditor-toolbar-table-dimensions-rows' ).val( 3 ); $( '#wikieditor-toolbar-table-dimensions-columns' ).val( 3 ); $( '#wikieditor-toolbar-table-wikitable' ).click( function() { $( '.wikieditor-toolbar-table-preview' ).toggleClass( 'wikitable' ); }); // Hack for sortable preview: dynamically adding // sortable class doesn't work, so we use a clone // FIXME: Relies on sortable table internals $( '#wikieditor-toolbar-table-preview' ) .clone() .attr( 'id', 'wikieditor-toolbar-table-preview2' ) .addClass( 'sortable' ) .insertAfter( $( '#wikieditor-toolbar-table-preview' ) ) .hide(); if ( typeof ts_makeSortable == 'function' ) ts_makeSortable( $( '#wikieditor-toolbar-table-preview2' ).get( 0 ) ); $( '#wikieditor-toolbar-table-sortable' ).click( function() { // Swap the currently shown one clone with the other one $( '#wikieditor-toolbar-table-preview' ) .hide() .attr( 'id', 'wikieditor-toolbar-table-preview3' ); $( '#wikieditor-toolbar-table-preview2' ) .attr( 'id', 'wikieditor-toolbar-table-preview' ) .show(); $( '#wikieditor-toolbar-table-preview3' ).attr( 'id', 'wikieditor-toolbar-table-preview2' ); }); $( '#wikieditor-toolbar-table-dimensions-header' ).click( function() { // Instead of show/hiding, switch the HTML around // We do this because the sortable tables script styles the first row, // visible or not var headerHTML = $( '.wikieditor-toolbar-table-preview-header' ).html(); var hiddenHTML = $( '.wikieditor-toolbar-table-preview-hidden' ).html(); $( '.wikieditor-toolbar-table-preview-header' ).html( hiddenHTML ); $( '.wikieditor-toolbar-table-preview-hidden' ).html( headerHTML ); if ( typeof ts_makeSortable == 'function' ) ts_makeSortable( $( '#wikieditor-toolbar-table-preview, #wikieditor-toolbar-table-preview2' ) .filter( '.sortable' ) .get( 0 ) ); }); }, dialog: { resizable: false, dialogClass: 'wikiEditor-toolbar-dialog', width: 590, buttons: { 'wikieditor-toolbar-tool-table-insert': function() { var rowsVal = $( '#wikieditor-toolbar-table-dimensions-rows' ).val(); var colsVal = $( '#wikieditor-toolbar-table-dimensions-columns' ).val(); var rows = parseInt( rowsVal, 10 ); var cols = parseInt( colsVal, 10 ); var header = $( '#wikieditor-toolbar-table-dimensions-header' ).is( ':checked' ) ? 1 : 0; var msg = mediaWiki.msg; if ( isNaN( rows ) || isNaN( cols ) || rows != rowsVal || cols != colsVal ) { alert( msg.get( 'wikieditor-toolbar-tool-table-invalidnumber' ) ); return; } if ( rows + header == 0 || cols == 0 ) { alert( msg.get( 'wikieditor-toolbar-tool-table-zero' ) ); return; } if ( rows * cols > 1000 ) { alert( msg.get( 'wikieditor-toolbar-tool-table-toomany', 1000 ) ); return; } var headerText = msg.get( 'wikieditor-toolbar-tool-table-example-header' ); var normalText = msg.get( 'wikieditor-toolbar-tool-table-example' ); var table = ""; for ( var r = 0; r < rows + header; r++ ) { table += "|-\n"; for ( var c = 0; c < cols; c++ ) { var isHeader = ( header && r == 0 ); var delim = isHeader ? '!' : '|'; if ( c > 0 ) { delim += delim; } table += delim + ' ' + ( isHeader ? headerText : normalText ) + ' '; } // Replace trailing space by newline // table[table.length - 1] is read-only table = table.substr( 0, table.length - 1 ) + "\n"; } var classes = []; if ( $( '#wikieditor-toolbar-table-wikitable' ).is( ':checked' ) ) classes.push( 'wikitable' ); if ( $( '#wikieditor-toolbar-table-sortable' ).is( ':checked' ) ) classes.push( 'sortable' ); var classStr = classes.length > 0 ? ' class="' + classes.join( ' ' ) + '"' : ''; $(this).dialog( 'close' ); $.wikiEditor.modules.toolbar.fn.doAction( $(this).data( 'context' ), { type: 'replace', options: { pre: '{|' + classStr + "\n", peri: table, post: '|}', ownline: true } }, $(this) ); // Restore form state $( '#wikieditor-toolbar-table-dimensions-rows' ).val( 3 ); $( '#wikieditor-toolbar-table-dimensions-columns' ).val( 3 ); // Simulate clicks instead of setting values, so the according // actions are performed if ( !$( '#wikieditor-toolbar-table-dimensions-header' ).is( ':checked' ) ) $( '#wikieditor-toolbar-table-dimensions-header' ).click(); if ( !$( '#wikieditor-toolbar-table-wikitable' ).is( ':checked' ) ) $( '#wikieditor-toolbar-table-wikitable' ).click(); if ( $( '#wikieditor-toolbar-table-sortable' ).is( ':checked' ) ) $( '#wikieditor-toolbar-table-sortable' ).click(); }, 'wikieditor-toolbar-tool-table-cancel': function() { $(this).dialog( 'close' ); } }, open: function() { $( '#wikieditor-toolbar-table-dimensions-rows' ).focus(); if ( !( $(this).data( 'dialogkeypressset' ) ) ) { $(this).data( 'dialogkeypressset', true ); // Execute the action associated with the first button // when the user presses Enter $(this).closest( '.ui-dialog' ).keypress( function( e ) { if ( ( e.keyCode || e.which ) == 13 ) { var button = $(this).data( 'dialogaction' ) || $(this).find( 'button:first' ); button.click(); e.preventDefault(); } }); // Make tabbing to a button and pressing // Enter do what people expect $(this).closest( '.ui-dialog' ).find( 'button' ).focus( function() { $(this).closest( '.ui-dialog' ).data( 'dialogaction', this ); }); } } } }, 'search-and-replace': { 'browsers': { // Left-to-right languages 'ltr': { 'msie': false, 'firefox': [['>=', 2]], 'opera': false, 'safari': [['>=', 3]], 'chrome': [['>=', 3]] }, // Right-to-left languages 'rtl': { 'msie': false, 'firefox': [['>=', 2]], 'opera': false, 'safari': [['>=', 3]], 'chrome': [['>=', 3]] } }, titleMsg: 'wikieditor-toolbar-tool-replace-title', id: 'wikieditor-toolbar-replace-dialog', html: '\
\
\
\
\
\
\
\
\ \ \
\
\ \ \
\
\ \ \
\
\ \ \
\
', init: function() { var msg = mediaWiki.msg; $(this).find( '[rel]' ).each( function() { $(this).text( msg.get( $(this).attr( 'rel' ) ) ); }); // Set tabindexes on form fields $.wikiEditor.modules.dialogs.fn.setTabindexes( $(this).find( 'input' ).not( '[tabindex]' ) ); // TODO: Find a cleaner way to share this function $(this).data( 'replaceCallback', function( mode ) { $( '#wikieditor-toolbar-replace-nomatch, #wikieditor-toolbar-replace-success, #wikieditor-toolbar-replace-emptysearch, #wikieditor-toolbar-replace-invalidregex' ).hide(); var searchStr = $( '#wikieditor-toolbar-replace-search' ).val(); if ( searchStr == '' ) { $( '#wikieditor-toolbar-replace-emptysearch' ).show(); return; } var replaceStr = $( '#wikieditor-toolbar-replace-replace' ).val(); var flags = 'm'; var matchCase = $( '#wikieditor-toolbar-replace-case' ).is( ':checked' ); var isRegex = $( '#wikieditor-toolbar-replace-regex' ).is( ':checked' ); if ( !matchCase ) { flags += 'i'; } if ( mode == 'replaceAll' ) { flags += 'g'; } if ( !isRegex ) { searchStr = RegExp.escape( searchStr ); } try { var regex = new RegExp( searchStr, flags ); } catch( e ) { $( '#wikieditor-toolbar-replace-invalidregex' ) .text( msg.get( 'wikieditor-toolbar-tool-replace-invalidregex', e.message ) ) .show(); return; } var $textarea = $(this).data( 'context' ).$textarea; var text = $textarea.textSelection( 'getContents' ); var match = false; var offset, s; if ( mode != 'replaceAll' ) { offset = $(this).data( 'offset' ); s = text.substr( offset ); match = s.match( regex ); } if ( !match ) { // Search hit BOTTOM, continuing at TOP offset = 0; s = text; match = s.match( regex ); } if ( !match ) { $( '#wikieditor-toolbar-replace-nomatch' ).show(); } else if ( mode == 'replaceAll' ) { // Instead of using repetitive .match() calls, we use one .match() call with /g // and indexOf() followed by substr() to find the offsets. This is actually // faster because our indexOf+substr loop is faster than a match loop, and the // /g match is so ridiculously fast that it's negligible. // FIXME: Repetitively calling encapsulateSelection() is probably the best strategy // in Firefox/Webkit, but in IE replacing the entire content once is better. var index; for ( var i = 0; i < match.length; i++ ) { index = s.indexOf( match[i] ); if ( index == -1 ) { // This shouldn't happen break; } var matchedText = s.substr( index, match[i].length ); s = s.substr( index + match[i].length ); var start = index + offset; var end = start + match[i].length; // Make regex placeholder substitution ($1) work var replace = isRegex ? matchedText.replace( regex, replaceStr ) : replaceStr; var newEnd = start + replace.length; $textarea .textSelection( 'setSelection', { 'start': start, 'end': end } ) .textSelection( 'encapsulateSelection', { 'peri': replace, 'replace': true } ) .textSelection( 'setSelection', { 'start': start, 'end': newEnd } ); offset = newEnd; } $( '#wikieditor-toolbar-replace-success' ) .text( msg.get( 'wikieditor-toolbar-tool-replace-success', match.length ) ) .show(); $(this).data( 'offset', 0 ); } else { // Make regex placeholder substitution ($1) work var replace = isRegex ? match[0].replace( regex, replaceStr ): replaceStr; var start = match.index + offset; var end = start + match[0].length; var newEnd = start + replace.length; var context = $( this ).data( 'context' ); $textarea.textSelection( 'setSelection', { 'start': start, 'end': end } ); if ( mode == 'replace' ) { $textarea .textSelection( 'encapsulateSelection', { 'peri': replace, 'replace': true } ) .textSelection( 'setSelection', { 'start': start, 'end': newEnd } ); } $textarea.textSelection( 'scrollToCaretPosition' ); $textarea.textSelection( 'setSelection', { 'start': start, 'end': mode == 'replace' ? newEnd : end } ); $( this ).data( 'offset', mode == 'replace' ? newEnd : end ); var textbox = typeof context.$iframe != 'undefined' ? context.$iframe[0].contentWindow : $textarea[0]; textbox.focus(); } }); }, dialog: { width: 500, dialogClass: 'wikiEditor-toolbar-dialog', buttons: { 'wikieditor-toolbar-tool-replace-button-findnext': function( e ) { $(this).closest( '.ui-dialog' ).data( 'dialogaction', e.target ); $(this).data( 'replaceCallback' ).call( this, 'find' ); }, 'wikieditor-toolbar-tool-replace-button-replacenext': function( e ) { $(this).closest( '.ui-dialog' ).data( 'dialogaction', e.target ); $(this).data( 'replaceCallback' ).call( this, 'replace' ); }, 'wikieditor-toolbar-tool-replace-button-replaceall': function( e ) { $(this).closest( '.ui-dialog' ).data( 'dialogaction', e.target ); $(this).data( 'replaceCallback' ).call( this, 'replaceAll' ); }, 'wikieditor-toolbar-tool-replace-close': function() { $(this).dialog( 'close' ); } }, open: function() { $(this).data( 'offset', 0 ); $( '#wikieditor-toolbar-replace-search' ).focus(); $( '#wikieditor-toolbar-replace-nomatch, #wikieditor-toolbar-replace-success, #wikieditor-toolbar-replace-emptysearch, #wikieditor-toolbar-replace-invalidregex' ).hide(); if ( !( $(this).data( 'onetimeonlystuff' ) ) ) { $(this).data( 'onetimeonlystuff', true ); // Execute the action associated with the first button // when the user presses Enter $(this).closest( '.ui-dialog' ).keypress( function( e ) { if ( ( e.keyCode || e.which ) == 13 ) { var button = $(this).data( 'dialogaction' ) || $(this).find( 'button:first' ); button.click(); e.preventDefault(); } }); // Make tabbing to a button and pressing // Enter do what people expect $(this).closest( '.ui-dialog' ).find( 'button' ).focus( function() { $(this).closest( '.ui-dialog' ).data( 'dialogaction', this ); }); } var dialog = $(this).closest( '.ui-dialog' ); var that = this; var context = $(this).data( 'context' ); var textbox = typeof context.$iframe != 'undefined' ? context.$iframe[0].contentWindow.document : context.$textarea; $( textbox ) .bind( 'keypress.srdialog', function( e ) { if ( ( e.keyCode || e.which ) == 13 ) { // Enter var button = dialog.data( 'dialogaction' ) || dialog.find( 'button:first' ); button.click(); e.preventDefault(); } else if ( ( e.keyCode || e.which ) == 27 ) { // Escape $(that).dialog( 'close' ); } }); }, close: function() { var context = $(this).data( 'context' ); var textbox = typeof context.$iframe != 'undefined' ? context.$iframe[0].contentWindow.document : context.$textarea; $( textbox ).unbind( 'keypress.srdialog' ); $(this).closest( '.ui-dialog' ).data( 'dialogaction', false ); } } } } } ); } );