|
|
@@ -0,0 +1,187 @@ |
|
|
'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]); |
|
|
}, |
|
|
|
|
|
getSelectionCmd: function() { |
|
|
if (this.isInputOrTextarea) { |
|
|
return 'var sel = SpecialPowers.wrap(arguments[0]).editor.selection;' + |
|
|
'sel = SpecialPowers.unwrap(sel);'; |
|
|
} 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]); |
|
|
}, |
|
|
|
|
|
rangeCount: function() { |
|
|
var cmd = this.getSelectionCmd() + 'return sel.rangeCount;'; |
|
|
return this.client.executeScript(cmd, [this.element]); |
|
|
}, |
|
|
|
|
|
/** |
|
|
* 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]); |
|
|
} |
|
|
}; |