mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/WikiEditor
synced 2024-11-14 19:31:55 +00:00
(bug 20919) Search & Replace: Change "Replace Next" functionality to "Replace" functionality. Patch by Amir E. Aharoni.
Submitter's comment: "Replace next" now replaces the currently selected text instead of finding the next occurrence and replacing it. To keep the location of the current occurrence, i added matchIndex to $(this).data. I added some comments renamed a couple of variable for readability: * s to textRemainder * replace to actualReplacement This is my first significant jQuery-style patch so it may have embarrassing mistakes - constructive criticism is welcome.
This commit is contained in:
parent
7dc0dec3c3
commit
868eec7504
Notes:
Siebrand Mazeland
2011-09-13 08:53:12 +00:00
|
@ -963,24 +963,31 @@ getDefaultConfig: function () {
|
||||||
// TODO: Find a cleaner way to share this function
|
// TODO: Find a cleaner way to share this function
|
||||||
$(this).data( 'replaceCallback', function( mode ) {
|
$(this).data( 'replaceCallback', function( mode ) {
|
||||||
$( '#wikieditor-toolbar-replace-nomatch, #wikieditor-toolbar-replace-success, #wikieditor-toolbar-replace-emptysearch, #wikieditor-toolbar-replace-invalidregex' ).hide();
|
$( '#wikieditor-toolbar-replace-nomatch, #wikieditor-toolbar-replace-success, #wikieditor-toolbar-replace-emptysearch, #wikieditor-toolbar-replace-invalidregex' ).hide();
|
||||||
|
|
||||||
|
// Search string cannot be empty
|
||||||
var searchStr = $( '#wikieditor-toolbar-replace-search' ).val();
|
var searchStr = $( '#wikieditor-toolbar-replace-search' ).val();
|
||||||
if ( searchStr == '' ) {
|
if ( searchStr == '' ) {
|
||||||
$( '#wikieditor-toolbar-replace-emptysearch' ).show();
|
$( '#wikieditor-toolbar-replace-emptysearch' ).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Replace string can be empty
|
||||||
var replaceStr = $( '#wikieditor-toolbar-replace-replace' ).val();
|
var replaceStr = $( '#wikieditor-toolbar-replace-replace' ).val();
|
||||||
|
|
||||||
|
// Prepare the regular expression flags
|
||||||
var flags = 'm';
|
var flags = 'm';
|
||||||
var matchCase = $( '#wikieditor-toolbar-replace-case' ).is( ':checked' );
|
var matchCase = $( '#wikieditor-toolbar-replace-case' ).is( ':checked' );
|
||||||
var isRegex = $( '#wikieditor-toolbar-replace-regex' ).is( ':checked' );
|
|
||||||
if ( !matchCase ) {
|
if ( !matchCase ) {
|
||||||
flags += 'i';
|
flags += 'i';
|
||||||
}
|
}
|
||||||
|
var isRegex = $( '#wikieditor-toolbar-replace-regex' ).is( ':checked' );
|
||||||
|
if ( !isRegex ) {
|
||||||
|
searchStr = $.escapeRE( searchStr );
|
||||||
|
}
|
||||||
if ( mode == 'replaceAll' ) {
|
if ( mode == 'replaceAll' ) {
|
||||||
flags += 'g';
|
flags += 'g';
|
||||||
}
|
}
|
||||||
if ( !isRegex ) {
|
|
||||||
searchStr = $.escapeRE( searchStr );
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
var regex = new RegExp( searchStr, flags );
|
var regex = new RegExp( searchStr, flags );
|
||||||
} catch( e ) {
|
} catch( e ) {
|
||||||
|
@ -990,20 +997,26 @@ getDefaultConfig: function () {
|
||||||
.show();
|
.show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var $textarea = $(this).data( 'context' ).$textarea;
|
var $textarea = $(this).data( 'context' ).$textarea;
|
||||||
var text = $textarea.textSelection( 'getContents' );
|
var text = $textarea.textSelection( 'getContents' );
|
||||||
var match = false;
|
var match = false;
|
||||||
var offset, s;
|
var offset, textRemainder;
|
||||||
if ( mode != 'replaceAll' ) {
|
if ( mode != 'replaceAll' ) {
|
||||||
offset = $(this).data( 'offset' );
|
if (mode == 'replace') {
|
||||||
s = text.substr( offset );
|
offset = $(this).data( 'matchIndex' );
|
||||||
match = s.match( regex );
|
} else {
|
||||||
|
offset = $(this).data( 'offset' );
|
||||||
|
}
|
||||||
|
textRemainder = text.substr( offset );
|
||||||
|
match = textRemainder.match( regex );
|
||||||
}
|
}
|
||||||
if ( !match ) {
|
if ( !match ) {
|
||||||
// Search hit BOTTOM, continuing at TOP
|
// Search hit BOTTOM, continuing at TOP
|
||||||
|
// TODO: Add a "Wrap around" option.
|
||||||
offset = 0;
|
offset = 0;
|
||||||
s = text;
|
textRemainder = text;
|
||||||
match = s.match( regex );
|
match = textRemainder.match( regex );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !match ) {
|
if ( !match ) {
|
||||||
|
@ -1017,13 +1030,13 @@ getDefaultConfig: function () {
|
||||||
// in Firefox/Webkit, but in IE replacing the entire content once is better.
|
// in Firefox/Webkit, but in IE replacing the entire content once is better.
|
||||||
var index;
|
var index;
|
||||||
for ( var i = 0; i < match.length; i++ ) {
|
for ( var i = 0; i < match.length; i++ ) {
|
||||||
index = s.indexOf( match[i] );
|
index = textRemainder.indexOf( match[i] );
|
||||||
if ( index == -1 ) {
|
if ( index == -1 ) {
|
||||||
// This shouldn't happen
|
// This shouldn't happen
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var matchedText = s.substr( index, match[i].length );
|
var matchedText = textRemainder.substr( index, match[i].length );
|
||||||
s = s.substr( index + match[i].length );
|
textRemainder = textRemainder.substr( index + match[i].length );
|
||||||
|
|
||||||
var start = index + offset;
|
var start = index + offset;
|
||||||
var end = start + match[i].length;
|
var end = start + match[i].length;
|
||||||
|
@ -1043,27 +1056,63 @@ getDefaultConfig: function () {
|
||||||
.show();
|
.show();
|
||||||
$(this).data( 'offset', 0 );
|
$(this).data( 'offset', 0 );
|
||||||
} else {
|
} else {
|
||||||
// Make regex placeholder substitution ($1) work
|
var start, end;
|
||||||
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' ) {
|
if ( mode == 'replace' ) {
|
||||||
$textarea
|
var actualReplacement;
|
||||||
.textSelection( 'encapsulateSelection', {
|
|
||||||
'peri': replace,
|
if (isRegex) {
|
||||||
'replace': true } )
|
// If backreferences (like $1) are used, the actual actual replacement string will be different
|
||||||
.textSelection( 'setSelection', {
|
actualReplacement = match[0].replace( regex, replaceStr );
|
||||||
'start': start,
|
} else {
|
||||||
'end': newEnd } );
|
actualReplacement = replaceStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
// Do the replacement
|
||||||
|
$textarea.textSelection( 'encapsulateSelection', {
|
||||||
|
'peri': actualReplacement,
|
||||||
|
'replace': true } );
|
||||||
|
// Reload the text after replacement
|
||||||
|
text = $textarea.textSelection( 'getContents' );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the next instance
|
||||||
|
offset = offset + match[0].length + actualReplacement.length;
|
||||||
|
textRemainder = text.substr( offset );
|
||||||
|
match = textRemainder.match( regex );
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
start = offset + match.index;
|
||||||
|
end = start + match[0].length;
|
||||||
|
} else {
|
||||||
|
// If no new string was found, try searching from the beginning.
|
||||||
|
// TODO: Add a "Wrap around" option.
|
||||||
|
textRemainder = text;
|
||||||
|
match = textRemainder.match( regex );
|
||||||
|
if (match) {
|
||||||
|
start = match.index;
|
||||||
|
end = start + match[0].length;
|
||||||
|
} else {
|
||||||
|
// Give up
|
||||||
|
start = 0;
|
||||||
|
end = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
start = offset + match.index;
|
||||||
|
end = start + match[0].length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$( this ).data( 'matchIndex', start);
|
||||||
|
|
||||||
|
$textarea.textSelection( 'setSelection', {
|
||||||
|
'start': start,
|
||||||
|
'end': end
|
||||||
|
} );
|
||||||
$textarea.textSelection( 'scrollToCaretPosition' );
|
$textarea.textSelection( 'scrollToCaretPosition' );
|
||||||
$textarea.textSelection( 'setSelection', { 'start': start,
|
$( this ).data( 'offset', end );
|
||||||
'end': mode == 'replace' ? newEnd : end } );
|
var context = $( this ).data( 'context' );
|
||||||
$( this ).data( 'offset', mode == 'replace' ? newEnd : end );
|
|
||||||
var textbox = typeof context.$iframe != 'undefined' ?
|
var textbox = typeof context.$iframe != 'undefined' ?
|
||||||
context.$iframe[0].contentWindow : $textarea[0];
|
context.$iframe[0].contentWindow : $textarea[0];
|
||||||
textbox.focus();
|
textbox.focus();
|
||||||
|
@ -1092,6 +1141,8 @@ getDefaultConfig: function () {
|
||||||
},
|
},
|
||||||
open: function() {
|
open: function() {
|
||||||
$(this).data( 'offset', 0 );
|
$(this).data( 'offset', 0 );
|
||||||
|
$(this).data( 'matchIndex', 0 );
|
||||||
|
|
||||||
$( '#wikieditor-toolbar-replace-search' ).focus();
|
$( '#wikieditor-toolbar-replace-search' ).focus();
|
||||||
$( '#wikieditor-toolbar-replace-nomatch, #wikieditor-toolbar-replace-success, #wikieditor-toolbar-replace-emptysearch, #wikieditor-toolbar-replace-invalidregex' ).hide();
|
$( '#wikieditor-toolbar-replace-nomatch, #wikieditor-toolbar-replace-success, #wikieditor-toolbar-replace-emptysearch, #wikieditor-toolbar-replace-invalidregex' ).hide();
|
||||||
if ( !( $(this).data( 'onetimeonlystuff' ) ) ) {
|
if ( !( $(this).data( 'onetimeonlystuff' ) ) ) {
|
||||||
|
|
Loading…
Reference in a new issue