Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Commit

Permalink
Bug 985853 - [Keyboard UX update][User Story] Hold shift to enter upp…
Browse files Browse the repository at this point in the history
…er case characters
  • Loading branch information
dxue committed Sep 2, 2014
1 parent 97748c8 commit cb8ce50
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 10 deletions.
4 changes: 3 additions & 1 deletion apps/keyboard/js/keyboard/active_targets_manager.js
Expand Up @@ -93,7 +93,9 @@ ActiveTargetsManager.prototype._handlePressStart = function(press, id) {
// All targets before the new touch need to be committed,
// according to UX requirement.
this.activeTargets.forEach(function(target, id) {
this._handlePressEnd(press, id);
if (!this.app.upperCaseStateManager.isUpperCasePressed) {
this._handlePressEnd(press, id);
}
}, this);

var target = press.target;
Expand Down
19 changes: 17 additions & 2 deletions apps/keyboard/js/keyboard/target_handlers.js
Expand Up @@ -38,6 +38,11 @@ DefaultTargetHandler.prototype.commit = function() {
return;
}

if (this.app.upperCaseStateManager.isUpperCasePressed) {
this.app.upperCaseStateManager.switchUpperCaseState({
isUpperCaseCombo: true
});
}
var keyCode = parseInt(this.target.dataset.keycode, 10);
var upperCaseKeyCode = parseInt(this.target.dataset.keycodeUpper, 10);
var engine = this.app.inputMethodManager.currentIMEngine;
Expand Down Expand Up @@ -244,10 +249,20 @@ var CapsLockTargetHandler = function(target, app) {
DefaultTargetHandler.apply(this, arguments);
};
CapsLockTargetHandler.prototype = Object.create(DefaultTargetHandler.prototype);
CapsLockTargetHandler.prototype.activate = function() {
this.app.upperCaseStateManager.switchUpperCaseState({
isUpperCasePressed: true
});
this.app.feedbackManager.triggerFeedback(this.target);
this.app.visualHighlightManager.show(this.target);
};
CapsLockTargetHandler.prototype.commit = function() {
this.app.upperCaseStateManager.switchUpperCaseState({
isUpperCase: !this.app.upperCaseStateManager.isUpperCase,
isUpperCaseLocked: false
isUpperCase: !this.app.upperCaseStateManager.isUpperCaseCombo &&
!this.app.upperCaseStateManager.isUpperCase,
isUpperCaseLocked: false,
isUpperCasePressed: false,
isUpperCaseCombo: false
});
this.app.visualHighlightManager.hide(this.target);
};
Expand Down
18 changes: 16 additions & 2 deletions apps/keyboard/js/keyboard/upper_case_state_manager.js
Expand Up @@ -5,6 +5,8 @@
var UpperCaseStateManager = function() {
this.isUpperCase = undefined;
this.isUpperCaseLocked = undefined;
this.isUpperCasePressed = undefined;
this.isUpperCaseCombo = undefined;
};

UpperCaseStateManager.prototype.onstatechange = null;
Expand All @@ -13,11 +15,15 @@ UpperCaseStateManager.prototype.start =
UpperCaseStateManager.prototype.reset = function() {
this.isUpperCase = false;
this.isUpperCaseLocked = false;
this.isUpperCasePressed = false;
this.isUpperCaseCombo = false;
};

UpperCaseStateManager.prototype.stop = function() {
this.isUpperCase = undefined;
this.isUpperCaseLocked = undefined;
this.isUpperCasePressed = undefined;
this.isUpperCaseCombo = undefined;
};

UpperCaseStateManager.prototype.switchUpperCaseState = function(state) {
Expand All @@ -31,17 +37,23 @@ UpperCaseStateManager.prototype.switchUpperCaseState = function(state) {
state.isUpperCase : this.isUpperCase;
var newIsUpperCaseLocked = (typeof state.isUpperCaseLocked === 'boolean') ?
state.isUpperCaseLocked : this.isUpperCaseLocked;
var newIsUpperCasePressed = (typeof state.isUpperCasePressed === 'boolean') ?
state.isUpperCasePressed : this.isUpperCasePressed;
var newIsUpperCaseCombo = (typeof state.isUpperCaseCombo === 'boolean') ?
state.isUpperCaseCombo : this.isUpperCaseCombo;

// It doesn't really make any sense to set isUpperCase to false but
// change/keep isUpperCaseLocked to true.
// This also means isUpperCaseLocked can overwrite isUpperCase changes,
// and literally keep the caps "lock".
if (newIsUpperCaseLocked) {
if (newIsUpperCaseLocked || newIsUpperCaseCombo) {
newIsUpperCase = true;
}

var statechanged = (this.isUpperCase !== newIsUpperCase) ||
(this.isUpperCaseLocked !== newIsUpperCaseLocked);
(this.isUpperCaseLocked !== newIsUpperCaseLocked) ||
(this.isUpperCasePressed !== newIsUpperCasePressed) ||
(this.isUpperCaseCombo !== newIsUpperCaseCombo);

// Don't do anything if the state is unchanged.
if (!statechanged) {
Expand All @@ -51,6 +63,8 @@ UpperCaseStateManager.prototype.switchUpperCaseState = function(state) {
// Set the new states.
this.isUpperCase = newIsUpperCase;
this.isUpperCaseLocked = newIsUpperCaseLocked;
this.isUpperCasePressed = newIsUpperCasePressed;
this.isUpperCaseCombo = newIsUpperCaseCombo;

// Call onstatechange callback.
if (typeof this.onstatechange === 'function') {
Expand Down
7 changes: 5 additions & 2 deletions apps/keyboard/js/render.js
Expand Up @@ -107,6 +107,7 @@ var IMERender = (function() {
};

// Accepts a state object with two properties.
// Set isUpperCasePressed to true if pressed
// Set isUpperCaseLocked to true if locked
// Set isUpperCase to true when uppercase is enabled
// Use false on both of these properties when uppercase is disabled
Expand All @@ -123,8 +124,10 @@ var IMERender = (function() {
capsLockKey.classList.remove('kbr-key-active');
capsLockKey.classList.add('kbr-key-hold');
} else if (state.isUpperCase) {
capsLockKey.classList.add('kbr-key-active');
capsLockKey.classList.remove('kbr-key-hold');
if (!state.isUpperCasePressed) {
capsLockKey.classList.add('kbr-key-active');
capsLockKey.classList.remove('kbr-key-hold');
}
} else {
capsLockKey.classList.remove('kbr-key-active');
capsLockKey.classList.remove('kbr-key-hold');
Expand Down
14 changes: 11 additions & 3 deletions apps/keyboard/test/unit/keyboard/target_handlers_test.js
Expand Up @@ -743,8 +743,14 @@ suite('target handlers', function() {
});

test('activate', function() {
assert.equal(handler.activate, DefaultTargetHandler.prototype.activate,
'function not overwritten');
handler.activate();

assert.isTrue(app.upperCaseStateManager.switchUpperCaseState.calledWith({
isUpperCasePressed: true
}));

assert.isTrue(app.visualHighlightManager.hide.calledWith(target));
assert.isTrue(app.visualHighlightManager.hide.calledOnce);
});

test('longPress', function() {
Expand All @@ -767,7 +773,9 @@ suite('target handlers', function() {

assert.isTrue(app.upperCaseStateManager.switchUpperCaseState.calledWith({
isUpperCase: true,
isUpperCaseLocked: false
isUpperCaseLocked: false,
isUpperCasePressed: false,
isUpperCaseCombo: false
}));

assert.isTrue(app.visualHighlightManager.hide.calledWith(target));
Expand Down
102 changes: 102 additions & 0 deletions apps/keyboard/test/unit/keyboard/upper_case_state_manager_test.js
Expand Up @@ -97,6 +97,40 @@ suite('UpperCaseStateManager', function() {
assert.isFalse(manager.isUpperCaseLocked);
assert.isFalse(manager.onstatechange.calledOnce);
});

test('set isUpperCasePressed = true', function() {
manager.switchUpperCaseState({
isUpperCasePressed: true
});

assert.isTrue(manager.isUpperCase);
assert.isTrue(manager.isUpperCasePressed);
assert.isFalse(manager.onstatechange.calledOnce);
});

test('set isUpperCaseCombo = true', function() {
manager.switchUpperCaseState({
isUpperCaseCombo: true
});

assert.isTrue(manager.isUpperCase);
assert.isTrue(manager.isUpperCasePressed);
assert.isTrue(manager.isUpperCaseCombo);
assert.isFalse(manager.onstatechange.calledOnce);
});

test('set isUpperCasePressed = false, isUpperCaseCombo = false',
function() {
manager.switchUpperCaseState({
isUpperCasePressed: false,
isUpperCaseCombo: false
});

assert.isFalse(manager.isUpperCase);
assert.isFalse(manager.isUpperCasePressed);
assert.isFalse(manager.isUpperCaseCombo);
assert.isFalse(manager.onstatechange.calledOnce);
});
});

suite('isUpperCase = true, isUpperCaseLocked = false', function() {
Expand Down Expand Up @@ -187,6 +221,40 @@ suite('UpperCaseStateManager', function() {
assert.isFalse(manager.isUpperCaseLocked);
assert.isFalse(manager.onstatechange.calledOnce);
});

test('set isUpperCasePressed = true', function() {
manager.switchUpperCaseState({
isUpperCasePressed: true
});

assert.isTrue(manager.isUpperCase);
assert.isTrue(manager.isUpperCasePressed);
assert.isFalse(manager.onstatechange.calledOnce);
});

test('set isUpperCaseCombo = true', function() {
manager.switchUpperCaseState({
isUpperCaseCombo: true
});

assert.isTrue(manager.isUpperCase);
assert.isTrue(manager.isUpperCasePressed);
assert.isTrue(manager.isUpperCaseCombo);
assert.isFalse(manager.onstatechange.calledOnce);
});

test('set isUpperCasePressed = false, isUpperCaseCombo = false',
function() {
manager.switchUpperCaseState({
isUpperCasePressed: false,
isUpperCaseCombo: false
});

assert.isFalse(manager.isUpperCase);
assert.isFalse(manager.isUpperCasePressed);
assert.isFalse(manager.isUpperCaseCombo);
assert.isFalse(manager.onstatechange.calledOnce);
});
});

suite('isUpperCase = true, isUpperCaseLocked = true', function() {
Expand Down Expand Up @@ -278,5 +346,39 @@ suite('UpperCaseStateManager', function() {
assert.isFalse(manager.isUpperCaseLocked);
assert.isTrue(manager.onstatechange.calledOnce);
});

test('set isUpperCasePressed = true', function() {
manager.switchUpperCaseState({
isUpperCasePressed: true
});

assert.isTrue(manager.isUpperCase);
assert.isTrue(manager.isUpperCasePressed);
assert.isFalse(manager.onstatechange.calledOnce);
});

test('set isUpperCaseCombo = true', function() {
manager.switchUpperCaseState({
isUpperCaseCombo: true
});

assert.isTrue(manager.isUpperCase);
assert.isTrue(manager.isUpperCasePressed);
assert.isTrue(manager.isUpperCaseCombo);
assert.isFalse(manager.onstatechange.calledOnce);
});

test('set isUpperCasePressed = false, isUpperCaseCombo = false',
function() {
manager.switchUpperCaseState({
isUpperCasePressed: false,
isUpperCaseCombo: false
});

assert.isFalse(manager.isUpperCase);
assert.isFalse(manager.isUpperCasePressed);
assert.isFalse(manager.isUpperCaseCombo);
assert.isFalse(manager.onstatechange.calledOnce);
});
});
});

0 comments on commit cb8ce50

Please sign in to comment.