*/
cr.define('uber', function() {
-
/**
* Fixed position header elements on the page to be shifted by handleScroll.
* @type {NodeList}
function onContentFrameLoaded() {
headerElements = document.getElementsByTagName('header');
document.addEventListener('scroll', handleScroll);
+ document.addEventListener('mousedown', handleMouseDownInFrame, true);
invokeMethodOnParent('ready');
/**
* Handles scroll events on the document. This adjusts the position of all
* headers and updates the parent frame when the page is scrolled.
- * @private
*/
function handleScroll() {
var scrollLeft = scrollLeftForDocument(document);
}
/**
+ * Tells the parent to focus the current frame if the mouse goes down in the
+ * current frame (and it doesn't already have focus).
+ * @param {Event} e A mousedown event.
+ */
+ function handleMouseDownInFrame(e) {
+ if (!e.isSynthetic && !document.hasFocus())
+ window.focus();
+ }
+
+ /**
* Handles 'message' events on window.
* @param {Event} e The message event.
*/
function handleWindowMessage(e) {
e = /** @type {!MessageEvent.<!{method: string, params: *}>} */(e);
- if (e.data.method === 'frameSelected')
+ if (e.data.method === 'frameSelected') {
handleFrameSelected();
- else if (e.data.method === 'mouseWheel')
+ } else if (e.data.method === 'mouseWheel') {
handleMouseWheel(
/** @type {{deltaX: number, deltaY: number}} */(e.data.params));
- else if (e.data.method === 'popState')
+ } else if (e.data.method === 'mouseDown') {
+ handleMouseDown();
+ } else if (e.data.method === 'popState') {
handlePopState(e.data.params.state, e.data.params.path);
+ }
}
/**
* This is called when a user selects this frame via the navigation bar
* frame (and is triggered via postMessage() from the uber page).
- * @private
*/
function handleFrameSelected() {
setScrollTopForDocument(document, 0);
}
/**
+ * Fire a synthetic mousedown on the body to dismiss transient things like
+ * bubbles or menus that listen for mouse presses outside of their UI. We
+ * dispatch a fake mousedown rather than a 'mousepressedinnavframe' so that
+ * settings/history/extensions don't need to know about their embedder.
+ */
+ function handleMouseDown() {
+ var mouseEvent = new MouseEvent('mousedown');
+ mouseEvent.isSynthetic = true;
+ document.dispatchEvent(mouseEvent);
+ }
+
+ /**
* Called when the parent window restores some state saved by uber.pushState
* or uber.replaceState. Simulates a popstate event.
* @param {PopStateEvent} state A state object for replaceState and pushState.
* @param {string} method The name of the method to invoke.
* @param {?=} opt_params Optional property bag of parameters to pass to the
* invoked method.
- * @private
*/
function invokeMethodOnParent(method, opt_params) {
if (!hasParent())
* @param {?=} opt_params Optional property bag of parameters to pass to the
* invoked method.
* @param {string=} opt_url The origin of the target window.
- * @private
*/
function invokeMethodOnWindow(targetWindow, method, opt_params, opt_url) {
var data = {method: method, params: opt_params};
* @param {Object} state A state object for replaceState and pushState.
* @param {string} path The path the page navigated to.
* @param {boolean} replace If true, navigate with replacement.
- * @private
*/
function updateHistory(state, path, replace) {
var historyFunction = replace ?