1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import Element from './Element'; 17import Node from './Node'; 18import { Log } from '../utils'; 19 20/** 21 * Document element is the root element in a Document. 22 * @extends Element 23 */ 24class DocumentElement extends Element { 25 constructor(type: string = 'div', props: object = {}, isExtended?: boolean) { 26 super(type, props, isExtended); 27 } 28 29 /** 30 * Destroy this document element. 31 */ 32 public destroy() { 33 const doc = this._ownerDocument; 34 if (doc) { 35 delete this.docId; 36 delete doc.nodeMap[this.nodeId]; 37 } 38 super.destroy(); 39 } 40 41 /** 42 * Append a child node. 43 * @param {Node} node - Target node. 44 * @param {number} before - The node next to the target position. 45 * @override 46 */ 47 public appendChild(node: Node, before?: Node): void { 48 Log.debug(`DocumentElement#appendChild, node = ${node}, before = ${before}.`); 49 50 if (this.pureChildren.length > 0 || node.parentNode) { 51 return; 52 } 53 const children = this.children; 54 const beforeIndex = children.indexOf(before); 55 if (beforeIndex < 0) { 56 children.push(node); 57 } else { 58 children.splice(beforeIndex, 0, node); 59 } 60 61 if (node.nodeType === Node.NodeType.Element) { 62 const element = node as Element; 63 if (element.role === 'body') { 64 element.docId = this.id; 65 element.ownerDocument = this.ownerDocument; 66 element.parentNode = this; 67 this.linkChild(element); 68 } else { 69 element.children.forEach(child => { 70 child.parentNode = element; 71 }); 72 const document = this.ownerDocument; 73 document.setElementToBody(element); 74 element.docId = document.id; 75 element.ownerDocument = document; 76 this.linkChild(this); 77 if (this.ownerDocument) { 78 delete this.ownerDocument.nodeMap[element.nodeId]; 79 } 80 } 81 this.pureChildren.push(element); 82 this.ownerDocument.sentBodyToNative(element); 83 } else { 84 node.parentNode = this; 85 this.ownerDocument.nodeMap[node.ref] = node; 86 } 87 } 88} 89 90export default DocumentElement; 91