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.
5 cr
.define('print_preview', function() {
9 * Class that represents a UI component.
11 * @extends {cr.EventTarget}
13 function Component() {
14 cr
.EventTarget
.call(this);
17 * Component's HTML element.
23 this.isInDocument_
= false;
26 * Component's event tracker.
27 * @type {EventTracker}
30 this.tracker_
= new EventTracker();
33 * Child components of the component.
34 * @type {Array.<print_preview.Component>}
40 Component
.prototype = {
41 __proto__
: cr
.EventTarget
.prototype,
43 /** Gets the component's element. */
44 getElement: function() {
48 /** @return {EventTracker} Component's event tracker. */
54 * @return {boolean} Whether the element of the component is already in the
58 return this.isInDocument_
;
62 * Creates the root element of the component. Sub-classes should override
65 createDom: function() {
66 this.element_
= cr
.doc
.createElement('div');
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.
74 enterDocument: function() {
75 this.isInDocument_
= true;
76 this.children_
.forEach(function(child
) {
77 if (!child
.isInDocument
&& child
.getElement()) {
78 child
.enterDocument();
83 /** Removes all event listeners. */
84 exitDocument: function() {
85 this.children_
.forEach(function(child
) {
86 if (child
.isInDocument
) {
90 this.tracker_
.removeAll();
91 this.isInDocument_
= false;
95 * Renders this UI component and appends the element to the given parent
97 * @param {!Element} parentElement Element to render the component's
100 render: function(parentElement
) {
101 assert(!this.isInDocument
, 'Component is already in the document');
102 if (!this.element_
) {
105 parentElement
.appendChild(this.element_
);
106 this.enterDocument();
110 * Decorates an existing DOM element. Sub-classes should override the
111 * override the decorateInternal method.
112 * @param {Element} element Element to decorate.
114 decorate: function(element
) {
115 assert(!this.isInDocument
, 'Component is already in the document');
116 this.setElementInternal(element
);
117 this.decorateInternal();
118 this.enterDocument();
122 * @param {print_preview.Component} child Component to add as a child of
125 addChild: function(child
) {
126 this.children_
.push(child
);
130 * @param {!print_preview.Component} child Component to remove from this
131 * component's children.
133 removeChild: function(child
) {
134 var childIdx
= this.children_
.indexOf(child
);
135 if (childIdx
!= -1) {
136 this.children_
.splice(childIdx
, 1);
138 if (child
.isInDocument
) {
139 child
.exitDocument();
140 if (child
.getElement()) {
141 child
.getElement().parentNode
.removeChild(child
.getElement());
146 /** Removes all of the component's children. */
147 removeChildren: function() {
148 while (this.children_
.length
> 0) {
149 this.removeChild(this.children_
[0]);
154 * @param {string} query Selector query to select an element starting from
155 * the component's root element using a depth first search for the first
156 * element that matches the query.
157 * @return {HTMLElement} Element selected by the given query.
159 getChildElement: function(query
) {
160 return this.element_
.querySelector(query
);
164 * Sets the component's element.
165 * @param {Element} element HTML element to set as the component's element.
168 setElementInternal: function(element
) {
169 this.element_
= element
;
173 * Decorates the given element for use as the element of the component.
176 decorateInternal: function() { /*abstract*/ },
179 * Clones a template HTML DOM tree.
180 * @param {string} templateId Template element ID.
181 * @param {boolean=} opt_keepHidden Whether to leave the cloned template
182 * hidden after cloning.
183 * @return {Element} Cloned element with its 'id' attribute stripped.
186 cloneTemplateInternal: function(templateId
, opt_keepHidden
) {
187 var templateEl
= $(templateId
);
188 assert(templateEl
!= null,
189 'Could not find element with ID: ' + templateId
);
190 var el
= templateEl
.cloneNode(true);
192 if (!opt_keepHidden
) {
193 setIsVisible(el
, true);