summaryrefslogtreecommitdiffstats
path: root/ui/keyboard
diff options
context:
space:
mode:
authorbshe@chromium.org <bshe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-20 16:32:33 +0000
committerbshe@chromium.org <bshe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-20 16:32:33 +0000
commit575ca202312dd7df1dd08f5df2fc55afd1e2ddb8 (patch)
tree4dfe4e4818d8d4ea8285f82d4dbb136910ed23e4 /ui/keyboard
parent59661e5adb337208e2a142ab043f819d419b592e (diff)
downloadchromium_src-575ca202312dd7df1dd08f5df2fc55afd1e2ddb8.zip
chromium_src-575ca202312dd7df1dd08f5df2fc55afd1e2ddb8.tar.gz
chromium_src-575ca202312dd7df1dd08f5df2fc55afd1e2ddb8.tar.bz2
Web Component Virtual Keyboard
Convert existing keyboard to web component keyboard. Also fix touch down state of keys. BUG=242539, 240346 R=bryeung@chromium.org, miket@chromium.org, stevet@chromium.org Review URL: https://codereview.chromium.org/15176004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207448 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/keyboard')
-rw-r--r--ui/keyboard/keyboard_resources.grd25
-rw-r--r--ui/keyboard/keyboard_ui_controller.cc24
-rw-r--r--ui/keyboard/resources/common.js811
-rw-r--r--ui/keyboard/resources/constants.js24
-rw-r--r--ui/keyboard/resources/elements/kb-key.html56
-rw-r--r--ui/keyboard/resources/elements/kb-keyboard.html159
-rw-r--r--ui/keyboard/resources/elements/kb-keyset.html28
-rw-r--r--ui/keyboard/resources/elements/kb-row.html28
-rw-r--r--ui/keyboard/resources/images/ret.svg17
-rw-r--r--ui/keyboard/resources/images/shift-down.svg15
-rw-r--r--ui/keyboard/resources/images/shift.svg15
-rw-r--r--ui/keyboard/resources/images/tab.svg14
-rw-r--r--ui/keyboard/resources/index.html21
-rw-r--r--ui/keyboard/resources/keysets.html131
-rw-r--r--ui/keyboard/resources/layout_us.js70
-rw-r--r--ui/keyboard/resources/main.css170
-rw-r--r--ui/keyboard/resources/main.js197
-rw-r--r--ui/keyboard/resources/manifest.json3
-rw-r--r--ui/keyboard/resources/polymer.min.js5
-rw-r--r--ui/keyboard/resources/voice_input.js71
-rw-r--r--ui/keyboard/resources/webui/constants.js26
-rw-r--r--ui/keyboard/resources/webui/keysets.html119
-rw-r--r--ui/keyboard/resources/webui/layout_us.js64
-rw-r--r--ui/keyboard/resources/webui/main.css181
24 files changed, 801 insertions, 1473 deletions
diff --git a/ui/keyboard/keyboard_resources.grd b/ui/keyboard/keyboard_resources.grd
index e437051..26bad75 100644
--- a/ui/keyboard/keyboard_resources.grd
+++ b/ui/keyboard/keyboard_resources.grd
@@ -15,22 +15,25 @@
<release seq="1">
<includes>
<include name="IDR_KEYBOARD_API_ADAPTER_JS" file="resources/api_adapter.js" type="BINDATA" />
- <include name="IDR_KEYBOARD_COMMON_JS" file="resources/common.js" type="BINDATA" />
- <include name="IDR_KEYBOARD_IMAGES_CHEVRON" file="resources/images/chevron.svg" type="BINDATA" />
- <include name="IDR_KEYBOARD_IMAGES_DEL" file="resources/images/del.svg" type="BINDATA" />
+ <include name="IDR_KEYBOARD_CONSTANTS_JS" file="resources/constants.js" type="BINDATA" />
+ <include name="IDR_KEYBOARD_ELEMENTS_KEY" file="resources/elements/kb-key.html" type="BINDATA" />
+ <include name="IDR_KEYBOARD_ELEMENTS_KEYBOARD" file="resources/elements/kb-keyboard.html" type="BINDATA" />
+ <include name="IDR_KEYBOARD_ELEMENTS_KEYSET" file="resources/elements/kb-keyset.html" type="BINDATA" />
+ <include name="IDR_KEYBOARD_ELEMENTS_ROW" file="resources/elements/kb-row.html" type="BINDATA" />
<include name="IDR_KEYBOARD_IMAGES_KEYBOARD" file="resources/images/keyboard.svg" type="BINDATA" />
<include name="IDR_KEYBOARD_IMAGES_MIC" file="resources/images/mic.svg" type="BINDATA" />
- <include name="IDR_KEYBOARD_IMAGES_RET" file="resources/images/ret.svg" type="BINDATA" />
- <include name="IDR_KEYBOARD_IMAGES_SHIFT" file="resources/images/shift.svg" type="BINDATA" />
- <include name="IDR_KEYBOARD_IMAGES_SHIFT_DOWN" file="resources/images/shift-down.svg" type="BINDATA" />
- <include name="IDR_KEYBOARD_IMAGES_TAB" file="resources/images/tab.svg" type="BINDATA" />
- <include name="IDR_KEYBOARD_INDEX" file="resources/index.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
- <include name="IDR_KEYBOARD_LAYOUT_US_JS" file="resources/layout_us.js" type="BINDATA" />
- <include name="IDR_KEYBOARD_MAIN_CSS" file="resources/main.css" type="BINDATA" />
+ <include name="IDR_KEYBOARD_IMAGES_MIC_GREEN" file="resources/images/mic-green.svg" type="BINDATA" />
+ <!-- Don't flatten html file here. Otherwise, webui keyboard will not load the correct css file. -->
+ <include name="IDR_KEYBOARD_INDEX" file="resources/index.html" allowexternalscript="true" type="BINDATA" />
+ <include name="IDR_KEYBOARD_KEYSETS" file="resources/keysets.html" type="BINDATA" />
<include name="IDR_KEYBOARD_MAIN_JS" file="resources/main.js" type="BINDATA" />
<include name="IDR_KEYBOARD_MANIFEST" file="resources/manifest.json" type="BINDATA" />
+ <include name="IDR_KEYBOARD_MAIN_CSS" file="resources/main.css" type="BINDATA" />
+ <include name="IDR_KEYBOARD_POLYMER" file="resources/polymer.min.js" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_KEYBOARD_VOICE_INPUT_JS" file="resources/voice_input.js" type="BINDATA" />
<include name="IDR_KEYBOARD_WEBUI_API_ADAPTER_JS" file="resources/webui/api_adapter.js" type="BINDATA" />
- <include name="IDR_KEYBOARD_WEBUI_LAYOUT_US_JS" file="resources/webui/layout_us.js" type="BINDATA" />
+ <include name="IDR_KEYBOARD_WEBUI_CONSTANTS_JS" file="resources/webui/constants.js" type="BINDATA" />
+ <include name="IDR_KEYBOARD_WEBUI_KEYSETS" file="resources/webui/keysets.html" type="BINDATA" />
<include name="IDR_KEYBOARD_WEBUI_MAIN_CSS" file="resources/webui/main.css" type="BINDATA" />
</includes>
</release>
diff --git a/ui/keyboard/keyboard_ui_controller.cc b/ui/keyboard/keyboard_ui_controller.cc
index 7cc76d8..7732681 100644
--- a/ui/keyboard/keyboard_ui_controller.cc
+++ b/ui/keyboard/keyboard_ui_controller.cc
@@ -20,22 +20,24 @@ content::WebUIDataSource* CreateKeyboardUIDataSource() {
source->SetDefaultResource(IDR_KEYBOARD_INDEX);
- source->AddResourcePath("common.js", IDR_KEYBOARD_COMMON_JS);
- source->AddResourcePath("images/chevron.svg", IDR_KEYBOARD_IMAGES_CHEVRON);
- source->AddResourcePath("images/del.svg", IDR_KEYBOARD_IMAGES_DEL);
- source->AddResourcePath("images/keyboard.svg", IDR_KEYBOARD_IMAGES_KEYBOARD);
+ source->AddResourcePath("elements/kb-key.html", IDR_KEYBOARD_ELEMENTS_KEY);
+ source->AddResourcePath("elements/kb-keyboard.html",
+ IDR_KEYBOARD_ELEMENTS_KEYBOARD);
+ source->AddResourcePath("elements/kb-keyset.html",
+ IDR_KEYBOARD_ELEMENTS_KEYSET);
+ source->AddResourcePath("elements/kb-row.html", IDR_KEYBOARD_ELEMENTS_ROW);
source->AddResourcePath("images/mic.svg", IDR_KEYBOARD_IMAGES_MIC);
- source->AddResourcePath("images/ret.svg", IDR_KEYBOARD_IMAGES_RET);
- source->AddResourcePath("images/shift.svg", IDR_KEYBOARD_IMAGES_SHIFT);
- source->AddResourcePath("images/shift_down.svg",
- IDR_KEYBOARD_IMAGES_SHIFT_DOWN);
- source->AddResourcePath("images/tab.svg", IDR_KEYBOARD_IMAGES_TAB);
+ source->AddResourcePath("images/mic-green.svg",
+ IDR_KEYBOARD_IMAGES_MIC_GREEN);
source->AddResourcePath("main.js", IDR_KEYBOARD_MAIN_JS);
+ source->AddResourcePath("polymer.min.js", IDR_KEYBOARD_POLYMER);
+ source->AddResourcePath("voice_input.js", IDR_KEYBOARD_VOICE_INPUT_JS);
// These files are specific to the WebUI version
- source->AddResourcePath("layout_us.js", IDR_KEYBOARD_WEBUI_LAYOUT_US_JS);
- source->AddResourcePath("main.css", IDR_KEYBOARD_WEBUI_MAIN_CSS);
source->AddResourcePath("api_adapter.js", IDR_KEYBOARD_WEBUI_API_ADAPTER_JS);
+ source->AddResourcePath("constants.js", IDR_KEYBOARD_WEBUI_CONSTANTS_JS);
+ source->AddResourcePath("keysets.html", IDR_KEYBOARD_WEBUI_KEYSETS);
+ source->AddResourcePath("main.css", IDR_KEYBOARD_WEBUI_MAIN_CSS);
return source;
}
diff --git a/ui/keyboard/resources/common.js b/ui/keyboard/resources/common.js
deleted file mode 100644
index e0e5aca..0000000
--- a/ui/keyboard/resources/common.js
+++ /dev/null
@@ -1,811 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview A simple virtual keyboard implementation.
- */
-
-var KEY_MODE = 'key';
-var SHIFT_MODE = 'shift';
-var NUMBER_MODE = 'number';
-var SYMBOL_MODE = 'symbol';
-// TODO(bryeung): tear out all of this mode switching code
-var MODES = [KEY_MODE, SHIFT_MODE, NUMBER_MODE, SYMBOL_MODE];
-var currentMode = KEY_MODE;
-var enterShiftModeOnSpace = false;
-var MODE_CODES = {};
-var MODE_TRANSITIONS = {};
-
-MODE_CODES[KEY_MODE] = 0;
-MODE_CODES[SHIFT_MODE] = 1;
-MODE_CODES[NUMBER_MODE] = 2;
-MODE_CODES[SYMBOL_MODE] = 3;
-
-MODE_TRANSITIONS[KEY_MODE + SHIFT_MODE] = SHIFT_MODE;
-MODE_TRANSITIONS[KEY_MODE + NUMBER_MODE] = NUMBER_MODE;
-MODE_TRANSITIONS[SHIFT_MODE + SHIFT_MODE] = KEY_MODE;
-MODE_TRANSITIONS[SHIFT_MODE + NUMBER_MODE] = NUMBER_MODE;
-MODE_TRANSITIONS[NUMBER_MODE + SHIFT_MODE] = SYMBOL_MODE;
-MODE_TRANSITIONS[NUMBER_MODE + NUMBER_MODE] = KEY_MODE;
-MODE_TRANSITIONS[SYMBOL_MODE + SHIFT_MODE] = NUMBER_MODE;
-MODE_TRANSITIONS[SYMBOL_MODE + NUMBER_MODE] = KEY_MODE;
-
-var KEYBOARDS = {};
-
-/**
- * The long-press delay in milliseconds before long-press handler is invoked.
- * @type {number}
- */
-var LONGPRESS_DELAY_MSEC = 500;
-
-/**
- * The repeat delay in milliseconds before a key starts repeating. Use the same
- * rate as Chromebook. (See chrome/browser/chromeos/language_preferences.cc)
- * @type {number}
- */
-var REPEAT_DELAY_MSEC = 500;
-
-/**
- * The repeat interval or number of milliseconds between subsequent keypresses.
- * Use the same rate as Chromebook.
- * @type {number}
- */
-var REPEAT_INTERVAL_MSEC = 50;
-
-/**
- * The keyboard layout name currently in use.
- * @type {string}
- */
-var currentKeyboardLayout = 'us';
-
-/**
- * A structure to track the currently repeating key on the keyboard.
- */
-var repeatKey = {
- /**
- * The timer for the delay before repeating behaviour begins.
- * @type {number|undefined}
- */
- timer: undefined,
-
- /**
- * The interval timer for issuing keypresses of a repeating key.
- * @type {number|undefined}
- */
- interval: undefined,
-
- /**
- * The key which is currently repeating.
- * @type {BaseKey|undefined}
- */
- key: undefined,
-
- /**
- * Cancel the repeat timers of the currently active key.
- */
- cancel: function() {
- clearTimeout(this.timer);
- clearInterval(this.interval);
- this.timer = undefined;
- this.interval = undefined;
- this.key = undefined;
- }
-};
-
-/**
- * Set the keyboard mode.
- * @param {string} mode The new mode.
- */
-function setMode(mode) {
- currentMode = mode;
-
- var rows = KEYBOARDS[currentKeyboardLayout]['rows'];
- for (var i = 0; i < rows.length; ++i) {
- rows[i].showMode(currentMode);
- }
-}
-
-/**
- * Transition the mode according to the given transition.
- * @param {string} transition The transition to take.
- */
-function transitionMode(transition) {
- setMode(MODE_TRANSITIONS[currentMode + transition]);
-}
-
-/**
- * Send the given key to chrome but don't update the keyboard state.
- */
-function sendKeyRaw(key) {
- var keyIdentifier = key;
-
- // Fix up some keys to their respective identifiers for convenience.
- if (keyIdentifier == ' ') {
- keyIdentifier = 'Spacebar';
- }
-
- var keyEvent = {
- keyIdentifier: keyIdentifier
- };
- sendKeyEvent(keyEvent);
-}
-
-/**
- * Send the given key to chrome, via the experimental extension API.
- * Also updates the current keyboard state based on the current state and which
- * character was sent.
- * @param {string} keyIdentifier The key to send.
- */
-function sendKey(keyIdentifier) {
- sendKeyRaw(keyIdentifier);
-
- // Exit shift mode after pressing any key but space.
- if (currentMode == SHIFT_MODE && keyIdentifier != 'Spacebar') {
- transitionMode(SHIFT_MODE);
- }
- // Enter shift mode after typing a closing punctuation and then a space for a
- // new sentence.
- if (enterShiftModeOnSpace) {
- enterShiftModeOnSpace = false;
- if (currentMode != SHIFT_MODE && keyIdentifier == 'Spacebar') {
- setMode(SHIFT_MODE);
- }
- }
- if (currentMode != SHIFT_MODE &&
- (keyIdentifier == '.' || keyIdentifier == '?' || keyIdentifier == '!')) {
- enterShiftModeOnSpace = true;
- }
-}
-
-/**
- * Add a child div element that represents the content of the given element.
- * A child div element that represents a text content is added if
- * opt_textContent is given. Otherwise a child element that represents an image
- * content is added. If the given element already has a child, the child element
- * is modified.
- * @param {Element} element The DOM Element to which the content is added.
- * @param {string} opt_textContent The text to be inserted.
- */
-function addContent(element, opt_textContent) {
- if (element.childNodes.length > 0) {
- var content = element.childNodes[0];
- if (opt_textContent) {
- content.textContent = opt_textContent;
- }
- return;
- }
-
- var content = document.createElement('div');
- if (opt_textContent) {
- content.textContent = opt_textContent;
- content.className = 'text-key';
- } else {
- content.className = 'image-key';
- }
- element.appendChild(content);
-}
-
-/**
- * Set up the event handlers necessary to respond to mouse and touch events on
- * the virtual keyboard.
- * @param {BaseKey} key The BaseKey object corresponding to this key.
- * @param {Element} element The top-level DOM Element to set event handlers on.
- * @param {Object.<string, function()>} handlers The object that contains key
- * event handlers in the following form.
- *
- * { 'up': keyUpHandler,
- * 'down': keyDownHandler,
- * 'long': keyLongHandler }
- *
- * keyDownHandler: Called when the key is pressed. This will be called
- * repeatedly when holding a repeating key.
- * keyUpHandler: Called when the key is released. This is only called
- * once per actual key press.
- * keyLongHandler: Called when the key is long-pressed for
- * |LONGPRESS_DELAY_MSEC| milliseconds.
- *
- * The object does not necessarily contain all the handlers above, but
- * needs to contain at least one of them.
- */
-function setupKeyEventHandlers(key, element, handlers) {
- var keyDownHandler = handlers['down'];
- var keyUpHandler = handlers['up'];
- var keyLongHandler = handlers['long'];
- if (!(keyDownHandler || keyUpHandler || keyLongPressHandler)) {
- throw new Error('Invalid handlers passed to setupKeyEventHandlers');
- }
-
- /**
- * Handle a key down event on the virtual key.
- * @param {UIEvent} evt The UI event which triggered the key down.
- */
- var downHandler = function(evt) {
- // Prevent any of the system gestures from happening.
- evt.preventDefault();
-
- // Don't process a key down if the key is already down.
- if (key.pressed) {
- return;
- }
- key.pressed = true;
- if (keyDownHandler) {
- keyDownHandler();
- }
- repeatKey.cancel();
-
- // Start a repeating timer if there is a repeat interval and a function to
- // process key down events.
- if (key.repeat && keyDownHandler) {
- repeatKey.key = key;
- // The timeout for the repeating timer occurs at
- // REPEAT_DELAY_MSEC - REPEAT_INTERVAL_MSEC so that the interval
- // function can handle all repeat keypresses and will get the first one
- // at the correct time.
- repeatKey.timer = setTimeout(function() {
- repeatKey.timer = undefined;
- repeatKey.interval = setInterval(function() {
- keyDownHandler();
- }, REPEAT_INTERVAL_MSEC);
- }, Math.max(0, REPEAT_DELAY_MSEC - REPEAT_INTERVAL_MSEC));
- }
-
- if (keyLongHandler) {
- // Copy the currentTarget of event, which is neccessary because |evt| can
- // be modified before |keyLongHandler| is called.
- var evtCopy = {};
- evtCopy.currentTarget = evt.currentTarget;
- key.longPressTimer = setTimeout(function() {
- keyLongHandler(evtCopy),
- clearTimeout(key.longPressTimer);
- delete key.longPressTimer;
- key.pressed = false;
- }, LONGPRESS_DELAY_MSEC);
- }
- };
-
- /**
- * Handle a key up event on the virtual key.
- * @param {UIEvent} evt The UI event which triggered the key up.
- */
- var upHandler = function(evt) {
- // Prevent any of the system gestures from happening.
- evt.preventDefault();
-
- // Reset long-press timer.
- if (key.longPressTimer) {
- clearTimeout(key.longPressTimer);
- delete key.longPressTimer;
- }
-
- // If they key was not actually pressed do not send a key up event.
- if (!key.pressed) {
- return;
- }
- key.pressed = false;
-
- // Cancel running repeat timer for the released key only.
- if (repeatKey.key == key) {
- repeatKey.cancel();
- }
-
- if (keyUpHandler) {
- keyUpHandler();
- }
- };
-
- // Setup mouse event handlers.
- element.addEventListener('mousedown', downHandler);
- element.addEventListener('mouseup', upHandler);
-
- // Setup touch handlers.
- element.addEventListener('touchstart', downHandler);
- element.addEventListener('touchend', upHandler);
-}
-
-/**
- * Create closure for the sendKey function.
- * @param {string} key The key paramater to sendKey.
- * @return {function()} A function which calls sendKey(key).
- */
-function sendKeyFunction(key) {
- return function() {
- sendKey(key);
- };
-}
-
-/**
- * Plain-old-data class to represent a character.
- * @param {string} display The HTML to be displayed.
- * @param {string} id The key identifier for this Character.
- * @constructor
- */
-function Character(display, id) {
- this.display = display;
- this.keyIdentifier = id;
-}
-
-/**
- * Convenience function to make the keyboard data more readable.
- * @param {string} display The display for the created Character.
- * @param {string} opt_id The id for the created Character.
- * @return {Character} A character that contains display and opt_id. If
- * opt_id is omitted, display is used as the id.
- */
-function C(display, opt_id) {
- var id = opt_id || display;
- return new Character(display, id);
-}
-
-/**
- * An abstract base-class for all keys on the keyboard.
- * @constructor
- */
-function BaseKey() {}
-
-BaseKey.prototype = {
- /**
- * The cell type of this key. Determines the background colour.
- * @type {string}
- */
- cellType_: '',
-
- /**
- * If true, holding this key will issue repeat keypresses.
- * @type {boolean}
- */
- repeat_: false,
-
- /**
- * Track the pressed state of the key. This is true if currently pressed.
- * @type {boolean}
- */
- pressed_: false,
-
- /**
- * Get the repeat behaviour of the key.
- * @return {boolean} True if the key will repeat.
- */
- get repeat() {
- return this.repeat_;
- },
-
- /**
- * Set the repeat behaviour of the key
- * @param {boolean} repeat True if the key should repeat.
- */
- set repeat(repeat) {
- this.repeat_ = repeat;
- },
-
- /**
- * Get the pressed state of the key.
- * @return {boolean} True if the key is currently pressed.
- */
- get pressed() {
- return this.pressed_;
- },
-
- /**
- * Set the pressed state of the key.
- * @param {boolean} pressed True if the key is currently pressed.
- */
- set pressed(pressed) {
- this.pressed_ = pressed;
- },
-
- /**
- * Create the DOM elements for the given keyboard mode. Must be overridden.
- * @param {string} mode The keyboard mode to create elements for.
- * @return {Element} The top-level DOM Element for the key.
- */
- makeDOM: function(mode) {
- throw new Error('makeDOM not implemented in BaseKey');
- },
-};
-
-/**
- * A simple key which displays Characters.
- * @param {Object} key The Character for KEY_MODE.
- * @param {Object} shift The Character for SHIFT_MODE.
- * @param {Object} num The Character for NUMBER_MODE.
- * @param {Object} symbol The Character for SYMBOL_MODE.
- * @param {string} className An optional class name for the key.
- * @constructor
- * @extends {BaseKey}
- */
-function Key(key, shift, num, symbol, className) {
- this.modeElements_ = {};
- this.cellType_ = '';
- this.className_ = (className) ? 'key ' + className : 'key';
-
- this.modes_ = {};
- this.modes_[KEY_MODE] = key;
- this.modes_[SHIFT_MODE] = shift;
- this.modes_[NUMBER_MODE] = num;
- this.modes_[SYMBOL_MODE] = symbol;
-}
-
-Key.prototype = {
- __proto__: BaseKey.prototype,
-
- /** @override */
- makeDOM: function(mode) {
- if (!this.modes_[mode]) {
- return null;
- }
-
- this.modeElements_[mode] = document.createElement('div');
- var element = this.modeElements_[mode];
- element.className = this.className_;
-
- addContent(element, this.modes_[mode].display);
-
- setupKeyEventHandlers(this, element,
- { 'up': sendKeyFunction(this.modes_[mode].keyIdentifier) });
- return element;
- }
-};
-
-/**
- * A key which displays an SVG image.
- * @param {string} className The class that provides the image.
- * @param {string} keyId The key identifier for the key.
- * @param {boolean} opt_repeat True if the key should repeat.
- * @constructor
- * @extends {BaseKey}
- */
-function SvgKey(className, keyId, opt_repeat) {
- this.modeElements_ = {};
- this.cellType_ = 'nc';
- this.className_ = className;
- this.keyId_ = keyId;
- this.repeat_ = opt_repeat || false;
-}
-
-SvgKey.prototype = {
- __proto__: BaseKey.prototype,
-
- /** @override */
- makeDOM: function(mode) {
- this.modeElements_[mode] = document.createElement('div');
- this.modeElements_[mode].className = 'key dark';
- this.modeElements_[mode].classList.add(this.className_);
- addContent(this.modeElements_[mode]);
-
- // send the key event on key down if key repeat is enabled
- var handler = this.repeat_ ? { 'down' : sendKeyFunction(this.keyId_) } :
- { 'up' : sendKeyFunction(this.keyId_) };
- setupKeyEventHandlers(this, this.modeElements_[mode], handler);
-
- return this.modeElements_[mode];
- }
-};
-
-/**
- * A Key that remains the same through all modes.
- * @param {string} className The class name for the key.
- * @param {string} content The display text for the key.
- * @param {string} keyId The key identifier for the key.
- * @constructor
- * @extends {BaseKey}
- */
-function SpecialKey(className, content, keyId) {
- this.modeElements_ = {};
- this.cellType_ = 'nc';
- this.content_ = content;
- this.keyId_ = keyId;
- this.className_ = className;
-}
-
-SpecialKey.prototype = {
- __proto__: BaseKey.prototype,
-
- /** @override */
- makeDOM: function(mode) {
- this.modeElements_[mode] = document.createElement('div');
- this.modeElements_[mode].className = 'key dark';
- this.modeElements_[mode].classList.add(this.className_);
- addContent(this.modeElements_[mode], this.content_);
-
- setupKeyEventHandlers(this, this.modeElements_[mode],
- { 'up': sendKeyFunction(this.keyId_) });
-
- return this.modeElements_[mode];
- }
-};
-
-/**
- * A shift key.
- * @constructor
- * @param {string} className The class name for the key.
- * @extends {BaseKey}
- */
-function ShiftKey(className) {
- this.modeElements_ = {};
- this.cellType_ = 'nc';
- this.className_ = className;
-}
-
-ShiftKey.prototype = {
- __proto__: BaseKey.prototype,
-
- /** @override */
- makeDOM: function(mode) {
- this.modeElements_[mode] = document.createElement('div');
- this.modeElements_[mode].className = 'key shift dark';
- this.modeElements_[mode].classList.add(this.className_);
-
- if (mode == KEY_MODE || mode == SHIFT_MODE) {
- addContent(this.modeElements_[mode]);
- } else if (mode == NUMBER_MODE) {
- addContent(this.modeElements_[mode], 'more');
- } else if (mode == SYMBOL_MODE) {
- addContent(this.modeElements_[mode], '#123');
- }
-
- if (mode == SHIFT_MODE || mode == SYMBOL_MODE) {
- this.modeElements_[mode].classList.add('moddown');
- } else {
- this.modeElements_[mode].classList.remove('moddown');
- }
-
- setupKeyEventHandlers(this, this.modeElements_[mode],
- { 'down': function() {
- transitionMode(SHIFT_MODE);
- }});
-
- return this.modeElements_[mode];
- },
-};
-
-/**
- * The symbol key: switches the keyboard into symbol mode.
- * @constructor
- * @extends {BaseKey}
- */
-function SymbolKey() {
- this.modeElements_ = {};
- this.cellType_ = 'nc';
-}
-
-SymbolKey.prototype = {
- __proto__: BaseKey.prototype,
-
- /** @override */
- makeDOM: function(mode, height) {
- this.modeElements_[mode] = document.createElement('div');
- this.modeElements_[mode].className = 'key symbol dark';
-
- if (mode == KEY_MODE || mode == SHIFT_MODE) {
- addContent(this.modeElements_[mode], '#123');
- } else if (mode == NUMBER_MODE || mode == SYMBOL_MODE) {
- addContent(this.modeElements_[mode], 'abc');
- }
-
- if (mode == NUMBER_MODE || mode == SYMBOL_MODE) {
- this.modeElements_[mode].classList.add('moddown');
- } else {
- this.modeElements_[mode].classList.remove('moddown');
- }
-
- setupKeyEventHandlers(this, this.modeElements_[mode],
- { 'down': function() {
- transitionMode(NUMBER_MODE);
- }});
-
- return this.modeElements_[mode];
- }
-};
-
-/**
- * The ".com" key.
- * @constructor
- * @extends {BaseKey}
- */
-function DotComKey() {
- this.modeElements_ = {};
- this.cellType_ = 'nc';
-}
-
-DotComKey.prototype = {
- __proto__: BaseKey.prototype,
-
- /** @override */
- makeDOM: function(mode) {
- this.modeElements_[mode] = document.createElement('div');
- this.modeElements_[mode].className = 'key com dark';
- addContent(this.modeElements_[mode], '.com');
-
- setupKeyEventHandlers(this, this.modeElements_[mode],
- { 'up': function() {
- sendKeyRaw('.');
- sendKeyRaw('c');
- sendKeyRaw('o');
- sendKeyRaw('m');
- }});
-
- return this.modeElements_[mode];
- }
-};
-
-/**
- * The key that hides the keyboard.
- * @constructor
- * @extends {BaseKey}
- */
-function HideKeyboardKey() {
- this.modeElements_ = {};
- this.cellType_ = 'nc';
-}
-
-HideKeyboardKey.prototype = {
- __proto__: BaseKey.prototype,
-
- /** @override */
- makeDOM: function(mode) {
- this.modeElements_[mode] = document.createElement('div');
- this.modeElements_[mode].className = 'key hide dark';
- addContent(this.modeElements_[mode]);
-
- setupKeyEventHandlers(this, this.modeElements_[mode],
- { 'down': function() { console.log('Hide the keyboard!'); } });
-
- return this.modeElements_[mode];
- }
-};
-
-/**
- * The mic key: activate speech input.
- * @constructor
- * @extends {BaseKey}
- */
-function MicKey() {
- this.modeElements_ = {};
- this.recognition_ = new webkitSpeechRecognition();
- this.recognition_.onstart = this.onStartHandler.bind(this);
- this.recognition_.onresult = this.onResultHandler.bind(this);
- this.recognition_.onerror = this.onErrorHandler.bind(this);
- this.recognition_.onend = this.onEndHandler.bind(this);
- this.finalResult_ = '';
- this.recognizing_ = false;
- this.cellType_ = 'nc';
-}
-
-MicKey.prototype = {
- __proto__: BaseKey.prototype,
-
- /**
- * Event handler for mouse/touch down events.
- */
- onDown: function() {
- if (this.recognizing_) {
- this.recognition_.stop();
- return;
- }
- this.recognition_.start();
- },
-
- /**
- * Speech recognition started. Change mic key's icon.
- */
- onStartHandler: function() {
- this.recognizing_ = true;
- this.finalResult_ = '';
- for (var i = 0; i < MODES.length; ++i)
- this.modeElements_[MODES[i]].classList.add('start');
- },
-
- /**
- * Speech recognizer returns a result.
- * @param{Event} e The SpeechRecognition event that is raised each time there
- * are any changes to interim or final results.
- */
- onResultHandler: function(e) {
- for (var i = e.resultIndex; i < e.results.length; i++) {
- if (e.results[i].isFinal)
- this.finalResult_ = e.results[i][0].transcript;
- }
- for (var i = 0; i < this.finalResult_.length; i++) {
- sendKeyRaw(this.finalResult_.charAt(i));
- }
- },
-
- /**
- * Speech recognizer returns an error.
- * @param{Event} e The SpeechRecognitionError event that is raised each time
- * there is an error.
- */
- onErrorHandler: function(e) {
- console.error('error code = ' + e.error);
- },
-
- /**
- * Speech recognition ended. Reset mic key's icon.
- */
- onEndHandler: function() {
- for (var i = 0; i < MODES.length; ++i)
- this.modeElements_[MODES[i]].classList.remove('start');
-
- this.recognizing_ = false;
- },
-
- /** @override */
- makeDOM: function(mode) {
- this.modeElements_[mode] = document.createElement('div');
- this.modeElements_[mode].className = 'key mic';
- addContent(this.modeElements_[mode]);
-
- setupKeyEventHandlers(this, this.modeElements_[mode],
- { 'down': this.onDown.bind(this) });
-
- return this.modeElements_[mode];
- }
-};
-
-/**
- * A container for keys.
- * @param {number} position The position of the row (0-3).
- * @param {Array.<BaseKey>} keys The keys in the row.
- * @constructor
- */
-function Row(position, keys) {
- this.position_ = position;
- this.keys_ = keys;
- this.element_ = null;
- this.modeElements_ = {};
-}
-
-Row.prototype = {
- /**
- * Create the DOM elements for the row.
- * @return {Element} The top-level DOM Element for the row.
- */
- makeDOM: function() {
- this.element_ = document.createElement('div');
- this.element_.className = 'row';
- for (var i = 0; i < MODES.length; ++i) {
- var mode = MODES[i];
- this.modeElements_[mode] = document.createElement('div');
- this.modeElements_[mode].style.display = 'none';
- this.element_.appendChild(this.modeElements_[mode]);
- }
-
- for (var j = 0; j < this.keys_.length; ++j) {
- var key = this.keys_[j];
- for (var i = 0; i < MODES.length; ++i) {
- var keyDom = key.makeDOM(MODES[i]);
- if (keyDom) {
- this.modeElements_[MODES[i]].appendChild(keyDom);
- }
- }
- }
-
- for (var i = 0; i < MODES.length; ++i) {
- var clearingDiv = document.createElement('div');
- clearingDiv.style.clear = 'both';
- this.modeElements_[MODES[i]].appendChild(clearingDiv);
- }
-
- return this.element_;
- },
-
- /**
- * Shows the given mode.
- * @param {string} mode The mode to show.
- */
- showMode: function(mode) {
- for (var i = 0; i < MODES.length; ++i) {
- this.modeElements_[MODES[i]].style.display = 'none';
- }
- this.modeElements_[mode].style.display = '-webkit-box';
- },
-
- /**
- * Returns the size of keys this row contains.
- * @return {number} The size of keys.
- */
- get length() {
- return this.keys_.length;
- }
-};
diff --git a/ui/keyboard/resources/constants.js b/ui/keyboard/resources/constants.js
new file mode 100644
index 0000000..f5700da
--- /dev/null
+++ b/ui/keyboard/resources/constants.js
@@ -0,0 +1,24 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * Aspect ratio of keyboard.
+ * @type {number}
+ */
+var ASPECT_RATIO = 4.5;
+
+/**
+ * Ratio of key height and font size.
+ * @type {number}
+ */
+var FONT_SIZE_RATIO = 3.5;
+
+/**
+ * The number of rows in each keyset.
+ * @type {number}
+ */
+// TODO(bshe): The number of rows should equal to the number of kb-row elements
+// in kb-keyset. Remove this variable once figure out how to calculate the
+// number from keysets.
+var ROW_LENGTH = 4;
diff --git a/ui/keyboard/resources/elements/kb-key.html b/ui/keyboard/resources/elements/kb-key.html
new file mode 100644
index 0000000..c0d2556
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-key.html
@@ -0,0 +1,56 @@
+<!--
+ -- Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ -- Use of this source code is governed by a BSD-style license that can be
+ -- found in the LICENSE file.
+ -->
+
+<element name="kb-key" attributes="toKeyset char repeat" on-pointerdown="down"
+ on-pointerup="up">
+ <template>
+ <style>
+ @host {
+ * {
+ -webkit-box-flex: 1;
+ display: -webkit-box;
+ position: relative;
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-size: contain;
+ }
+ }
+ .key {
+ bottom: 0;
+ left: 0;
+ height: 1.2em;
+ margin: auto;
+ position: absolute;
+ right: 0;
+ top: 0;
+ text-align: center;
+ }
+ </style>
+ <div id="key" class="key">
+ <content></content>
+ </div>
+ </template>
+ <script>
+ Polymer.register(this, {
+ repeat: false,
+ down: function(event) {
+ var detail = {
+ char: this.char || this.textContent,
+ toKeyset: this.toKeyset,
+ repeat: this.repeat
+ };
+ this.send('key-down', detail);
+ },
+ up: function(event) {
+ var detail = {
+ char: this.char || this.textContent,
+ toKeyset: this.toKeyset
+ };
+ this.send('key-up', detail);
+ }
+ });
+ </script>
+</element>
diff --git a/ui/keyboard/resources/elements/kb-keyboard.html b/ui/keyboard/resources/elements/kb-keyboard.html
new file mode 100644
index 0000000..0f19ccd
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-keyboard.html
@@ -0,0 +1,159 @@
+<!--
+ -- Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ -- Use of this source code is governed by a BSD-style license that can be
+ -- found in the LICENSE file.
+ -->
+
+<element name="kb-keyboard" on-key-over="keyOver" on-key-up="keyUp"
+ on-key-down="keyDown" attributes="keyset rows">
+ <template>
+ <content select="#{{keyset}}"></content>
+ </template>
+ <script>
+ /**
+ * The long-press delay in milliseconds before long-press handler is
+ * invoked.
+ * @type {number}
+ */
+ var LONGPRESS_DELAY_MSEC = 500;
+
+ /**
+ * The repeat delay in milliseconds before a key starts repeating. Use the
+ * same rate as Chromebook.
+ * (See chrome/browser/chromeos/language_preferences.cc)
+ * @type {number}
+ */
+ var REPEAT_DELAY_MSEC = 500;
+
+ /**
+ * The repeat interval or number of milliseconds between subsequent
+ * keypresses. Use the same rate as Chromebook.
+ * @type {number}
+ */
+ var REPEAT_INTERVAL_MSEC = 50;
+
+ /**
+ * The boolean to decide if keyboard should transit to upper case keyset
+ * when spacebar is pressed. If a closing punctuation is followed by a
+ * spacebar, keyboard should automatically transit to upper case.
+ * @type {boolean}
+ */
+ var enterUpperOnSpace = false;
+
+ /**
+ * A structure to track the currently repeating key on the keyboard.
+ */
+ var repeatKey = {
+ /**
+ * The timer for the delay before repeating behaviour begins.
+ * @type {number|undefined}
+ */
+ timer: undefined,
+
+ /**
+ * The interval timer for issuing keypresses of a repeating key.
+ * @type {number|undefined}
+ */
+ interval: undefined,
+
+ /**
+ * The key which is currently repeating.
+ * @type {BaseKey|undefined}
+ */
+ key: undefined,
+
+ /**
+ * Cancel the repeat timers of the currently active key.
+ */
+ cancel: function() {
+ clearTimeout(this.timer);
+ clearInterval(this.interval);
+ this.timer = undefined;
+ this.interval = undefined;
+ this.key = undefined;
+ }
+ };
+
+ Polymer.register(this, {
+ lastPressedKey: null,
+ voiceInput_: null,
+
+ ready: function() {
+ this.voiceInput_ = new VoiceInput(this);
+ },
+
+ /**
+ * Handles key-down event that is sent by kb-key.
+ * @param {CustomEvent} event The key-down event dispatched by kb-key.
+ * @param {Object} detail The detail of pressed kb-key.
+ */
+ keyDown: function(event, detail) {
+ var toKeyset = detail.toKeyset;
+ if (this.lastPressedKey)
+ this.lastPressedKey.classList.remove('active');
+ this.lastPressedKey = event.target;
+ this.lastPressedKey.classList.add('active');
+ repeatKey.cancel();
+ if (detail.repeat) {
+ sendKey(detail.char);
+ repeatKey.key = this.lastPressedKey;
+ repeatKey.timer = setTimeout(function() {
+ repeatKey.timer = undefined;
+ repeatKey.interval = setInterval(function() {
+ sendKey(detail.char);
+ }, REPEAT_INTERVAL_MSEC);
+ }, Math.max(0, REPEAT_DELAY_MSEC - REPEAT_INTERVAL_MSEC));
+ }
+ },
+
+ /**
+ * Handles key-up event that is sent by kb-key.
+ * @param {CustomEvent} event The key-up event dispatched by kb-key.
+ * @param {Object} detail The detail of pressed kb-key.
+ */
+ keyUp: function(event, detail) {
+ this.lastPressedKey.classList.remove('active');
+ if (this.lastPressedKey != event.target)
+ return;
+ if (repeatKey.key == event.target) {
+ repeatKey.cancel();
+ return;
+ }
+ var toKeyset = detail.toKeyset;
+ // Keyset transtion key.
+ if (toKeyset) {
+ this.keyset = toKeyset;
+ }
+ var char = detail.char;
+ if (enterUpperOnSpace) {
+ enterUpperOnSpace = false;
+ if (char == 'Spacebar')
+ this.keyset = 'upper';
+ }
+ switch(char) {
+ case 'Invalid':
+ return;
+ case 'Mic':
+ this.voiceInput_.onDown();
+ return;
+ case '.':
+ case '?':
+ case '!':
+ enterUpperOnSpace = true;
+ break;
+ case 'Tab':
+ case 'Spacebar':
+ case 'Enter':
+ sendKey(char);
+ return;
+ default:
+ break;
+ }
+ for (var i = 0; i < char.length; i++) {
+ sendKey(char.charAt(i));
+ }
+ }
+ });
+ </script>
+</element>
+
diff --git a/ui/keyboard/resources/elements/kb-keyset.html b/ui/keyboard/resources/elements/kb-keyset.html
new file mode 100644
index 0000000..c953aed
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-keyset.html
@@ -0,0 +1,28 @@
+<!--
+ -- Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ -- Use of this source code is governed by a BSD-style license that can be
+ -- found in the LICENSE file.
+ -->
+
+<element name="kb-keyset" attributes="toKeyset" on-key-up="keyUp">
+ <template>
+ <style>
+ @host {
+ * {
+ -webkit-box-orient: vertical;
+ -webkit-box-flex: 1;
+ display: -webkit-box;
+ }
+ }
+ </style>
+ <content></content>
+ </template>
+ <script>
+ Polymer.register(this, {
+ keyUp: function(event, detail) {
+ if (!detail.toKeyset)
+ detail.toKeyset = this.toKeyset;
+ }
+ });
+ </script>
+</element>
diff --git a/ui/keyboard/resources/elements/kb-row.html b/ui/keyboard/resources/elements/kb-row.html
new file mode 100644
index 0000000..21525b8
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-row.html
@@ -0,0 +1,28 @@
+<!--
+ -- Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ -- Use of this source code is governed by a BSD-style license that can be
+ -- found in the LICENSE file.
+ -->
+
+<element name="kb-row">
+ <template>
+ <style>
+ @host {
+ * {
+ -webkit-box-flex: 1;
+ display: -webkit-box;
+ text-align: center;
+ margin-right: 5px;
+ margin-top: 5px;
+ }
+ }
+ content::-webkit-distributed(kb-key) {
+ -webkit-flex: 1 auto;
+ }
+ </style>
+ <content select="*"></content>
+ </template>
+ <script>
+ Polymer.register(this);
+ </script>
+</element>
diff --git a/ui/keyboard/resources/images/ret.svg b/ui/keyboard/resources/images/ret.svg
deleted file mode 100644
index 9f327f95..0000000
--- a/ui/keyboard/resources/images/ret.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
-<g>
- <g>
- <path fill="#bababb" d="M22.75,31.432c-0.043,0-0.087-0.012-0.126-0.034l-6-3.5c-0.077-0.045-0.124-0.127-0.124-0.216
- s0.047-0.171,0.124-0.216l6-3.5c0.039-0.023,0.083-0.034,0.126-0.034c0.043,0,0.086,0.011,0.125,0.033
- C22.952,24.01,23,24.093,23,24.182v7c0,0.09-0.048,0.172-0.125,0.217C22.835,31.421,22.792,31.432,22.75,31.432L22.75,31.432z"/>
- <path fill="#bababb" d="M22.75,24.182v7l-6-3.5L22.75,24.182 M22.75,23.682c-0.087,0-0.174,0.022-0.252,0.068l-6,3.5
- c-0.154,0.089-0.248,0.254-0.248,0.432s0.094,0.342,0.248,0.432l6,3.5c0.078,0.046,0.165,0.068,0.252,0.068
- c0.086,0,0.172-0.022,0.249-0.066c0.155-0.089,0.251-0.255,0.251-0.434v-7c0-0.179-0.096-0.344-0.251-0.434
- C22.921,23.704,22.835,23.682,22.75,23.682L22.75,23.682z"/>
- </g>
- <path fill="#bababb" d="M30.25,20.083v6.1h-10v3h11.5c0.828,0,1.5-0.672,1.5-1.5v-8.865L30.25,20.083z"/>
-</g>
-</svg>
diff --git a/ui/keyboard/resources/images/shift-down.svg b/ui/keyboard/resources/images/shift-down.svg
deleted file mode 100644
index 958aa29..0000000
--- a/ui/keyboard/resources/images/shift-down.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="50px" height="50px" viewBox="10 10 30 30">
-<!-- TODO(fsamuel): remove the width and height workaround above after fixing SVG bug -->
-<g>
- <path fill="#e0e0e0" d="M23,29.25c-0.138,0-0.25-0.112-0.25-0.25v-2.75H20c-0.101,0-0.192-0.061-0.231-0.154
- s-0.017-0.201,0.054-0.272l5-5c0.049-0.049,0.113-0.073,0.177-0.073s0.128,0.024,0.177,0.073l5,5
- c0.071,0.071,0.093,0.179,0.055,0.272c-0.039,0.093-0.13,0.154-0.231,0.154h-2.75V29c0,0.138-0.112,0.25-0.25,0.25H23z"/>
- <path fill="#e0e0e0" d="M25,21l5,5h-3v3h-4v-3h-3L25,21 M25,20.5c-0.128,0-0.256,0.049-0.354,0.146l-5,5
- c-0.143,0.143-0.186,0.358-0.108,0.545C19.615,26.377,19.797,26.5,20,26.5h2.5V29c0,0.276,0.224,0.5,0.5,0.5h4
- c0.276,0,0.5-0.224,0.5-0.5v-2.5H30c0.202,0,0.385-0.122,0.462-0.309c0.077-0.187,0.034-0.402-0.108-0.545l-5-5
- C25.255,20.548,25.127,20.5,25,20.5L25,20.5z"/>
-</g>
-</svg>
diff --git a/ui/keyboard/resources/images/shift.svg b/ui/keyboard/resources/images/shift.svg
deleted file mode 100644
index 08d8c8a..0000000
--- a/ui/keyboard/resources/images/shift.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="50px" height="50px" viewBox="10 10 30 30">
-<!-- TODO(fsamuel): remove the width and height workaround above after fixing SVG bug -->
-<g>
- <path fill="#bababb" d="M23,29.25c-0.138,0-0.25-0.112-0.25-0.25v-2.75H20c-0.101,0-0.192-0.061-0.231-0.154
- s-0.017-0.201,0.054-0.272l5-5c0.049-0.049,0.113-0.073,0.177-0.073s0.128,0.024,0.177,0.073l5,5
- c0.071,0.071,0.093,0.179,0.055,0.272c-0.039,0.093-0.13,0.154-0.231,0.154h-2.75V29c0,0.138-0.112,0.25-0.25,0.25H23z"/>
- <path fill="#bababb" d="M25,21l5,5h-3v3h-4v-3h-3L25,21 M25,20.5c-0.128,0-0.256,0.049-0.354,0.146l-5,5
- c-0.143,0.143-0.186,0.358-0.108,0.545C19.615,26.377,19.797,26.5,20,26.5h2.5V29c0,0.276,0.224,0.5,0.5,0.5h4
- c0.276,0,0.5-0.224,0.5-0.5v-2.5H30c0.202,0,0.385-0.122,0.462-0.309c0.077-0.187,0.034-0.402-0.108-0.545l-5-5
- C25.255,20.548,25.127,20.5,25,20.5L25,20.5z"/>
-</g>
-</svg>
diff --git a/ui/keyboard/resources/images/tab.svg b/ui/keyboard/resources/images/tab.svg
deleted file mode 100644
index 774e306..0000000
--- a/ui/keyboard/resources/images/tab.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="100%" height="100%" viewBox="5 5 40 40" enable-background="new" xml:space="preserve">
-<g>
- <line fill="none" stroke="#bababb" stroke-width="1.7" stroke-linecap="round" x1="36.377" y1="20.5" x2="36.377" y2="29.5"/>
- <g>
- <path fill="#bababb" d="M27.377,28.75c-0.043,0-0.086-0.011-0.125-0.033c-0.077-0.045-0.125-0.127-0.125-0.217v-7
- c0-0.089,0.048-0.172,0.125-0.217c0.039-0.022,0.082-0.033,0.125-0.033c0.044,0,0.087,0.011,0.126,0.034l6,3.5
- c0.077,0.045,0.124,0.127,0.124,0.216s-0.047,0.171-0.124,0.216l-6,3.5C27.464,28.738,27.421,28.75,27.377,28.75L27.377,28.75z"/>
- </g>
- <polygon fill="#bababb" points="14.888,23.5 13.623,26.5 29.877,26.5 29.877,23.5 "/>
-</g>
-</svg>
diff --git a/ui/keyboard/resources/index.html b/ui/keyboard/resources/index.html
index fd05578..e00d88e 100644
--- a/ui/keyboard/resources/index.html
+++ b/ui/keyboard/resources/index.html
@@ -1,11 +1,26 @@
<!DOCTYPE HTML>
+<!--
+ -- Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ -- Use of this source code is governed by a BSD-style license that can be
+ -- found in the LICENSE file.
+ -->
+
<html>
<head>
+ <meta charset="UTF-8">
<link rel="stylesheet" href="main.css">
+ <script src="constants.js"></script>
+ <script src="polymer.min.js"></script>
<script src="api_adapter.js"></script>
- <script src="common.js"></script>
- <script src="layout_us.js"></script>
+ <script src="voice_input.js"></script>
+ <link rel="import" href="elements/kb-key.html">
+ <link rel="import" href="elements/kb-row.html">
+ <link rel="import" href="elements/kb-keyset.html">
+ <link rel="import" href="elements/kb-keyboard.html">
+ <link id="keysets" rel="import" href="keysets.html">
<script src="main.js"></script>
</head>
- <body id="b"></body>
+ <body>
+ <kb-keyboard id="keyboard" touch-action="none" keyset="lower"></kb-keyboard>
+ </body>
</html>
diff --git a/ui/keyboard/resources/keysets.html b/ui/keyboard/resources/keysets.html
new file mode 100644
index 0000000..256cbbd
--- /dev/null
+++ b/ui/keyboard/resources/keysets.html
@@ -0,0 +1,131 @@
+<!--
+ -- Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ -- Use of this source code is governed by a BSD-style license that can be
+ -- found in the LICENSE file.
+ -->
+
+<template>
+ <kb-keyset id="upper" toKeyset="lower">
+ <kb-row>
+ <kb-key class="tab dark" char="Tab">tab</kb-key><kb-key>Q</kb-key>
+ <kb-key>W</kb-key><kb-key>E</kb-key><kb-key>R</kb-key><kb-key>T</kb-key>
+ <kb-key>Y</kb-key><kb-key>U</kb-key><kb-key>I</kb-key><kb-key>O</kb-key>
+ <kb-key>P</kb-key>
+ <kb-key class="backspace dark" char="Backspace" repeat>backspace</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="symbol dark" toKeyset="symbol" char="Invalid">#123</kb-key>
+ <kb-key>A</kb-key><kb-key>S</kb-key><kb-key>D</kb-key><kb-key>F</kb-key>
+ <kb-key>G</kb-key><kb-key>H</kb-key><kb-key>J</kb-key><kb-key>K</kb-key>
+ <kb-key>L</kb-key><kb-key>\</kb-key>
+ <kb-key class='return dark' char="Enter">enter</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="left-shift dark" toKeyset="lower" char="Invalid">shift</kb-key>
+ <kb-key>Z</kb-key><kb-key>X</kb-key><kb-key>C</kb-key><kb-key>V</kb-key>
+ <kb-key>B</kb-key><kb-key>N</kb-key><kb-key>M</kb-key><kb-key>@</kb-key>
+ <kb-key>!</kb-key><kb-key>/</kb-key>
+ <kb-key class="right-shift dark" toKeyset="lower" char="Invalid">shift</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="mic dark" char="Mic"></kb-key>
+ <kb-key class="dark">.com</kb-key>
+ <kb-key char="Spacebar" class="space dark" toKeyset="upper"></kb-key>
+ <kb-key class="dark">@</kb-key>
+ <kb-key class="hide dark"></kb-key>
+ </kb-row>
+ </kb-keyset>
+
+ <kb-keyset id="lower">
+ <kb-row>
+ <kb-key class="tab dark" char="Tab">tab</kb-key><kb-key>q</kb-key>
+ <kb-key>w</kb-key><kb-key>e</kb-key><kb-key>r</kb-key><kb-key>t</kb-key>
+ <kb-key>y</kb-key><kb-key>u</kb-key><kb-key>i</kb-key><kb-key>o</kb-key>
+ <kb-key>p</kb-key>
+ <kb-key class="backspace dark" char="Backspace" repeat>backspace</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="symbol dark" toKeyset="symbol" char="Invalid">#123</kb-key>
+ <kb-key>a</kb-key><kb-key>s</kb-key><kb-key>d</kb-key><kb-key>f</kb-key>
+ <kb-key>g</kb-key><kb-key>h</kb-key><kb-key>j</kb-key><kb-key>k</kb-key>
+ <kb-key>l</kb-key><kb-key>;</kb-key>
+ <kb-key class='return dark' char="Enter">enter</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="left-shift dark" toKeyset="upper" char="Invalid">shift</kb-key>
+ <kb-key>z</kb-key><kb-key>x</kb-key><kb-key>c</kb-key><kb-key>v</kb-key>
+ <kb-key>b</kb-key><kb-key>n</kb-key><kb-key>m</kb-key><kb-key>,</kb-key>
+ <kb-key>.</kb-key><kb-key>?</kb-key>
+ <kb-key class="right-shift dark" toKeyset="upper" char="Invalid">shift</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="mic dark" char="Mic"></kb-key>
+ <kb-key class="dark">.com</kb-key>
+ <kb-key class="space dark" char="Spacebar"></kb-key>
+ <kb-key class="dark">@</kb-key>
+ <kb-key class="hide dark"></kb-key>
+ </kb-row>
+ </kb-keyset>
+
+ <kb-keyset id="symbol">
+ <kb-row>
+ <kb-key class="tab dark" char="Tab">tab</kb-key><kb-key>1</kb-key>
+ <kb-key>2</kb-key><kb-key>3</kb-key><kb-key>4</kb-key><kb-key>5</kb-key>
+ <kb-key>6</kb-key><kb-key>7</kb-key><kb-key>8</kb-key><kb-key>9</kb-key>
+ <kb-key>0</kb-key>
+ <kb-key class="backspace dark" char="Backspace" repeat>backspace</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="symbol dark" toKeyset="lower" char="Invalid">abc</kb-key>
+ <kb-key>!</kb-key><kb-key>@</kb-key><kb-key>#</kb-key><kb-key>$</kb-key>
+ <kb-key>%</kb-key><kb-key>^</kb-key><kb-key>&</kb-key><kb-key>*</kb-key>
+ <kb-key>(</kb-key><kb-key>)</kb-key>
+ <kb-key class='return dark' char="Enter">enter</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="left-more dark" toKeyset="more" char="Invalid">more</kb-key>
+ <kb-key>/</kb-key><kb-key>-</kb-key><kb-key>'</kb-key><kb-key>"</kb-key>
+ <kb-key>:</kb-key><kb-key>;</kb-key><kb-key>_</kb-key><kb-key>,</kb-key>
+ <kb-key>.</kb-key><kb-key>?</kb-key>
+ <kb-key class="right-more dark" toKeyset="more" char="Invalid">more</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="mic dark" char="Mic"></kb-key>
+ <kb-key class="dark">.com</kb-key>
+ <kb-key class="space dark" char="Spacebar"></kb-key>
+ <kb-key class="dark">@</kb-key>
+ <kb-key class="hide dark"></kb-key>
+ </kb-row>
+ </kb-keyset>
+
+ <kb-keyset id="more">
+ <kb-row>
+ <kb-key class="tab dark" char="Tab">tab</kb-key><kb-key>`</kb-key>
+ <kb-key>~</kb-key><kb-key>&#60</kb-key><kb-key>&#62</kb-key>
+ <kb-key>[</kb-key><kb-key>]</kb-key><kb-key>{</kb-key><kb-key>}</kb-key>
+ <kb-key>\</kb-key><kb-key>|</kb-key>
+ <kb-key class="backspace dark" char="Backspace" repeat>backspace</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="symbol dark" toKeyset="lower" char="Invalid">abc</kb-key>
+ <kb-key>+</kb-key><kb-key>=</kb-key><kb-key></kb-key><kb-key></kb-key>
+ <kb-key></kb-key><kb-key></kb-key><kb-key></kb-key><kb-key></kb-key>
+ <kb-key></kb-key><kb-key></kb-key>
+ <kb-key class='return dark' char="Enter">enter</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="left-more dark" toKeyset="symbol" char="Invalid">#123</kb-key>
+ <kb-key></kb-key><kb-key></kb-key><kb-key></kb-key><kb-key></kb-key>
+ <kb-key></kb-key><kb-key></kb-key><kb-key></kb-key><kb-key></kb-key>
+ <kb-key></kb-key><kb-key></kb-key>
+ <kb-key class="right-more dark" toKeyset="symbol" char="Invalid">#123</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="mic dark" char="Mic"></kb-key>
+ <kb-key class="dark">.com</kb-key>
+ <kb-key class="space dark" char="Spacebar"></kb-key>
+ <kb-key class="dark">@</kb-key>
+ <kb-key class="hide dark"></kb-key>
+ </kb-row>
+ </kb-keyset>
+</template>
diff --git a/ui/keyboard/resources/layout_us.js b/ui/keyboard/resources/layout_us.js
deleted file mode 100644
index 83a0439..0000000
--- a/ui/keyboard/resources/layout_us.js
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview A simple English virtual keyboard implementation.
- */
-
-/**
- * All keys for the rows of the keyboard.
- * NOTE: every row below should have an aspect of 12.6.
- * @type {Array.<Array.<BaseKey>>}
- */
-var KEYS_US = [
- [
- new SvgKey('tab', 'Tab'),
- new Key(C('q'), C('Q'), C('1'), C('`')),
- new Key(C('w'), C('W'), C('2'), C('~')),
- new Key(C('e'), C('E'), C('3'), C('<', 'LessThan')),
- new Key(C('r'), C('R'), C('4'), C('>', 'GreaterThan')),
- new Key(C('t'), C('T'), C('5'), C('[')),
- new Key(C('y'), C('Y'), C('6'), C(']')),
- new Key(C('u'), C('U'), C('7'), C('{')),
- new Key(C('i'), C('I'), C('8'), C('}')),
- new Key(C('o'), C('O'), C('9'), C('\\')),
- new Key(C('p'), C('P'), C('0'), C('|')),
- new SvgKey('backspace', 'Backspace', true /* repeat */)
- ],
- [
- new SymbolKey(),
- new Key(C('a'), C('A'), C('!'), C('+')),
- new Key(C('s'), C('S'), C('@'), C('=')),
- new Key(C('d'), C('D'), C('#'), C(' ')),
- new Key(C('f'), C('F'), C('$'), C(' ')),
- new Key(C('g'), C('G'), C('%'), C(' ')),
- new Key(C('h'), C('H'), C('^'), C(' ')),
- new Key(C('j'), C('J'), C('&', 'Ampersand'), C(' ')),
- new Key(C('k'), C('K'), C('*'), C(' ')),
- new Key(C('l'), C('L'), C('('), C(' ')),
- new Key(C(';'), C('\''), C(')'), C(' ')),
- new SvgKey('return', 'Enter')
- ],
- [
- new ShiftKey('left-shift'),
- new Key(C('z'), C('Z'), C('/'), C(' ')),
- new Key(C('x'), C('X'), C('-'), C(' ')),
- new Key(C('c'), C('C'), C('\''), C(' ')),
- new Key(C('v'), C('V'), C('\"'), C(' ')),
- new Key(C('b'), C('B'), C(':'), C(' ')),
- new Key(C('n'), C('N'), C(';'), C(' ')),
- new Key(C('m'), C('M'), C('_'), C(' ')),
- new Key(C(','), C('@'), C(','), C(' ')),
- new Key(C('.'), C('!'), C('.'), C(' ')),
- new Key(C('?'), C('/'), C('?'), C(' ')),
- new ShiftKey('right-shift')
- ],
- [
- new MicKey(),
- new DotComKey(),
- new SpecialKey('space', ' ', 'Spacebar'),
- new SpecialKey('at', '@', '@'),
- new HideKeyboardKey()
- ]
-];
-
-// Add layout to KEYBOARDS, which is defined in common.js
-KEYBOARDS['us'] = {
- 'definition': KEYS_US,
- 'aspect': 4.50
-};
diff --git a/ui/keyboard/resources/main.css b/ui/keyboard/resources/main.css
index 0e96e41..172b9f3 100644
--- a/ui/keyboard/resources/main.css
+++ b/ui/keyboard/resources/main.css
@@ -14,111 +14,31 @@ body {
padding: 0;
}
-div.main {
+kb-keyboard {
-webkit-box-orient: vertical;
display: -webkit-box;
max-width: 1280px;
+ width: 1280px;
}
-div.keyboard {
- -webkit-box-flex: 1;
- display: -webkit-box;
- margin: 0 auto;
- text-align: center;
-}
-
-div.rows {
- -webkit-box-flex: 1;
- -webkit-box-orient: vertical;
- display: -webkit-box;
- margin-bottom: 5px;
- text-align: center;
-}
-
-div.row {
- -webkit-box-flex: 1;
- display: -webkit-box;
- margin-right: 5px;
- margin-top: 5px;
-}
-
-div.row > div {
- -webkit-box-flex: 1;
- display: -webkit-box;
-}
-
-.panel {
- border: 0;
- clear: both;
- margin-left: 5px;
- text-align: left;
-}
-
-.backspace > div {
- background-image: url('images/del.svg');
-}
-
-.tab > div {
- background-image: url('images/tab.svg');
-}
-
-.return > div {
- background-image: url('images/ret.svg');
-}
-
-.mic > div {
- background-image: url('images/mic.svg');
-}
-
-.mic.start > div {
- background-image: url('images/mic-green.svg');
-}
-
-.button {
- background: -webkit-linear-gradient(rgb(90, 97, 111), rgb(80, 86, 98));
-}
-.button:active {
- background: -webkit-linear-gradient(rgb(80, 86, 98), rgb(90, 97, 111));
-}
-
-.auxiliary:active {
- background: -webkit-linear-gradient(rgb(90, 97, 111), rgb(80, 86, 98));
-}
-
-.key {
- -webkit-box-flex: 1;
+kb-key {
background-color: #444444;
border-top: 1px solid #666666;
border-radius: 3px;
- /* Reserving equivalent space to .key:active so
- keys don't shift when selected. */
- /* Do not use box shadow until performance improves
- * http://code.google.com/p/chromium/issues/detail?id=99045
- box-shadow: 0px 1px 1px #000;
- */
color: #ffffff;
- display: -webkit-box;
font-family: sans-serif;
font-weight: 100;
margin-left: 5px;
- position: relative;
}
-.key.dark {
+kb-key.dark {
background-color: #333333;
}
-.key > div {
- bottom: 0;
- left: 0;
- margin: auto;
- position: absolute;
- right: 0;
- top: 0;
-}
-
-.key:active {
- background-color: #acacac;
+#upper .left-shift,
+#upper .right-shift,
+.active {
+ background-color: #acacac !important;
border-top: 1px solid rgba(125,125,125,0.5);
/* Do not use box shadow until performance improves
* http://code.google.com/p/chromium/issues/detail?id=99045
@@ -126,36 +46,6 @@ div.row > div {
*/
}
-div.moddown.dark {
- background-color: #acacac;
- border-color: rgb(48, 74, 155);
-}
-
-.image-key {
- background-position: center center;
- background-repeat: no-repeat;
- background-size: contain;
- height: 100%;
- width: 100%;
-}
-
-.text-key {
- height: 1.2em;
-}
-
-
-.shift > div.image-key {
- background-image: url('images/shift.svg');
-}
-
-.moddown.shift > div.image-key {
- background-image: url('images/shift-down.svg');
-}
-
-.hide > div {
- background-image: url('images/keyboard.svg');
-}
-
.at,
.com,
.comma,
@@ -163,34 +53,56 @@ div.moddown.dark {
.mic,
.period,
.tab {
- -webkit-box-flex: 1.3;
+ -webkit-box-flex: 1.3 !important;
}
.symbol,
.return {
- -webkit-box-flex: 1.5;
+ -webkit-box-flex: 1.5 !important;
}
.backspace {
- -webkit-box-flex: 1.7;
+ -webkit-box-flex: 1.7 !important;
}
-.left-shift {
- -webkit-box-flex: 1.4;
+.left-shift,
+.left-more {
+ -webkit-box-flex: 1.4 !important;
}
-.right-shift {
- -webkit-box-flex: 1.6;
+.right-shift,
+.right-more {
+ -webkit-box-flex: 1.6 !important;
}
.space {
- -webkit-box-flex: 4.8;
+ -webkit-box-flex: 4.8 !important;
}
.bar {
- -webkit-box-flex: 0.6;
+ -webkit-box-flex: 0.6 !important;
+}
+
+.backspace,
+.tab,
+.return,
+.left-shift,
+.right-shift,
+.left-more,
+.right-more,
+.symbol,
+.moddown.shift {
+ font-size: 80%;
}
-.nodisplay {
- display: none;
+.mic {
+ background-image: url('images/mic.svg');
+}
+
+.audio .mic {
+ background-image: url('images/mic-green.svg');
+}
+
+.hide {
+ background-image: url('images/keyboard.svg');
}
diff --git a/ui/keyboard/resources/main.js b/ui/keyboard/resources/main.js
index a628cad..9ae319b 100644
--- a/ui/keyboard/resources/main.js
+++ b/ui/keyboard/resources/main.js
@@ -1,192 +1,39 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-/**
- * @fileoverview A simple virtual keyboard implementation.
- */
-
-/**
- * The ratio of the row height to the font size.
- * @type {number}
- */
-/** @const */ var kFontSizeRatio = 3.5;
-
-/**
- * Alias for document.getElementById.
- * @param {string} id The ID of the element to find.
- * @return {HTMLElement} The found element or null if not found.
- */
-function $(id) {
- return document.getElementById(id);
-}
-
-/**
- * Return the id attribute of the keyboard element for the given layout.
- * @param {string} layout The keyboard layout.
- * @return {string} The id attribute of the keyboard element.
- */
-function getKeyboardId(layout) {
- return 'keyboard_' + layout;
-}
-
-/**
- * Return the aspect ratio of the current keyboard.
- * @return {number} The aspect ratio of the current keyboard.
- */
-function getKeyboardAspect() {
- return KEYBOARDS[currentKeyboardLayout]['aspect'];
-}
-
-/**
- * Calculate the height of the keyboard based on the size of the page.
- * @return {number} The height of the keyboard in pixels.
- */
-function getKeyboardHeight() {
+var onResize = function() {
var x = window.innerWidth;
var y = window.innerHeight;
- return (x > getKeyboardAspect() * y) ?
- y : Math.floor(x / getKeyboardAspect());
-}
-
-/**
- * Create a DOM of the keyboard rows for the given keyboard layout.
- * Do nothing if the DOM is already created.
- * @param {string} layout The keyboard layout for which rows are created.
- * @param {Element} element The DOM Element to which rows are appended.
- * @param {boolean} autoPadding True if padding needs to be added to both side
- * of the rows that have less keys.
- */
-function initRows(layout, element, autoPadding) {
- var keyboard = KEYBOARDS[layout];
- if ('rows' in keyboard) {
- return;
- }
- var def = keyboard['definition'];
- var rows = [];
- for (var i = 0; i < def.length; ++i) {
- rows.push(new Row(i, def[i]));
- }
- keyboard['rows'] = rows;
-
- var maxRowLength = -1;
- for (var i = 0; i < rows.length; ++i) {
- if (rows[i].length > maxRowLength) {
- maxRowLength = rows[i].length;
- }
- }
-
- // A div element which holds rows for the layout.
- var rowsDiv = document.createElement('div');
- rowsDiv.className = 'rows';
- for (var i = 0; i < rows.length; ++i) {
- var rowDiv = rows[i].makeDOM();
- if (autoPadding && rows[i].length < maxRowLength) {
- var padding = 50 * (maxRowLength - rows[i].length) / maxRowLength;
- rowDiv.style.paddingLeft = padding + '%';
- rowDiv.style.paddingRight = padding + '%';
- }
- rowsDiv.appendChild(rowDiv);
- rows[i].showMode(currentMode);
- }
- keyboard['rowsDiv'] = rowsDiv;
- element.appendChild(rowsDiv);
-}
-
-/**
- * Create a DOM of the keyboard for the given keyboard layout.
- * Do nothing if the DOM is already created.
- * @param {string} layout The keyboard layout for which keyboard is created.
- * @param {Element} element The DOM Element to which keyboard is appended.
- */
-function initKeyboard(layout, element) {
- var keyboard = KEYBOARDS[layout];
- if (!keyboard || keyboard['keyboardDiv']) {
- return;
- }
- var keyboardDiv = document.createElement('div');
- keyboardDiv.id = getKeyboardId(layout);
- keyboardDiv.className = 'keyboard';
- initRows(layout, keyboardDiv);
- keyboard['keyboardDiv'] = keyboardDiv;
- window.onresize();
- element.appendChild(keyboardDiv);
-}
-
-/**
- * Resize the keyboard according to the new window size.
- */
-window.onresize = function() {
- var keyboardDiv = KEYBOARDS[currentKeyboardLayout]['keyboardDiv'];
- var height = getKeyboardHeight();
- keyboardDiv.style.height = height + 'px';
- var mainDiv = $('main');
- mainDiv.style.width = Math.floor(getKeyboardAspect() * height) + 'px';
- var rowsLength = KEYBOARDS[currentKeyboardLayout]['rows'].length;
- keyboardDiv.style.fontSize = (height / kFontSizeRatio / rowsLength) + 'px';
+ var height = (x > ASPECT_RATIO * y) ? y : Math.floor(x / ASPECT_RATIO);
+ keyboard.style.height = height + 'px';
+ keyboard.style.width = Math.floor(ASPECT_RATIO * height) + 'px';
+ keyboard.style.fontSize = (height / FONT_SIZE_RATIO / ROW_LENGTH) + 'px';
};
/**
- * Init the keyboard.
+ * Send the given key to chrome.
*/
-var mainDiv = null;
+function sendKey(key) {
+ var keyIdentifier = key;
-/**
- * Initialize keyboard.
- */
-window.onload = function() {
- var body = $('b');
-
- // Catch all unhandled touch events and prevent default, to prevent the
- // keyboard from responding to gestures like double tap.
- function disableGestures(evt) {
- evt.preventDefault();
+ // Fix up some keys to their respective identifiers for convenience.
+ if (keyIdentifier == ' ') {
+ keyIdentifier = 'Spacebar';
}
- body.addEventListener('touchstart', disableGestures);
- body.addEventListener('touchmove', disableGestures);
- body.addEventListener('touchend', disableGestures);
- mainDiv = document.createElement('div');
- mainDiv.className = 'main';
- mainDiv.id = 'main';
- body.appendChild(mainDiv);
+ var keyEvent = {
+ keyIdentifier: keyIdentifier
+ };
- initKeyboard(currentKeyboardLayout, mainDiv);
-
- window.onhashchange();
+ sendKeyEvent(keyEvent);
};
-/**
- * Switch the keyboard layout based on the current URL hash.
- */
-window.onhashchange = function() {
- var oldLayout = currentKeyboardLayout;
- var newLayout = location.hash.replace(/^#/, '');
- if (oldLayout == newLayout) {
- return;
- }
-
- if (KEYBOARDS[newLayout] === undefined) {
- // Unsupported layout.
- newLayout = 'us';
- }
- currentKeyboardLayout = newLayout;
+addEventListener('WebComponentsReady', function() {
+ keyboard.appendChild(
+ keysets.content.body.firstElementChild.createInstance());
+});
- var mainDiv = $('main');
- initKeyboard(currentKeyboardLayout, mainDiv);
+addEventListener('resize', onResize);
- [newLayout, oldLayout].forEach(function(layout) {
- var visible = (layout == newLayout);
- var keyboardDiv = KEYBOARDS[layout]['keyboardDiv'];
- keyboardDiv.className = visible ? 'keyboard' : 'nodisplay';
- var canvas = KEYBOARDS[layout]['canvas'];
- if (canvas !== undefined) {
- if (!visible) {
- canvas.clear();
- }
- }
- if (visible) {
- window.onresize();
- }
- });
-};
+addEventListener('load', onResize);
diff --git a/ui/keyboard/resources/manifest.json b/ui/keyboard/resources/manifest.json
index f07121c..93d4a8f 100644
--- a/ui/keyboard/resources/manifest.json
+++ b/ui/keyboard/resources/manifest.json
@@ -11,5 +11,6 @@
"permissions": [
"audioCapture",
"experimental"
- ]
+ ],
+ "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
}
diff --git a/ui/keyboard/resources/polymer.min.js b/ui/keyboard/resources/polymer.min.js
new file mode 100644
index 0000000..915f7d9
--- /dev/null
+++ b/ui/keyboard/resources/polymer.min.js
@@ -0,0 +1,5 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+<include src="../../../third_party/polymer/polymer.min.js"></include>
diff --git a/ui/keyboard/resources/voice_input.js b/ui/keyboard/resources/voice_input.js
new file mode 100644
index 0000000..bb8d9f7
--- /dev/null
+++ b/ui/keyboard/resources/voice_input.js
@@ -0,0 +1,71 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function VoiceInput(keyboard) {
+ this.finaResult_ = null;
+ this.recognizing_ = false;
+ this.keyboard_ = keyboard;
+ this.recognition_ = new webkitSpeechRecognition();
+ this.recognition_.onstart = this.onStartHandler.bind(this);
+ this.recognition_.onresult = this.onResultHandler.bind(this);
+ this.recognition_.onerror = this.onErrorHandler.bind(this);
+ this.recognition_.onend = this.onEndHandler.bind(this);
+};
+
+VoiceInput.prototype = {
+ /**
+ * Event handler for mouse/touch down events.
+ */
+ onDown: function() {
+ if (this.recognizing_) {
+ this.recognition_.stop();
+ return;
+ }
+ this.recognition_.start();
+ },
+
+ /**
+ * Speech recognition started. Change mic key's icon.
+ */
+ onStartHandler: function() {
+ this.recognizing_ = true;
+ this.finalResult_ = '';
+ if (!this.keyboard_.classList.contains('audio'))
+ this.keyboard_.classList.add('audio');
+ },
+
+ /**
+ * Speech recognizer returns a result.
+ * @param{Event} e The SpeechRecognition event that is raised each time
+ * there
+ * are any changes to interim or final results.
+ */
+ onResultHandler: function(e) {
+ for (var i = e.resultIndex; i < e.results.length; i++) {
+ if (e.results[i].isFinal)
+ this.finalResult_ = e.results[i][0].transcript;
+ }
+ for (var i = 0; i < this.finalResult_.length; i++) {
+ sendKey(this.finalResult_.charAt(i));
+ }
+ },
+
+ /**
+ * Speech recognizer returns an error.
+ * @param{Event} e The SpeechRecognitionError event that is raised each time
+ * there is an error.
+ */
+ onErrorHandler: function(e) {
+ console.error('error code = ' + e.error);
+ },
+
+ /**
+ * Speech recognition ended. Reset mic key's icon.
+ */
+ onEndHandler: function() {
+ if (this.keyboard_.classList.contains('audio'))
+ this.keyboard_.classList.remove('audio');
+ this.recognizing_ = false;
+ }
+};
diff --git a/ui/keyboard/resources/webui/constants.js b/ui/keyboard/resources/webui/constants.js
new file mode 100644
index 0000000..ea620c6
--- /dev/null
+++ b/ui/keyboard/resources/webui/constants.js
@@ -0,0 +1,26 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/**
+ * Aspect ratio of keyboard.
+ * @type {number}
+ */
+var ASPECT_RATIO = 2.0;
+
+/**
+ * Ratio of key height and font size.
+ * @type {number}
+ */
+var FONT_SIZE_RATIO = 3.5;
+
+/**
+ * The number of rows in each keyset.
+ * @type {number}
+ */
+// TODO(bshe): The number of rows should equal to the number of kb-row elements
+// in kb-keyset. Remove this variable once figure out how to calculate the
+// number from keysets.
+
+var ROW_LENGTH = 4;
diff --git a/ui/keyboard/resources/webui/keysets.html b/ui/keyboard/resources/webui/keysets.html
new file mode 100644
index 0000000..91c7bf2
--- /dev/null
+++ b/ui/keyboard/resources/webui/keysets.html
@@ -0,0 +1,119 @@
+<!--
+ -- Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ -- Use of this source code is governed by a BSD-style license that can be
+ -- found in the LICENSE file.
+ -->
+
+<template>
+ <kb-keyset id="upper" toKeyset="lower">
+ <kb-row>
+ <kb-key>Q</kb-key><kb-key>W</kb-key><kb-key>E</kb-key><kb-key>R</kb-key>
+ <kb-key>T</kb-key><kb-key>Y</kb-key><kb-key>U</kb-key><kb-key>I</kb-key>
+ <kb-key>O</kb-key><kb-key>P</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="tab dark" char="Tab">tab</kb-key>
+ <kb-key>A</kb-key><kb-key>S</kb-key><kb-key>D</kb-key><kb-key>F</kb-key>
+ <kb-key>G</kb-key><kb-key>H</kb-key><kb-key>J</kb-key><kb-key>K</kb-key>
+ <kb-key>L</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="left-shift dark" toKeyset="lower" char="Invalid">shift</kb-key>
+ <kb-key>Z</kb-key><kb-key>X</kb-key><kb-key>C</kb-key><kb-key>V</kb-key>
+ <kb-key>B</kb-key><kb-key>N</kb-key><kb-key>M</kb-key>
+ <kb-key class="backspace dark" char="Backspace" repeat>backspace</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="mic dark" char="Mic"></kb-key>
+ <kb-key class="symbol dark" toKeyset="symbol" char="Invalid">#123</kb-key>
+ <kb-key class="dark">.com</kb-key>
+ <kb-key class="space dark" char="Spacebar"></kb-key>
+ <kb-key class="dark">@</kb-key>
+ <kb-key class='return dark' char="Enter">enter</kb-key>
+ </kb-row>
+ </kb-keyset>
+
+ <kb-keyset id="lower">
+ <kb-row>
+ <kb-key>q</kb-key><kb-key>w</kb-key><kb-key>e</kb-key><kb-key>r</kb-key>
+ <kb-key>t</kb-key><kb-key>y</kb-key><kb-key>u</kb-key><kb-key>i</kb-key>
+ <kb-key>o</kb-key><kb-key>p</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="tab dark" char="Tab">tab</kb-key>
+ <kb-key>a</kb-key><kb-key>s</kb-key><kb-key>d</kb-key><kb-key>f</kb-key>
+ <kb-key>g</kb-key><kb-key>h</kb-key><kb-key>j</kb-key><kb-key>k</kb-key>
+ <kb-key>l</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="left-shift dark" toKeyset="upper" char="Invalid">shift</kb-key>
+ <kb-key>z</kb-key><kb-key>x</kb-key><kb-key>c</kb-key><kb-key>v</kb-key>
+ <kb-key>b</kb-key><kb-key>n</kb-key><kb-key>m</kb-key>
+ <kb-key class="backspace dark" char="Backspace" repeat>backspace</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="mic dark" char="Mic"></kb-key>
+ <kb-key class="symbol dark" toKeyset="symbol" char="Invalid">#123</kb-key>
+ <kb-key class="dark">.com</kb-key>
+ <kb-key class="space dark" char="Spacebar"></kb-key>
+ <kb-key class="dark">@</kb-key>
+ <kb-key class='return dark' char="Enter">enter</kb-key>
+ </kb-row>
+ </kb-keyset>
+
+ <kb-keyset id="symbol">
+ <kb-row>
+ <kb-key>1</kb-key><kb-key>2</kb-key><kb-key>3</kb-key><kb-key>4</kb-key>
+ <kb-key>5</kb-key><kb-key>6</kb-key><kb-key>7</kb-key><kb-key>8</kb-key>
+ <kb-key>9</kb-key><kb-key>0</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="tab dark" char="Tab">tab</kb-key>
+ <kb-key>!</kb-key><kb-key>@</kb-key><kb-key>#</kb-key><kb-key>$</kb-key>
+ <kb-key>%</kb-key><kb-key>^</kb-key><kb-key>&</kb-key><kb-key>*</kb-key>
+ <kb-key>(</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="left-more dark" toKeyset="more" char="Invalid">more</kb-key>
+ <kb-key>)</kb-key><kb-key>/</kb-key><kb-key>-</kb-key><kb-key>'</kb-key>
+ <kb-key>"</kb-key><kb-key>:</kb-key><kb-key>;</kb-key>
+ <kb-key class="backspace dark" char="Backspace" repeat>backspace</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="mic dark" char="Mic"></kb-key>
+ <kb-key class="symbol dark" toKeyset="lower" char="Invalid">abc</kb-key>
+ <kb-key class="dark">.com</kb-key>
+ <kb-key class="space dark" char="Spacebar"></kb-key>
+ <kb-key class="dark">@</kb-key>
+ <kb-key class='return dark' char="Enter">enter</kb-key>
+ </kb-row>
+ </kb-keyset>
+
+ <kb-keyset id="more">
+ <kb-row>
+ <kb-key>_</kb-key><kb-key>`</kb-key><kb-key>~</kb-key>
+ <kb-key>&#60</kb-key><kb-key>&#62</kb-key><kb-key>[</kb-key>
+ <kb-key>]</kb-key><kb-key>{</kb-key><kb-key>}</kb-key><kb-key>\</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="tab dark" char="Tab">tab</kb-key>
+ <kb-key>|</kb-key><kb-key>+</kb-key><kb-key>=</kb-key><kb-key></kb-key>
+ <kb-key></kb-key><kb-key></kb-key><kb-key></kb-key><kb-key></kb-key>
+ <kb-key></kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="left-more dark" toKeyset="symbol" char="Invalid">#123</kb-key>
+ <kb-key></kb-key><kb-key></kb-key><kb-key></kb-key><kb-key></kb-key>
+ <kb-key></kb-key><kb-key></kb-key><kb-key></kb-key>
+ <kb-key class="backspace dark" char="Backspace" repeat>backspace</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="mic dark" char="Mic"></kb-key>
+ <kb-key class="symbol dark" toKeyset="lower" char="Invalid">abc</kb-key>
+ <kb-key class="dark">.com</kb-key>
+ <kb-key class="space dark" char="Spacebar"></kb-key>
+ <kb-key class="dark">@</kb-key>
+ <kb-key class='return dark' char="Enter">enter</kb-key>
+ </kb-row>
+ </kb-keyset>
+</template>
diff --git a/ui/keyboard/resources/webui/layout_us.js b/ui/keyboard/resources/webui/layout_us.js
deleted file mode 100644
index 6c9565c..0000000
--- a/ui/keyboard/resources/webui/layout_us.js
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview A simple English virtual keyboard implementation.
- */
-
-/**
- * All keys for the rows of the keyboard.
- * NOTE: every row below should have an aspect of 12.6.
- * @type {Array.<Array.<BaseKey>>}
- */
-var KEYS_US = [
- [
- new Key(C('q'), C('Q'), C('1'), C('`')),
- new Key(C('w'), C('W'), C('2'), C('~')),
- new Key(C('e'), C('E'), C('3'), C('<', 'LessThan')),
- new Key(C('r'), C('R'), C('4'), C('>', 'GreaterThan')),
- new Key(C('t'), C('T'), C('5'), C('[')),
- new Key(C('y'), C('Y'), C('6'), C(']')),
- new Key(C('u'), C('U'), C('7'), C('{')),
- new Key(C('i'), C('I'), C('8'), C('}')),
- new Key(C('o'), C('O'), C('9'), C('\'')),
- new Key(C('p'), C('P'), C('0'), C('|')),
- ],
- [
- new SvgKey('tab', 'Tab'),
- new Key(C('a'), C('A'), C('!'), C('+')),
- new Key(C('s'), C('S'), C('@'), C('=')),
- new Key(C('d'), C('D'), C('#'), C(' ')),
- new Key(C('f'), C('F'), C('$'), C(' ')),
- new Key(C('g'), C('G'), C('%'), C(' ')),
- new Key(C('h'), C('H'), C('^'), C(' ')),
- new Key(C('j'), C('J'), C('&', 'Ampersand'), C(' ')),
- new Key(C('k'), C('K'), C('*'), C('#')),
- new Key(C('l'), C('L'), C('('), C(' ')),
- ],
- [
- new ShiftKey('left_shift'),
- new Key(C('z'), C('Z'), C('/'), C(' ')),
- new Key(C('x'), C('X'), C('-'), C(' ')),
- new Key(C('c'), C('C'), C('\''), C(' ')),
- new Key(C('v'), C('V'), C('"'), C(' ')),
- new Key(C('b'), C('B'), C(':'), C('.')),
- new Key(C('n'), C('N'), C(';'), C(' ')),
- new Key(C('m'), C('M'), C('_'), C(' ')),
- new SvgKey('backspace', 'Backspace', true /* repeat */)
- ],
- [
- new MicKey(),
- new SymbolKey(),
- new SpecialKey('comma', ',', ','),
- new SpecialKey('space', ' ', 'Spacebar'),
- new SpecialKey('period', '.', '.'),
- new SvgKey('return', 'Enter')
- ]
-];
-
-// Add layout to KEYBOARDS, which is defined in common.js
-KEYBOARDS['us'] = {
- 'definition': KEYS_US,
- 'aspect': 2.00,
-};
diff --git a/ui/keyboard/resources/webui/main.css b/ui/keyboard/resources/webui/main.css
index 0a5e3b5..66244b1 100644
--- a/ui/keyboard/resources/webui/main.css
+++ b/ui/keyboard/resources/webui/main.css
@@ -7,189 +7,96 @@
body {
-webkit-box-pack: center;
-webkit-user-select: none;
- color: white;
+ background-color: #0b0b0b;
display: -webkit-box;
margin: 0;
overflow: hidden;
padding: 0;
}
-div.main {
+kb-keyboard {
-webkit-box-orient: vertical;
- background: -webkit-linear-gradient(#bababa, #868686) no-repeat;
display: -webkit-box;
}
-div.keyboard {
- -webkit-box-flex: 1;
- display: -webkit-box;
- margin: 0 auto;
- text-align: center;
-}
-
-div.rows {
- -webkit-box-flex: 1;
- -webkit-box-orient: vertical;
- display: -webkit-box;
- margin-bottom: 3px;
- text-align: center;
-}
-
-div.row {
- -webkit-box-flex: 1;
- display: -webkit-box;
- margin-right: 3px;
- margin-top: 3px;
-}
-
-div.row > div {
- -webkit-box-flex: 1;
- display: -webkit-box;
-}
-
-.panel {
- border: 0;
- clear: both;
- margin-left: 5px;
- text-align: left;
-}
-
-.backspace > div {
- background-image: url('images/del.svg');
-}
-
-.tab > div {
- background-image: url('images/tab.svg');
-}
-
-.return > div {
- background-image: url('images/ret.svg');
-}
-
-.mic > div {
- background-image: url('images/mic.svg');
-}
-
-.mic.start > div {
- background-image: url('images/mic-green.svg');
-}
-
-.button {
- background: -webkit-linear-gradient(rgb(90, 97, 111), rgb(80, 86, 98));
-}
-.button:active {
- background: -webkit-linear-gradient(rgb(80, 86, 98), rgb(90, 97, 111));
-}
-
-.auxiliary:active {
- background: -webkit-linear-gradient(rgb(90, 97, 111), rgb(80, 86, 98));
-}
-
-.key {
- -webkit-box-flex: 1;
- background: -webkit-linear-gradient(#fff, #cacaca);
- border: 1px solid transparent;
+kb-key {
+ background-color: #444444;
+ border-top: 1px solid #666666;
border-radius: 3px;
- /* Reserving equivalent space to .key:active so
- keys don't shift when selected. */
- /* Do not use box shadow until performance improves
- * http://code.google.com/p/chromium/issues/detail?id=99045
- box-shadow: 0px 1px 1px #000;
- */
- color: #535353;
- display: -webkit-box;
+ color: #ffffff;
font-family: sans-serif;
font-weight: 100;
margin-left: 3px;
- position: relative;
}
-.key > div {
- bottom: 0;
- left: 0;
- margin: auto;
- position: absolute;
- right: 0;
- top: 0;
+kb-key.dark {
+ background-color: #333333;
}
-.key:active {
- background: -webkit-linear-gradient(#d6d6d6, #acacac);
- border: 1px solid rgba(125,125,125,0.5);
+#upper .left-shift,
+#upper .right-shift,
+.active {
+ background-color: #acacac !important;
+ border-top: 1px solid rgba(125,125,125,0.5);
/* Do not use box shadow until performance improves
* http://code.google.com/p/chromium/issues/detail?id=99045
box-shadow: 0px 0px 15px #fff;
*/
}
-div.moddown {
- background: -webkit-linear-gradient(#d6d6d6, #acacac);
- border-color: rgb(48, 74, 155);
-}
-
-.image-key {
- background-position: center center;
- background-repeat: no-repeat;
- background-size: contain;
- height: 100%;
- width: 100%;
-}
-
-.text-key {
- height: 1.2em;
-}
-
-
-.shift > div.image-key {
- background-image: url('images/shift.svg');
-}
-
-.moddown.shift > div.image-key {
- background-image: url('images/shift-down.svg');
-}
-
-.hide > div {
- background-image: url('images/keyboard.svg');
-}
-
.at,
.com,
.comma,
.hide,
.mic,
-.period {
- -webkit-box-flex: 1.3;
+.period,
+.tab {
+ -webkit-box-flex: 1.3 !important;
}
.symbol,
-.shift {
- -webkit-box-flex: 1.4;
-}
-
.return {
- -webkit-box-flex: 1.5;
+ -webkit-box-flex: 1.5 !important;
}
.backspace {
- -webkit-box-flex: 1.6;
+ -webkit-box-flex: 1.7 !important;
}
-.left-shift {
- -webkit-box-flex: 1.8;
+.left-shift,
+.left-more {
+ -webkit-box-flex: 1.4 !important;
}
-.right-shift {
- -webkit-box-flex: 2.0;
+.right-shift,
+.right-more {
+ -webkit-box-flex: 1.6 !important;
}
.space {
- -webkit-box-flex: 4.8;
+ -webkit-box-flex: 4.8 !important;
}
.bar {
- -webkit-box-flex: 0.6;
+ -webkit-box-flex: 0.6 !important;
}
-.nodisplay {
- display: none;
+.backspace,
+.tab,
+.return,
+.left-shift,
+.right-shift,
+.left-more,
+.right-more,
+.symbol,
+.moddown.shift {
+ font-size: 80%;
+}
+
+.mic {
+ background-image: url('images/mic.svg');
+}
+
+.audio .mic {
+ background-image: url('images/mic-green.svg');
}