Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2070)

Unified Diff: chrome/browser/resources/shared/js/cr/ui/bubble.js

Issue 11962043: Move webui resources from chrome\browser\resources\shared to ui\webui\resources. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/shared/js/cr/ui/bubble.js
===================================================================
--- chrome/browser/resources/shared/js/cr/ui/bubble.js (revision 177292)
+++ chrome/browser/resources/shared/js/cr/ui/bubble.js (working copy)
@@ -1,514 +0,0 @@
-// 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.
-
-// require: event_tracker.js
-
-cr.define('cr.ui', function() {
-
- /**
- * The arrow location specifies how the arrow and bubble are positioned in
- * relation to the anchor node.
- * @enum
- */
- var ArrowLocation = {
- // The arrow is positioned at the top and the start of the bubble. In left
- // to right mode this is the top left. The entire bubble is positioned below
- // the anchor node.
- TOP_START: 'top-start',
- // The arrow is positioned at the top and the end of the bubble. In left to
- // right mode this is the top right. The entire bubble is positioned below
- // the anchor node.
- TOP_END: 'top-end',
- // The arrow is positioned at the bottom and the start of the bubble. In
- // left to right mode this is the bottom left. The entire bubble is
- // positioned above the anchor node.
- BOTTOM_START: 'bottom-start',
- // The arrow is positioned at the bottom and the end of the bubble. In
- // left to right mode this is the bottom right. The entire bubble is
- // positioned above the anchor node.
- BOTTOM_END: 'bottom-end'
- };
-
- /**
- * The bubble alignment specifies the position of the bubble in relation to
- * the anchor node.
- * @enum
- */
- var BubbleAlignment = {
- // The bubble is positioned just above or below the anchor node (as
- // specified by the arrow location) so that the arrow points at the midpoint
- // of the anchor.
- ARROW_TO_MID_ANCHOR: 'arrow-to-mid-anchor',
- // The bubble is positioned just above or below the anchor node (as
- // specified by the arrow location) so that its reference edge lines up with
- // the edge of the anchor.
- BUBBLE_EDGE_TO_ANCHOR_EDGE: 'bubble-edge-anchor-edge',
- // The bubble is positioned so that it is entirely within view and does not
- // obstruct the anchor element, if possible. The specified arrow location is
- // taken into account as the preferred alignment but may be overruled if
- // there is insufficient space (see BubbleBase.reposition for the exact
- // placement algorithm).
- ENTIRELY_VISIBLE: 'entirely-visible'
- };
-
- /**
- * Abstract base class that provides common functionality for implementing
- * free-floating informational bubbles with a triangular arrow pointing at an
- * anchor node.
- */
- var BubbleBase = cr.ui.define('div');
-
- /**
- * The horizontal distance between the tip of the arrow and the reference edge
- * of the bubble (as specified by the arrow location). In pixels.
- * @type {number}
- * @const
- */
- BubbleBase.ARROW_OFFSET = 30;
-
- /**
- * Minimum horizontal spacing between edge of bubble and edge of viewport
- * (when using the ENTIRELY_VISIBLE alignment). In pixels.
- * @type {number}
- * @const
- */
- BubbleBase.MIN_VIEWPORT_EDGE_MARGIN = 2;
-
- BubbleBase.prototype = {
- // Set up the prototype chain.
- __proto__: HTMLDivElement.prototype,
-
- /**
- * Initialization function for the cr.ui framework.
- */
- decorate: function() {
- this.className = 'bubble';
- this.innerHTML =
- '<div class="bubble-content"></div>' +
- '<div class="bubble-shadow"></div>' +
- '<div class="bubble-arrow"></div>';
- this.hidden = true;
- this.bubbleAlignment = BubbleAlignment.ENTIRELY_VISIBLE;
- },
-
- /**
- * Set the anchor node, i.e. the node that this bubble points at. Only
- * available when the bubble is not being shown.
- * @param {HTMLElement} node The new anchor node.
- */
- set anchorNode(node) {
- if (!this.hidden)
- return;
-
- this.anchorNode_ = node;
- },
-
- /**
- * Set the conent of the bubble. Only available when the bubble is not being
- * shown.
- * @param {HTMLElement} node The root node of the new content.
- */
- set content(node) {
- if (!this.hidden)
- return;
-
- var bubbleContent = this.querySelector('.bubble-content');
- bubbleContent.innerHTML = '';
- bubbleContent.appendChild(node);
- },
-
- /**
- * Set the arrow location. Only available when the bubble is not being
- * shown.
- * @param {cr.ui.ArrowLocation} location The new arrow location.
- */
- set arrowLocation(location) {
- if (!this.hidden)
- return;
-
- this.arrowAtRight_ = location == ArrowLocation.TOP_END ||
- location == ArrowLocation.BOTTOM_END;
- if (document.documentElement.dir == 'rtl')
- this.arrowAtRight_ = !this.arrowAtRight_;
- this.arrowAtTop_ = location == ArrowLocation.TOP_START ||
- location == ArrowLocation.TOP_END;
- },
-
- /**
- * Set the bubble alignment. Only available when the bubble is not being
- * shown.
- * @param {cr.ui.BubbleAlignment} alignment The new bubble alignment.
- */
- set bubbleAlignment(alignment) {
- if (!this.hidden)
- return;
-
- this.bubbleAlignment_ = alignment;
- },
-
- /**
- * Update the position of the bubble. Whenever the layout may have changed,
- * the bubble should either be repositioned by calling this function or
- * hidden so that it does not point to a nonsensical location on the page.
- */
- reposition: function() {
- var documentWidth = document.documentElement.clientWidth;
- var documentHeight = document.documentElement.clientHeight;
- var anchor = this.anchorNode_.getBoundingClientRect();
- var anchorMid = (anchor.left + anchor.right) / 2;
- var bubble = this.getBoundingClientRect();
- var arrow = this.querySelector('.bubble-arrow').getBoundingClientRect();
-
- if (this.bubbleAlignment_ == BubbleAlignment.ENTIRELY_VISIBLE) {
- // Work out horizontal placement. The bubble is initially positioned so
- // that the arrow tip points toward the midpoint of the anchor and is
- // BubbleBase.ARROW_OFFSET pixels from the reference edge and (as
- // specified by the arrow location). If the bubble is not entirely
- // within view, it is then shifted, preserving the arrow tip position.
- var left = this.arrowAtRight_ ?
- anchorMid + BubbleBase.ARROW_OFFSET - bubble.width :
- anchorMid - BubbleBase.ARROW_OFFSET;
- var max_left_pos =
- documentWidth - bubble.width - BubbleBase.MIN_VIEWPORT_EDGE_MARGIN;
- var min_left_pos = BubbleBase.MIN_VIEWPORT_EDGE_MARGIN;
- if (document.documentElement.dir == 'rtl')
- left = Math.min(Math.max(left, min_left_pos), max_left_pos);
- else
- left = Math.max(Math.min(left, max_left_pos), min_left_pos);
- var arrowTip = Math.min(
- Math.max(arrow.width / 2,
- this.arrowAtRight_ ? left + bubble.width - anchorMid :
- anchorMid - left),
- bubble.width - arrow.width / 2);
-
- // Work out the vertical placement, attempting to fit the bubble
- // entirely into view. The following placements are considered in
- // decreasing order of preference:
- // * Outside the anchor, arrow tip touching the anchor (arrow at
- // top/bottom as specified by the arrow location).
- // * Outside the anchor, arrow tip touching the anchor (arrow at
- // bottom/top, opposite the specified arrow location).
- // * Outside the anchor, arrow tip overlapping the anchor (arrow at
- // top/bottom as specified by the arrow location).
- // * Outside the anchor, arrow tip overlapping the anchor (arrow at
- // bottom/top, opposite the specified arrow location).
- // * Overlapping the anchor.
- var offsetTop = Math.min(documentHeight - anchor.bottom - bubble.height,
- arrow.height / 2);
- var offsetBottom = Math.min(anchor.top - bubble.height,
- arrow.height / 2);
- if (offsetTop < 0 && offsetBottom < 0) {
- var top = 0;
- this.updateArrowPosition_(false, false, arrowTip);
- } else if (offsetTop > offsetBottom ||
- offsetTop == offsetBottom && this.arrowAtTop_) {
- var top = anchor.bottom + offsetTop;
- this.updateArrowPosition_(true, true, arrowTip);
- } else {
- var top = anchor.top - bubble.height - offsetBottom;
- this.updateArrowPosition_(true, false, arrowTip);
- }
- } else {
- if (this.bubbleAlignment_ ==
- BubbleAlignment.BUBBLE_EDGE_TO_ANCHOR_EDGE) {
- var left = this.arrowAtRight_ ? anchor.right - bubble.width :
- anchor.left;
- } else {
- var left = this.arrowAtRight_ ?
- anchorMid - this.clientWidth + BubbleBase.ARROW_OFFSET :
- anchorMid - BubbleBase.ARROW_OFFSET;
- }
- var top = this.arrowAtTop_ ? anchor.bottom + arrow.height / 2 :
- anchor.top - this.clientHeight - arrow.height / 2;
- this.updateArrowPosition_(true, this.arrowAtTop_,
- BubbleBase.ARROW_OFFSET);
- }
-
- this.style.left = left + 'px';
- this.style.top = top + 'px';
- },
-
- /**
- * Show the bubble.
- */
- show: function() {
- if (!this.hidden)
- return;
-
- this.attachToDOM_();
- this.hidden = false;
- this.reposition();
-
- var doc = this.ownerDocument;
- this.eventTracker_ = new EventTracker;
- this.eventTracker_.add(doc, 'keydown', this, true);
- this.eventTracker_.add(doc, 'mousedown', this, true);
- },
-
- /**
- * Hide the bubble.
- */
- hide: function() {
- if (this.hidden)
- return;
-
- this.eventTracker_.removeAll();
- this.hidden = true;
- this.parentNode.removeChild(this);
- },
-
- /**
- * Handle keyboard events, dismissing the bubble if necessary.
- * @param {Event} event The event.
- */
- handleEvent: function(event) {
- // Close the bubble when the user presses <Esc>.
- if (event.type == 'keydown' && event.keyCode == 27) {
- this.hide();
- event.preventDefault();
- event.stopPropagation();
- }
- },
-
- /**
- * Attach the bubble to the document's DOM.
- * @private
- */
- attachToDOM_: function() {
- document.body.appendChild(this);
- },
-
- /**
- * Update the arrow so that it appears at the correct position.
- * @param {boolean} visible Whether the arrow should be visible.
- * @param {boolean} atTop Whether the arrow should be at the top of the
- * bubble.
- * @param {number} tipOffset The horizontal distance between the tip of the
- * arrow and the reference edge of the bubble (as specified by the arrow
- * location).
- * @private
- */
- updateArrowPosition_: function(visible, atTop, tipOffset) {
- var bubbleArrow = this.querySelector('.bubble-arrow');
- bubbleArrow.hidden = !visible;
- if (!visible)
- return;
-
- var edgeOffset = (-bubbleArrow.clientHeight / 2) + 'px';
- bubbleArrow.style.top = atTop ? edgeOffset : 'auto';
- bubbleArrow.style.bottom = atTop ? 'auto' : edgeOffset;
-
- edgeOffset = (tipOffset - bubbleArrow.offsetWidth / 2) + 'px';
- bubbleArrow.style.left = this.arrowAtRight_ ? 'auto' : edgeOffset;
- bubbleArrow.style.right = this.arrowAtRight_ ? edgeOffset : 'auto';
- },
- };
-
- /**
- * A bubble that remains open until the user explicitly dismisses it or clicks
- * outside the bubble after it has been shown for at least the specified
- * amount of time (making it less likely that the user will unintentionally
- * dismiss the bubble). The bubble repositions itself on layout changes.
- */
- var Bubble = cr.ui.define('div');
-
- Bubble.prototype = {
- // Set up the prototype chain.
- __proto__: BubbleBase.prototype,
-
- /**
- * Initialization function for the cr.ui framework.
- */
- decorate: function() {
- BubbleBase.prototype.decorate.call(this);
-
- var close = document.createElement('div');
- close.className = 'bubble-close';
- this.insertBefore(close, this.querySelector('.bubble-content'));
-
- this.handleCloseEvent = this.hide;
- this.deactivateToDismissDelay_ = 0;
- this.bubbleAlignment = BubbleAlignment.ARROW_TO_MID_ANCHOR;
- },
-
- /**
- * Handler for close events triggered when the close button is clicked. By
- * default, set to this.hide. Only available when the bubble is not being
- * shown.
- * @param {function} handler The new handler, a function with no parameters.
- */
- set handleCloseEvent(handler) {
- if (!this.hidden)
- return;
-
- this.handleCloseEvent_ = handler;
- },
-
- /**
- * Set the delay before the user is allowed to click outside the bubble to
- * dismiss it. Using a delay makes it less likely that the user will
- * unintentionally dismiss the bubble.
- * @param {number} delay The delay in milliseconds.
- */
- set deactivateToDismissDelay(delay) {
- this.deactivateToDismissDelay_ = delay;
- },
-
- /**
- * Hide or show the close button.
- * @param {boolean} isVisible True if the close button should be visible.
- */
- set closeButtonVisible(isVisible) {
- this.querySelector('.bubble-close').hidden = !isVisible;
- },
-
- /**
- * Show the bubble.
- */
- show: function() {
- if (!this.hidden)
- return;
-
- BubbleBase.prototype.show.call(this);
-
- this.showTime_ = Date.now();
- this.eventTracker_.add(window, 'resize', this.reposition.bind(this));
- },
-
- /**
- * Handle keyboard and mouse events, dismissing the bubble if necessary.
- * @param {Event} event The event.
- */
- handleEvent: function(event) {
- BubbleBase.prototype.handleEvent.call(this, event);
-
- if (event.type == 'mousedown') {
- // Dismiss the bubble when the user clicks on the close button.
- if (event.target == this.querySelector('.bubble-close')) {
- this.handleCloseEvent_();
- // Dismiss the bubble when the user clicks outside it after the
- // specified delay has passed.
- } else if (!this.contains(event.target) &&
- Date.now() - this.showTime_ >= this.deactivateToDismissDelay_) {
- this.hide();
- }
- }
- },
- };
-
- /**
- * A bubble that closes automatically when the user clicks or moves the focus
- * outside the bubble and its target element, scrolls the underlying document
- * or resizes the window.
- */
- var AutoCloseBubble = cr.ui.define('div');
-
- AutoCloseBubble.prototype = {
- // Set up the prototype chain.
- __proto__: BubbleBase.prototype,
-
- /**
- * Initialization function for the cr.ui framework.
- */
- decorate: function() {
- BubbleBase.prototype.decorate.call(this);
- this.classList.add('auto-close-bubble');
- },
-
- /**
- * Set the DOM sibling node, i.e. the node as whose sibling the bubble
- * should join the DOM to ensure that focusable elements inside the bubble
- * follow the target element in the document's tab order. Only available
- * when the bubble is not being shown.
- * @param {HTMLElement} node The new DOM sibling node.
- */
- set domSibling(node) {
- if (!this.hidden)
- return;
-
- this.domSibling_ = node;
- },
-
- /**
- * Show the bubble.
- */
- show: function() {
- if (!this.hidden)
- return;
-
- BubbleBase.prototype.show.call(this);
- this.domSibling_.showingBubble = true;
-
- var doc = this.ownerDocument;
- this.eventTracker_.add(doc, 'mousewheel', this, true);
- this.eventTracker_.add(doc, 'scroll', this, true);
- this.eventTracker_.add(doc, 'elementFocused', this, true);
- this.eventTracker_.add(window, 'resize', this);
- },
-
- /**
- * Hide the bubble.
- */
- hide: function() {
- BubbleBase.prototype.hide.call(this);
- this.domSibling_.showingBubble = false;
- },
-
- /**
- * Handle events, closing the bubble when the user clicks or moves the focus
- * outside the bubble and its target element, scrolls the underlying
- * document or resizes the window.
- * @param {Event} event The event.
- */
- handleEvent: function(event) {
- BubbleBase.prototype.handleEvent.call(this, event);
-
- switch (event.type) {
- // Close the bubble when the user clicks outside it, except if it is a
- // left-click on the bubble's target element (allowing the target to
- // handle the event and close the bubble itself).
- case 'mousedown':
- if (event.button == 0 && this.anchorNode_.contains(event.target))
- break;
- // Close the bubble when the underlying document is scrolled.
- case 'mousewheel':
- case 'scroll':
- if (this.contains(event.target))
- break;
- // Close the bubble when the window is resized.
- case 'resize':
- this.hide();
- break;
- // Close the bubble when the focus moves to an element that is not the
- // bubble target and is not inside the bubble.
- case 'elementFocused':
- if (!this.anchorNode_.contains(event.target) &&
- !this.contains(event.target)) {
- this.hide();
- }
- break;
- }
- },
-
- /**
- * Attach the bubble to the document's DOM, making it a sibling of the
- * |domSibling_| so that focusable elements inside the bubble follow the
- * target element in the document's tab order.
- * @private
- */
- attachToDOM_: function() {
- var parent = this.domSibling_.parentNode;
- parent.insertBefore(this, this.domSibling_.nextSibling);
- },
- };
-
-
- return {
- ArrowLocation: ArrowLocation,
- BubbleAlignment: BubbleAlignment,
- BubbleBase: BubbleBase,
- Bubble: Bubble,
- AutoCloseBubble: AutoCloseBubble
- };
-});

Powered by Google App Engine
This is Rietveld 408576698