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('cr.ui', function() {
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The class name to set on the document element.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @const
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var CLASS_NAME = 'focus-outline-visible';
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * This class sets a CSS class name on the HTML element of |doc| when the user
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * presses the tab key. It removes the class name when the user clicks
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * anywhere.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * This allows you to write CSS like this:
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * html.focus-outline-visible my-element:focus {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   outline: 5px auto -webkit-focus-ring-color;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * }
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * And the outline will only be shown if the user uses the keyboard to get to
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * it.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Document} doc The document to attach the focus outline manager to.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @constructor
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function FocusOutlineManager(doc) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this.classList_ = doc.documentElement.classList;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var self = this;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    doc.addEventListener('keydown', function(e) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (e.keyCode == 9)  // Tab
35bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        self.focusByKeyboard_ = true;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }, true);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    doc.addEventListener('mousedown', function(e) {
39bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      self.focusByKeyboard_ = false;
40bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    }, true);
41bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
42bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    doc.addEventListener('focus', function(event) {
43bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      // Update visibility only when focus is actually changed.
44bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      self.visible = self.focusByKeyboard_;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }, true);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FocusOutlineManager.prototype = {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
50bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch     * Whether focus change is triggered by TAB key.
51bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch     * @type {boolean}
52bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch     * @private
53bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch     */
54ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    focusByKeyboard_: true,
55bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
56bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    /**
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Whether the focus outline should be visible.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @type {boolean}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set visible(visible) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (visible)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this.classList_.add(CLASS_NAME);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this.classList_.remove(CLASS_NAME);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    get visible() {
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return this.classList_.contains(CLASS_NAME);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Array of Document and FocusOutlineManager pairs.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {Array}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var docsToManager = [];
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Gets a per document sigleton focus outline manager.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Document} doc The document to get the |FocusOutlineManager| for.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {FocusOutlineManager} The per document singleton focus outline
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     manager.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FocusOutlineManager.forDocument = function(doc) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (var i = 0; i < docsToManager.length; i++) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (doc == docsToManager[i][0])
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return docsToManager[i][1];
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var manager = new FocusOutlineManager(doc);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    docsToManager.push([doc, manager]);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return manager;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FocusOutlineManager: FocusOutlineManager
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)});
97