| Index: chrome/browser/resources/keyboard/common.js
|
| diff --git a/chrome/browser/resources/keyboard/common.js b/chrome/browser/resources/keyboard/common.js
|
| index a3dff78eca727ce3e482ba347865a5b989f48d01..ca7ca4cdeb2c825fe5aedf9350da9cad74b09d2c 100644
|
| --- a/chrome/browser/resources/keyboard/common.js
|
| +++ b/chrome/browser/resources/keyboard/common.js
|
| @@ -47,6 +47,18 @@ var REPEAT_DELAY_MSEC = 500;
|
| var REPEAT_INTERVAL_MSEC = 50;
|
|
|
| /**
|
| + * The keyboard layout name currently in use.
|
| + * @type {string}
|
| + */
|
| +var currentKeyboardLayout = 'us';
|
| +
|
| +/**
|
| + * The popup keyboard layout name currently in use.
|
| + * @type {string}
|
| + */
|
| +var currentPopupName = '';
|
| +
|
| +/**
|
| * A structure to track the currently repeating key on the keyboard.
|
| */
|
| var repeatKey = {
|
| @@ -81,6 +93,31 @@ var repeatKey = {
|
| };
|
|
|
| /**
|
| + * An array to track the currently touched keys on the popup keyboard.
|
| + */
|
| +var touchedKeys = [];
|
| +
|
| +/**
|
| + * Set the keyboard mode.
|
| + * @param {string} mode The new mode.
|
| + * @return {void}
|
| + */
|
| +function setMode(mode) {
|
| + var rows = KEYBOARDS[currentKeyboardLayout]['rows'];
|
| + for (var i = 0; i < rows.length; ++i) {
|
| + rows[i].showMode(mode);
|
| + }
|
| +
|
| + if (!currentPopupName) {
|
| + return;
|
| + }
|
| + var popupRows = KEYBOARDS[currentPopupName]['rows'];
|
| + for (var i = 0; i < popupRows.length; ++i) {
|
| + popupRows[i].showMode(mode);
|
| + }
|
| +}
|
| +
|
| +/**
|
| * Transition the mode according to the given transition.
|
| * @param {string} transition The transition to take.
|
| * @return {void}
|
| @@ -214,8 +251,14 @@ function setupKeyEventHandlers(key, element, handlers) {
|
| }
|
|
|
| if (keyLongHandler) {
|
| + // Copy the current state of event because |evt| can be modified before
|
| + // |keyLongHandler| is called.
|
| + var evt2 = {};
|
| + for (var name in evt) {
|
| + evt2[name] = evt[name];
|
| + }
|
| key.longPressTimer = setTimeout(function() {
|
| - keyLongHandler(evt),
|
| + keyLongHandler(evt2),
|
| clearTimeout(key.longPressTimer);
|
| delete key.longPressTimer;
|
| key.pressed = false;
|
| @@ -252,6 +295,10 @@ function setupKeyEventHandlers(key, element, handlers) {
|
| };
|
|
|
| var outHandler = function(evt) {
|
| + if (evt.target != evt.currentTarget ||
|
| + evt.toElement.parentNode == evt.fromElement) {
|
| + return;
|
| + }
|
| // Reset key press state if the point goes out of the element.
|
| key.pressed = false;
|
| // Reset long-press timer.
|
| @@ -285,12 +332,123 @@ function sendKeyFunction(key) {
|
| }
|
|
|
| /**
|
| + * Dispatch custom events to the elements at the touch points.
|
| + * touchpointmove events are dispatched responding to a touchmove and
|
| + * touchpointend events responding to a touchend event respectively.
|
| + * @param {UIEvent} evt The touch event that contains touch points information.
|
| + * @return {void}
|
| + */
|
| +function dispatchTouchPointEvent(evt) {
|
| + var type = null;
|
| + var touches = null;
|
| + if (evt.type == 'touchmove') {
|
| + type = 'touchpointmove';
|
| + touches = evt.touches;
|
| + } else if (evt.type == 'touchend') {
|
| + type = 'touchpointend';
|
| + touches = evt.changedTouches;
|
| + } else {
|
| + return;
|
| + }
|
| +
|
| + for (var i = 0; i < touches.length; ++i) {
|
| + var dispatchedEvent = document.createEvent('Event');
|
| + dispatchedEvent.initEvent(type, true, false);
|
| + var touch = touches[i];
|
| + var key = document.elementFromPoint(touch.screenX, touch.screenY);
|
| + if (key) {
|
| + key.dispatchEvent(dispatchedEvent);
|
| + }
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * Handle a touch move event on the key to make changes to the popup keyboard.
|
| + * @param {UIEvent} evt The UI event which triggered the touch move.
|
| + * @return {void}
|
| +*/
|
| +function trackTouchMoveForPopup(evt) {
|
| + var previous = touchedKeys;
|
| + touchedKeys = [];
|
| + dispatchTouchPointEvent(evt);
|
| + for (var i = 0; i < previous.length; ++i) {
|
| + if (touchedKeys.indexOf(previous[i]) == -1) {
|
| + previous[i].classList.remove('highlighted');
|
| + }
|
| + }
|
| + for (var i = 0; i < touchedKeys.length; ++i) {
|
| + touchedKeys[i].classList.add('highlighted');
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * Handle a touch end event on the key to make changes to the popup keyboard.
|
| + * @param {UIEvent} evt The UI event which triggered the touch end.
|
| + * @return {void}
|
| +*/
|
| +function trackTouchEndForPopup(evt) {
|
| + for (var i = 0; i < touchedKeys.length; ++i) {
|
| + touchedKeys[i].classList.remove('highlighted');
|
| + }
|
| + dispatchTouchPointEvent(evt);
|
| + hidePopupKeyboard();
|
| +
|
| + touchedKeys = [];
|
| + evt.target.removeEventListener('touchmove', trackTouchMoveForPopup);
|
| + evt.target.removeEventListener('touchend', trackTouchEndForPopup);
|
| +}
|
| +
|
| +/**
|
| * Show the popup keyboard.
|
| * @param {string} name The name of the popup keyboard.
|
| + * @return {void}
|
| */
|
| -function showPopupKeyboard(name) {
|
| - // TODO(mazda): Implement this function.
|
| - console.warn('Popup keyboard is not implemented yet.');
|
| +function showPopupKeyboard(name, evt) {
|
| + var popupDiv = document.getElementById('popup');
|
| + if (popupDiv.style.visibility == 'visible') {
|
| + return;
|
| + }
|
| +
|
| + // Reinitialize the rows of the popup keyboard
|
| + if (currentPopupName != name) {
|
| + while (popupDiv.firstChild) {
|
| + popupDiv.removeChild(popupDiv.firstChild);
|
| + }
|
| + if (currentPopupName in KEYBOARDS) {
|
| + delete KEYBOARDS[currentPopupName].rows;
|
| + }
|
| + initRows(name, popupDiv, true);
|
| + currentPopupName = name;
|
| + }
|
| +
|
| + // Set the mode of the popup keyboard
|
| + var popupRows = KEYBOARDS[currentPopupName]['rows'];
|
| + for (var i = 0; i < popupRows.length; ++i) {
|
| + popupRows[i].showMode(currentMode);
|
| + }
|
| +
|
| + // Calculate the size of popup keyboard based on the size of the key.
|
| + var keyElement = evt.currentTarget;
|
| + var keyboard = KEYBOARDS[name];
|
| + var rows = keyboard['definition'];
|
| + var height = keyElement.offsetHeight * rows.length;
|
| + var aspect = keyboard['aspect'];
|
| + var width = aspect * height;
|
| + popupDiv.style.width = width + 'px';
|
| + popupDiv.style.height = height + 'px';
|
| +
|
| + // Place the popup keyboard above the key
|
| + var rect = keyElement.getBoundingClientRect();
|
| + var left = (rect.left + rect.right) / 2 - width / 2;
|
| + left = Math.min(Math.max(left, 0), window.innerWidth - width);
|
| + var top = rect.top - height;
|
| + top = Math.min(Math.max(top, 0), window.innerHeight - height);
|
| + popupDiv.style.left = left + 'px';
|
| + popupDiv.style.top = top + 'px';
|
| + popupDiv.style.visibility = 'visible';
|
| +
|
| + keyElement.addEventListener('touchmove', trackTouchMoveForPopup);
|
| + keyElement.addEventListener('touchend', trackTouchEndForPopup);
|
| }
|
|
|
| /**
|
| @@ -299,12 +457,21 @@ function showPopupKeyboard(name) {
|
| * @return {function()} A function which calls showPopupKeyboard(name).
|
| */
|
| function showPopupKeyboardFunction(name) {
|
| - return function () {
|
| - showPopupKeyboard(name);
|
| + return function (evt) {
|
| + showPopupKeyboard(name, evt);
|
| };
|
| }
|
|
|
| /**
|
| + * Hide the popup keyboard.
|
| + * @return {void}
|
| + */
|
| +function hidePopupKeyboard() {
|
| + var popupDiv = document.getElementById('popup');
|
| + popupDiv.style.visibility = 'hidden';
|
| +}
|
| +
|
| +/**
|
| * 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.
|
| @@ -317,10 +484,30 @@ function Character(display, id) {
|
|
|
| /**
|
| * Convenience function to make the keyboard data more readable.
|
| - * @param {string} display Both the display and id for the created Character.
|
| + * @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) {
|
| - return new Character(display, display);
|
| +function C(display, opt_id) {
|
| + var id = opt_id || display;
|
| + return new Character(display, 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.
|
| + * @param {string} opt_popupName The popup keyboard name for this character.
|
| + * @return {Object} An object that contains a Character and the popup keyboard
|
| + * name.
|
| + */
|
| +function CP(display, opt_id, opt_popupName) {
|
| + var result = { character: C(display, opt_id) };
|
| + if (opt_popupName) {
|
| + result['popupName'] = opt_popupName;
|
| + }
|
| + return result;
|
| }
|
|
|
| /**
|
| @@ -402,6 +589,56 @@ BaseKey.prototype = {
|
|
|
| /**
|
| * A simple key which displays Characters.
|
| + * @param {Object} key The Character and the popup name for KEY_MODE.
|
| + * @param {Object} shift The Character and the popup name for SHIFT_MODE.
|
| + * @param {Object} num The Character and the popup name for NUMBER_MODE.
|
| + * @param {Object} symbol The Character and the popup name for SYMBOL_MODE.
|
| + * @constructor
|
| + * @extends {BaseKey}
|
| + */
|
| +function Key(key, shift, num, symbol) {
|
| + this.modeElements_ = {};
|
| + this.cellType_ = '';
|
| +
|
| + this.modes_ = {};
|
| + this.modes_[KEY_MODE] = key ? key.character : null;
|
| + this.modes_[SHIFT_MODE] = shift ? shift.character : null;
|
| + this.modes_[NUMBER_MODE] = num ? num.character : null;
|
| + this.modes_[SYMBOL_MODE] = symbol ? symbol.character : null;
|
| +
|
| + this.popupNames_ = {};
|
| + this.popupNames_[KEY_MODE] = key ? key.popupName : null;
|
| + this.popupNames_[SHIFT_MODE] = shift ? shift.popupName : null;
|
| + this.popupNames_[NUMBER_MODE] = num ? num.popupName : null;
|
| + this.popupNames_[SYMBOL_MODE] = symbol ? symbol.popupName : null;
|
| +}
|
| +
|
| +Key.prototype = {
|
| + __proto__: BaseKey.prototype,
|
| +
|
| + /** @inheritDoc */
|
| + makeDOM: function(mode) {
|
| + if (!this.modes_[mode]) {
|
| + return null;
|
| + }
|
| +
|
| + this.modeElements_[mode] = document.createElement('div');
|
| + var element = this.modeElements_[mode];
|
| + element.className = 'key';
|
| +
|
| + addContent(element, this.modes_[mode].display);
|
| +
|
| + var longHandler = this.popupNames_[mode] ?
|
| + showPopupKeyboardFunction(this.popupNames_[mode]) : null;
|
| + setupKeyEventHandlers(this, element,
|
| + { 'up': sendKeyFunction(this.modes_[mode].keyIdentifier),
|
| + 'long': longHandler });
|
| + return element;
|
| + }
|
| +};
|
| +
|
| +/**
|
| + * A simple key which displays Characters on the popup keyboard.
|
| * @param {Character} key The Character for KEY_MODE.
|
| * @param {Character} shift The Character for SHIFT_MODE.
|
| * @param {Character} num The Character for NUMBER_MODE.
|
| @@ -409,7 +646,7 @@ BaseKey.prototype = {
|
| * @constructor
|
| * @extends {BaseKey}
|
| */
|
| -function Key(key, shift, num, symbol) {
|
| +function PopupKey(key, shift, num, symbol) {
|
| this.modeElements_ = {};
|
| this.cellType_ = '';
|
|
|
| @@ -420,7 +657,7 @@ function Key(key, shift, num, symbol) {
|
| this.modes_[SYMBOL_MODE] = symbol;
|
| }
|
|
|
| -Key.prototype = {
|
| +PopupKey.prototype = {
|
| __proto__: BaseKey.prototype,
|
|
|
| /** @inheritDoc */
|
| @@ -430,16 +667,24 @@ Key.prototype = {
|
| }
|
|
|
| this.modeElements_[mode] = document.createElement('div');
|
| - this.modeElements_[mode].className = 'key';
|
| - addContent(this.modeElements_[mode], this.modes_[mode].display);
|
| -
|
| - // TODO(mazda): Set the long-press handler only if the key has characters
|
| - // to show on the popup keyboard.
|
| - setupKeyEventHandlers(this, this.modeElements_[mode],
|
| - { 'up': sendKeyFunction(this.modes_[mode].keyIdentifier),
|
| - 'long': showPopupKeyboardFunction('') });
|
| -
|
| - return this.modeElements_[mode];
|
| + var element = this.modeElements_[mode];
|
| + element.className = 'key popupkey';
|
| +
|
| + addContent(element, this.modes_[mode].display);
|
| +
|
| + var upHandler = sendKeyFunction(this.modes_[mode].keyIdentifier);
|
| + element.addEventListener('touchpointmove', function(evt) {
|
| + touchedKeys.push(element);
|
| + });
|
| + element.addEventListener('touchpointend', upHandler);
|
| + element.addEventListener('mouseup', upHandler);
|
| + element.addEventListener('mouseover', function(evt) {
|
| + element.classList.add('highlighted');
|
| + });
|
| + element.addEventListener('mouseout', function(evt) {
|
| + element.classList.remove('highlighted');
|
| + });
|
| + return element;
|
| }
|
| };
|
|
|
| @@ -715,4 +960,12 @@ Row.prototype = {
|
| }
|
| 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;
|
| + }
|
| };
|
|
|