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