15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cr.define('print_preview', function() { 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'use strict'; 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Class that represents a UI component. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @extends {cr.EventTarget} 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function Component() { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cr.EventTarget.call(this); 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Component's HTML element. 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {Element} 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.element_ = null; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.isInDocument_ = false; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Component's event tracker. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {EventTracker} 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.tracker_ = new EventTracker(); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Child components of the component. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {Array.<print_preview.Component>} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.children_ = []; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Component.prototype = { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __proto__: cr.EventTarget.prototype, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Gets the component's element. */ 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getElement: function() { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.element_; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** @return {EventTracker} Component's event tracker. */ 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get tracker() { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.tracker_; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} Whether the element of the component is already in the 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * HTML document. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get isInDocument() { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.isInDocument_; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Creates the root element of the component. Sub-classes should override 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this method. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) createDom: function() { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.element_ = cr.doc.createElement('div'); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called when the component's element is known to be in the document. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Anything using document.getElementById etc. should be done at this stage. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Sub-classes should extend this method and attach listeners. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enterDocument: function() { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.isInDocument_ = true; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.children_.forEach(function(child) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!child.isInDocument && child.getElement()) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child.enterDocument(); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Removes all event listeners. */ 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exitDocument: function() { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.children_.forEach(function(child) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (child.isInDocument) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child.exitDocument(); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.tracker_.removeAll(); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.isInDocument_ = false; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Renders this UI component and appends the element to the given parent 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * element. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!Element} parentElement Element to render the component's 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * element into. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render: function(parentElement) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(!this.isInDocument, 'Component is already in the document'); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.element_) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.createDom(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parentElement.appendChild(this.element_); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.enterDocument(); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Decorates an existing DOM element. Sub-classes should override the 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * override the decorateInternal method. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Element} element Element to decorate. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decorate: function(element) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(!this.isInDocument, 'Component is already in the document'); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.setElementInternal(element); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.decorateInternal(); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.enterDocument(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {print_preview.Component} child Component to add as a child of 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this component. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addChild: function(child) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.children_.push(child); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!print_preview.Component} child Component to remove from this 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * component's children. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) removeChild: function(child) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var childIdx = this.children_.indexOf(child); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (childIdx != -1) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.children_.splice(childIdx, 1); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (child.isInDocument) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child.exitDocument(); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (child.getElement()) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child.getElement().parentNode.removeChild(child.getElement()); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Removes all of the component's children. */ 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) removeChildren: function() { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (this.children_.length > 0) { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeChild(this.children_[0]); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} query Selector query to select an element starting from 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the component's root element using a depth first search for the first 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * element that matches the query. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {HTMLElement} Element selected by the given query. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getChildElement: function(query) { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.element_.querySelector(query); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Sets the component's element. 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Element} element HTML element to set as the component's element. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @protected 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setElementInternal: function(element) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.element_ = element; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Decorates the given element for use as the element of the component. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @protected 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decorateInternal: function() { /*abstract*/ }, 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Clones a template HTML DOM tree. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} templateId Template element ID. 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean=} opt_keepHidden Whether to leave the cloned template 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * hidden after cloning. 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {Element} Cloned element with its 'id' attribute stripped. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @protected 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cloneTemplateInternal: function(templateId, opt_keepHidden) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var templateEl = $(templateId); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(templateEl != null, 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Could not find element with ID: ' + templateId); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var el = templateEl.cloneNode(true); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) el.id = ''; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!opt_keepHidden) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setIsVisible(el, true); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return el; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Component: Component 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}); 203