Keyboard shortcuts optimizations (#70, #109)

This commit is contained in:
RainLoop Team 2014-04-08 23:22:17 +04:00
parent 0b30bac43f
commit 05f455c34e
17 changed files with 400 additions and 264 deletions

View file

@ -158,6 +158,13 @@ NewHtmlEditorWrapper.prototype.init = function ()
oConfig.language = Globals.oHtmlEditorLangsMap[sLanguage] || 'en';
self.editor = window.CKEDITOR.appendTo(self.$element[0], oConfig);
self.editor.on('key', function(oEvent) {
if (oEvent && oEvent.data && 9 === oEvent.data.keyCode)
{
return false;
}
});
self.editor.on('blur', function() {
self.blurTrigger();
});

View file

@ -75,7 +75,15 @@ function Selector(oKoList, oKoFocusedItem, oKoSelectedItem,
if (this.useItemSelectCallback)
{
this.selectItemCallbacks(oItem);
if (oItem)
{
this.selectItemCallbacks(oItem, !!oItem.__clicked);
oItem.__clicked = false;
}
else
{
this.selectItemCallbacks(null);
}
}
}, this);
@ -169,19 +177,19 @@ function Selector(oKoList, oKoFocusedItem, oKoSelectedItem,
this.selectItemCallbacksThrottle = _.debounce(this.selectItemCallbacks, 300);
}
Selector.prototype.selectItemCallbacks = function (oItem)
Selector.prototype.selectItemCallbacks = function (oItem, bClick)
{
(this.oCallbacks['onItemSelect'] || this.emptyFunction)(oItem);
(this.oCallbacks['onItemSelect'] || this.emptyFunction)(oItem, bClick);
};
Selector.prototype.goDown = function ()
Selector.prototype.goDown = function (bForceSelect)
{
this.newSelectPosition(Enums.EventKeyCode.Down, false);
this.newSelectPosition(Enums.EventKeyCode.Down, false, bForceSelect);
};
Selector.prototype.goUp = function ()
Selector.prototype.goUp = function (bForceSelect)
{
this.newSelectPosition(Enums.EventKeyCode.Up, false);
this.newSelectPosition(Enums.EventKeyCode.Up, false, bForceSelect);
};
Selector.prototype.init = function (oContentVisible, oContentScrollable, sKeyScope)
@ -205,7 +213,8 @@ Selector.prototype.init = function (oContentVisible, oContentScrollable, sKeySco
}
})
.on('click', this.sItemSelector, function (oEvent) {
self.actionClick(ko.dataFor(this), oEvent);
self.actionClick(ko.dataFor(this), oEvent, true);
return false;
})
.on('click', this.sItemCheckedSelector, function (oEvent) {
var oItem = ko.dataFor(this);
@ -244,6 +253,10 @@ Selector.prototype.init = function (oContentVisible, oContentScrollable, sKeySco
}
});
key('ctrl+up, command+up, ctrl+down, command+down', sKeyScope, function () {
return false;
});
key('up, shift+up, down, shift+down, home, end, pageup, pagedown, insert, space', sKeyScope, function (event, handler) {
if (event && handler && handler.shortcut)
{
@ -340,8 +353,9 @@ Selector.prototype.getItemUid = function (oItem)
/**
* @param {number} iEventKeyCode
* @param {boolean} bShiftKey
* @param {boolean=} bForceSelect = false
*/
Selector.prototype.newSelectPosition = function (iEventKeyCode, bShiftKey)
Selector.prototype.newSelectPosition = function (iEventKeyCode, bShiftKey, bForceSelect)
{
var
self = this,
@ -462,7 +476,7 @@ Selector.prototype.newSelectPosition = function (iEventKeyCode, bShiftKey)
this.focusedItem(oResult);
if (this.bAutoSelect && Enums.EventKeyCode.Space !== iEventKeyCode)
if ((this.bAutoSelect || !!bForceSelect) && Enums.EventKeyCode.Space !== iEventKeyCode)
{
window.clearTimeout(this.iSelectTimer);
this.iSelectTimer = window.setTimeout(function () {
@ -572,8 +586,9 @@ Selector.prototype.eventClickFunction = function (oItem, oEvent)
/**
* @param {Object} oItem
* @param {Object=} oEvent
* @param {boolean=} bRealClick
*/
Selector.prototype.actionClick = function (oItem, oEvent)
Selector.prototype.actionClick = function (oItem, oEvent, bRealClick)
{
if (oItem)
{
@ -607,6 +622,11 @@ Selector.prototype.actionClick = function (oItem, oEvent)
if (bClick)
{
if (bRealClick)
{
oItem.__clicked = true;
}
this.selectedItem(oItem);
}
}

View file

@ -1235,6 +1235,17 @@ Utils.removeBlockquoteSwitcher = function (oMessageTextBody)
}
};
/**
* @param {Object} oMessageTextBody
*/
Utils.toggleMessageBlockquote = function (oMessageTextBody)
{
if (oMessageTextBody)
{
oMessageTextBody.find('.rlBlockquoteSwitcher').click();
}
};
/**
* @param {string} sName
* @param {Function} ViewModelClass

View file

@ -262,6 +262,7 @@ function WebMailDataStorage()
if (!oMessage)
{
this.message.focused(false);
this.hideMessageBodies();
}
else if (Enums.Layout.NoPreview === this.layout())
{
@ -303,7 +304,6 @@ function WebMailDataStorage()
if (null === oMessage)
{
this.currentMessage(null);
this.hideMessageBodies();
}
}, this);

View file

@ -196,16 +196,21 @@ function MailBoxMessageListViewModel()
'.messageListItem .actionHandle', '.messageListItem.selected', '.messageListItem .checkboxMessage',
'.messageListItem.focused');
this.selector.on('onItemSelect', _.bind(function (oMessage) {
this.selector.on('onItemSelect', _.bind(function (oMessage, bClick) {
if (oMessage)
{
oData.message(oData.staticMessageList.populateByMessageListItem(oMessage));
this.populateMessageBody(oData.message());
if (Enums.Layout.NoPreview === oData.layout())
{
kn.setHash(RL.link().messagePreview(), true);
oData.message.focused(true);
}
else if (bClick)
{
oData.message.focused(false);
}
oData.message(oData.staticMessageList.populateByMessageListItem(oMessage));
this.populateMessageBody(oData.message());
}
else
{
@ -226,10 +231,10 @@ function MailBoxMessageListViewModel()
RL
.sub('mailbox.message-list.selector.go-down', function () {
this.selector.goDown();
this.selector.goDown(true);
}, this)
.sub('mailbox.message-list.selector.go-up', function () {
this.selector.goUp();
this.selector.goUp(true);
}, this)
;
@ -696,7 +701,7 @@ MailBoxMessageListViewModel.prototype.initShortcuts = function ()
});
// change focused state
key('tab', Enums.KeyState.MessageList, function () {
key('tab, shift+tab', Enums.KeyState.MessageList, function () {
if (oData.useKeyboardShortcuts())
{
if (self.message())

View file

@ -450,15 +450,16 @@ MailBoxMessageViewViewModel.prototype.initShortcuts = function ()
}
});
key('ctrl+left, command+left', Enums.KeyState.MessageView, function () {
if (oData.useKeyboardShortcuts())
// toggle message blockquotes
key('b', Enums.KeyState.MessageView, function () {
if (oData.useKeyboardShortcuts() && oData.message() && oData.message().body)
{
self.goDownCommand();
Utils.toggleMessageBlockquote(oData.message().body);
return false;
}
});
key('ctrl+right, command+right', Enums.KeyState.MessageView, function () {
key('ctrl+left, command+left, ctrl+up, command+up', Enums.KeyState.MessageView, function () {
if (oData.useKeyboardShortcuts())
{
self.goUpCommand();
@ -466,6 +467,14 @@ MailBoxMessageViewViewModel.prototype.initShortcuts = function ()
}
});
key('ctrl+right, command+right, ctrl+down, command+down', Enums.KeyState.MessageView, function () {
if (oData.useKeyboardShortcuts())
{
self.goDownCommand();
return false;
}
});
// print
key('ctrl+p, command+p', Enums.KeyState.MessageView, function () {
if (oData.useKeyboardShortcuts())
@ -505,7 +514,7 @@ MailBoxMessageViewViewModel.prototype.initShortcuts = function ()
});
// change focused state
key('tab', Enums.KeyState.MessageView, function () {
key('tab, shift+tab', Enums.KeyState.MessageView, function () {
if (oData.useKeyboardShortcuts())
{
if (!self.fullScreenMode() && self.message())

View file

@ -92,7 +92,7 @@
<span class="i18n" data-i18n-text="COMPOSE/TITLE_SUBJECT"></span>
</div>
<div class="e-cell e-value">
<input type="text" size="70" data-bind="value: subject" />
<input type="text" size="70" data-bind="value: subject, valueUpdate: 'afterkeydown'" />
</div>
</div>
<div class="e-row">

View file

@ -1581,7 +1581,7 @@ table {
height : 5px;
}
.nano:hover > .pane, .nano:hover > .pane2, .pane.active, .pane2.active, .pane.flashed, .pane2.flashed {
.nano:hover > .pane, .nano:hover > .pane2, .pane.activescroll, .pane2.activescroll, .pane.active, .pane2.active, .pane.flashed, .pane2.flashed {
visibility : visible\9; /* Target only IE7 and IE8 with this hack */
opacity : 0.99;
filter: alpha(opacity=99);

File diff suppressed because one or more lines are too long

View file

@ -1950,6 +1950,17 @@ Utils.removeBlockquoteSwitcher = function (oMessageTextBody)
}
};
/**
* @param {Object} oMessageTextBody
*/
Utils.toggleMessageBlockquote = function (oMessageTextBody)
{
if (oMessageTextBody)
{
oMessageTextBody.find('.rlBlockquoteSwitcher').click();
}
};
/**
* @param {string} sName
* @param {Function} ViewModelClass

File diff suppressed because one or more lines are too long

View file

@ -1954,6 +1954,17 @@ Utils.removeBlockquoteSwitcher = function (oMessageTextBody)
}
};
/**
* @param {Object} oMessageTextBody
*/
Utils.toggleMessageBlockquote = function (oMessageTextBody)
{
if (oMessageTextBody)
{
oMessageTextBody.find('.rlBlockquoteSwitcher').click();
}
};
/**
* @param {string} sName
* @param {Function} ViewModelClass
@ -3823,6 +3834,13 @@ NewHtmlEditorWrapper.prototype.init = function ()
oConfig.language = Globals.oHtmlEditorLangsMap[sLanguage] || 'en';
self.editor = window.CKEDITOR.appendTo(self.$element[0], oConfig);
self.editor.on('key', function(oEvent) {
if (oEvent && oEvent.data && 9 === oEvent.data.keyCode)
{
return false;
}
});
self.editor.on('blur', function() {
self.blurTrigger();
});
@ -3959,7 +3977,15 @@ function Selector(oKoList, oKoFocusedItem, oKoSelectedItem,
if (this.useItemSelectCallback)
{
this.selectItemCallbacks(oItem);
if (oItem)
{
this.selectItemCallbacks(oItem, !!oItem.__clicked);
oItem.__clicked = false;
}
else
{
this.selectItemCallbacks(null);
}
}
}, this);
@ -4053,19 +4079,19 @@ function Selector(oKoList, oKoFocusedItem, oKoSelectedItem,
this.selectItemCallbacksThrottle = _.debounce(this.selectItemCallbacks, 300);
}
Selector.prototype.selectItemCallbacks = function (oItem)
Selector.prototype.selectItemCallbacks = function (oItem, bClick)
{
(this.oCallbacks['onItemSelect'] || this.emptyFunction)(oItem);
(this.oCallbacks['onItemSelect'] || this.emptyFunction)(oItem, bClick);
};
Selector.prototype.goDown = function ()
Selector.prototype.goDown = function (bForceSelect)
{
this.newSelectPosition(Enums.EventKeyCode.Down, false);
this.newSelectPosition(Enums.EventKeyCode.Down, false, bForceSelect);
};
Selector.prototype.goUp = function ()
Selector.prototype.goUp = function (bForceSelect)
{
this.newSelectPosition(Enums.EventKeyCode.Up, false);
this.newSelectPosition(Enums.EventKeyCode.Up, false, bForceSelect);
};
Selector.prototype.init = function (oContentVisible, oContentScrollable, sKeyScope)
@ -4089,7 +4115,8 @@ Selector.prototype.init = function (oContentVisible, oContentScrollable, sKeySco
}
})
.on('click', this.sItemSelector, function (oEvent) {
self.actionClick(ko.dataFor(this), oEvent);
self.actionClick(ko.dataFor(this), oEvent, true);
return false;
})
.on('click', this.sItemCheckedSelector, function (oEvent) {
var oItem = ko.dataFor(this);
@ -4128,6 +4155,10 @@ Selector.prototype.init = function (oContentVisible, oContentScrollable, sKeySco
}
});
key('ctrl+up, command+up, ctrl+down, command+down', sKeyScope, function () {
return false;
});
key('up, shift+up, down, shift+down, home, end, pageup, pagedown, insert, space', sKeyScope, function (event, handler) {
if (event && handler && handler.shortcut)
{
@ -4224,8 +4255,9 @@ Selector.prototype.getItemUid = function (oItem)
/**
* @param {number} iEventKeyCode
* @param {boolean} bShiftKey
* @param {boolean=} bForceSelect = false
*/
Selector.prototype.newSelectPosition = function (iEventKeyCode, bShiftKey)
Selector.prototype.newSelectPosition = function (iEventKeyCode, bShiftKey, bForceSelect)
{
var
self = this,
@ -4346,7 +4378,7 @@ Selector.prototype.newSelectPosition = function (iEventKeyCode, bShiftKey)
this.focusedItem(oResult);
if (this.bAutoSelect && Enums.EventKeyCode.Space !== iEventKeyCode)
if ((this.bAutoSelect || !!bForceSelect) && Enums.EventKeyCode.Space !== iEventKeyCode)
{
window.clearTimeout(this.iSelectTimer);
this.iSelectTimer = window.setTimeout(function () {
@ -4456,8 +4488,9 @@ Selector.prototype.eventClickFunction = function (oItem, oEvent)
/**
* @param {Object} oItem
* @param {Object=} oEvent
* @param {boolean=} bRealClick
*/
Selector.prototype.actionClick = function (oItem, oEvent)
Selector.prototype.actionClick = function (oItem, oEvent, bRealClick)
{
if (oItem)
{
@ -4491,6 +4524,11 @@ Selector.prototype.actionClick = function (oItem, oEvent)
if (bClick)
{
if (bRealClick)
{
oItem.__clicked = true;
}
this.selectedItem(oItem);
}
}
@ -11924,16 +11962,21 @@ function MailBoxMessageListViewModel()
'.messageListItem .actionHandle', '.messageListItem.selected', '.messageListItem .checkboxMessage',
'.messageListItem.focused');
this.selector.on('onItemSelect', _.bind(function (oMessage) {
this.selector.on('onItemSelect', _.bind(function (oMessage, bClick) {
if (oMessage)
{
oData.message(oData.staticMessageList.populateByMessageListItem(oMessage));
this.populateMessageBody(oData.message());
if (Enums.Layout.NoPreview === oData.layout())
{
kn.setHash(RL.link().messagePreview(), true);
oData.message.focused(true);
}
else if (bClick)
{
oData.message.focused(false);
}
oData.message(oData.staticMessageList.populateByMessageListItem(oMessage));
this.populateMessageBody(oData.message());
}
else
{
@ -11954,10 +11997,10 @@ function MailBoxMessageListViewModel()
RL
.sub('mailbox.message-list.selector.go-down', function () {
this.selector.goDown();
this.selector.goDown(true);
}, this)
.sub('mailbox.message-list.selector.go-up', function () {
this.selector.goUp();
this.selector.goUp(true);
}, this)
;
@ -12424,7 +12467,7 @@ MailBoxMessageListViewModel.prototype.initShortcuts = function ()
});
// change focused state
key('tab', Enums.KeyState.MessageList, function () {
key('tab, shift+tab', Enums.KeyState.MessageList, function () {
if (oData.useKeyboardShortcuts())
{
if (self.message())
@ -13009,15 +13052,16 @@ MailBoxMessageViewViewModel.prototype.initShortcuts = function ()
}
});
key('ctrl+left, command+left', Enums.KeyState.MessageView, function () {
if (oData.useKeyboardShortcuts())
// toggle message blockquotes
key('b', Enums.KeyState.MessageView, function () {
if (oData.useKeyboardShortcuts() && oData.message() && oData.message().body)
{
self.goDownCommand();
Utils.toggleMessageBlockquote(oData.message().body);
return false;
}
});
key('ctrl+right, command+right', Enums.KeyState.MessageView, function () {
key('ctrl+left, command+left, ctrl+up, command+up', Enums.KeyState.MessageView, function () {
if (oData.useKeyboardShortcuts())
{
self.goUpCommand();
@ -13025,6 +13069,14 @@ MailBoxMessageViewViewModel.prototype.initShortcuts = function ()
}
});
key('ctrl+right, command+right, ctrl+down, command+down', Enums.KeyState.MessageView, function () {
if (oData.useKeyboardShortcuts())
{
self.goDownCommand();
return false;
}
});
// print
key('ctrl+p, command+p', Enums.KeyState.MessageView, function () {
if (oData.useKeyboardShortcuts())
@ -13064,7 +13116,7 @@ MailBoxMessageViewViewModel.prototype.initShortcuts = function ()
});
// change focused state
key('tab', Enums.KeyState.MessageView, function () {
key('tab, shift+tab', Enums.KeyState.MessageView, function () {
if (oData.useKeyboardShortcuts())
{
if (!self.fullScreenMode() && self.message())
@ -14889,6 +14941,7 @@ function WebMailDataStorage()
if (!oMessage)
{
this.message.focused(false);
this.hideMessageBodies();
}
else if (Enums.Layout.NoPreview === this.layout())
{
@ -14930,7 +14983,6 @@ function WebMailDataStorage()
if (null === oMessage)
{
this.currentMessage(null);
this.hideMessageBodies();
}
}, this);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -336,6 +336,23 @@
*/
NanoScroll.prototype.scrollClassTimer = 0;
NanoScroll.prototype.scrollClassTrigger = function() {
window.clearTimeout(this.scrollClassTimer);
var _this = this;
_this.pane.addClass('activescroll');
_this.pane2.addClass('activescroll');
this.scrollClassTimer = window.setTimeout(function () {
_this.pane.removeClass('activescroll');
_this.pane2.removeClass('activescroll');
}, 1000);
};
NanoScroll.prototype.nativeScrolling = function() {
this.$content.css({
WebkitOverflowScrolling: 'touch'
@ -471,6 +488,10 @@
}
_this.$el.trigger('scrolltop');
}
if (!_this.iOSNativeScrolling) {
_this.scrollClassTrigger();
}
},
/**
* @param {{wheelDeltaY:number, delta:number}} e

View file

@ -95,7 +95,7 @@
height : 5px;
}
.nano:hover > .pane, .nano:hover > .pane2, .pane.active, .pane2.active, .pane.flashed, .pane2.flashed {
.nano:hover > .pane, .nano:hover > .pane2, .pane.activescroll, .pane2.activescroll, .pane.active, .pane2.active, .pane.flashed, .pane2.flashed {
visibility : visible\9; /* Target only IE7 and IE8 with this hack */
opacity : 0.99;
filter: alpha(opacity=99);