1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 * The long-press delay in milliseconds before long-press handler is
11 var LONGPRESS_DELAY_MSEC = 500;
14 * The maximum number of elements in one keyset rule.
18 var MAXIMUM_NUM_OF_RULE_ELEMENTS = 3;
21 * The minumum number of elements in one keyset rule.
25 var MINIMUM_NUM_OF_RULE_ELEMENTS = 2;
28 * The index of event type element in the splitted keyset rule.
35 * The index of toKeyset element in the splitted keyset rule.
42 * The index of nextKeyset element in the splitted keyset rule.
49 * The index offset of toKeyset and nextKeyset elements in splitted keyset
50 * rule array and the array in keysetRules.
57 * The minumum number of elements in one keyset rule.
60 var MINIMUM_NUM_OF_RULE_ELEMENTS = 2;
62 Polymer('kb-key-base', {
69 * The keyset transition rules. It defines which keyset to transit to on
70 * which key events. It consists at most four rules (down, up, long, dbl).
71 * If no rule is defined for a key event, the event wont trigger a keyset
73 * @type {Object.<string, Array.<string>}
79 // Parsing keyset rules from toKeyset attribute string.
80 // An rule can be defined as: (down|up|long|dbl):keysetid[:keysetid]
81 // and each rule are separated by a semicolon. The first element
82 // defines the event this rule applies to. The second element defines
83 // what keyset to transit to after event received. The third optional
84 // element defines what keyset to transit to after a key is pressed in
85 // the new keyset. It is useful when you want to transit to a not
86 // locked keyset. For example, after transit to a upper case keyset,
87 // it may make sense to transit back to lower case after user typed
88 // any key at the upper case keyset.
90 this.toKeyset.replace(/(\r\n|\n|\r| )/g, '').split(';');
91 this.keysetRules = {};
93 rules.forEach(function(element) {
96 var keyValues = element.split(':', MAXIMUM_NUM_OF_RULE_ELEMENTS);
97 if (keyValues.length < MINIMUM_NUM_OF_RULE_ELEMENTS) {
98 console.error('Invalid keyset rules: ' + element);
101 self.keysetRules[keyValues[EVENT_TYPE]] = [keyValues[TO_KEYSET],
102 (keyValues[NEXT_KEYSET] ? keyValues[NEXT_KEYSET] : null)];
107 down: function(event) {
108 this.pointerId = event.pointerId;
109 var detail = this.populateDetails('down');
110 this.fire('key-down', detail);
111 this.longPressTimer = this.generateLongPressTimer();
113 out: function(event) {
114 this.classList.remove('active');
115 clearTimeout(this.longPressTimer);
117 up: function(event) {
118 this.generateKeyup();
122 * Releases the pressed key programmatically and fires key-up event. This
123 * should be called if a second key is pressed while the first key is not
126 autoRelease: function() {
127 this.generateKeyup();
131 * Drops the pressed key.
133 dropKey: function() {
134 this.classList.remove('active');
135 clearTimeout(this.longPressTimer);
136 this.pointerId = undefined;
140 * Populates details for this key, and then fires a key-up event.
142 generateKeyup: function() {
143 if (this.pointerId === undefined)
146 // Invalidates the pointerId so the subsequent pointerup event is a
148 this.pointerId = undefined;
149 clearTimeout(this.longPressTimer);
150 var detail = this.populateDetails('up');
151 this.fire('key-up', detail);
155 * Character value associated with the key. Typically, the value is a
156 * single character, but may be multi-character in cases like a ".com"
161 return this.invert ? this.hintText : (this.char || this.textContent);
165 * Hint text value associated with the key. Typically, the value is a
169 get hintTextValue() {
170 return this.invert ? (this.char || this.textContent) : this.hintText;
174 * Handles a swipe flick that originated from this key.
175 * @param {detail} The details of the swipe.
177 onFlick: function(detail) {
178 if (!(detail.direction & SwipeDirection.UP) || !this.hintTextValue)
180 var typeDetails = {char: this.hintTextValue};
181 this.fire('type-key', typeDetails);
185 * Returns a subset of the key attributes.
186 * @param {string} caller The id of the function which called
189 populateDetails: function(caller) {
191 char: this.charValue,
192 toLayout: this.toLayout,
198 if (this.keysetRules && this.keysetRules.up != undefined) {
199 detail.toKeyset = this.keysetRules.up[TO_KEYSET - OFFSET];
200 detail.nextKeyset = this.keysetRules.up[NEXT_KEYSET - OFFSET];
204 if (this.keysetRules && this.keysetRules.down != undefined) {
205 detail.toKeyset = this.keysetRules.down[TO_KEYSET - OFFSET];
206 detail.nextKeyset = this.keysetRules.down[NEXT_KEYSET - OFFSET];
215 generateLongPressTimer: function() {
216 return this.async(function() {
218 char: this.charValue,
219 hintText: this.hintTextValue
221 if (this.keysetRules && this.keysetRules.long != undefined) {
222 detail.toKeyset = this.keysetRules.long[TO_KEYSET - OFFSET];
223 detail.nextKeyset = this.keysetRules.long[NEXT_KEYSET - OFFSET];
225 this.fire('key-longpress', detail);
226 }, null, LONGPRESS_DELAY_MSEC);