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
sel

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
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.

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