From cb6ff9643147d3cff42d9c8154babf0bff5ddc05 Mon Sep 17 00:00:00 2001 From: Trevor Parscal Date: Mon, 4 Oct 2010 21:08:41 +0000 Subject: [PATCH] Got more dialogs working again --- WikiEditor.hooks.php | 27 +- WikiEditor.i18n.php | 2 - WikiEditor.php | 8 +- modules/ext.wikiEditor.dialogs.js | 2179 +++++++++++++------------- modules/ext.wikiEditor.toolbar.js | 26 - modules/jquery.wikiEditor.toolbar.js | 2 +- 6 files changed, 1118 insertions(+), 1126 deletions(-) diff --git a/WikiEditor.hooks.php b/WikiEditor.hooks.php index 94b59998..5bd5470d 100644 --- a/WikiEditor.hooks.php +++ b/WikiEditor.hooks.php @@ -28,7 +28,6 @@ class WikiEditorHooks { 'jquery.client', 'jquery.textSelection', 'jquery.delayedBind', - 'contentCollector', ), 'messages' => array( 'wikieditor-wikitext-tab', @@ -38,7 +37,10 @@ class WikiEditorHooks { ), 'jquery.wikiEditor.iframe' => array( 'scripts' => 'extensions/WikiEditor/modules/jquery.wikiEditor.iframe.js', - 'dependencies' => 'jquery.wikiEditor', + 'dependencies' => array( + 'jquery.wikiEditor', + 'contentCollector', + ), 'group' => 'ext.wikiEditor', ), 'jquery.wikiEditor.dialogs' => array( @@ -137,7 +139,8 @@ class WikiEditorHooks { 'dependencies' => array( 'ext.wikiEditor', 'ext.wikiEditor.toolbar', - // jquery.wikiEditor.dialogs and jquery.suggestions will be loaded on the fly + 'jquery.wikiEditor.dialogs', + 'jquery.suggestions', ), 'group' => 'ext.wikiEditor', ), @@ -197,6 +200,7 @@ class WikiEditorHooks { 'scripts' => 'extensions/WikiEditor/modules/ext.wikiEditor.templateEditor.js', 'dependencies' => array( 'ext.wikiEditor', + 'ext.wikiEditor.highlight', 'jquery.wikiEditor.templateEditor', ), 'messages' => array( @@ -210,6 +214,7 @@ class WikiEditorHooks { 'scripts' => 'extensions/WikiEditor/modules/ext.wikiEditor.templates.js', 'dependencies' => array( 'ext.wikiEditor', + 'ext.wikiEditor.highlight', 'jquery.wikiEditor.templates', ), 'group' => 'ext.wikiEditor', @@ -218,6 +223,7 @@ class WikiEditorHooks { 'scripts' => 'extensions/WikiEditor/modules/ext.wikiEditor.toc.js', 'dependencies' => array( 'ext.wikiEditor', + 'ext.wikiEditor.highlight', 'jquery.wikiEditor.toc', ), 'messages' => array( @@ -478,21 +484,6 @@ class WikiEditorHooks { /* Labs Features */ - 'highlight' => array( - 'preferences' => array( - 'wikieditor-highlight' => array( - 'type' => 'toggle', - 'label-message' => 'wikieditor-highlight-preference', - 'section' => 'editing/labs', - ), - ), - 'requirements' => array( - 'wikieditor-highlight' => true, - ), - 'modules' => array( - 'ext.wikiEditor.highlight', - ), - ), 'templateEditor' => array( 'preferences' => array( 'wikieditor-template-editor' => array( diff --git a/WikiEditor.i18n.php b/WikiEditor.i18n.php index 97607cad..ab2fba39 100644 --- a/WikiEditor.i18n.php +++ b/WikiEditor.i18n.php @@ -22,8 +22,6 @@ $messages['en'] = array( 'wikieditor-loading' => 'Loading', /* AddMediaWizard */ 'wikieditor-addMediaWizard-preference' => 'Enable "Add media wizard" gadget', - /* Highlight */ - 'wikieditor-highlight-preference' => 'Enable syntax highlighting when editing', /* Preview */ 'wikieditor-preview-preference' => 'Enable side-by-side preview', 'wikieditor-preview-tab' => 'Preview', diff --git a/WikiEditor.php b/WikiEditor.php index f3c76282..1256744e 100644 --- a/WikiEditor.php +++ b/WikiEditor.php @@ -26,20 +26,18 @@ $wgWikiEditorFeatures = array( // Adds a tab for previewing in-line 'preview' => array( 'global' => false, 'user' => true ), // Adds a button for previewing in a dialog - 'previewDialog' => array( 'global' => false, 'user' => true ), + 'previewDialog' => array( 'global' => false, 'user' => false ), // Adds a button and dialog for step-by-step publishing 'publish' => array( 'global' => false, 'user' => true ), /* I-frame dependent (do not deploy!) */ - // Experimental wikitext parsing/syntax highlight - 'highlight' => array( 'global' => false, 'user' => true ), // Failry stable table of contents 'toc' => array( 'global' => false, 'user' => true ), // Pretty broken template collapsing/editing - 'templateEditor' => array( 'global' => false, 'user' => true ), + 'templateEditor' => array( 'global' => false, 'user' => false ), // Bare-bones (probably broken) template collapsing - 'templates' => array( 'global' => false, 'user' => true ), + 'templates' => array( 'global' => false, 'user' => false ), /* Unknown status */ diff --git a/modules/ext.wikiEditor.dialogs.js b/modules/ext.wikiEditor.dialogs.js index 1b10f3be..f8f22f0a 100644 --- a/modules/ext.wikiEditor.dialogs.js +++ b/modules/ext.wikiEditor.dialogs.js @@ -3,1115 +3,1146 @@ */ $( document ).ready( function() { + /* if ( !$.wikiEditor.isSupported( $.wikiEditor.modules.dialogs ) ) { return; } - mediaWiki.loader.using( [ 'jquery.wikiEditor.dialogs', 'jquery.suggestions' ], function() { - // 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( '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' + */ + // 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': { - filters: [ '#wpTextbox1.toolbar-dialogs' ], - titleMsg: 'wikieditor-toolbar-tool-link-title', - id: 'wikieditor-toolbar-link-dialog', - html: '\ -
\ -
\ - \ - \ - \ + } + } ); + + // 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 ); +
\ +
', + 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'); } - // 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'); - } + 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 ); } - // 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; + 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(); } - 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 ); - } - } ) - ); + updateWidget( 'external' ); } - $( '#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 ); } - 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] ); } }); - - // 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.restoreStuffForIE(); - $(this).dialog( 'close' ); - } + $(this).data( 'request', request ); }, - 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.restoreStuffForIE(); - context.fn.saveStuffForIE(); - 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 ); - }); - } + cancel: function() { + var request = $(this).data( 'request' ); + if ( request ) + request.abort(); } - } + }); }, - 'insert-reference': { - filters: [ '#wpTextbox1.toolbar-dialogs' ], - 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.restoreStuffForIE(); - $( this ).dialog( 'close' ); + 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' ); } - }, - 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.restoreStuffForIE(); - context.fn.saveStuffForIE(); - 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 ); + function escapeExternalTarget( s ) { + return s.replace( / /g, '%20' ) + .replace( /\[/g, '%5B' ) + .replace( /]/g, '%5D' ); } - 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 ); - } ); + function escapeExternalText( s ) { + // FIXME: Should this escape [ too? Seems to work without that + return s.replace( /(]+)/g, '$1' ); } - } - } - }, - 'insert-table': { - filters: [ '#wpTextbox1.toolbar-dialogs' ], - 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]] - } - }, - filters: [ '#wpTextbox1.toolbar-dialogs' ], - 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(); + 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; } - 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 ( $.trim( text ) == '' ) { + // [[Foo| ]] creates an invisible link + // Instead, generate [[Foo|]] + text = ''; } - 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; + 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; } - $( '#wikieditor-toolbar-replace-success' ) - .text( msg.get( 'wikieditor-toolbar-tool-replace-success', match.length ) ) - .show(); - $(this).data( 'offset', 0 ); + + if ( target == text || !text.length ) + insertText = '[[' + target + ']]'; + else + insertText = '[[' + target + '|' + escapeInternalText( text ) + ']]'; } 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; + // Prepend http:// if there is no protocol + if ( !target.match( /^[a-z]+:\/\/./ ) ) + target = 'http://' + target; - $( 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' ); - } - }); + // 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', '' ); }, - close: function() { + 'wikieditor-toolbar-tool-link-cancel': function() { + // Clear any saved selection state 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 ); + context.fn.restoreStuffForIE(); + $(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.restoreStuffForIE(); + context.fn.saveStuffForIE(); + 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.restoreStuffForIE(); + $( 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.restoreStuffForIE(); + context.fn.saveStuffForIE(); + 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 ); + } + } + } + } } ); } ); \ No newline at end of file diff --git a/modules/ext.wikiEditor.toolbar.js b/modules/ext.wikiEditor.toolbar.js index 34f7daf2..55481bf3 100644 --- a/modules/ext.wikiEditor.toolbar.js +++ b/modules/ext.wikiEditor.toolbar.js @@ -415,17 +415,6 @@ $( document ).ready( function() { } } }, - 'tableCGD': { - 'labelMsg': 'wikieditor-toolbar-tool-table', - 'type': 'button', - 'icon': 'insert-table.png', - 'offset': [2, -1942], - 'filters': [ '#wpTextbox1.toolbar-dialogs' ], - 'action': { - 'type': 'dialog', - 'module': 'insert-table' - } - }, 'table': { 'labelMsg': 'wikieditor-toolbar-tool-table', 'type': 'button', @@ -458,21 +447,6 @@ $( document ).ready( function() { } } } - }, - 'search': { - 'tools': { - 'replace': { - 'labelMsg': 'wikieditor-toolbar-tool-replace', - 'type': 'button', - 'icon': 'search-replace.png', - 'offset': [-70, -214], - 'filters': [ '#wpTextbox1.toolbar-dialogs' ], - 'action': { - 'type': 'dialog', - 'module': 'search-and-replace' - } - } - } } } }, diff --git a/modules/jquery.wikiEditor.toolbar.js b/modules/jquery.wikiEditor.toolbar.js index f70bb4de..da534047 100644 --- a/modules/jquery.wikiEditor.toolbar.js +++ b/modules/jquery.wikiEditor.toolbar.js @@ -59,7 +59,7 @@ api : { ); for ( tool in data[type] ) { // Tool - $group.append( $.wikiEditor.modules.toolbar.fn.buildTool( context, tool,data[type][tool] ) ); + $group.append( $.wikiEditor.modules.toolbar.fn.buildTool( context, tool, data[type][tool] ) ); } if ( $group.children().length ) { $group.show();