1010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis// Use of this source code is governed by a BSD-style license that can be 3010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis// found in the LICENSE file. 4010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 5010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis/** 6010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * The global object. 7010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @type {!Object} 8010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @const 9010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 10010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennisvar global = this; 11010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 12010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis/** Platform, package, object property, and Event support. **/ 13010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennisthis.cr = (function() { 14010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 'use strict'; 15010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 16010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 17010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Tags the html element with an attribute that allows touch-specific css 18010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * rules. 19010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * TODO(rbyers): make Chrome always touch-optimized. http://crbug.com/105380 20010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 21010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis function enableTouchOptimizedCss() { 22010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis if (cr.isTouchOptimized) 23010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis doc.documentElement.setAttribute('touch-optimized', ''); 24010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 25010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 26010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 27010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Builds an object structure for the provided namespace path, 28010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * ensuring that names that already exist are not overwritten. For 29010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * example: 30010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * "a.b.c" -> a = {};a.b={};a.b.c={}; 31010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {string} name Name of the object that this file defines. 32010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {*=} opt_object The object to expose at the end of the path. 33010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {Object=} opt_objectToExportTo The object to add the path to; 34010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * default is {@code global}. 35010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @private 36010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 37010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis function exportPath(name, opt_object, opt_objectToExportTo) { 38010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var parts = name.split('.'); 39010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var cur = opt_objectToExportTo || global; 40010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 41010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis for (var part; parts.length && (part = parts.shift());) { 42010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis if (!parts.length && opt_object !== undefined) { 43010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis // last part and we have an object; use it 44010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis cur[part] = opt_object; 45010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } else if (part in cur) { 46010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis cur = cur[part]; 47010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } else { 48010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis cur = cur[part] = {}; 49010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 50010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 51010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return cur; 52010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis }; 53010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 54010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 55010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Fires a property change event on the target. 56010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {EventTarget} target The target to dispatch the event on. 57010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {string} propertyName The name of the property that changed. 58010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {*} newValue The new value for the property. 59010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {*} oldValue The old value for the property. 60010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 61010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis function dispatchPropertyChange(target, propertyName, newValue, oldValue) { 62010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var e = new cr.Event(propertyName + 'Change'); 63010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis e.propertyName = propertyName; 64010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis e.newValue = newValue; 65010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis e.oldValue = oldValue; 66010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis target.dispatchEvent(e); 67010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 68010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 69010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 70010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Converts a camelCase javascript property name to a hyphenated-lower-case 71010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * attribute name. 72010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {string} jsName The javascript camelCase property name. 73010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @return {string} The equivalent hyphenated-lower-case attribute name. 74010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 75010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis function getAttributeName(jsName) { 76010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return jsName.replace(/([A-Z])/g, '-$1').toLowerCase(); 77010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 78010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 79010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 80010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * The kind of property to define in {@code defineProperty}. 81010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @enum {number} 82010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @const 83010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 84010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var PropertyKind = { 85010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 86010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Plain old JS property where the backing data is stored as a "private" 87010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * field on the object. 88010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 89010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis JS: 'js', 90010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 91010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 92010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * The property backing data is stored as an attribute on an element. 93010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 94010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis ATTR: 'attr', 95010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 96010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 97010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * The property backing data is stored as an attribute on an element. If the 98010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * element has the attribute then the value is true. 99010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 100010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis BOOL_ATTR: 'boolAttr' 101010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis }; 102010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 103010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 104010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Helper function for defineProperty that returns the getter to use for the 105010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * property. 106010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {string} name The name of the property. 107010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {cr.PropertyKind} kind The kind of the property. 108010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @return {function():*} The getter for the property. 109010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 110010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis function getGetter(name, kind) { 111010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis switch (kind) { 112010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis case PropertyKind.JS: 113010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var privateName = name + '_'; 114010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return function() { 115010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return this[privateName]; 116010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis }; 117010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis case PropertyKind.ATTR: 118010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var attributeName = getAttributeName(name); 119010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return function() { 120010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return this.getAttribute(attributeName); 121010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis }; 122010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis case PropertyKind.BOOL_ATTR: 123010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var attributeName = getAttributeName(name); 124010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return function() { 125010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return this.hasAttribute(attributeName); 126010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis }; 127010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 128010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 129010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 130010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 131010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Helper function for defineProperty that returns the setter of the right 132010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * kind. 133010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {string} name The name of the property we are defining the setter 134010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * for. 135010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {cr.PropertyKind} kind The kind of property we are getting the 136010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * setter for. 137010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {function(*):void} opt_setHook A function to run after the property 138010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * is set, but before the propertyChange event is fired. 139010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @return {function(*):void} The function to use as a setter. 140010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 141010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis function getSetter(name, kind, opt_setHook) { 142010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis switch (kind) { 143010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis case PropertyKind.JS: 144010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var privateName = name + '_'; 145010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return function(value) { 146010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var oldValue = this[privateName]; 147010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis if (value !== oldValue) { 148010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis this[privateName] = value; 149010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis if (opt_setHook) 150010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis opt_setHook.call(this, value, oldValue); 151010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis dispatchPropertyChange(this, name, value, oldValue); 152010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 153010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis }; 154010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 155010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis case PropertyKind.ATTR: 156010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var attributeName = getAttributeName(name); 157010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return function(value) { 158010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var oldValue = this[attributeName]; 159010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis if (value !== oldValue) { 160010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis if (value == undefined) 161010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis this.removeAttribute(attributeName); 162010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis else 163010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis this.setAttribute(attributeName, value); 164010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis if (opt_setHook) 165010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis opt_setHook.call(this, value, oldValue); 166010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis dispatchPropertyChange(this, name, value, oldValue); 167010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 168010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis }; 169010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 170010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis case PropertyKind.BOOL_ATTR: 171010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var attributeName = getAttributeName(name); 172010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return function(value) { 173010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var oldValue = this[attributeName]; 174010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis if (value !== oldValue) { 175010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis if (value) 176010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis this.setAttribute(attributeName, name); 177010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis else 178010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis this.removeAttribute(attributeName); 179010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis if (opt_setHook) 180010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis opt_setHook.call(this, value, oldValue); 181010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis dispatchPropertyChange(this, name, value, oldValue); 182010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 183010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis }; 184010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 185010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 186010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 187010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 188010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Defines a property on an object. When the setter changes the value a 189010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * property change event with the type {@code name + 'Change'} is fired. 190010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {!Object} obj The object to define the property for. 191010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {string} name The name of the property. 192010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {cr.PropertyKind=} opt_kind What kind of underlying storage to use. 193010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {function(*):void} opt_setHook A function to run after the 194010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * property is set, but before the propertyChange event is fired. 195010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 196010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis function defineProperty(obj, name, opt_kind, opt_setHook) { 197010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis if (typeof obj == 'function') 198010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis obj = obj.prototype; 199010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 200010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var kind = opt_kind || PropertyKind.JS; 201010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 202010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis if (!obj.__lookupGetter__(name)) 203010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis obj.__defineGetter__(name, getGetter(name, kind)); 204010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 205010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis if (!obj.__lookupSetter__(name)) 206010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis obj.__defineSetter__(name, getSetter(name, kind, opt_setHook)); 207010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 208010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 209010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 210010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Counter for use with createUid 211010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 212010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var uidCounter = 1; 213010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 214010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 215010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @return {number} A new unique ID. 216010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 217010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis function createUid() { 218010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return uidCounter++; 219010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 220010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 221010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 222010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Returns a unique ID for the item. This mutates the item so it needs to be 223010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * an object 224010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {!Object} item The item to get the unique ID for. 225010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @return {number} The unique ID for the item. 226010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 227010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis function getUid(item) { 228010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis if (item.hasOwnProperty('uid')) 229010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return item.uid; 230010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return item.uid = createUid(); 231010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 232010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 233010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 234010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Dispatches a simple event on an event target. 235010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {!EventTarget} target The event target to dispatch the event on. 236010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {string} type The type of the event. 237010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {boolean=} opt_bubbles Whether the event bubbles or not. 238010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {boolean=} opt_cancelable Whether the default action of the event 239010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * can be prevented. 240010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @return {boolean} If any of the listeners called {@code preventDefault} 241010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * during the dispatch this will return false. 242010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 243010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis function dispatchSimpleEvent(target, type, opt_bubbles, opt_cancelable) { 244010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var e = new cr.Event(type, opt_bubbles, opt_cancelable); 245010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return target.dispatchEvent(e); 246010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 247010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 248010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 249010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Calls |fun| and adds all the fields of the returned object to the object 250010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * named by |name|. For example, cr.define('cr.ui', function() { 251010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * function List() { 252010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * ... 253010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * } 254010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * function ListItem() { 255010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * ... 256010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * } 257010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * return { 258010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * List: List, 259010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * ListItem: ListItem, 260010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * }; 261010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * }); 262010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * defines the functions cr.ui.List and cr.ui.ListItem. 263010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {string} name The name of the object that we are adding fields to. 264010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {!Function} fun The function that will return an object containing 265010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * the names and values of the new fields. 266010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 267010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis function define(name, fun) { 268010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var obj = exportPath(name); 269010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var exports = fun(); 270010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis for (var propertyName in exports) { 271010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis // Maybe we should check the prototype chain here? The current usage 272010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis // pattern is always using an object literal so we only care about own 273010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis // properties. 274010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var propertyDescriptor = Object.getOwnPropertyDescriptor(exports, 275010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis propertyName); 276010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis if (propertyDescriptor) 277010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis Object.defineProperty(obj, propertyName, propertyDescriptor); 278010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 279010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 280010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 281010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 282010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Adds a {@code getInstance} static method that always return the same 283010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * instance object. 284010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {!Function} ctor The constructor for the class to add the static 285010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * method to. 286010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 287010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis function addSingletonGetter(ctor) { 288010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis ctor.getInstance = function() { 289010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return ctor.instance_ || (ctor.instance_ = new ctor()); 290010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis }; 291010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 292010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 293010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 294010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Creates a new event to be used with cr.EventTarget or DOM EventTarget 295010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * objects. 296010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {string} type The name of the event. 297010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {boolean=} opt_bubbles Whether the event bubbles. 298010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Default is false. 299010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @param {boolean=} opt_preventable Whether the default action of the event 300010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * can be prevented. 301010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @constructor 302010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @extends {Event} 303010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 304010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis function Event(type, opt_bubbles, opt_preventable) { 305010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var e = cr.doc.createEvent('Event'); 306010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis e.initEvent(type, !!opt_bubbles, !!opt_preventable); 307010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis e.__proto__ = global.Event.prototype; 308010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return e; 309010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis }; 310010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 311010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 312010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Initialization which must be deferred until run-time. 313010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 314010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis function initialize() { 315010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis // If 'document' isn't defined, then we must be being pre-compiled, 316010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis // so set a trap so that we're initialized on first access at run-time. 317010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis if (!global.document) { 318010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis var originalCr = cr; 319010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 320010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis Object.defineProperty(global, 'cr', { 321010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis get: function() { 322010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis Object.defineProperty(global, 'cr', {value: originalCr}); 323010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis originalCr.initialize(); 324010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return originalCr; 325010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis }, 326010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis configurable: true 327010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis }); 328010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 329010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return; 330010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 331010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 332010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis Event.prototype = {__proto__: global.Event.prototype}; 333010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 334010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 335010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Whether we are using a Mac or not. 336010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 337010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis cr.isMac = /Mac/.test(navigator.platform); 338010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 339010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 340010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Whether this is on the Windows platform or not. 341010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 342010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis cr.isWindows = /Win/.test(navigator.platform); 343010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 344010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 345010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Whether this is on chromeOS or not. 346010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 347010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis cr.isChromeOS = /CrOS/.test(navigator.userAgent); 348010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 349010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 350010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Whether this is on vanilla Linux (not chromeOS). 351010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 352010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis cr.isLinux = /Linux/.test(navigator.userAgent); 353010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 354010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 355010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Whether this uses GTK or not. 356010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 357010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis cr.isGTK = /GTK/.test(chrome.toolkit); 358010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 359010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 360010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Whether this uses the views toolkit or not. 361010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 362010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis cr.isViews = /views/.test(chrome.toolkit); 363010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 364010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 365010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * Whether this window is optimized for touch-based input. 366010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 367010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis cr.isTouchOptimized = !!chrome.touchOptimized; 368010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 369010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis enableTouchOptimizedCss(); 370010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 371010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 372010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return { 373010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis addSingletonGetter: addSingletonGetter, 374010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis createUid: createUid, 375010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis define: define, 376010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis defineProperty: defineProperty, 377010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis dispatchPropertyChange: dispatchPropertyChange, 378010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis dispatchSimpleEvent: dispatchSimpleEvent, 379010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis Event: Event, 380010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis getUid: getUid, 381010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis initialize: initialize, 382010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis PropertyKind: PropertyKind, 383010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 384010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis /** 385010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * The document that we are currently using. 386010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @type {!Document} 387010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 388010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis get doc() { 389010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis return document; 390010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis } 391010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis }; 392010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis})(); 393010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 394010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis 395010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis/** 396010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * TODO(kgr): Move this to another file which is to be loaded last. 397010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * This will be done as part of future work to make this code pre-compilable. 398010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */ 399010583560e0e6db74fe50b840bce46ba6537de63Jamie Genniscr.initialize(); 400