User:V111P/js/valSel

From wikishia

valSel.js is a cross-browser textarea and text input value and selection manipulation library plug-in for jQuery. It lets you determine the position of the cursor/selection in a textarea or text input field and change the text around it. Note that you should probably use MediaWiki's textSelection plugin instead (see below).

Please write on the talk page if you find this script useful and if you have any questions or suggestions. Thanks. If you are going to be using this script, you may want to add this page to your watchlist, so you get notified of any changes. Also, check out my other useful scripts.

You can see the source code here: User:V111P/js/valSel.js.

About MediaWiki's textSelection jQuery plugin

You can use MediaWiki's textSelection jQuery plugin [1] instead of this script, it seems to be loaded by default, so it makes no sense to load another script for the same functionality. It's API is not as nice, but you can write some wrapper functions around it. Here is an example:

mw.loader.using('jquery.textSelection');

// get and set the text and selection in a textarea
function valParts($el, textBefore, selText, textAfter) {
	if (typeof textBefore == 'string') {
		$el.val(textBefore + selText + textAfter);
		var beforeLen = textBefore.length;
		$el.textSelection('setSelection', {
			'start': beforeLen,
			'end': beforeLen + selText.length
		});

		return;
	}
	else {
		var s = $el.textSelection('getCaretPosition', {startAndEnd: true} );
		var text = $el.val().replace(/\r/g, '');

		return [text.slice(0, s[0]), text.slice(s[0], s[1]), text.slice(s[1])];
	}
}; // valParts

Important! Note that as of now (May 2014), jquery.textSelection does not remove carriage returns (\r's) from the text in IE 8 and below. That's probably because now there is a special version of jQuery for these browsers, but MediaWiki doesn't use it. However, the cursor position used is as if the \r's are not there. That's why always remember to remove all \r's when getting either the selected text or the whole text. IE 9 was only released in 2011, so the previous version should still be supported.

How to use

Loading the script

Here is an example code showing how you can load this script from another script.

First include the URL:

var valSelUrl = '//en.wikipedia.org/w/index.php?title=' // Backlink: [[User:V111P/js/valSel.js]]
	+ 'User:V111P/js/valSel.js&action=raw&ctype=text/javascript';

If you don't need to do something with the script immediately, you can do a simple ajax call to load it (check for either of the jQuery methods first to verify it is not yet loaded):

if (!$.fn.valParts)
	$.ajax({
		url: valSelUrl,
		dataType: 'script',
		cache: true
	});

If you need to do something with it as soon as it loads and executes, you need to do more than that. For example, if you need to run the function doSomething:

function checkIfExecuted(objectToCheck, propToCheck, callback, cntr) {
	if (typeof cntr == 'undefined') cntr = 50; // try for 5 seconds
	if (objectToCheck[propToCheck])
		callback();
	else if (cntr > 0)
		setTimeout(function () {
			checkIfExecuted(objectToCheck, propToCheck, callback, cntr - 1);
		}, 100);
}

if ($.fn.valParts)
	doSomething();
else
	$.ajax({
		url: valSelUrl,
		dataType: 'script',
		cache: true,
		success: function () {
			checkIfExecuted($.fn, 'valParts', doSomething);
		}
	});

The function checkIfExecuted is needed because (sometimes, in some browsers) the success callback is called after the script file has been downloaded, but before it has been executed.[1] Also, do not use jQuery's getScript() method, because it disables the caching of the script file[2]. Instead, use ajax() as in the example above. You can also use mw.loader.load(url).

If you need to load several scripts instead of just one, the easiest way is to load them one after the other.

Using the jQuery methods

valSel.js is a jQuery plugin. To use it you call one of the methods listed below on a jQuery object containing (as a first element) the textarea or text input you want to work with. Note the relationship between selection and cursor position. If no text is currently selected, then the selection is said to be collapsed, having the same starting and ending position (the position of the cursor) and a length of zero.

Attention! Since not everything has been tested yet, if you notice something not working as advertized here, you should report it on the talk page, so I can fix it.

Normalized value

The text value of the textarea or text input element is normalized as through the jQuery's val() method - all \r characters are removed, so the lines are left separated only with \n characters. (For example old versions of Internet Explorer separate the lines in the textareas with \r\n. See also the article Newline for more information).

The collapse parameter

The parameter collapse should be a number: 0 means keep the selection (this is the default), 1 (or any positive number) means collapse the selection to its end, -1 (or any negative number) means collapse the selection to its start.

The methods

In the listed method signatures below, the type of the parameters is given and the optional parameters are in square brackets. This of course is not legal JavaScript. Hopefully the examples will help clarify how to actually use the methods if you are confused.

valParts
  • valParts() - returns an array with three strings - the first one is the text before the selection/cursor, the second one is the selected text (if any), and the third one is the text after the selection/cursor.
  • valParts(textBefore, selText, textAfter) - sets the text in the textarea/text input and sets the selection at the same time by specifying which text appears before, within, and after the selection.
  • valParts(beforeSelAfterArray) - as above, but the three strings are passed in an array as a single argument. Example: valParts(['This text is before the selection. ', 'This text is selected.', ' This text is after the selection.'])
  • valParts(fn) - where fn is a function that will be called.
    • The function is called immediately with the following three parameters:
      1. a string with the text before the selection/cursor;
      2. a string with the text within the selection (or an empty string if no text is selected);
      3. a string with the text after the selection/cursor;
      4. the total length of the text in the textarea/text input.
    • The function should either return nothing/undefined (or false), or an array with three string elements to replace the value in the textarea/text input as follows:
      1. The first element of the array will be the text before the selection/cursor;
      2. The second element of the array will be the text within the selection (could be an empty string if no text is to be selected);
      3. The third element of the array will be the text after the selection/cursor;
sel
  • sel() - returns an object with the following properties:
    • text - the selected text. An example of getting the selected text: alert($('#wpTextarea1').sel().text);
    • start, end - the starting and ending position of the selection within the value of the textarea/text input. The ending position is greater than or equal to the starting position. Note that these are the positions within the normalized value (see the explanation above).
    • length - the length of the string text
  • sel(string newVal[, int collapse]) - the newVal is the string to replace the current selection, or, if no text is currently selected, the string to be added at the cursor's position. The newly added text will be selected, unless a non-zero number is passed as a second argument (see the explanation for collapse in the section #The collapse parameter above). Examples: $('#wpTextbox1').sel('{{stub}}', 1); $('#wpTextbox1').sel('{{stub}}');
  • sel(int newStartPos[, int newEndPos]) - sets the selection ends to the provided positions. (Note that no text is moved or changed here.) If the second parameter is not a number, then both the start and end positions of the selection will be set to the value passed as argument #1. Negative values are interpreted as zero, while values greater than the length of the textarea/text input value are interpreted as the same as the value's length. If you try to move the end of the selection before its start or its start after its end, the values will be swapped so that the start is again the smaller value (this may not be what you want!).
  • sel(fn) - where fn is a function that will be called.
    • The function is called immediately with the following four parameters:
      1. the text of the current selection;
      2. the starting position of the selection;
      3. the ending position of the selection (greater than or equal to the starting position);
      4. the length of the selection.
    • The function should either return nothing/undefined (or false), or it should return a string to replace the current selection with, or an object with any (or none) of the following properties:
      • text - a string to replace the current selection with;
      • collapse - a number, as explained above in #The collapse parameter (ignored if start is given);
      • start and end - the new start and end positions of the selection (end defaults to the same value that start is given). Negative values are interpreted as zero, while values greater than the length of the textarea/text input value are interpreted as the same as the value's length. If you try to move the end before the start or the start after the end, the values will be swapped so that start is again the smaller value (this may not be what you want!).

Example of calling sel() with a function argument:

// If there is a selection, reduce its size by 5 by moving its end 5 character backward.
// If there are fewer that 5 characters in the selection, collapse the selection to its start.
$('#wpTextbox1').sel(function (currSelText, start, end, length) {
	var reduceWith = (length > 5 ? 5 : length);
	return {end: end - reduceWith}; // if it's negative that's the same as zero
}

// if the selection is "stub", replace it with {<nowiki/>{stub}},
// if it is "afd", replace it with {<nowiki/>{subst:afd}}.
// Collapse the selection to its end
$('#wpTextbox1').sel(function (currSelText, start, end, length) {
	var newSel;
	switch (currSelText) {
	case 'stub':
		newSel = '{<nowiki/>{stub}}';
		break;
	case 'afd':
		newSel = '{<nowiki/>{subst:afd}}';
		break;
	}
	return {text: newSel, collapse: 1}; // if newSel is undefined here, nothing will happen
}
collapseSel
  • collapseSel([bool toStart]) - if toStart is true, collapses the selection to its start, otherwise collapses the selection to its end.
aroundSel

This method can be used to insert text around the selection. The parameter collapse is explained above in #The collapse parameter. The parameter include dictates whether to include the inserted text in the selection or to insert it before/after it.

  • aroundSel(string surround, [bool include, [int collapse]]) - surround is a string that will be inserted on both sides of the selection/cursor. See above for the explanation of the include and collapse parameters.
  • aroundSel(string before, string after, [bool include, [int collapse]]) - like aroundSel(string surround, [bool include, [int collapse]]), but here you can insert two different strings before and after the selection/cursor.
  • aroundSel(string before, string prepend, string append, string after, [int collapse]) - before and after are inserted around the selection and are left outside of it, while prepend and append are inserted at the start and end of the selection itself. See above for the explanation of the collapse parameter.

Credits

Much of the code in this script is from Rangy Text Inputs (A version from 5 November 2010), a cross-browser textarea and text input library plug-in for jQuery, Copyright 2010, Tim Down, licensed under the MIT license. (The 2013 version is not much different).

You can use the code that I added in the file (the code not from Rangy Text Inputs) under CC0.

References

  1. http://api.jquery.com/jQuery.getScript/#success-callback (although this note is on the getScript's documentation page, not on ajax's)
  2. http://api.jquery.com/jQuery.getScript/#caching-requests

See also