Index: chrome/browser/resources/print_preview/component.js |
diff --git a/chrome/browser/resources/print_preview/component.js b/chrome/browser/resources/print_preview/component.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f51c3ae1313f679019cd1a26c52bbf98773a575c |
--- /dev/null |
+++ b/chrome/browser/resources/print_preview/component.js |
@@ -0,0 +1,192 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+cr.define('print_preview', function() { |
+ 'use strict'; |
+ |
+ /** |
+ * Class that represents a UI component. |
+ * @constructor |
+ * @extends {cr.EventTarget} |
+ */ |
+ function Component() { |
+ cr.EventTarget.call(this); |
+ |
+ /** |
+ * Component's HTML element. |
+ * @type {Element} |
+ * @private |
+ */ |
+ this.element_ = null; |
+ |
+ this.isInDocument_ = false; |
+ |
+ /** |
+ * Component's event tracker. |
+ * @type {EventTracker} |
+ * @private |
+ */ |
+ this.tracker_ = new EventTracker(); |
+ |
+ /** |
+ * Child components of the component. |
+ * @type {Array.<print_preview.Component>} |
+ * @private |
+ */ |
+ this.children_ = []; |
+ }; |
+ |
+ Component.prototype = { |
+ __proto__: cr.EventTarget.prototype, |
+ |
+ /** Gets the component's element. */ |
+ getElement: function() { |
+ return this.element_; |
+ }, |
+ |
+ /** @return {EventTracker} Component's event tracker. */ |
+ get tracker() { |
+ return this.tracker_; |
+ }, |
+ |
+ /** |
+ * @return {boolean} Whether the element of the component is already in the |
+ * HTML document. |
+ */ |
+ get isInDocument() { |
+ return this.isInDocument_; |
+ }, |
+ |
+ /** |
+ * Creates the root element of the component. Sub-classes should override |
+ * this method. |
+ */ |
+ createDom: function() { |
+ this.element_ = cr.doc.createElement('div'); |
+ }, |
+ |
+ /** |
+ * Called when the component's element is known to be in the document. |
+ * Anything using document.getElementById etc. should be done at this stage. |
+ * Sub-classes should extend this method and attach listeners. |
+ */ |
+ enterDocument: function() { |
+ this.isInDocument_ = true; |
+ for (var child, i = 0; child = this.children_[i]; i++) { |
+ if (!child.isInDocument && child.getElement()) { |
+ child.enterDocument(); |
+ } |
+ } |
+ }, |
+ |
+ /** Removes all event listeners. */ |
+ exitDocument: function() { |
+ for (var child, i = 0; child = this.children_[i]; i++) { |
+ if (child.isInDocument) { |
+ child.exitDocument(); |
+ } |
+ } |
+ this.tracker_.removeAll(); |
+ this.isInDocument_ = false; |
+ }, |
+ |
+ /** |
+ * Renders this UI component and appends the element to the given parent |
+ * element. |
+ * @param {!Element} parentElement Element to render the component's |
+ * element into. |
+ */ |
+ render: function(parentElement) { |
+ assert(!this.isInDocument, 'Component is already in the document'); |
+ if (!this.element_) { |
+ this.createDom(); |
+ } |
+ parentElement.appendChild(this.element_); |
+ this.enterDocument(); |
+ }, |
+ |
+ /** |
+ * Decorates an existing DOM element. Sub-classes should override the |
+ * override the decorateInternal method. |
+ * @param {Element} element Element to decorate. |
+ */ |
+ decorate: function(element) { |
+ assert(!this.isInDocument, 'Component is already in the document'); |
+ this.setElementInternal(element); |
+ this.decorateInternal(); |
+ this.enterDocument(); |
+ }, |
+ |
+ /** |
+ * @param {print_preview.Component} child Component to add as a child of |
+ * this component. |
+ */ |
+ addChild: function(child) { |
+ this.children_.push(child); |
+ }, |
+ |
+ /** |
+ * @param {!print_preview.Component} child Component to remove from this |
+ * component's children. |
+ */ |
+ removeChild: function(child) { |
+ var childIdx = this.children_.indexOf(child); |
+ if (childIdx != -1) { |
+ this.children_.splice(childIdx, 1); |
+ } |
+ if (child.isInDocument) { |
+ child.exitDocument(); |
+ if (child.getElement()) { |
+ child.getElement().parentNode.removeChild(child.getElement()); |
+ } |
+ } |
+ }, |
+ |
+ /** Removes all of the component's children. */ |
+ removeChildren: function() { |
+ while (this.children_.length > 0) { |
+ this.removeChild(this.children_[0]); |
+ } |
+ }, |
+ |
+ /** |
+ * Sets the component's element. |
+ * @param {Element} element HTML element to set as the component's element. |
+ * @protected |
+ */ |
+ setElementInternal: function(element) { |
+ this.element_ = element; |
+ }, |
+ |
+ /** |
+ * Decorates the given element for use as the element of the component. |
+ * @protected |
+ */ |
+ decorateInternal: function() { /*abstract*/ }, |
+ |
+ /** |
+ * Clones a template HTML DOM tree. |
+ * @param {string} templateId Template element ID. |
+ * @param {boolean=} opt_keepHidden Whether to leave the cloned template |
+ * hidden after cloning. |
+ * @return {Element} Cloned element with its 'id' attribute stripped. |
+ * @protected |
+ */ |
+ cloneTemplateInternal: function(templateId, opt_keepHidden) { |
+ var templateEl = $(templateId); |
+ assert(templateEl != null, |
+ 'Could not find element with ID: ' + templateId); |
+ var el = templateEl.cloneNode(true); |
+ el.id = ''; |
+ if (!opt_keepHidden) { |
+ setIsVisible(el, true); |
+ } |
+ return el; |
+ } |
+ }; |
+ |
+ return { |
+ Component: Component |
+ }; |
+}); |