siesta-lite
Version:
Stress-free JavaScript unit testing and functional testing tool, works in NodeJS and browsers
173 lines (134 loc) • 5.65 kB
JavaScript
/*
Siesta 5.6.1
Copyright(c) 2009-2022 Bryntum AB
https://bryntum.com/contact
https://bryntum.com/products/siesta/license
*/
/**
@class Siesta.Test.TextSelection
This is a mixin providing text selection functionality.
*/
Role('Siesta.Test.TextSelection', {
methods : {
/**
* Utility method which returns the selected text in the passed element or in the document
* @param {Siesta.Test.ActionTarget} el The element
* @return {String} The selected text
*/
getSelectedText : function (el) {
el = this.normalizeElement(el);
if ('selectionStart' in el) {
try {
return el.value.substring(el.selectionStart, el.selectionEnd);
} catch (e) {
// the "email" and "number" input fields (possibly some other too) does not allow to access
// the "selectionStart/End" properties and throws exceptions
}
}
var win = this.global,
doc = win.document;
if (win.getSelection) {
return win.getSelection().toString();
} else if (doc.getSelection) {
return doc.getSelection();
} else if (doc.selection) {
return doc.selection.createRange().text;
}
},
/**
* Utility method which selects text in the passed element (should be an <input> element).
* @param {Siesta.Test.ActionTarget} el The element
* @param {Int} start (optional) The selection start index
* @param {Int} end (optional) The selection end index
*/
selectText : function (el, start, end, callback) {
el = this.normalizeElement(el, true);
if (el && this.elementSupportsSelection(el)) {
var v = el.value || el.innerHTML,
doFocus = true;
if (v.length > 0) {
start = start === undefined ? 0 : start;
end = end === undefined ? v.length : end;
if (el.setSelectionRange) {
try {
// can throw exception in IE9 (if element is not visible)
el.setSelectionRange(start, end);
} catch (e) {
}
} else if (el.createTextRange) {
var R = el.createTextRange();
R.moveStart('character', start);
R.moveEnd('character', end - v.length);
R.select();
}
doFocus = bowser.gecko || bowser.opera;
}
if (doFocus) {
this.focus(el);
}
}
callback && callback.call(this);
},
// Returns undefined if caret pos cannot be determined (older IEs with contentEditable)
getCaretPosition : function (el) {
var pos;
var win = this.global;
var document = win.document;
if ('selectionStart' in el) {
try {
// the exception can be thrown in case of manipulating with input#type=email fields
// and possibly some other input types
pos = el.selectionStart;
} catch (e) {
pos = null
}
} else if (win.getSelection && this.isEditableNode(el)){
var sel = win.getSelection();
if (sel.rangeCount) {
var range = sel.getRangeAt(0);
if (range.commonAncestorContainer.parentNode == el) {
pos = range.endOffset;
}
}
} else if (document.selection) { // Legacy IE
this.focus(el)
var oSel = document.selection.createRange();
oSel.moveStart('character', -el.value.length);
pos = oSel.text.length;
}
return pos;
},
setCaretPosition : function (el, caretPos) {
if (el.createTextRange) {
// seems range methods throws sometimes in IE
try {
var range = el.createTextRange();
range.move('character', caretPos);
range.select();
} catch (e) {
}
} else {
if (el.setSelectionRange) {
this.focus(el)
try {
// the exception can be thrown in case of manipulating with input#type=email fields
// and possibly some other input types
el.setSelectionRange(caretPos, caretPos);
} catch (e) {
}
} else {
this.focus(el)
}
}
},
moveCaretPosition : function (el, distance) {
var pos = Math.min(Math.max(0, this.getCaretPosition(el) + distance), el.value.length);
this.setCaretPosition(el, pos);
},
elementSupportsSelection : function (el) {
var tagName = el.tagName.toLowerCase();
var inputTypes = /^text|password|tel|url|search$/i;
return tagName === 'textarea' || tagName === 'input' && inputTypes.test(el.getAttribute('type'));
}
}
})