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_ciimport { hasOwn } from '../../../utils/index'; 21e484b35bSopenharmony_ci 22e484b35bSopenharmony_ci/** 23e484b35bSopenharmony_ci * This class provides action for page refresh. 24e484b35bSopenharmony_ci */ 25e484b35bSopenharmony_ciexport default class Differ { 26e484b35bSopenharmony_ci private _id: string; 27e484b35bSopenharmony_ci private _map: object[]; 28e484b35bSopenharmony_ci private _hooks: Function[]; 29e484b35bSopenharmony_ci private _hasTimer: boolean; 30e484b35bSopenharmony_ci 31e484b35bSopenharmony_ci constructor(id: string) { 32e484b35bSopenharmony_ci this._id = id; 33e484b35bSopenharmony_ci this._map = []; 34e484b35bSopenharmony_ci this._hooks = []; 35e484b35bSopenharmony_ci } 36e484b35bSopenharmony_ci 37e484b35bSopenharmony_ci /** 38e484b35bSopenharmony_ci * Check whether the map is empty. 39e484b35bSopenharmony_ci * @return {boolean} 40e484b35bSopenharmony_ci */ 41e484b35bSopenharmony_ci public isEmpty(): boolean { 42e484b35bSopenharmony_ci return this._map.length === 0; 43e484b35bSopenharmony_ci } 44e484b35bSopenharmony_ci 45e484b35bSopenharmony_ci /** 46e484b35bSopenharmony_ci * Id of the page. 47e484b35bSopenharmony_ci * @type {string} 48e484b35bSopenharmony_ci */ 49e484b35bSopenharmony_ci public get id() { 50e484b35bSopenharmony_ci return this._id; 51e484b35bSopenharmony_ci } 52e484b35bSopenharmony_ci 53e484b35bSopenharmony_ci /** 54e484b35bSopenharmony_ci * Append action. 55e484b35bSopenharmony_ci * @param {string} type 56e484b35bSopenharmony_ci * @param {string} ref 57e484b35bSopenharmony_ci * @param {Function} handler 58e484b35bSopenharmony_ci */ 59e484b35bSopenharmony_ci public append(type: string, ref: string, handler: Function): void { 60e484b35bSopenharmony_ci // Ignore depth to speed up render. 61e484b35bSopenharmony_ci const defaultDepth: number = 1; 62e484b35bSopenharmony_ci if (!this._hasTimer) { 63e484b35bSopenharmony_ci this._hasTimer = true; 64e484b35bSopenharmony_ci 65e484b35bSopenharmony_ci // Use setTimeout instead of setTimeoutDiffer 66e484b35bSopenharmony_ci // avoid invoking setTimeout after appDestroy 67e484b35bSopenharmony_ci if (typeof setTimeout === "function") { 68e484b35bSopenharmony_ci setTimeout(() => { 69e484b35bSopenharmony_ci this._hasTimer = false; 70e484b35bSopenharmony_ci this.flush(); 71e484b35bSopenharmony_ci }, 0); 72e484b35bSopenharmony_ci } 73e484b35bSopenharmony_ci } 74e484b35bSopenharmony_ci const map: object[] = this._map; 75e484b35bSopenharmony_ci if (!map[defaultDepth]) { 76e484b35bSopenharmony_ci map[defaultDepth] = {}; 77e484b35bSopenharmony_ci } 78e484b35bSopenharmony_ci const group: object = map[defaultDepth]; 79e484b35bSopenharmony_ci if (!group[type]) { 80e484b35bSopenharmony_ci group[type] = {}; 81e484b35bSopenharmony_ci } 82e484b35bSopenharmony_ci if (type === 'element') { 83e484b35bSopenharmony_ci if (!group[type][ref]) { 84e484b35bSopenharmony_ci group[type][ref] = []; 85e484b35bSopenharmony_ci } 86e484b35bSopenharmony_ci group[type][ref].push(handler); 87e484b35bSopenharmony_ci } else { 88e484b35bSopenharmony_ci group[type][ref] = handler; 89e484b35bSopenharmony_ci } 90e484b35bSopenharmony_ci } 91e484b35bSopenharmony_ci 92e484b35bSopenharmony_ci /** 93e484b35bSopenharmony_ci * Execute actions of differ. 94e484b35bSopenharmony_ci */ 95e484b35bSopenharmony_ci public flush(): void { 96e484b35bSopenharmony_ci const map: object[] = this._map.slice(); 97e484b35bSopenharmony_ci this._map.length = 0; 98e484b35bSopenharmony_ci map.forEach((group) => { 99e484b35bSopenharmony_ci callTypeList(group, 'element'); 100e484b35bSopenharmony_ci callTypeMap(group, 'repeat'); 101e484b35bSopenharmony_ci callTypeMap(group, 'shown'); 102e484b35bSopenharmony_ci }); 103e484b35bSopenharmony_ci 104e484b35bSopenharmony_ci const hooks: Function[] = this._hooks.slice(); 105e484b35bSopenharmony_ci this._hooks.length = 0; 106e484b35bSopenharmony_ci hooks.forEach((fn) => { 107e484b35bSopenharmony_ci fn(); 108e484b35bSopenharmony_ci }); 109e484b35bSopenharmony_ci 110e484b35bSopenharmony_ci if (!this.isEmpty()) { 111e484b35bSopenharmony_ci this.flush(); 112e484b35bSopenharmony_ci } 113e484b35bSopenharmony_ci } 114e484b35bSopenharmony_ci then(fn) { 115e484b35bSopenharmony_ci this._hooks.push(fn); 116e484b35bSopenharmony_ci } 117e484b35bSopenharmony_ci} 118e484b35bSopenharmony_ci 119e484b35bSopenharmony_cifunction callTypeMap(group: any, type: string): void { 120e484b35bSopenharmony_ci const map: Function[] = group[type]; 121e484b35bSopenharmony_ci for (const ref in map) { 122e484b35bSopenharmony_ci map[ref](); 123e484b35bSopenharmony_ci } 124e484b35bSopenharmony_ci} 125e484b35bSopenharmony_ci 126e484b35bSopenharmony_cifunction callTypeList(group: any, type: string): void { 127e484b35bSopenharmony_ci const map: any = group[type]; 128e484b35bSopenharmony_ci for (const ref in map) { 129e484b35bSopenharmony_ci if (hasOwn(map, ref)) { 130e484b35bSopenharmony_ci const list: Function[] = map[ref]; 131e484b35bSopenharmony_ci list.forEach((handler) => { 132e484b35bSopenharmony_ci handler(); 133e484b35bSopenharmony_ci }); 134e484b35bSopenharmony_ci } 135e484b35bSopenharmony_ci } 136e484b35bSopenharmony_ci} 137