Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / resources / print_preview / component.js
blob3c18829a22e2e16a445447b69bc77a467f05dc62
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() {
6 'use strict';
8 /**
9 * Class that represents a UI component.
10 * @constructor
11 * @extends {cr.EventTarget}
13 function Component() {
14 cr.EventTarget.call(this);
16 /**
17 * Component's HTML element.
18 * @type {Element}
19 * @private
21 this.element_ = null;
23 this.isInDocument_ = false;
25 /**
26 * Component's event tracker.
27 * @type {EventTracker}
28 * @private
30 this.tracker_ = new EventTracker();
32 /**
33 * Child components of the component.
34 * @type {!Array<!print_preview.Component>}
35 * @private
37 this.children_ = [];
40 Component.prototype = {
41 __proto__: cr.EventTarget.prototype,
43 /** Gets the component's element. */
44 getElement: function() {
45 return this.element_;
48 /** @return {EventTracker} Component's event tracker. */
49 get tracker() {
50 return this.tracker_;
53 /**
54 * @return {boolean} Whether the element of the component is already in the
55 * HTML document.
57 get isInDocument() {
58 return this.isInDocument_;
61 /**
62 * Creates the root element of the component. Sub-classes should override
63 * this method.
65 createDom: function() {
66 this.element_ = cr.doc.createElement('div');
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.
74 enterDocument: function() {
75 this.isInDocument_ = true;
76 this.children_.forEach(function(child) {
77 if (!child.isInDocument && child.getElement()) {
78 child.enterDocument();
80 });
83 /** Removes all event listeners. */
84 exitDocument: function() {
85 this.children_.forEach(function(child) {
86 if (child.isInDocument) {
87 child.exitDocument();
89 });
90 this.tracker_.removeAll();
91 this.isInDocument_ = false;
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.
100 render: function(parentElement) {
101 assert(!this.isInDocument, 'Component is already in the document');
102 if (!this.element_) {
103 this.createDom();
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 * @return {!Array<!print_preview.Component>} Child components of this
123 * component.
125 get children() {
126 return this.children_;
130 * @param {!print_preview.Component} child Component to add as a child of
131 * this component.
133 addChild: function(child) {
134 this.children_.push(child);
138 * @param {!print_preview.Component} child Component to remove from this
139 * component's children.
141 removeChild: function(child) {
142 var childIdx = this.children_.indexOf(child);
143 if (childIdx != -1) {
144 this.children_.splice(childIdx, 1);
146 if (child.isInDocument) {
147 child.exitDocument();
148 if (child.getElement()) {
149 child.getElement().parentNode.removeChild(child.getElement());
154 /** Removes all of the component's children. */
155 removeChildren: function() {
156 while (this.children_.length > 0) {
157 this.removeChild(this.children_[0]);
162 * @param {string} query Selector query to select an element starting from
163 * the component's root element using a depth first search for the first
164 * element that matches the query.
165 * @return {HTMLElement} Element selected by the given query.
166 * TODO(alekseys): Check all call sites and rename this function to
167 * something like getRequiredChildElement.
169 getChildElement: function(query) {
170 return this.element_.querySelector(query);
174 * Sets the component's element.
175 * @param {Element} element HTML element to set as the component's element.
176 * @protected
178 setElementInternal: function(element) {
179 this.element_ = element;
183 * Decorates the given element for use as the element of the component.
184 * @protected
186 decorateInternal: function() { /*abstract*/ },
189 * Clones a template HTML DOM tree.
190 * @param {string} templateId Template element ID.
191 * @param {boolean=} opt_keepHidden Whether to leave the cloned template
192 * hidden after cloning.
193 * @return {Element} Cloned element with its 'id' attribute stripped.
194 * @protected
196 cloneTemplateInternal: function(templateId, opt_keepHidden) {
197 var templateEl = $(templateId);
198 assert(templateEl != null,
199 'Could not find element with ID: ' + templateId);
200 var el = assertInstanceof(templateEl.cloneNode(true), HTMLElement);
201 el.id = '';
202 if (!opt_keepHidden) {
203 setIsVisible(el, true);
205 return el;
209 return {
210 Component: Component