]>
Commit | Line | Data |
---|---|---|
33585038 DI |
1 | /** |
2 | * @module xterm/utils/DomElementObjectPool | |
3 | * @license MIT | |
4 | */ | |
5 | ||
6 | /** | |
7 | * An object pool that manages acquisition and releasing of DOM elements for | |
8 | * when reuse is desirable. | |
9 | */ | |
10 | export class DomElementObjectPool { | |
11 | private static readonly OBJECT_ID_ATTRIBUTE = 'data-obj-id'; | |
12 | ||
13 | private static _objectCount = 0; | |
14 | ||
15 | private _type: string; | |
16 | private _pool: HTMLElement[]; | |
17 | private _inUse: {[key: string]: HTMLElement}; | |
18 | ||
19 | /** | |
20 | * @param type The DOM element type (div, span, etc.). | |
21 | */ | |
22 | constructor(private type: string) { | |
23 | this._type = type; | |
24 | this._pool = []; | |
25 | this._inUse = {}; | |
26 | } | |
27 | ||
537018f7 DI |
28 | /** |
29 | * Acquire an element from the pool, creating it if the pool is empty. | |
30 | */ | |
33585038 DI |
31 | public acquire(): HTMLElement { |
32 | let element: HTMLElement; | |
33 | if (this._pool.length === 0) { | |
2b4c019f | 34 | element = this._createNew(); |
33585038 DI |
35 | } else { |
36 | element = this._pool.pop(); | |
37 | } | |
38 | this._inUse[element.getAttribute(DomElementObjectPool.OBJECT_ID_ATTRIBUTE)] = element; | |
39 | return element; | |
40 | } | |
41 | ||
537018f7 DI |
42 | /** |
43 | * Release an element back into the pool. It's up to the caller of this | |
44 | * function to ensure that all external references to the element have been | |
45 | * removed. | |
46 | * @param element The element being released. | |
47 | */ | |
1a777edf | 48 | public release(element: HTMLElement): void { |
33585038 DI |
49 | if (!this._inUse[element.getAttribute(DomElementObjectPool.OBJECT_ID_ATTRIBUTE)]) { |
50 | throw new Error('Could not release an element not yet acquired'); | |
51 | } | |
52 | delete this._inUse[element.getAttribute(DomElementObjectPool.OBJECT_ID_ATTRIBUTE)]; | |
2b4c019f | 53 | this._cleanElement(element); |
33585038 DI |
54 | this._pool.push(element); |
55 | } | |
56 | ||
537018f7 DI |
57 | /** |
58 | * Creates a new element for the pool. | |
59 | */ | |
2b4c019f | 60 | private _createNew(): HTMLElement { |
33585038 DI |
61 | const element = document.createElement(this._type); |
62 | const id = DomElementObjectPool._objectCount++; | |
63 | element.setAttribute(DomElementObjectPool.OBJECT_ID_ATTRIBUTE, id.toString(10)); | |
64 | return element; | |
65 | } | |
2b4c019f | 66 | |
537018f7 DI |
67 | /** |
68 | * Resets an element back to a "clean state". | |
69 | * @param element The element to be cleaned. | |
70 | */ | |
2b4c019f DI |
71 | private _cleanElement(element: HTMLElement): void { |
72 | element.className = ''; | |
73 | element.innerHTML = ''; | |
74 | } | |
33585038 | 75 | } |