1 <!-- 2 Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 3 This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt 4 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 5 The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt 6 Code distributed by Google as part of the polymer project is also 7 subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt 8 --> 9 10 <!-- 11 /** 12 * @group Paper Elements 13 * 14 * paper-focusable is a base class for paper elements that can be focused. 15 * 16 * @element paper-focusable 17 * @status beta 18 * @homepage github.io 19 */ 20 --> 21 22 <link href="../polymer/polymer.html" rel="import"> 23 24 <polymer-element name="paper-focusable" attributes="active focused disabled isToggle" tabindex="0" on-down="{{downAction}}" on-up="{{upAction}}" on-focus="{{focusAction}}" on-blur="{{blurAction}}" on-contextmenu="{{contextMenuAction}}"> 25 26 <template> 27 <style> 28 :host([disabled]) { 29 pointer-events: none; 30 } 31 </style> 32 <content></content> 33 </template> 34 35 <script> 36 Polymer('paper-focusable', { 37 38 publish: { 39 40 /** 41 * If true, the button is currently active either because the 42 * user is holding down the button, or the button is a toggle 43 * and is currently in the active state. 44 * 45 * @attribute active 46 * @type boolean 47 * @default false 48 */ 49 active: {value: false, reflect: true}, 50 51 /** 52 * If true, the element currently has focus due to keyboard 53 * navigation. 54 * 55 * @attribute focused 56 * @type boolean 57 * @default false 58 */ 59 focused: {value: false, reflect: true}, 60 61 /** 62 * If true, the user is currently holding down the button. 63 * 64 * @attribute pressed 65 * @type boolean 66 * @default false 67 */ 68 pressed: {value: false, reflect: true}, 69 70 /** 71 * If true, the user cannot interact with this element. 72 * 73 * @attribute disabled 74 * @type boolean 75 * @default false 76 */ 77 disabled: {value: false, reflect: true}, 78 79 /** 80 * If true, the button toggles the active state with each tap. 81 * Otherwise, the button becomes active when the user is holding 82 * it down. 83 * 84 * @attribute isToggle 85 * @type boolean 86 * @default false 87 */ 88 isToggle: {value: false, reflect: false} 89 90 }, 91 92 disabledChanged: function() { 93 if (this.disabled) { 94 this.removeAttribute('tabindex'); 95 } else { 96 this.setAttribute('tabindex', 0); 97 } 98 }, 99 100 downAction: function() { 101 this.pressed = true; 102 this.focused = false; 103 104 if (this.isToggle) { 105 this.active = !this.active; 106 } else { 107 this.active = true; 108 } 109 }, 110 111 // Pulling up the context menu for an item should focus it; but we need to 112 // be careful about how we deal with down/up events surrounding context 113 // menus. The up event typically does not fire until the context menu 114 // closes: so we focus immediately. 115 // 116 // This fires _after_ downAction. 117 contextMenuAction: function(e) { 118 // Note that upAction may fire _again_ on the actual up event. 119 this.upAction(e); 120 this.focusAction(); 121 }, 122 123 upAction: function() { 124 this.pressed = false; 125 126 if (!this.isToggle) { 127 this.active = false; 128 } 129 }, 130 131 focusAction: function() { 132 if (!this.pressed) { 133 // Only render the "focused" state if the element gains focus due to 134 // keyboard navigation. 135 this.focused = true; 136 } 137 }, 138 139 blurAction: function() { 140 this.focused = false; 141 } 142 143 }); 144 145 </script> 146 </polymer-element> 147