Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
186 lines
5.6 KiB
JavaScript
Executable file
186 lines
5.6 KiB
JavaScript
Executable file
'use strict';
|
|
|
|
var Actions = require('marionette-client').Actions;
|
|
function SelectionHelper(client, element) {
|
|
this.client = client;
|
|
this.isInputOrTextarea =
|
|
(element.getAttribute('tagName') === 'INPUT' ||
|
|
element.getAttribute('tagName') === 'TEXTAREA');
|
|
this.element = element;
|
|
this.action = new Actions(this.client);
|
|
}
|
|
|
|
module.exports = SelectionHelper;
|
|
|
|
SelectionHelper.prototype = {
|
|
get content() {
|
|
if (this.isInputOrTextarea) {
|
|
return this.element.getAttribute('value');
|
|
} else {
|
|
return this.element.text;
|
|
}
|
|
},
|
|
|
|
get selectedContent() {
|
|
return this.client.executeScript(this.getSelectionCmd() +
|
|
'return sel.toString();', [this.element], null, 'system');
|
|
},
|
|
|
|
getSelectionCmd: function() {
|
|
if (this.isInputOrTextarea) {
|
|
return 'var sel = arguments[0].editor.selection;';
|
|
} else {
|
|
return 'var sel = window.getSelection();';
|
|
}
|
|
},
|
|
|
|
selectionRectList: function(idx) {
|
|
var cmd = this.getSelectionCmd() + 'return sel.getRangeAt(' + idx + ')' +
|
|
'.getClientRects();';
|
|
return this.client.executeScript(cmd, [this.element], null, 'system');
|
|
},
|
|
|
|
rangeCount: function() {
|
|
var cmd = this.getSelectionCmd() + 'return sel.rangeCount;';
|
|
return this.client.executeScript(cmd, [this.element], null, 'system');
|
|
},
|
|
|
|
/**
|
|
* Move caret by absolute position.
|
|
*
|
|
* @param {Object} data
|
|
* {caretA: {
|
|
* offset: {
|
|
* x: //poistion relative to element,
|
|
* y: //poistion relative to element
|
|
* },
|
|
* caretB: {
|
|
* offset: {
|
|
* x: //poistion relative to element,
|
|
* y: //poistion relative to element
|
|
* }
|
|
* }}
|
|
*
|
|
*/
|
|
moveCaretByPosition: function(data) {
|
|
var caretPositions = this.selectionLocationHelper();
|
|
if (data.caretA) {
|
|
this.action.flick(this.element, caretPositions.caretA.x,
|
|
caretPositions.caretA.y + 15,
|
|
caretPositions.caretA.x + data.caretA.offset.x,
|
|
caretPositions.caretA.y + 15 + data.caretA.offset.y).perform();
|
|
this.client.wait(500);
|
|
}
|
|
if (data.caretB) {
|
|
this.action.flick(this.element, caretPositions.caretB.x,
|
|
caretPositions.caretB.y + 15,
|
|
caretPositions.caretB.x + data.caretB.offset.x,
|
|
caretPositions.caretB.y + 15 + data.caretB.offset.y).perform();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Move caret by word's position.
|
|
*
|
|
* @param {Object} data
|
|
* {caretA: {offset: //integer}, caretB: {offset //integer}}
|
|
*
|
|
*/
|
|
moveCaretByWords: function(data) {
|
|
if (!this.isInputOrTextarea) {
|
|
console.log('only support input or textarea');
|
|
return;
|
|
}
|
|
var caretA = data.caretA;
|
|
var caretB = data.caretB;
|
|
var caretPositions = this.selectionLocationHelper();
|
|
var content = this.content;
|
|
var contentLength = content.length;
|
|
|
|
this.client.executeScript('arguments[0].setSelectionRange(' +
|
|
(caretA ? caretA.offset : 0) + ',' +
|
|
(contentLength + (caretB ? caretB.offset : 0)) + ' )',
|
|
[this.element]);
|
|
|
|
var newCaretPositions = this.selectionLocationHelper();
|
|
|
|
var eltSize = this.element.size();
|
|
this.action.tap(this.element, eltSize.width / 2, eltSize.height / 2)
|
|
.wait(2).press(this.element, eltSize.width / 2, eltSize.height / 2).
|
|
moveByOffset(0, 0).wait(2).release().perform();
|
|
|
|
var flickPosition = {};
|
|
|
|
if (caretA) {
|
|
flickPosition.caretA = {
|
|
offset: {
|
|
x: newCaretPositions.caretA.x - caretPositions.caretA.x,
|
|
y: newCaretPositions.caretA.y - caretPositions.caretA.y
|
|
}
|
|
};
|
|
}
|
|
if (caretB) {
|
|
flickPosition.caretB = {
|
|
offset: {
|
|
x: newCaretPositions.caretB.x - caretPositions.caretB.x,
|
|
y: newCaretPositions.caretB.y - caretPositions.caretB.y
|
|
}
|
|
};
|
|
}
|
|
this.moveCaretByPosition(flickPosition);
|
|
},
|
|
|
|
selectionLocationHelper: function(locationType) {
|
|
var rangeCount = this.rangeCount();
|
|
var firstRectList = this.selectionRectList(0);
|
|
var lastRectList = this.selectionRectList(rangeCount - 1);
|
|
var lastListLength = lastRectList.length;
|
|
var firstRect = firstRectList[0];
|
|
var lastRect = lastRectList[lastListLength - 1];
|
|
var originX = this.element.location.x;
|
|
var originY = this.element.location.y;
|
|
var startPos = 'left';
|
|
var endPos = 'right';
|
|
var startYOffset, endYOffset;
|
|
|
|
if (this.element.getAttribute('dir') === 'rtl') {
|
|
startPos = 'right';
|
|
endPos = 'left';
|
|
}
|
|
if (locationType === 'center') {
|
|
startYOffset = firstRect.height / 2;
|
|
endYOffset = lastRect.height / 2;
|
|
} else if (locationType === 'caret') {
|
|
startYOffset = firstRect.height + 5;
|
|
endYOffset = lastRect.height + 5;
|
|
} else {
|
|
startYOffset = endYOffset = 0;
|
|
}
|
|
|
|
return {
|
|
caretA: {
|
|
x: firstRect[startPos] - originX,
|
|
y: firstRect.top + startYOffset - originY
|
|
},
|
|
caretB: {
|
|
x: lastRect[endPos] - originX,
|
|
y: lastRect.top + endYOffset - originY
|
|
}
|
|
};
|
|
},
|
|
|
|
selectAll: function() {
|
|
var cmd;
|
|
if (this.isInputOrTextarea) {
|
|
cmd = 'var len = arguments[0].value.length; arguments[0].focus();' +
|
|
'arguments[0].setSelectionRange(0, len);';
|
|
} else {
|
|
cmd = 'var range = document.createRange();' +
|
|
'range.setStart(arguments[0].firstChild, 0);' +
|
|
'range.setEnd(arguments[0].lastChild, 0);' +
|
|
'var sel = window.getSelection();' +
|
|
'sel.removeAllRanges(); sel.addRange(range);';
|
|
}
|
|
this.client.executeScript(cmd, [this.element]);
|
|
}
|
|
};
|