1e484b35bSopenharmony_ci/* 2e484b35bSopenharmony_ci * Licensed to the Apache Software Foundation (ASF) under one 3e484b35bSopenharmony_ci * or more contributor license agreements. See the NOTICE file 4e484b35bSopenharmony_ci * distributed with this work for additional information 5e484b35bSopenharmony_ci * regarding copyright ownership. The ASF licenses this file 6e484b35bSopenharmony_ci * to you under the Apache License, Version 2.0 (the 7e484b35bSopenharmony_ci * "License"); you may not use this file except in compliance 8e484b35bSopenharmony_ci * with the License. You may obtain a copy of the License at 9e484b35bSopenharmony_ci * 10e484b35bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 11e484b35bSopenharmony_ci * 12e484b35bSopenharmony_ci * Unless required by applicable law or agreed to in writing, 13e484b35bSopenharmony_ci * software distributed under the License is distributed on an 14e484b35bSopenharmony_ci * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15e484b35bSopenharmony_ci * KIND, either express or implied. See the License for the 16e484b35bSopenharmony_ci * specific language governing permissions and limitations 17e484b35bSopenharmony_ci * under the License. 18e484b35bSopenharmony_ci */ 19e484b35bSopenharmony_ci/* 20e484b35bSopenharmony_ci * 2021.01.08 - Remove docMap. 21e484b35bSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 22e484b35bSopenharmony_ci */ 23e484b35bSopenharmony_ci 24e484b35bSopenharmony_ciimport Comment from './Comment'; 25e484b35bSopenharmony_ciimport DocumentElement from './DocumentElement'; 26e484b35bSopenharmony_ciimport Node from './Node'; 27e484b35bSopenharmony_ciimport Element from './Element'; 28e484b35bSopenharmony_ciimport { TaskCenter } from '../main/manage/event/TaskCenter'; 29e484b35bSopenharmony_ciimport { Log } from '../utils'; 30e484b35bSopenharmony_ci 31e484b35bSopenharmony_ci/** 32e484b35bSopenharmony_ci * When a document is loaded into a application runtime, it becomes a document object.<br> 33e484b35bSopenharmony_ci * The document object is the root node of the vdom document. 34e484b35bSopenharmony_ci */ 35e484b35bSopenharmony_ciclass Document { 36e484b35bSopenharmony_ci private _id: string; 37e484b35bSopenharmony_ci private _nodeMap: any; 38e484b35bSopenharmony_ci private _taskCenter: TaskCenter; 39e484b35bSopenharmony_ci private _documentElement: DocumentElement; 40e484b35bSopenharmony_ci private _body: Node; 41e484b35bSopenharmony_ci private _url: string 42e484b35bSopenharmony_ci 43e484b35bSopenharmony_ci constructor(id = '', url) { 44e484b35bSopenharmony_ci this._id = id; 45e484b35bSopenharmony_ci this._url = url; 46e484b35bSopenharmony_ci this._nodeMap = {}; 47e484b35bSopenharmony_ci this._taskCenter = new TaskCenter(id); 48e484b35bSopenharmony_ci this._createDocumentElement(); 49e484b35bSopenharmony_ci } 50e484b35bSopenharmony_ci 51e484b35bSopenharmony_ci /** 52e484b35bSopenharmony_ci * Body of this document. 53e484b35bSopenharmony_ci * @type {Node} 54e484b35bSopenharmony_ci * @readonly 55e484b35bSopenharmony_ci */ 56e484b35bSopenharmony_ci public get body() { 57e484b35bSopenharmony_ci return this._body; 58e484b35bSopenharmony_ci } 59e484b35bSopenharmony_ci 60e484b35bSopenharmony_ci /** 61e484b35bSopenharmony_ci * ID of this document. 62e484b35bSopenharmony_ci * @type {string} 63e484b35bSopenharmony_ci * @readonly 64e484b35bSopenharmony_ci */ 65e484b35bSopenharmony_ci public get id() { 66e484b35bSopenharmony_ci return this._id; 67e484b35bSopenharmony_ci } 68e484b35bSopenharmony_ci 69e484b35bSopenharmony_ci /** 70e484b35bSopenharmony_ci * Document element of this document. 71e484b35bSopenharmony_ci * @type {DocumentElement} 72e484b35bSopenharmony_ci * @readonly 73e484b35bSopenharmony_ci */ 74e484b35bSopenharmony_ci public get documentElement() { 75e484b35bSopenharmony_ci return this._documentElement; 76e484b35bSopenharmony_ci } 77e484b35bSopenharmony_ci 78e484b35bSopenharmony_ci /** 79e484b35bSopenharmony_ci * url of this document (page). 80e484b35bSopenharmony_ci * @type {url} 81e484b35bSopenharmony_ci * @readonly 82e484b35bSopenharmony_ci */ 83e484b35bSopenharmony_ci public get url() { 84e484b35bSopenharmony_ci return this._url; 85e484b35bSopenharmony_ci } 86e484b35bSopenharmony_ci 87e484b35bSopenharmony_ci /** 88e484b35bSopenharmony_ci * Node map of this document. 89e484b35bSopenharmony_ci * @type {Map} 90e484b35bSopenharmony_ci * @readonly 91e484b35bSopenharmony_ci */ 92e484b35bSopenharmony_ci public get nodeMap() { 93e484b35bSopenharmony_ci return this._nodeMap; 94e484b35bSopenharmony_ci } 95e484b35bSopenharmony_ci 96e484b35bSopenharmony_ci /** 97e484b35bSopenharmony_ci * Task center of this document. 98e484b35bSopenharmony_ci * @type {TaskCenter} 99e484b35bSopenharmony_ci * @readonly 100e484b35bSopenharmony_ci */ 101e484b35bSopenharmony_ci public get taskCenter() { 102e484b35bSopenharmony_ci return this._taskCenter; 103e484b35bSopenharmony_ci } 104e484b35bSopenharmony_ci 105e484b35bSopenharmony_ci /** 106e484b35bSopenharmony_ci * Set up body node. 107e484b35bSopenharmony_ci * @param {Node} el - Target element. 108e484b35bSopenharmony_ci */ 109e484b35bSopenharmony_ci public setElementToBody(el: Element): void { 110e484b35bSopenharmony_ci el.role = 'body'; 111e484b35bSopenharmony_ci el.depth = 1; 112e484b35bSopenharmony_ci delete this._nodeMap[el.nodeId]; 113e484b35bSopenharmony_ci el.ref = '_root'; 114e484b35bSopenharmony_ci this._nodeMap._root = el; 115e484b35bSopenharmony_ci this._body = el; 116e484b35bSopenharmony_ci } 117e484b35bSopenharmony_ci 118e484b35bSopenharmony_ci /** 119e484b35bSopenharmony_ci * Send body of this Document to native. 120e484b35bSopenharmony_ci * @param {Node} node - body element. 121e484b35bSopenharmony_ci */ 122e484b35bSopenharmony_ci public sentBodyToNative(node: Element): void { 123e484b35bSopenharmony_ci const body = node.toJSON(); 124e484b35bSopenharmony_ci if (this._taskCenter && typeof this._taskCenter.send === 'function') { 125e484b35bSopenharmony_ci this._taskCenter.send('dom', { action: 'createBody' }, [body]); 126e484b35bSopenharmony_ci } 127e484b35bSopenharmony_ci } 128e484b35bSopenharmony_ci 129e484b35bSopenharmony_ci /** 130e484b35bSopenharmony_ci * Get the node from nodeMap. 131e484b35bSopenharmony_ci * @param {string} ref - id of target node. 132e484b35bSopenharmony_ci * @return {object} node from node map. 133e484b35bSopenharmony_ci */ 134e484b35bSopenharmony_ci public getRef(ref: string) { 135e484b35bSopenharmony_ci return this._nodeMap[ref]; 136e484b35bSopenharmony_ci } 137e484b35bSopenharmony_ci 138e484b35bSopenharmony_ci /** 139e484b35bSopenharmony_ci * Create element of body. 140e484b35bSopenharmony_ci * @param {string} tagName - Tag name of body element. 141e484b35bSopenharmony_ci * @param {Object} options - Properties of element. 142e484b35bSopenharmony_ci * @return {Node} Body element. 143e484b35bSopenharmony_ci */ 144e484b35bSopenharmony_ci public createBody(tagName: string, options?: any): Node { 145e484b35bSopenharmony_ci if (!this._body) { 146e484b35bSopenharmony_ci const el = new Element(tagName, options); 147e484b35bSopenharmony_ci this.setElementToBody(el); 148e484b35bSopenharmony_ci } 149e484b35bSopenharmony_ci return this._body; 150e484b35bSopenharmony_ci } 151e484b35bSopenharmony_ci 152e484b35bSopenharmony_ci /** 153e484b35bSopenharmony_ci * Create an element. 154e484b35bSopenharmony_ci * @param {string} tagName - Tag name of element. 155e484b35bSopenharmony_ci * @param {Object} options - Properties of element. 156e484b35bSopenharmony_ci * @return {Node} New element 157e484b35bSopenharmony_ci */ 158e484b35bSopenharmony_ci public createElement(tagName: string, options?: any): Element { 159e484b35bSopenharmony_ci return new Element(tagName, options); 160e484b35bSopenharmony_ci } 161e484b35bSopenharmony_ci 162e484b35bSopenharmony_ci /** 163e484b35bSopenharmony_ci * Create an comment. 164e484b35bSopenharmony_ci * @param {string} commentText - Text of comment. 165e484b35bSopenharmony_ci * @return {object} comment 166e484b35bSopenharmony_ci */ 167e484b35bSopenharmony_ci public createComment(commentText: string): Comment { 168e484b35bSopenharmony_ci return new Comment(commentText); 169e484b35bSopenharmony_ci } 170e484b35bSopenharmony_ci 171e484b35bSopenharmony_ci /** 172e484b35bSopenharmony_ci * Fire an event on specified element manually. 173e484b35bSopenharmony_ci * @param {Element} element - Event target element. 174e484b35bSopenharmony_ci * @param {string} eventType - Event name 175e484b35bSopenharmony_ci * @param {Object} eventObj - Event object. 176e484b35bSopenharmony_ci * @param {boolean} isDomChanges - if need to change dom 177e484b35bSopenharmony_ci * @param {object} options - Event options 178e484b35bSopenharmony_ci * @return {*} anything returned by handler function 179e484b35bSopenharmony_ci */ 180e484b35bSopenharmony_ci public fireEvent(element: Element, eventType: string, eventObj: any, isDomChanges: boolean, options: any) { 181e484b35bSopenharmony_ci Log.debug(`Document#fireEvent, element = ${element}, eventType = ${eventType}, eventObj = ${eventObj}, isDomChanges = ${isDomChanges}.`); 182e484b35bSopenharmony_ci if (!element) { 183e484b35bSopenharmony_ci return; 184e484b35bSopenharmony_ci } 185e484b35bSopenharmony_ci eventObj = eventObj || {}; 186e484b35bSopenharmony_ci eventObj.type = eventObj.type || eventType; 187e484b35bSopenharmony_ci eventObj.target = element; 188e484b35bSopenharmony_ci eventObj.currentTarget = element; 189e484b35bSopenharmony_ci eventObj.timestamp = Date.now(); 190e484b35bSopenharmony_ci if (isDomChanges) { 191e484b35bSopenharmony_ci this._updateElement(element, isDomChanges); 192e484b35bSopenharmony_ci } 193e484b35bSopenharmony_ci let isBubble; 194e484b35bSopenharmony_ci const $root = this.getRef('_root'); 195e484b35bSopenharmony_ci if ($root && $root.attr) { 196e484b35bSopenharmony_ci isBubble = $root.attr['bubble'] === 'true'; 197e484b35bSopenharmony_ci } 198e484b35bSopenharmony_ci return element.fireEvent(eventType, eventObj, isBubble, options); 199e484b35bSopenharmony_ci } 200e484b35bSopenharmony_ci 201e484b35bSopenharmony_ci /** 202e484b35bSopenharmony_ci * Destroy current document, and remove itself form docMap. 203e484b35bSopenharmony_ci */ 204e484b35bSopenharmony_ci public destroy() { 205e484b35bSopenharmony_ci this.taskCenter.destroyCallback(); 206e484b35bSopenharmony_ci delete this._nodeMap; 207e484b35bSopenharmony_ci delete this._taskCenter; 208e484b35bSopenharmony_ci } 209e484b35bSopenharmony_ci 210e484b35bSopenharmony_ci /** 211e484b35bSopenharmony_ci * Create the document element. 212e484b35bSopenharmony_ci * @return {object} documentElement 213e484b35bSopenharmony_ci */ 214e484b35bSopenharmony_ci private _createDocumentElement(): void { 215e484b35bSopenharmony_ci if (!this._documentElement) { 216e484b35bSopenharmony_ci const el = new DocumentElement('document'); 217e484b35bSopenharmony_ci el.docId = this._id; 218e484b35bSopenharmony_ci el.ownerDocument = this; 219e484b35bSopenharmony_ci el.role = 'documentElement'; 220e484b35bSopenharmony_ci el.depth = 0; 221e484b35bSopenharmony_ci el.ref = '_documentElement'; 222e484b35bSopenharmony_ci this._nodeMap._documentElement = el; 223e484b35bSopenharmony_ci this._documentElement = el; 224e484b35bSopenharmony_ci } 225e484b35bSopenharmony_ci } 226e484b35bSopenharmony_ci 227e484b35bSopenharmony_ci private _updateElement(el: Element, changes: any): void { 228e484b35bSopenharmony_ci Log.debug(`Document#_updateElement, el = ${el}, changes = ${JSON.stringify(changes)}.`); 229e484b35bSopenharmony_ci const attrs = changes.attrs || {}; 230e484b35bSopenharmony_ci for (const name in attrs) { 231e484b35bSopenharmony_ci el.setAttr(name, attrs[name], true); 232e484b35bSopenharmony_ci } 233e484b35bSopenharmony_ci const style = changes.style || {}; 234e484b35bSopenharmony_ci for (const name in style) { 235e484b35bSopenharmony_ci el.setStyle(name, style[name], true); 236e484b35bSopenharmony_ci } 237e484b35bSopenharmony_ci } 238e484b35bSopenharmony_ci} 239e484b35bSopenharmony_ci 240e484b35bSopenharmony_ciexport default Document; 241