- add sources.
[platform/framework/web/crosswalk.git] / src / ui / keyboard / resources / elements / kb-key-base.html
1 <!--
2   -- Copyright 2013 The Chromium Authors. All rights reserved.
3   -- Use of this source code is governed by a BSD-style license that can be
4   -- found in the LICENSE file.
5   -->
6
7 <polymer-element name="kb-key-base"
8     on-pointerdown="down" on-pointerup="up" on-pointerout="out"
9     attributes="char invert repeat hintText toKeyset toLayout">
10   <script>
11     /**
12      * The long-press delay in milliseconds before long-press handler is
13      * invoked.
14      * @const
15      * @type {number}
16      */
17     var LONGPRESS_DELAY_MSEC = 500;
18
19     /**
20      * The maximum number of elements in one keyset rule.
21      * @const
22      * @type {number}
23      */
24     var MAXIMUM_NUM_OF_RULE_ELEMENTS = 3;
25
26     /**
27      * The minumum number of elements in one keyset rule.
28      * @const
29      * @type {number}
30      */
31     var MINIMUM_NUM_OF_RULE_ELEMENTS = 2;
32
33     /**
34      * The index of event type element in the splitted keyset rule.
35      * @const
36      * @type {number}
37      */
38     var EVENT_TYPE = 0;
39
40     /**
41      * The index of toKeyset element in the splitted keyset rule.
42      * @const
43      * @type {number}
44      */
45     var TO_KEYSET = 1;
46
47     /**
48      * The index of nextKeyset element in the splitted keyset rule.
49      * @const
50      * @type {number}
51      */
52     var NEXT_KEYSET = 2;
53
54     /**
55      * The index offset of toKeyset and nextKeyset elements in splitted keyset
56      * rule array and the array in keysetRules.
57      * @const
58      * @type {number}
59      */
60     var OFFSET = 1;
61
62     /**
63      * The minumum number of elements in one keyset rule.
64      * @const {number}
65      */
66     var MINIMUM_NUM_OF_RULE_ELEMENTS = 2;
67
68     Polymer('kb-key-base', {
69       repeat: false,
70       invert: false,
71       longPressTimer: null,
72       pointerId: undefined,
73
74       /**
75        * The keyset transition rules. It defines which keyset to transit to on
76        * which key events. It consists at most four rules (down, up, long, dbl).
77        * If no rule is defined for a key event, the event wont trigger a keyset
78        * change.
79        * @type {Object.<string, Array.<string>}
80        */
81       keysetRules: null,
82
83       ready: function() {
84         if (this.toKeyset) {
85           // Parsing keyset rules from toKeyset attribute string.
86           // An rule can be defined as: (down|up|long|dbl):keysetid[:keysetid]
87           // and each rule are separated by a semicolon. The first element
88           // defines the event this rule applies to. The second element defines
89           // what keyset to transit to after event received. The third optional
90           // element defines what keyset to transit to after a key is pressed in
91           // the new keyset. It is useful when you want to transit to a not
92           // locked keyset. For example, after transit to a upper case keyset,
93           // it may make sense to transit back to lower case after user typed
94           // any key at the upper case keyset.
95           var rules =
96               this.toKeyset.replace(/(\r\n|\n|\r| )/g, '').split(';');
97           this.keysetRules = {};
98           var self = this;
99           rules.forEach(function(element) {
100             if (element == '')
101               return;
102             var keyValues = element.split(':', MAXIMUM_NUM_OF_RULE_ELEMENTS);
103             if (keyValues.length < MINIMUM_NUM_OF_RULE_ELEMENTS) {
104               console.error('Invalid keyset rules: ' + element);
105               return;
106             }
107             self.keysetRules[keyValues[EVENT_TYPE]] = [keyValues[TO_KEYSET],
108                 (keyValues[NEXT_KEYSET] ? keyValues[NEXT_KEYSET] : null)];
109           });
110         }
111       },
112
113       down: function(event) {
114         this.pointerId = event.pointerId;
115         var detail = this.populateDetails('down');
116         this.fire('key-down', detail);
117         this.longPressTimer = this.generateLongPressTimer();
118       },
119       out: function(event) {
120         this.classList.remove('active');
121         clearTimeout(this.longPressTimer);
122       },
123       up: function(event) {
124         this.generateKeyup();
125       },
126
127       /**
128        * Releases the pressed key programmatically and fires key-up event. This
129        * should be called if a second key is pressed while the first key is not
130        * released yet.
131        */
132       autoRelease: function() {
133         this.generateKeyup();
134       },
135
136       /**
137        * Drops the pressed key.
138        */
139       dropKey: function() {
140         this.classList.remove('active');
141         clearTimeout(this.longPressTimer);
142         this.pointerId = undefined;
143       },
144
145       /**
146        * Populates details for this key, and then fires a key-up event.
147        */
148       generateKeyup: function() {
149         if (this.pointerId === undefined)
150           return;
151
152         // Invalidates the pointerId so the subsequent pointerup event is a
153         // noop.
154         this.pointerId = undefined;
155         clearTimeout(this.longPressTimer);
156         var detail = this.populateDetails('up');
157         this.fire('key-up', detail);
158       },
159
160       /**
161        * Character value associated with the key. Typically, the value is a
162        * single character, but may be multi-character in cases like a ".com"
163        * button.
164        * @return {string}
165        */
166       get charValue() {
167         return this.invert ? this.hintText : (this.char || this.textContent);
168       },
169
170       /* Hint text value associated with the key. Typically, the value is a
171        * single character.
172        * @return {string}
173        */
174       get hintTextValue() {
175         return this.invert ? (this.char || this.textContent) : this.hintText;
176       },
177
178       /**
179        * Returns a subset of the key attributes.
180        * @param {string} caller The id of the function which called
181        *     populateDetails.
182        */
183       populateDetails: function(caller) {
184         var detail = {
185           char: this.charValue,
186           toLayout: this.toLayout,
187           repeat: this.repeat
188         };
189
190         switch (caller) {
191           case ('up'):
192             if (this.keysetRules && this.keysetRules.up != undefined) {
193               detail.toKeyset = this.keysetRules.up[TO_KEYSET - OFFSET];
194               detail.nextKeyset = this.keysetRules.up[NEXT_KEYSET - OFFSET];
195             }
196             break;
197           case ('down'):
198             if (this.keysetRules && this.keysetRules.down != undefined) {
199               detail.toKeyset = this.keysetRules.down[TO_KEYSET - OFFSET];
200               detail.nextKeyset = this.keysetRules.down[NEXT_KEYSET - OFFSET];
201             }
202             break;
203           default:
204             break;
205         }
206         return detail;
207       },
208
209       generateLongPressTimer: function() {
210         return this.asyncMethod(function() {
211           var detail = {
212             char: this.charValue,
213             hintText: this.hintTextValue
214           };
215           if (this.keysetRules && this.keysetRules.long != undefined) {
216             detail.toKeyset = this.keysetRules.long[TO_KEYSET - OFFSET];
217             detail.nextKeyset = this.keysetRules.long[NEXT_KEYSET - OFFSET];
218           }
219           this.fire('key-longpress', detail);
220         }, null, LONGPRESS_DELAY_MSEC);
221       },
222     });
223   </script>
224 </polymer-element>