/**
* @file ElementHandle类
*/
import EventEmitter from "./EventEmitter.js"
import USKeyboardLayout from "./USKeyboardLayout.js"
import {uniqueId} from "./util.js"
/**
* @class ElementHandle frame的dom操作句柄
* @extends EventEmitter
*
* @property {Frame} frame 所属frame实例
* @property {string} selector 选择器
* @property {string} baseSelector 基础选择器,先查找baseSelector,再在baseSelector的基础上查找当前节点
*
*/
export default class ElementHandle extends EventEmitter {
/**
* @constructor ElementHandle
*
* @param {Frame} frame 所属frame实例
* @param {string} selector 选择器
* @param {string} baseSelector 基础选择器,先查找baseSelector,再在baseSelector的基础上查找当前节点
*
*/
constructor(frame, selector, baseSelector) {
super()
this.id = uniqueId("ElementHandle_")
this.ipc = frame.ipc
this.frame = frame
this.selector = selector
this.baseSelector = baseSelector
}
_joinSelfSelector() {
var baseSelector = this.baseSelector.slice(0)
baseSelector.push(this.selector)
return baseSelector
}
_joinSelector(selector, baseSelector) {
baseSelector = baseSelector.slice(0)
baseSelector.push(selector)
return baseSelector
}
/**
* 基于当前节点,查询新的单个节点, 对应elm.querySelector(selector)
* @param {string} selector
*
* @return {ElementHandle}
*/
$(selector) {
return new ElementHandle(this.frame, selector, this._joinSelfSelector())
}
/**
* 基于当前节点,查询新的节点集合, 对应elm.querySelectorAll(selector)
* @param {string} selector
*
* @return {Promise<ElementHandle[]>}
*/
$$(selector) {
return this.ipc
.send("elementHandle.$$", {
selector: selector,
baseSelector: this._joinSelfSelector(),
})
.then((length) => {
return new Array(length).map((v, i) => {
return new ElementHandle(
this.contentFrame(),
[selector, i],
this._joinSelfSelector()
)
})
})
}
/**
* 查找节点,并将查找的节点作为参数传为pageFunction
* @param {string} selector
* @param {Function} pageFunction
*
* @return {Promise<*>}
*/
$eval(selector, pageFunction) {
var args = [].slice.call(arguments, 1)
return this.ipc.send("elementHandle.$eval", {
selector: selector,
baseSelector: this._joinSelfSelector(),
pageFunction: pageFunction.toString(),
args: args,
})
}
/**
* 查找节点集合,并将查找的节点集合作为参数传为pageFunction
* @param {string} selector
* @param {Function} pageFunction
*
* @return {Promise<*>}
*/
$$eval(selector, pageFunction) {
var args = [].slice.call(arguments, 1)
return this.ipc.send("elementHandle.$$eval", {
selector: selector,
baseSelector: this._joinSelfSelector(),
pageFunction: pageFunction.toString(),
args: args,
})
}
/**
* todo
*/
$x(/* expression */) {
return Promise.reject("todo")
}
/**
* todo
*/
asElement() {
return Promise.reject("todo")
}
/**
* getBoundingClientRect
*
* @return {Promise<Object>}
*/
getBoundingClientRect() {
return this.ipc.send("elementHandle.getBoundingClientRect", {
selector: selector,
baseSelector: this.baseSelector,
})
}
/**
* todo
*/
boxModel() {
return Promise.reject("todo")
}
/**
* 点击当前节点
* @param {*} options 暂不支持
*
* @return {Promise<undefined>}
*/
click(options) {
return this.ipc.send("elementHandle.click", {
selector: this._joinSelfSelector(),
options,
})
}
/**
* 当前节点所属frame
*
* @return {Frame}
*/
contentFrame() {
return this.frame
}
/**
* todo
*/
dispose() {
return Promise.reject("todo")
}
/**
* todo
*/
executionContext() {
return Promise.reject("todo")
}
/**
* 设置checked属性为true,并触发change事件
*
* @return {Promise<undefined>}
*/
check() {
return this.ipc.send("elementHandle.check", {
selector: this._joinSelfSelector(),
})
}
/**
* 设置checked属性为false,并触发change事件
*
* @return {Promise<undefined>}
*/
uncheck() {
return this.ipc.send("elementHandle.uncheck", {
selector: this._joinSelfSelector(),
})
}
/**
* todo
*/
getProperties() {
return Promise.reject("todo")
}
/**
* todo
*/
getProperty(/* propertyName */) {
return Promise.reject("todo")
}
/**
* focus当前节点
*
* @return {Promise<undefined>}
*/
focus() {
// console.log('focus: ', this._joinSelfSelector());
return this.ipc.send("elementHandle.focus", {
selector: this._joinSelfSelector(),
})
}
/**
* 取消聚焦当前节点
*
* @return {Promise<undefined>}
*/
// @noitce puppeteer不支持blur
blur() {
return this.ipc.send("elementHandle.blur", {
selector: this._joinSelfSelector(),
})
}
/**
* 获取节点的属性集合
*
* @return {Promise<Map<string, Object>>}
*/
getAttributes() {
return this.ipc
.send("elementHandle.getAttributes", {
selector: this._joinSelfSelector(),
})
.then(function (attributes) {
var map = new Map()
for (var attr of attributes) {
if (attributes.hasOwnProperty(attr)) {
map.set(attr, {
// @notice: 先简单实现
jsonValue: (function (value) {
return value
})(attributes[attr]),
})
}
}
return map
})
}
/**
* 获取节点的指定属性值
*
* @return {Promise<Object>} 通过jsonValue()获取属性值
*/
getAttribute(attrName) {
return this.ipc
.send("elementHandle.getAttribute", {
selector: this._joinSelfSelector(),
attrName: attrName,
})
.then(function (value) {
// @notice: 先简单实现
return {
jsonValue: function () {
return value
},
}
})
}
/**
* hover当前节点
*
* @return {Promise<undefined>}
*/
hover() {
return this.ipc.send("elementHandle.hover", {
selector: this._joinSelfSelector(),
})
}
/**
* todo
*/
isIntersectingViewport() {
return Promise.reject("todo")
}
/**
* todo
*/
jsonValue() {
return Promise.reject("todo")
}
/**
* 键入文本
* @param {string} text 输入的文本内容, 暂时只支持单字符输入,即英文字母等
* @param {*} options 暂不支持
*/
// todo: 暂不支持options
// todo: 暂只支持文字输入、Backspace、Enter
press(text, options) {
var key = USKeyboardLayout[text]
if (!key) {
return Promise.reject("key not define")
}
return this.ipc.send("elementHandle.press", {
selector: this._joinSelfSelector(),
keyCode: key.keyCode,
text: text,
options: options,
})
}
/**
* todo
*/
screenshot(/* options */) {
return Promise.reject("todo")
}
/**
* todo
*/
tap() {
return Promise.reject("todo")
}
/**
* todo
*/
toString() {
return Promise.reject("todo")
}
/**
* todo
*/
type(/* text, options */) {
return Promise.reject("todo")
}
/**
* todo
*/
uploadFile(/* ...filePaths */) {
return Promise.reject("todo")
}
}