Index: resources/bookmark_manager/js/cr/ui.js |
=================================================================== |
--- resources/bookmark_manager/js/cr/ui.js (revision 0) |
+++ resources/bookmark_manager/js/cr/ui.js (revision 0) |
@@ -0,0 +1,173 @@ |
+// Copyright (c) 2010 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('cr.ui', function() { |
+ |
+ /** |
+ * Decorates elements as an instance of a class. |
+ * @param {string|!Element} source The way to find the element(s) to decorate. |
+ * If this is a string then {@code querySeletorAll} is used to find the |
+ * elements to decorate. |
+ * @param {!Function} constr The constructor to decorate with. The constr |
+ * needs to have a {@code decorate} function. |
+ */ |
+ function decorate(source, constr) { |
+ var elements; |
+ if (typeof source == 'string') |
+ elements = cr.doc.querySelectorAll(source); |
+ else |
+ elements = [source]; |
+ |
+ for (var i = 0, el; el = elements[i]; i++) { |
+ if (!(el instanceof constr)) |
+ constr.decorate(el); |
+ } |
+ } |
+ |
+ /** |
+ * Helper function for creating new element for define. |
+ */ |
+ function createElementHelper(tagName, opt_bag) { |
+ // Allow passing in ownerDocument to create in a different document. |
+ var doc; |
+ if (opt_bag && opt_bag.ownerDocument) |
+ doc = opt_bag.ownerDocument; |
+ else |
+ doc = cr.doc; |
+ return doc.createElement(tagName); |
+ } |
+ |
+ /** |
+ * Creates the constructor for a UI element class. |
+ * |
+ * Usage: |
+ * <pre> |
+ * var List = cr.ui.define('list'); |
+ * List.prototype = { |
+ * __proto__: HTMLUListElement.prototype, |
+ * decorate: function() { |
+ * ... |
+ * }, |
+ * ... |
+ * }; |
+ * </pre> |
+ * |
+ * @param {string|Function} tagNameOrFunction The tagName or |
+ * function to use for newly created elements. If this is a function it |
+ * needs to return a new element when called. |
+ * @return {function(Object=):Element} The constructor function which takes |
+ * an optional property bag. The function also has a static |
+ * {@code decorate} method added to it. |
+ */ |
+ function define(tagNameOrFunction) { |
+ var createFunction, tagName; |
+ if (typeof tagNameOrFunction == 'function') { |
+ createFunction = tagNameOrFunction; |
+ tagName = ''; |
+ } else { |
+ createFunction = createElementHelper; |
+ tagName = tagNameOrFunction; |
+ } |
+ |
+ /** |
+ * Creates a new UI element constructor. |
+ * @param {Object=} opt_propertyBag Optional bag of properties to set on the |
+ * object after created. The property {@code ownerDocument} is special |
+ * cased and it allows you to create the element in a different |
+ * document than the default. |
+ * @constructor |
+ */ |
+ function f(opt_propertyBag) { |
+ var el = createFunction(tagName, opt_propertyBag); |
+ f.decorate(el); |
+ for (var propertyName in opt_propertyBag) { |
+ el[propertyName] = opt_propertyBag[propertyName]; |
+ } |
+ return el; |
+ } |
+ |
+ /** |
+ * Decorates an element as a UI element class. |
+ * @param {!Element} el The element to decorate. |
+ */ |
+ f.decorate = function(el) { |
+ el.__proto__ = f.prototype; |
+ el.decorate(); |
+ }; |
+ |
+ return f; |
+ } |
+ |
+ /** |
+ * Input elements do not grow and shrink with their content. This is a simple |
+ * (and not very efficient) way of handling shrinking to content with support |
+ * for min width and limited by the width of the parent element. |
+ * @param {HTMLElement} el The element to limit the width for. |
+ * @param {number} parentEl The parent element that should limit the size. |
+ * @param {number} min The minimum width. |
+ */ |
+ function limitInputWidth(el, parentEl, min) { |
+ // Needs a size larger than borders |
+ el.style.width = '10px'; |
+ var doc = el.ownerDocument; |
+ var win = doc.defaultView; |
+ var computedStyle = win.getComputedStyle(el); |
+ var parentComputedStyle = win.getComputedStyle(parentEl); |
+ var rtl = computedStyle.direction == 'rtl'; |
+ |
+ // To get the max width we get the width of the treeItem minus the position |
+ // of the input. |
+ var inputRect = el.getBoundingClientRect(); // box-sizing |
+ var parentRect = parentEl.getBoundingClientRect(); |
+ var startPos = rtl ? parentRect.right - inputRect.right : |
+ inputRect.left - parentRect.left; |
+ |
+ // Add up border and padding of the input. |
+ var inner = parseInt(computedStyle.borderLeftWidth, 10) + |
+ parseInt(computedStyle.paddingLeft, 10) + |
+ parseInt(computedStyle.paddingRight, 10) + |
+ parseInt(computedStyle.borderRightWidth, 10); |
+ |
+ // We also need to subtract the padding of parent to prevent it to overflow. |
+ var parentPadding = rtl ? parseInt(parentComputedStyle.paddingLeft, 10) : |
+ parseInt(parentComputedStyle.paddingRight, 10); |
+ |
+ // The magic number 14 comes from trial and error :'( It consists of: |
+ // border + padding + treeItem.paddingEnd + treeItem.borderEnd + |
+ // tree.paddingEnd |
+ var max = parentEl.clientWidth - startPos - inner - parentPadding; |
+ |
+ var pcs = getComputedStyle(parentEl); |
+ console.log('pcs', 'borderLeft', pcs.borderLeftWidth, |
+ 'paddingLeft', pcs.paddingLeft, |
+ 'paddingRight', pcs.paddingRight, |
+ 'borderRight', pcs.borderRightWidth, |
+ 'width', pcs.width, |
+ 'clientWidth', parentEl.clientWidth, |
+ 'offsetWidth', parentEl.offsetWidth); |
+ |
+ function limit() { |
+ if (el.scrollWidth > max) { |
+ el.style.width = max + 'px'; |
+ } else { |
+ el.style.width = 0; |
+ var sw = el.scrollWidth; |
+ if (sw < min) { |
+ el.style.width = min + 'px'; |
+ } else { |
+ el.style.width = sw + 'px'; |
+ } |
+ } |
+ } |
+ |
+ el.addEventListener('input', limit); |
+ limit(); |
+ } |
+ |
+ return { |
+ decorate: decorate, |
+ define: define, |
+ limitInputWidth: limitInputWidth |
+ }; |
+}); |