| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 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. | |
| 4 | |
| 5 /** | |
| 6 * @fileoverview A simple virtual keyboard implementation. | |
| 7 */ | |
| 8 | |
| 9 /** | |
| 10 * The ratio of the row height to the font size. | |
| 11 * @type {number} | |
| 12 */ | |
| 13 const kFontSizeRatio = 3.5; | |
| 14 | |
| 15 /** | |
| 16 * Return the id attribute of the keyboard element for the given layout. | |
| 17 * @param {string} layout The keyboard layout. | |
| 18 * @return {string} The id attribute of the keyboard element. | |
| 19 */ | |
| 20 function getKeyboardId(layout) { | |
| 21 return 'keyboard_' + layout; | |
| 22 } | |
| 23 | |
| 24 /** | |
| 25 * Return the aspect ratio of the current keyboard. | |
| 26 * @param {string} layout The keyboard layout. | |
| 27 * @return {number} The aspect ratio of the current keyboard. | |
| 28 */ | |
| 29 function getKeyboardAspect() { | |
| 30 return KEYBOARDS[currentKeyboardLayout]['aspect']; | |
| 31 } | |
| 32 | |
| 33 /** | |
| 34 * Calculate the height of the keyboard based on the size of the page. | |
| 35 * @return {number} The height of the keyboard in pixels. | |
| 36 */ | |
| 37 function getKeyboardHeight() { | |
| 38 var x = window.innerWidth; | |
| 39 var y = window.innerHeight - ((imeui && imeui.visible) ? IME_HEIGHT : 0); | |
| 40 return (x > getKeyboardAspect() * y) ? | |
| 41 y : Math.floor(x / getKeyboardAspect()); | |
| 42 } | |
| 43 | |
| 44 /** | |
| 45 * Create a DOM of the keyboard rows for the given keyboard layout. | |
| 46 * Do nothing if the DOM is already created. | |
| 47 * @param {string} layout The keyboard layout for which rows are created. | |
| 48 * @param {Element} element The DOM Element to which rows are appended. | |
| 49 * @param {boolean} autoPadding True if padding needs to be added to both side | |
| 50 * of the rows that have less keys. | |
| 51 * @return {void} | |
| 52 */ | |
| 53 function initRows(layout, element, autoPadding) { | |
| 54 var keyboard = KEYBOARDS[layout]; | |
| 55 if ('rows' in keyboard) { | |
| 56 return; | |
| 57 } | |
| 58 var def = keyboard['definition']; | |
| 59 var rows = []; | |
| 60 for (var i = 0; i < def.length; ++i) { | |
| 61 rows.push(new Row(i, def[i])); | |
| 62 } | |
| 63 keyboard['rows'] = rows; | |
| 64 | |
| 65 var maxRowLength = -1; | |
| 66 for (var i = 0; i < rows.length; ++i) { | |
| 67 if (rows[i].length > maxRowLength) { | |
| 68 maxRowLength = rows[i].length; | |
| 69 } | |
| 70 } | |
| 71 | |
| 72 // A div element which holds rows for the layout. | |
| 73 var rowsDiv = document.createElement('div'); | |
| 74 rowsDiv.className = 'rows'; | |
| 75 for (var i = 0; i < rows.length; ++i) { | |
| 76 var rowDiv = rows[i].makeDOM(); | |
| 77 if (autoPadding && rows[i].length < maxRowLength) { | |
| 78 var padding = 50 * (maxRowLength - rows[i].length) / maxRowLength; | |
| 79 rowDiv.style.paddingLeft = padding + '%'; | |
| 80 rowDiv.style.paddingRight = padding + '%'; | |
| 81 } | |
| 82 rowsDiv.appendChild(rowDiv); | |
| 83 rows[i].showMode(currentMode); | |
| 84 } | |
| 85 keyboard['rowsDiv'] = rowsDiv; | |
| 86 element.appendChild(rowsDiv); | |
| 87 } | |
| 88 | |
| 89 /** | |
| 90 * Create a DOM of the handwriting canvas for the given keyboard layout. | |
| 91 * Do nothing if the DOM is already created or the layout doesn't have canvas. | |
| 92 * @param {string} layout The keyboard layout for which canvas is created. | |
| 93 * @param {Element} The DOM Element to which canvas is appended. | |
| 94 * @return {void} | |
| 95 */ | |
| 96 function initHandwritingCanvas(layout, element) { | |
| 97 var keyboard = KEYBOARDS[layout]; | |
| 98 if (!('canvas' in keyboard) || keyboard['canvas']) { | |
| 99 return; | |
| 100 } | |
| 101 var canvas = new HandwritingCanvas(); | |
| 102 canvas.className = 'handwritingcanvas'; | |
| 103 var border = 1; | |
| 104 var marginTop = 5; | |
| 105 var canvasHeight = getKeyboardHeight() - 2 * border - marginTop; | |
| 106 canvas.resize(canvasHeight); | |
| 107 keyboard['canvas'] = canvas; | |
| 108 element.appendChild(canvas); | |
| 109 } | |
| 110 | |
| 111 /** | |
| 112 * Create a DOM of the keyboard for the given keyboard layout. | |
| 113 * Do nothing if the DOM is already created. | |
| 114 * @param {string} layout The keyboard layout for which keyboard is created. | |
| 115 * @param {Element} The DOM Element to which keyboard is appended. | |
| 116 * @return {void} | |
| 117 */ | |
| 118 function initKeyboard(layout, element) { | |
| 119 var keyboard = KEYBOARDS[layout]; | |
| 120 if (!keyboard || keyboard['keyboardDiv']) { | |
| 121 return; | |
| 122 } | |
| 123 var keyboardDiv = document.createElement('div'); | |
| 124 keyboardDiv.id = getKeyboardId(layout); | |
| 125 keyboardDiv.className = 'keyboard'; | |
| 126 initRows(layout, keyboardDiv); | |
| 127 initHandwritingCanvas(layout, keyboardDiv); | |
| 128 keyboard['keyboardDiv'] = keyboardDiv; | |
| 129 window.onresize(); | |
| 130 element.appendChild(keyboardDiv); | |
| 131 } | |
| 132 | |
| 133 /** | |
| 134 * Create a DOM of the popup keyboard. | |
| 135 * @param {Element} The DOM Element to which the popup keyboard is appended. | |
| 136 * @return {void} | |
| 137 */ | |
| 138 function initPopupKeyboard(element) { | |
| 139 var popupDiv = document.createElement('div'); | |
| 140 popupDiv.id = 'popup'; | |
| 141 popupDiv.className = 'keyboard popup'; | |
| 142 popupDiv.style.visibility = 'hidden'; | |
| 143 element.appendChild(popupDiv); | |
| 144 element.addEventListener('mouseup', function(evt) { | |
| 145 hidePopupKeyboard(evt); | |
| 146 }); | |
| 147 } | |
| 148 | |
| 149 /** | |
| 150 * Resize the keyboard according to the new window size. | |
| 151 * @return {void} | |
| 152 */ | |
| 153 window.onresize = function() { | |
| 154 var keyboardDiv = KEYBOARDS[currentKeyboardLayout]['keyboardDiv']; | |
| 155 var height = getKeyboardHeight(); | |
| 156 keyboardDiv.style.height = height + 'px'; | |
| 157 var mainDiv = document.getElementById('main'); | |
| 158 mainDiv.style.width = Math.floor(getKeyboardAspect() * height) + 'px'; | |
| 159 var rowsLength = KEYBOARDS[currentKeyboardLayout]['rows'].length; | |
| 160 keyboardDiv.style.fontSize = (height / kFontSizeRatio / rowsLength) + 'px'; | |
| 161 updateIme(); | |
| 162 } | |
| 163 | |
| 164 /** | |
| 165 * Init the keyboard. | |
| 166 * @return {void} | |
| 167 */ | |
| 168 window.onload = function() { | |
| 169 var body = document.getElementById('b'); | |
| 170 | |
| 171 // Catch all unhandled touch events and prevent default, to prevent the | |
| 172 // keyboard from responding to gestures like double tap. | |
| 173 function disableGestures(evt) { | |
| 174 evt.preventDefault(); | |
| 175 } | |
| 176 body.addEventListener('touchstart', disableGestures); | |
| 177 body.addEventListener('touchmove', disableGestures); | |
| 178 body.addEventListener('touchend', disableGestures); | |
| 179 | |
| 180 var mainDiv = document.createElement('div'); | |
| 181 mainDiv.className = 'main'; | |
| 182 mainDiv.id = 'main'; | |
| 183 body.appendChild(mainDiv); | |
| 184 | |
| 185 initIme(mainDiv); | |
| 186 initKeyboard(currentKeyboardLayout, mainDiv); | |
| 187 initPopupKeyboard(body); | |
| 188 | |
| 189 window.onhashchange(); | |
| 190 | |
| 191 chrome.experimental.input.virtualKeyboard.onTextInputTypeChanged.addListener( | |
| 192 function(type) { | |
| 193 var newMode = SHIFT_MODE; | |
| 194 switch(type) { | |
| 195 case "text": | |
| 196 newMode = SHIFT_MODE; | |
| 197 break; | |
| 198 case "email": | |
| 199 case "password": | |
| 200 case "search": | |
| 201 case "url": | |
| 202 newMode = KEY_MODE; | |
| 203 break; | |
| 204 case "number": | |
| 205 case "tel": | |
| 206 newMode = NUMBER_MODE; | |
| 207 break; | |
| 208 default: | |
| 209 newMode = KEY_MODE; | |
| 210 break; | |
| 211 } | |
| 212 setMode(newMode); | |
| 213 }); | |
| 214 } | |
| 215 // TODO(bryeung): would be nice to leave less gutter (without causing | |
| 216 // rendering issues with floated divs wrapping at some sizes). | |
| 217 | |
| 218 /** | |
| 219 * Switch the keyboard layout based on the current URL hash. | |
| 220 * @return {void} | |
| 221 */ | |
| 222 window.onhashchange = function() { | |
| 223 var old_layout = currentKeyboardLayout; | |
| 224 var new_layout = location.hash.replace(/^#/, ""); | |
| 225 if (old_layout == new_layout) { | |
| 226 return; | |
| 227 } | |
| 228 | |
| 229 if (KEYBOARDS[new_layout] === undefined) { | |
| 230 // Unsupported layout. | |
| 231 new_layout = "us"; | |
| 232 } | |
| 233 currentKeyboardLayout = new_layout; | |
| 234 | |
| 235 var mainDiv = document.getElementById('main'); | |
| 236 initKeyboard(currentKeyboardLayout, mainDiv); | |
| 237 | |
| 238 [new_layout, old_layout].forEach(function(layout) { | |
| 239 var visible = (layout == new_layout); | |
| 240 var keyboardDiv = KEYBOARDS[layout]['keyboardDiv']; | |
| 241 keyboardDiv.className = visible ? 'keyboard' : 'nodisplay'; | |
| 242 var canvas = KEYBOARDS[layout]['canvas']; | |
| 243 if (canvas !== undefined) { | |
| 244 if (!visible) { | |
| 245 canvas.clear(); | |
| 246 } | |
| 247 } | |
| 248 if (visible) { | |
| 249 window.onresize(); | |
| 250 } | |
| 251 }); | |
| 252 } | |
| OLD | NEW |