OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 cr.define('print_preview', function() { |
| 6 'use strict'; |
| 7 |
| 8 /** |
| 9 * Class that represents a UI component. |
| 10 * @constructor |
| 11 * @extends {cr.EventTarget} |
| 12 */ |
| 13 function Component() { |
| 14 cr.EventTarget.call(this); |
| 15 |
| 16 /** |
| 17 * Component's HTML element. |
| 18 * @type {Element} |
| 19 * @private |
| 20 */ |
| 21 this.element_ = null; |
| 22 |
| 23 this.isInDocument_ = false; |
| 24 |
| 25 /** |
| 26 * Component's event tracker. |
| 27 * @type {EventTracker} |
| 28 * @private |
| 29 */ |
| 30 this.tracker_ = new EventTracker(); |
| 31 |
| 32 /** |
| 33 * Child components of the component. |
| 34 * @type {Array.<print_preview.Component>} |
| 35 * @private |
| 36 */ |
| 37 this.children_ = []; |
| 38 }; |
| 39 |
| 40 Component.prototype = { |
| 41 __proto__: cr.EventTarget.prototype, |
| 42 |
| 43 /** Gets the component's element. */ |
| 44 getElement: function() { |
| 45 return this.element_; |
| 46 }, |
| 47 |
| 48 /** @return {EventTracker} Component's event tracker. */ |
| 49 get tracker() { |
| 50 return this.tracker_; |
| 51 }, |
| 52 |
| 53 /** |
| 54 * @return {boolean} Whether the element of the component is already in the |
| 55 * HTML document. |
| 56 */ |
| 57 get isInDocument() { |
| 58 return this.isInDocument_; |
| 59 }, |
| 60 |
| 61 /** |
| 62 * Creates the root element of the component. Sub-classes should override |
| 63 * this method. |
| 64 */ |
| 65 createDom: function() { |
| 66 this.element_ = cr.doc.createElement('div'); |
| 67 }, |
| 68 |
| 69 /** |
| 70 * Called when the component's element is known to be in the document. |
| 71 * Anything using document.getElementById etc. should be done at this stage. |
| 72 * Sub-classes should extend this method and attach listeners. |
| 73 */ |
| 74 enterDocument: function() { |
| 75 this.isInDocument_ = true; |
| 76 for (var child, i = 0; child = this.children_[i]; i++) { |
| 77 if (!child.isInDocument && child.getElement()) { |
| 78 child.enterDocument(); |
| 79 } |
| 80 } |
| 81 }, |
| 82 |
| 83 /** Removes all event listeners. */ |
| 84 exitDocument: function() { |
| 85 for (var child, i = 0; child = this.children_[i]; i++) { |
| 86 if (child.isInDocument) { |
| 87 child.exitDocument(); |
| 88 } |
| 89 } |
| 90 this.tracker_.removeAll(); |
| 91 this.isInDocument_ = false; |
| 92 }, |
| 93 |
| 94 /** |
| 95 * Renders this UI component and appends the element to the given parent |
| 96 * element. |
| 97 * @param {!Element} parentElement Element to render the component's |
| 98 * element into. |
| 99 */ |
| 100 render: function(parentElement) { |
| 101 if (this.isInDocument) { |
| 102 throw Error('Component is already in the document'); |
| 103 } |
| 104 if (!this.element_) { |
| 105 this.createDom(); |
| 106 } |
| 107 parentElement.appendChild(this.element_); |
| 108 this.enterDocument(); |
| 109 }, |
| 110 |
| 111 /** |
| 112 * Decorates an existing DOM element. Sub-classes should override the |
| 113 * override the decorateInternal method. |
| 114 * @param {Element} element Element to decorate. |
| 115 */ |
| 116 decorate: function(element) { |
| 117 if (this.isInDocument) { |
| 118 throw Error('Component is already in the document'); |
| 119 } |
| 120 this.setElementInternal(element); |
| 121 this.decorateInternal(); |
| 122 this.enterDocument(); |
| 123 }, |
| 124 |
| 125 /** |
| 126 * @param {print_preview.Component} child Component to add as a child of |
| 127 * this component. |
| 128 */ |
| 129 addChild: function(child) { |
| 130 this.children_.push(child); |
| 131 }, |
| 132 |
| 133 /** |
| 134 * @param {!print_preview.Component} child Component to remove from this |
| 135 * component's children. |
| 136 */ |
| 137 removeChild: function(child) { |
| 138 var childIdx = this.children_.indexOf(child); |
| 139 if (childIdx != -1) { |
| 140 this.children_.splice(childIdx, 1); |
| 141 } |
| 142 if (child.isInDocument) { |
| 143 child.exitDocument(); |
| 144 if (child.getElement()) { |
| 145 child.getElement().parentNode.removeChild(child.getElement()); |
| 146 } |
| 147 } |
| 148 }, |
| 149 |
| 150 /** Removes all of the component's children. */ |
| 151 removeChildren: function() { |
| 152 while (this.children_.length > 0) { |
| 153 this.removeChild(this.children_[0]); |
| 154 } |
| 155 }, |
| 156 |
| 157 /** |
| 158 * Sets the component's element. |
| 159 * @param {Element} element HTML element to set as the component's element. |
| 160 * @protected |
| 161 */ |
| 162 setElementInternal: function(element) { |
| 163 this.element_ = element; |
| 164 }, |
| 165 |
| 166 /** |
| 167 * Decorates the given element for use as the element of the component. |
| 168 * @protected |
| 169 */ |
| 170 decorateInternal: function() { /*abstract*/ }, |
| 171 |
| 172 /** |
| 173 * Clones a template HTML DOM tree. |
| 174 * @param {string} templateId Template element ID. |
| 175 * @param {boolean=} opt_keepHidden Whether to leave the cloned template |
| 176 * hidden after cloning. |
| 177 * @return {Element} Cloned element with its 'id' attribute stripped. |
| 178 * @protected |
| 179 */ |
| 180 cloneTemplateInternal: function(templateId, opt_keepHidden) { |
| 181 var templateEl = $(templateId); |
| 182 if (!templateEl) { |
| 183 throw Error('Could not find element with ID: ' + templateId); |
| 184 } |
| 185 var el = templateEl.cloneNode(true); |
| 186 el.id = ''; |
| 187 if (!opt_keepHidden) { |
| 188 setIsVisible(el, true); |
| 189 } |
| 190 return el; |
| 191 } |
| 192 }; |
| 193 |
| 194 return { |
| 195 Component: Component |
| 196 }; |
| 197 }); |
OLD | NEW |