Non puoi selezionare più di 25 argomenti
Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
540 righe
17 KiB
540 righe
17 KiB
(function($, undefined) { |
|
|
|
var _input = document.createElement('input'); |
|
|
|
var _support = { |
|
setSelectionRange: ('setSelectionRange' in _input) || ('selectionStart' in _input), |
|
createTextRange: ('createTextRange' in _input) || ('selection' in document) |
|
}; |
|
|
|
var _rNewlineIE = /\r\n/g, |
|
_rCarriageReturn = /\r/g; |
|
|
|
var _getValue = function(input) { |
|
if (typeof(input.value) !== 'undefined') { |
|
return input.value; |
|
} |
|
return $(input).text(); |
|
}; |
|
|
|
var _setValue = function(input, value) { |
|
if (typeof(input.value) !== 'undefined') { |
|
input.value = value; |
|
} else { |
|
$(input).text(value); |
|
} |
|
}; |
|
|
|
var _getIndex = function(input, pos) { |
|
var norm = _getValue(input).replace(_rCarriageReturn, ''); |
|
var len = norm.length; |
|
|
|
if (typeof(pos) === 'undefined') { |
|
pos = len; |
|
} |
|
|
|
pos = Math.floor(pos); |
|
|
|
// Negative index counts backward from the end of the input/textarea's value |
|
if (pos < 0) { |
|
pos = len + pos; |
|
} |
|
|
|
// Enforce boundaries |
|
if (pos < 0) { pos = 0; } |
|
if (pos > len) { pos = len; } |
|
|
|
return pos; |
|
}; |
|
|
|
var _hasAttr = function(input, attrName) { |
|
return input.hasAttribute ? input.hasAttribute(attrName) : (typeof(input[attrName]) !== 'undefined'); |
|
}; |
|
|
|
/** |
|
* @class |
|
* @constructor |
|
*/ |
|
var Range = function(start, end, length, text) { |
|
this.start = start || 0; |
|
this.end = end || 0; |
|
this.length = length || 0; |
|
this.text = text || ''; |
|
}; |
|
|
|
Range.prototype.toString = function() { |
|
return JSON.stringify(this, null, ' '); |
|
}; |
|
|
|
var _getCaretW3 = function(input) { |
|
return input.selectionStart; |
|
}; |
|
|
|
/** |
|
* @see http://stackoverflow.com/q/6943000/467582 |
|
*/ |
|
var _getCaretIE = function(input) { |
|
var caret, range, textInputRange, rawValue, len, endRange; |
|
|
|
// Yeah, you have to focus twice for IE 7 and 8. *cries* |
|
input.focus(); |
|
input.focus(); |
|
|
|
range = document.selection.createRange(); |
|
|
|
if (range && range.parentElement() === input) { |
|
rawValue = _getValue(input); |
|
|
|
len = rawValue.length; |
|
|
|
// Create a working TextRange that lives only in the input |
|
textInputRange = input.createTextRange(); |
|
textInputRange.moveToBookmark(range.getBookmark()); |
|
|
|
// Check if the start and end of the selection are at the very end |
|
// of the input, since moveStart/moveEnd doesn't return what we want |
|
// in those cases |
|
endRange = input.createTextRange(); |
|
endRange.collapse(false); |
|
|
|
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) { |
|
caret = rawValue.replace(_rNewlineIE, '\n').length; |
|
} else { |
|
caret = -textInputRange.moveStart("character", -len); |
|
} |
|
|
|
return caret; |
|
} |
|
|
|
// NOTE: This occurs when you highlight part of a textarea and then click in the middle of the highlighted portion in IE 6-10. |
|
// There doesn't appear to be anything we can do about it. |
|
// alert("Your browser is incredibly stupid. I don't know what else to say."); |
|
// alert(range + '\n\n' + range.parentElement().tagName + '#' + range.parentElement().id); |
|
|
|
return 0; |
|
}; |
|
|
|
/** |
|
* Gets the position of the caret in the given input. |
|
* @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element |
|
* @returns {Number} |
|
* @see http://stackoverflow.com/questions/263743/how-to-get-cursor-position-in-textarea/263796#263796 |
|
*/ |
|
var _getCaret = function(input) { |
|
if (!input) { |
|
return undefined; |
|
} |
|
|
|
// Mozilla, et al. |
|
if (_support.setSelectionRange) { |
|
return _getCaretW3(input); |
|
} |
|
// IE |
|
else if (_support.createTextRange) { |
|
return _getCaretIE(input); |
|
} |
|
|
|
return undefined; |
|
}; |
|
|
|
var _setCaretW3 = function(input, pos) { |
|
input.setSelectionRange(pos, pos); |
|
}; |
|
|
|
var _setCaretIE = function(input, pos) { |
|
var range = input.createTextRange(); |
|
range.move('character', pos); |
|
range.select(); |
|
}; |
|
|
|
/** |
|
* Sets the position of the caret in the given input. |
|
* @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element |
|
* @param {Number} pos |
|
* @see http://parentnode.org/javascript/working-with-the-cursor-position/ |
|
*/ |
|
var _setCaret = function(input, pos) { |
|
input.focus(); |
|
|
|
pos = _getIndex(input, pos); |
|
|
|
// Mozilla, et al. |
|
if (_support.setSelectionRange) { |
|
_setCaretW3(input, pos); |
|
} |
|
// IE |
|
else if (_support.createTextRange) { |
|
_setCaretIE(input, pos); |
|
} |
|
}; |
|
|
|
/** |
|
* Inserts the specified text at the current caret position in the given input. |
|
* @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element |
|
* @param {String} text |
|
* @see http://parentnode.org/javascript/working-with-the-cursor-position/ |
|
*/ |
|
var _insertAtCaret = function(input, text) { |
|
var curPos = _getCaret(input); |
|
|
|
var oldValueNorm = _getValue(input).replace(_rCarriageReturn, ''); |
|
|
|
var newLength = +(curPos + text.length + (oldValueNorm.length - curPos)); |
|
var maxLength = +input.getAttribute('maxlength'); |
|
|
|
if(_hasAttr(input, 'maxlength') && newLength > maxLength) { |
|
var delta = text.length - (newLength - maxLength); |
|
text = text.substr(0, delta); |
|
} |
|
|
|
_setValue(input, oldValueNorm.substr(0, curPos) + text + oldValueNorm.substr(curPos)); |
|
|
|
_setCaret(input, curPos + text.length); |
|
}; |
|
|
|
var _getInputRangeW3 = function(input) { |
|
var range = new Range(); |
|
|
|
range.start = input.selectionStart; |
|
range.end = input.selectionEnd; |
|
|
|
var min = Math.min(range.start, range.end); |
|
var max = Math.max(range.start, range.end); |
|
|
|
range.length = max - min; |
|
range.text = _getValue(input).substring(min, max); |
|
|
|
return range; |
|
}; |
|
|
|
/** @see http://stackoverflow.com/a/3648244/467582 */ |
|
var _getInputRangeIE = function(input) { |
|
var range = new Range(); |
|
|
|
input.focus(); |
|
|
|
var selection = document.selection.createRange(); |
|
|
|
if (selection && selection.parentElement() === input) { |
|
var len, normalizedValue, textInputRange, endRange, start = 0, end = 0; |
|
var rawValue = _getValue(input); |
|
|
|
len = rawValue.length; |
|
normalizedValue = rawValue.replace(/\r\n/g, "\n"); |
|
|
|
// Create a working TextRange that lives only in the input |
|
textInputRange = input.createTextRange(); |
|
textInputRange.moveToBookmark(selection.getBookmark()); |
|
|
|
// Check if the start and end of the selection are at the very end |
|
// of the input, since moveStart/moveEnd doesn't return what we want |
|
// in those cases |
|
endRange = input.createTextRange(); |
|
endRange.collapse(false); |
|
|
|
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) { |
|
start = end = len; |
|
} else { |
|
start = -textInputRange.moveStart("character", -len); |
|
start += normalizedValue.slice(0, start).split("\n").length - 1; |
|
|
|
if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) { |
|
end = len; |
|
} else { |
|
end = -textInputRange.moveEnd("character", -len); |
|
end += normalizedValue.slice(0, end).split("\n").length - 1; |
|
} |
|
} |
|
|
|
/// normalize newlines |
|
start -= (rawValue.substring(0, start).split('\r\n').length - 1); |
|
end -= (rawValue.substring(0, end).split('\r\n').length - 1); |
|
/// normalize newlines |
|
|
|
range.start = start; |
|
range.end = end; |
|
range.length = range.end - range.start; |
|
range.text = normalizedValue.substr(range.start, range.length); |
|
} |
|
|
|
return range; |
|
}; |
|
|
|
/** |
|
* Gets the selected text range of the given input. |
|
* @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element |
|
* @returns {Range} |
|
* @see http://stackoverflow.com/a/263796/467582 |
|
* @see http://stackoverflow.com/a/2966703/467582 |
|
*/ |
|
var _getInputRange = function(input) { |
|
if (!input) { |
|
return undefined; |
|
} |
|
|
|
// Mozilla, et al. |
|
if (_support.setSelectionRange) { |
|
return _getInputRangeW3(input); |
|
} |
|
// IE |
|
else if (_support.createTextRange) { |
|
return _getInputRangeIE(input); |
|
} |
|
|
|
return undefined; |
|
}; |
|
|
|
var _setInputRangeW3 = function(input, startPos, endPos) { |
|
input.setSelectionRange(startPos, endPos); |
|
}; |
|
|
|
var _setInputRangeIE = function(input, startPos, endPos) { |
|
var tr = input.createTextRange(); |
|
tr.moveEnd('textedit', -1); |
|
tr.moveStart('character', startPos); |
|
tr.moveEnd('character', endPos - startPos); |
|
tr.select(); |
|
}; |
|
|
|
/** |
|
* Sets the selected text range of (i.e., highlights text in) the given input. |
|
* @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element |
|
* @param {Number} startPos Zero-based index |
|
* @param {Number} endPos Zero-based index |
|
* @see http://parentnode.org/javascript/working-with-the-cursor-position/ |
|
* @see http://stackoverflow.com/a/2966703/467582 |
|
*/ |
|
var _setInputRange = function(input, startPos, endPos) { |
|
startPos = _getIndex(input, startPos); |
|
endPos = _getIndex(input, endPos); |
|
|
|
// Mozilla, et al. |
|
if (_support.setSelectionRange) { |
|
_setInputRangeW3(input, startPos, endPos); |
|
} |
|
// IE |
|
else if (_support.createTextRange) { |
|
_setInputRangeIE(input, startPos, endPos); |
|
} |
|
}; |
|
|
|
/** |
|
* Replaces the currently selected text with the given string. |
|
* @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element |
|
* @param {String} text New text that will replace the currently selected text. |
|
* @see http://parentnode.org/javascript/working-with-the-cursor-position/ |
|
*/ |
|
var _replaceInputRange = function(input, text) { |
|
var $input = $(input); |
|
|
|
var oldValue = $input.val(); |
|
var selection = _getInputRange(input); |
|
|
|
var newLength = +(selection.start + text.length + (oldValue.length - selection.end)); |
|
var maxLength = +$input.attr('maxlength'); |
|
|
|
if($input.is('[maxlength]') && newLength > maxLength) { |
|
var delta = text.length - (newLength - maxLength); |
|
text = text.substr(0, delta); |
|
} |
|
|
|
// Now that we know what the user selected, we can replace it |
|
var startText = oldValue.substr(0, selection.start); |
|
var endText = oldValue.substr(selection.end); |
|
|
|
$input.val(startText + text + endText); |
|
|
|
// Reset the selection |
|
var startPos = selection.start; |
|
var endPos = startPos + text.length; |
|
|
|
_setInputRange(input, selection.length ? startPos : endPos, endPos); |
|
}; |
|
|
|
var _selectAllW3 = function(elem) { |
|
var selection = window.getSelection(); |
|
var range = document.createRange(); |
|
range.selectNodeContents(elem); |
|
selection.removeAllRanges(); |
|
selection.addRange(range); |
|
}; |
|
|
|
var _selectAllIE = function(elem) { |
|
var range = document.body.createTextRange(); |
|
range.moveToElementText(elem); |
|
range.select(); |
|
}; |
|
|
|
/** |
|
* Select all text in the given element. |
|
* @param {HTMLElement} elem Any block or inline element other than a form element. |
|
*/ |
|
var _selectAll = function(elem) { |
|
var $elem = $(elem); |
|
if ($elem.is('input, textarea') || elem.select) { |
|
$elem.select(); |
|
return; |
|
} |
|
|
|
// Mozilla, et al. |
|
if (_support.setSelectionRange) { |
|
_selectAllW3(elem); |
|
} |
|
// IE |
|
else if (_support.createTextRange) { |
|
_selectAllIE(elem); |
|
} |
|
}; |
|
|
|
var _deselectAll = function() { |
|
if (document.selection) { |
|
document.selection.empty(); |
|
} |
|
else if (window.getSelection) { |
|
window.getSelection().removeAllRanges(); |
|
} |
|
}; |
|
|
|
$.extend($.fn, { |
|
|
|
/** |
|
* Gets or sets the position of the caret or inserts text at the current caret position in an input or textarea element. |
|
* @returns {Number|jQuery} The current caret position if invoked as a getter (with no arguments) |
|
* or this jQuery object if invoked as a setter or inserter. |
|
* @see http://web.archive.org/web/20080704185920/http://parentnode.org/javascript/working-with-the-cursor-position/ |
|
* @since 1.0.0 |
|
* @example |
|
* <pre> |
|
* // Get position |
|
* var pos = $('input:first').caret(); |
|
* </pre> |
|
* @example |
|
* <pre> |
|
* // Set position |
|
* $('input:first').caret(15); |
|
* $('input:first').caret(-3); |
|
* </pre> |
|
* @example |
|
* <pre> |
|
* // Insert text at current position |
|
* $('input:first').caret('Some text'); |
|
* </pre> |
|
*/ |
|
caret: function() { |
|
var $inputs = this.filter('input, textarea'); |
|
|
|
// getCaret() |
|
if (arguments.length === 0) { |
|
var input = $inputs.get(0); |
|
return _getCaret(input); |
|
} |
|
// setCaret(position) |
|
else if (typeof arguments[0] === 'number') { |
|
var pos = arguments[0]; |
|
$inputs.each(function(_i, input) { |
|
_setCaret(input, pos); |
|
}); |
|
} |
|
// insertAtCaret(text) |
|
else { |
|
var text = arguments[0]; |
|
$inputs.each(function(_i, input) { |
|
_insertAtCaret(input, text); |
|
}); |
|
} |
|
|
|
return this; |
|
}, |
|
|
|
/** |
|
* Gets or sets the selection range or replaces the currently selected text in an input or textarea element. |
|
* @returns {Range|jQuery} The current selection range if invoked as a getter (with no arguments) |
|
* or this jQuery object if invoked as a setter or replacer. |
|
* @see http://stackoverflow.com/a/2966703/467582 |
|
* @since 1.0.0 |
|
* @example |
|
* <pre> |
|
* // Get selection range |
|
* var range = $('input:first').range(); |
|
* </pre> |
|
* @example |
|
* <pre> |
|
* // Set selection range |
|
* $('input:first').range(15); |
|
* $('input:first').range(15, 20); |
|
* $('input:first').range(-3); |
|
* $('input:first').range(-8, -3); |
|
* </pre> |
|
* @example |
|
* <pre> |
|
* // Replace the currently selected text |
|
* $('input:first').range('Replacement text'); |
|
* </pre> |
|
*/ |
|
range: function() { |
|
var $inputs = this.filter('input, textarea'); |
|
|
|
// getRange() = { start: pos, end: pos } |
|
if (arguments.length === 0) { |
|
var input = $inputs.get(0); |
|
return _getInputRange(input); |
|
} |
|
// setRange(startPos, endPos) |
|
else if (typeof arguments[0] === 'number') { |
|
var startPos = arguments[0]; |
|
var endPos = arguments[1]; |
|
$inputs.each(function(_i, input) { |
|
_setInputRange(input, startPos, endPos); |
|
}); |
|
} |
|
// replaceRange(text) |
|
else { |
|
var text = arguments[0]; |
|
$inputs.each(function(_i, input) { |
|
_replaceInputRange(input, text); |
|
}); |
|
} |
|
|
|
return this; |
|
}, |
|
|
|
/** |
|
* Selects all text in each element of this jQuery object. |
|
* @returns {jQuery} This jQuery object |
|
* @see http://stackoverflow.com/a/11128179/467582 |
|
* @since 1.5.0 |
|
* @example |
|
* <pre> |
|
* // Select the contents of span elements when clicked |
|
* $('span').on('click', function() { $(this).highlight(); }); |
|
* </pre> |
|
*/ |
|
selectAll: function() { |
|
return this.each(function(_i, elem) { |
|
_selectAll(elem); |
|
}); |
|
} |
|
|
|
}); |
|
|
|
$.extend($, { |
|
/** |
|
* Deselects all text on the page. |
|
* @returns {jQuery} The jQuery function |
|
* @since 1.5.0 |
|
* @example |
|
* <pre> |
|
* // Select some text |
|
* $('span').selectAll(); |
|
* |
|
* // Deselect the text |
|
* $.deselectAll(); |
|
* </pre> |
|
*/ |
|
deselectAll: function() { |
|
_deselectAll(); |
|
return this; |
|
} |
|
}); |
|
|
|
}(window.jQuery || window.Zepto || window.$)); |