mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-01 05:29:20 +03:00
Added keyboard shortcuts (part 1) (#70)
Scrolling in message view (#109)
This commit is contained in:
parent
3936a818b7
commit
8979687f88
37 changed files with 2095 additions and 333 deletions
|
|
@ -1,5 +1,6 @@
|
|||
<div id="rl-sub-left">
|
||||
<div class="messageList g-ui-user-select-none" data-bind="css: {'message-selected': isMessageSelected, 'loading': messageListCompleteLoadingThrottle, 'hideMessageListCheckbox': !useCheckboxesInList() }">
|
||||
<div class="messageList g-ui-user-select-none"
|
||||
data-bind="css: {'message-selected': isMessageSelected, 'message-focused': message.focused, 'loading': messageListCompleteLoadingThrottle, 'hideMessageListCheckbox': !useCheckboxesInList() }">
|
||||
<div class="toolbar">
|
||||
<div class="btn-toolbar">
|
||||
<div class="btn-group">
|
||||
|
|
@ -111,10 +112,6 @@
|
|||
</a>
|
||||
</div>
|
||||
<i class="checkboxCkeckAll" data-bind="css: checkAll() ? (isIncompleteChecked() ? 'icon-checkbox-partial' : 'icon-checkbox-checked') : 'icon-checkbox-unchecked'"></i>
|
||||
<!--
|
||||
<i class="checkboxCkeckAll" data-bind="css: checkAll() ? (isIncompleteChecked() ? 'icon-checkbox-partial' : 'icon-checkbox-checked') : 'icon-checkbox-unchecked', visible: !messageListCompleteLoadingThrottle()"></i>
|
||||
<i class="icon-spinner animated" style="margin-top: 4px;" data-bind="visible: messageListCompleteLoadingThrottle"></i>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="mainDelimiter toolbarDelimiter"></div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<div id="rl-sub-right">
|
||||
<div class="messageView" data-bind="css: {'message-selected': isMessageSelected}">
|
||||
<div class="messageView" data-bind="css: {'message-selected': isMessageSelected, 'message-focused': message.focused}">
|
||||
<div class="toolbar g-ui-user-select-none">
|
||||
<div class="messageButtons btn-toolbar">
|
||||
<div class="btn-group" data-placement="bottom" data-bind="visible: !usePreviewPane(), tooltip: 'MESSAGE/BUTTON_CLOSE'">
|
||||
|
|
@ -131,7 +131,7 @@
|
|||
</div>
|
||||
<div data-bind="visible: message">
|
||||
<div class="messageItem" data-bind="css: viewLineAsCcc(), nano: true">
|
||||
<div class="content g-scrollbox">
|
||||
<div class="content g-scrollbox" tabindex="0" data-bind="hasfocus: messageDomFocused">
|
||||
<div class="content-wrapper">
|
||||
<div>
|
||||
<span class="buttonUp" data-bind="click: scrollToTop">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
<div class="popups">
|
||||
<div class="modal hide b-shortcuts-content" data-bind="modal: modalVisibility">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-bind="command: cancelCommand">×</button>
|
||||
<h3>
|
||||
Keyboard shortcuts help
|
||||
</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<br />
|
||||
Coming soon!
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -6416,6 +6416,9 @@ html.rl-no-preview-pane #rl-right .ui-resizable-handle {
|
|||
.popups .b-ask-content .desc-place {
|
||||
font-size: 18px;
|
||||
}
|
||||
.popups .b-shortcuts-content .modal-header {
|
||||
background-color: #fff;
|
||||
}
|
||||
.b-folders .b-toolbar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
|
@ -7048,6 +7051,10 @@ html.rl-no-preview-pane .messageList.message-selected {
|
|||
.messageList .b-content .messageListItem.flagged .flagOn {
|
||||
display: inline-block;
|
||||
}
|
||||
.messageList.message-focused .b-content {
|
||||
opacity: 0.97;
|
||||
filter: alpha(opacity=97);
|
||||
}
|
||||
.messageList.hideMessageListCheckbox .checkedParent,
|
||||
.messageList.hideMessageListCheckbox .checkboxCkeckAll {
|
||||
display: none !important;
|
||||
|
|
@ -7096,10 +7103,9 @@ html.rl-no-preview-pane .messageView.message-selected {
|
|||
top: 58px;
|
||||
bottom: 13px;
|
||||
right: 8px;
|
||||
left: 0;
|
||||
left: -1px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #aaaaaa;
|
||||
border-left: 0px;
|
||||
-webkit-border-top-right-radius: 3px;
|
||||
-moz-border-radius-topright: 3px;
|
||||
border-top-right-radius: 3px;
|
||||
|
|
@ -7380,6 +7386,19 @@ html.rl-no-preview-pane .messageView.message-selected {
|
|||
border-left: 2px solid red;
|
||||
color: red;
|
||||
}
|
||||
.messageView.message-focused .messageItemHeader {
|
||||
background-color: #fafafa !important;
|
||||
}
|
||||
.messageView.message-focused .b-content {
|
||||
z-index: 102;
|
||||
-webkit-box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.3);
|
||||
-moz-box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.3);
|
||||
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.3);
|
||||
border-color: #9d9d9d;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
html.rl-no-preview-pane .messageView .toolbar {
|
||||
padding-left: 1px;
|
||||
}
|
||||
|
|
|
|||
2
rainloop/v/0.0.0/static/css/app.min.css
vendored
2
rainloop/v/0.0.0/static/css/app.min.css
vendored
File diff suppressed because one or more lines are too long
|
|
@ -367,6 +367,18 @@ Enums.StateType = {
|
|||
'Admin': 1
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
Enums.KeyState = {
|
||||
'None': 'none',
|
||||
'ContactList': 'contact-list',
|
||||
'MessageList': 'message-list',
|
||||
'MessageView': 'message-view',
|
||||
'Compose': 'compose',
|
||||
'PopupAsk': 'popup-ask'
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
|
|
@ -2421,6 +2433,34 @@ Utils.selectElement = function (element)
|
|||
/* jshint onevar: true */
|
||||
};
|
||||
|
||||
Utils.disableKeyFilter = function ()
|
||||
{
|
||||
if (window.key)
|
||||
{
|
||||
key.filter = function () {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Utils.restoreKeyFilter = function ()
|
||||
{
|
||||
if (window.key)
|
||||
{
|
||||
key.filter = function (event) {
|
||||
var
|
||||
element = event.target || event.srcElement,
|
||||
tagName = element ? element.tagName : ''
|
||||
;
|
||||
|
||||
tagName = tagName.toUpperCase();
|
||||
return !(tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA' ||
|
||||
(element && tagName === 'DIV' && 'editorHtmlArea' === element.className && element.contentEditable)
|
||||
);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Base64 encode / decode
|
||||
// http://www.webtoolkit.info/
|
||||
|
||||
|
|
@ -3889,16 +3929,13 @@ KnoinAbstractViewModel.prototype.cancelCommand = KnoinAbstractViewModel.prototyp
|
|||
|
||||
KnoinAbstractViewModel.prototype.registerPopupEscapeKey = function ()
|
||||
{
|
||||
var self = this;
|
||||
$window.on('keydown', function (oEvent) {
|
||||
if (oEvent && Enums.EventKeyCode.Esc === oEvent.keyCode && self.modalVisibility())
|
||||
key('esc', _.bind(function () {
|
||||
if (this.modalVisibility && this.modalVisibility())
|
||||
{
|
||||
Utils.delegateRun(self, 'cancelCommand');
|
||||
Utils.delegateRun(this, 'cancelCommand');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}, this));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -5072,16 +5109,13 @@ PopupsPluginViewModel.prototype.tryToClosePopup = function ()
|
|||
|
||||
PopupsPluginViewModel.prototype.onBuild = function ()
|
||||
{
|
||||
var self = this;
|
||||
$window.on('keydown', function (oEvent) {
|
||||
var bResult = true;
|
||||
if (oEvent && Enums.EventKeyCode.Esc === oEvent.keyCode && self.modalVisibility())
|
||||
key('esc', _.bind(function () {
|
||||
if (this.modalVisibility())
|
||||
{
|
||||
self.tryToClosePopup();
|
||||
bResult = false;
|
||||
this.tryToClosePopup();
|
||||
return false;
|
||||
}
|
||||
return bResult;
|
||||
});
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -5279,6 +5313,7 @@ function PopupsAskViewModel()
|
|||
this.fNoAction = null;
|
||||
|
||||
this.bDisabeCloseOnEsc = true;
|
||||
this.sKeyScope = Enums.KeyState.MessageList;
|
||||
|
||||
Knoin.constructorEnd(this);
|
||||
}
|
||||
|
|
@ -5300,22 +5335,22 @@ PopupsAskViewModel.prototype.clearPopup = function ()
|
|||
|
||||
PopupsAskViewModel.prototype.yesClick = function ()
|
||||
{
|
||||
this.cancelCommand();
|
||||
|
||||
if (Utils.isFunc(this.fYesAction))
|
||||
{
|
||||
this.fYesAction.call(null);
|
||||
}
|
||||
|
||||
this.cancelCommand();
|
||||
};
|
||||
|
||||
PopupsAskViewModel.prototype.noClick = function ()
|
||||
{
|
||||
this.cancelCommand();
|
||||
|
||||
if (Utils.isFunc(this.fNoAction))
|
||||
{
|
||||
this.fNoAction.call(null);
|
||||
}
|
||||
|
||||
this.cancelCommand();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -5342,6 +5377,9 @@ PopupsAskViewModel.prototype.onShow = function (sAskDesc, fYesFunc, fNoFunc, sYe
|
|||
{
|
||||
this.yesButton(sNoButton);
|
||||
}
|
||||
|
||||
this.sKeyScope = RL.data().keyScope();
|
||||
RL.data().keyScope(Enums.KeyState.PopupAsk);
|
||||
};
|
||||
|
||||
PopupsAskViewModel.prototype.onFocus = function ()
|
||||
|
|
@ -5351,32 +5389,26 @@ PopupsAskViewModel.prototype.onFocus = function ()
|
|||
|
||||
PopupsAskViewModel.prototype.onHide = function ()
|
||||
{
|
||||
RL.data().keyScope(this.sKeyScope);
|
||||
};
|
||||
|
||||
PopupsAskViewModel.prototype.onBuild = function ()
|
||||
{
|
||||
var self = this;
|
||||
$window.on('keydown', function (oEvent) {
|
||||
var bResult = true;
|
||||
if (oEvent && self.modalVisibility())
|
||||
key('tab, right, left', Enums.KeyState.PopupAsk, _.bind(function () {
|
||||
if (this.modalVisibility())
|
||||
{
|
||||
if (Enums.EventKeyCode.Tab === oEvent.keyCode || Enums.EventKeyCode.Right === oEvent.keyCode || Enums.EventKeyCode.Left === oEvent.keyCode)
|
||||
if (this.yesFocus())
|
||||
{
|
||||
if (self.yesFocus())
|
||||
{
|
||||
self.noFocus(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.yesFocus(true);
|
||||
}
|
||||
|
||||
bResult = false;
|
||||
this.noFocus(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.yesFocus(true);
|
||||
}
|
||||
}
|
||||
|
||||
return bResult;
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}, this));
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
8
rainloop/v/0.0.0/static/js/admin.min.js
vendored
8
rainloop/v/0.0.0/static/js/admin.min.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -1,5 +1,5 @@
|
|||
/*! RainLoop Webmail Main Module (c) RainLoop Team | Licensed under CC BY-NC-SA 3.0 */
|
||||
(function (window, $, ko, crossroads, hasher, moment, Jua, _, ifvisible) {
|
||||
(function (window, $, ko, crossroads, hasher, moment, Jua, _, ifvisible, key) {
|
||||
|
||||
'use strict';
|
||||
|
||||
|
|
@ -371,6 +371,18 @@ Enums.StateType = {
|
|||
'Admin': 1
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
Enums.KeyState = {
|
||||
'None': 'none',
|
||||
'ContactList': 'contact-list',
|
||||
'MessageList': 'message-list',
|
||||
'MessageView': 'message-view',
|
||||
'Compose': 'compose',
|
||||
'PopupAsk': 'popup-ask'
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
|
|
@ -2425,6 +2437,34 @@ Utils.selectElement = function (element)
|
|||
/* jshint onevar: true */
|
||||
};
|
||||
|
||||
Utils.disableKeyFilter = function ()
|
||||
{
|
||||
if (window.key)
|
||||
{
|
||||
key.filter = function () {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Utils.restoreKeyFilter = function ()
|
||||
{
|
||||
if (window.key)
|
||||
{
|
||||
key.filter = function (event) {
|
||||
var
|
||||
element = event.target || event.srcElement,
|
||||
tagName = element ? element.tagName : ''
|
||||
;
|
||||
|
||||
tagName = tagName.toUpperCase();
|
||||
return !(tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA' ||
|
||||
(element && tagName === 'DIV' && 'editorHtmlArea' === element.className && element.contentEditable)
|
||||
);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Base64 encode / decode
|
||||
// http://www.webtoolkit.info/
|
||||
|
||||
|
|
@ -3979,10 +4019,12 @@ Selector.prototype.goUp = function ()
|
|||
this.newSelectPosition(Enums.EventKeyCode.Up, false);
|
||||
};
|
||||
|
||||
Selector.prototype.init = function (oContentVisible, oContentScrollable)
|
||||
Selector.prototype.init = function (oContentVisible, oContentScrollable, sKeyScope)
|
||||
{
|
||||
this.oContentVisible = oContentVisible;
|
||||
this.oContentScrollable = oContentScrollable;
|
||||
|
||||
sKeyScope = sKeyScope || 'all';
|
||||
|
||||
if (this.oContentVisible && this.oContentScrollable)
|
||||
{
|
||||
|
|
@ -4025,27 +4067,43 @@ Selector.prototype.init = function (oContentVisible, oContentScrollable)
|
|||
})
|
||||
;
|
||||
|
||||
$(window.document).on('keydown', function (oEvent) {
|
||||
var bResult = true;
|
||||
if (oEvent && self.bUseKeyboard && !Utils.inFocus())
|
||||
key('space, enter', sKeyScope, function () {
|
||||
return false;
|
||||
});
|
||||
|
||||
key('up, shift+up, down, shift+down, insert, home, end, pageup, pagedown', sKeyScope, function (event, handler) {
|
||||
if (event && handler && handler.shortcut)
|
||||
{
|
||||
if (-1 < Utils.inArray(oEvent.keyCode, [Enums.EventKeyCode.Up, Enums.EventKeyCode.Down, Enums.EventKeyCode.Insert,
|
||||
Enums.EventKeyCode.Home, Enums.EventKeyCode.End, Enums.EventKeyCode.PageUp, Enums.EventKeyCode.PageDown]))
|
||||
var iKey = 0, aCodes = null;
|
||||
switch (handler.shortcut)
|
||||
{
|
||||
self.newSelectPosition(oEvent.keyCode, oEvent.shiftKey);
|
||||
bResult = false;
|
||||
case 'up':
|
||||
case 'shift+up':
|
||||
iKey = Enums.EventKeyCode.Up;
|
||||
break;
|
||||
case 'down':
|
||||
case 'shift+down':
|
||||
iKey = Enums.EventKeyCode.Down;
|
||||
break;
|
||||
case 'insert':
|
||||
case 'home':
|
||||
case 'end':
|
||||
case 'pageup':
|
||||
case 'pagedown':
|
||||
aCodes = key.getPressedKeyCodes();
|
||||
if (aCodes && aCodes[0])
|
||||
{
|
||||
iKey = aCodes[0];
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (Enums.EventKeyCode.Delete === oEvent.keyCode && !oEvent.ctrlKey && !oEvent.shiftKey)
|
||||
|
||||
if (0 < iKey)
|
||||
{
|
||||
if (self.oCallbacks['onDelete'])
|
||||
{
|
||||
self.oCallbacks['onDelete']();
|
||||
}
|
||||
|
||||
bResult = false;
|
||||
self.newSelectPosition(iKey, key.shift);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return bResult;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -4706,16 +4764,13 @@ KnoinAbstractViewModel.prototype.cancelCommand = KnoinAbstractViewModel.prototyp
|
|||
|
||||
KnoinAbstractViewModel.prototype.registerPopupEscapeKey = function ()
|
||||
{
|
||||
var self = this;
|
||||
$window.on('keydown', function (oEvent) {
|
||||
if (oEvent && Enums.EventKeyCode.Esc === oEvent.keyCode && self.modalVisibility())
|
||||
key('esc', _.bind(function () {
|
||||
if (this.modalVisibility && this.modalVisibility())
|
||||
{
|
||||
Utils.delegateRun(self, 'cancelCommand');
|
||||
Utils.delegateRun(this, 'cancelCommand');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}, this));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -5556,8 +5611,9 @@ function ContactModel()
|
|||
this.readOnly = false;
|
||||
this.scopeType = Enums.ContactScopeType.Default;
|
||||
|
||||
this.checked = ko.observable(false);
|
||||
this.focused = ko.observable(false);
|
||||
this.selected = ko.observable(false);
|
||||
this.checked = ko.observable(false);
|
||||
this.deleted = ko.observable(false);
|
||||
this.shared = ko.observable(false);
|
||||
}
|
||||
|
|
@ -5662,6 +5718,10 @@ ContactModel.prototype.lineAsCcc = function ()
|
|||
{
|
||||
aResult.push('shared');
|
||||
}
|
||||
if (this.focused())
|
||||
{
|
||||
aResult.push('focused');
|
||||
}
|
||||
|
||||
return aResult.join(' ');
|
||||
};
|
||||
|
|
@ -6020,6 +6080,7 @@ function MessageModel()
|
|||
this.forwarded = ko.observable(false);
|
||||
this.isReadReceipt = ko.observable(false);
|
||||
|
||||
this.focused = ko.observable(false);
|
||||
this.selected = ko.observable(false);
|
||||
this.checked = ko.observable(false);
|
||||
this.hasAttachments = ko.observable(false);
|
||||
|
|
@ -6499,6 +6560,10 @@ MessageModel.prototype.lineAsCcc = function ()
|
|||
{
|
||||
aResult.push('forwarded');
|
||||
}
|
||||
if (this.focused())
|
||||
{
|
||||
aResult.push('focused');
|
||||
}
|
||||
if (this.hasAttachments())
|
||||
{
|
||||
aResult.push('withAttachments');
|
||||
|
|
@ -7189,6 +7254,7 @@ function FolderModel()
|
|||
|
||||
this.type = ko.observable(Enums.FolderType.User);
|
||||
|
||||
this.focused = ko.observable(false);
|
||||
this.selected = ko.observable(false);
|
||||
this.edited = ko.observable(false);
|
||||
this.collapsed = ko.observable(true);
|
||||
|
|
@ -8262,7 +8328,8 @@ function PopupsComposeViewModel()
|
|||
// this.driveCallback = _.bind(this.driveCallback, this);
|
||||
|
||||
this.bDisabeCloseOnEsc = true;
|
||||
|
||||
this.sKeyScope = Enums.KeyState.MessageList;
|
||||
|
||||
Knoin.constructorEnd(this);
|
||||
}
|
||||
|
||||
|
|
@ -8479,6 +8546,8 @@ PopupsComposeViewModel.prototype.onHide = function ()
|
|||
{
|
||||
this.reset();
|
||||
kn.routeOn();
|
||||
|
||||
RL.data().keyScope(this.sKeyScope);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -8550,6 +8619,9 @@ PopupsComposeViewModel.prototype.editor = function (fOnInit)
|
|||
PopupsComposeViewModel.prototype.onShow = function (sType, oMessageOrArray, aToEmails)
|
||||
{
|
||||
kn.routeOff();
|
||||
|
||||
this.sKeyScope = RL.data().keyScope();
|
||||
RL.data().keyScope(Enums.KeyState.Compose);
|
||||
|
||||
var
|
||||
self = this,
|
||||
|
|
@ -8825,6 +8897,11 @@ PopupsComposeViewModel.prototype.tryToClosePopup = function ()
|
|||
}]);
|
||||
};
|
||||
|
||||
PopupsComposeViewModel.prototype.useShortcuts = function ()
|
||||
{
|
||||
return this.modalVisibility() && RL.data().useKeyboardShortcuts();
|
||||
};
|
||||
|
||||
PopupsComposeViewModel.prototype.onBuild = function ()
|
||||
{
|
||||
this.initUploader();
|
||||
|
|
@ -8834,29 +8911,25 @@ PopupsComposeViewModel.prototype.onBuild = function ()
|
|||
oScript = null
|
||||
;
|
||||
|
||||
$window.on('keydown', function (oEvent) {
|
||||
var bResult = true;
|
||||
|
||||
if (oEvent && self.modalVisibility() && RL.data().useKeyboardShortcuts())
|
||||
key('ctrl+s, command+s', Enums.KeyState.Compose, function () {
|
||||
if (self.useShortcuts())
|
||||
{
|
||||
if (oEvent.ctrlKey && !oEvent.shiftKey && !oEvent.altKey && Enums.EventKeyCode.S === oEvent.keyCode)
|
||||
{
|
||||
self.saveCommand();
|
||||
bResult = false;
|
||||
}
|
||||
else if (oEvent.ctrlKey && !oEvent.shiftKey && !oEvent.altKey && Enums.EventKeyCode.Enter === oEvent.keyCode)
|
||||
{
|
||||
self.sendCommand();
|
||||
bResult = false;
|
||||
}
|
||||
else if (Enums.EventKeyCode.Esc === oEvent.keyCode)
|
||||
{
|
||||
self.tryToClosePopup();
|
||||
bResult = false;
|
||||
}
|
||||
self.saveCommand();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return bResult;
|
||||
key('ctrl+enter, command+enter', Enums.KeyState.Compose, function () {
|
||||
if (self.useShortcuts())
|
||||
{
|
||||
self.sendCommand();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
key('esc', Enums.KeyState.Compose, function () {
|
||||
self.tryToClosePopup();
|
||||
return false;
|
||||
});
|
||||
|
||||
$window.on('resize', function () {
|
||||
|
|
@ -9569,10 +9642,6 @@ function PopupsContactsViewModel()
|
|||
return oContact ? oContact.generateUid() : '';
|
||||
});
|
||||
|
||||
this.selector.on('onDelete', _.bind(function () {
|
||||
this.deleteCommand();
|
||||
}, this));
|
||||
|
||||
this.newCommand = Utils.createCommand(this, function () {
|
||||
this.populateViewContact(null);
|
||||
this.currentContact(null);
|
||||
|
|
@ -9705,6 +9774,8 @@ function PopupsContactsViewModel()
|
|||
}
|
||||
}, this);
|
||||
|
||||
this.sKeyScope = Enums.KeyState.MessageList;
|
||||
|
||||
Knoin.constructorEnd(this);
|
||||
}
|
||||
|
||||
|
|
@ -9975,10 +10046,18 @@ PopupsContactsViewModel.prototype.onBuild = function (oDom)
|
|||
this.oContentVisible = $('.b-list-content', oDom);
|
||||
this.oContentScrollable = $('.content', this.oContentVisible);
|
||||
|
||||
this.selector.init(this.oContentVisible, this.oContentScrollable);
|
||||
this.selector.init(this.oContentVisible, this.oContentScrollable, Enums.KeyState.ContactList);
|
||||
|
||||
var self = this;
|
||||
|
||||
key('delete', Enums.KeyState.ContactList, function () {
|
||||
if (RL.data().useKeyboardShortcuts())
|
||||
{
|
||||
self.deleteCommand();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
ko.computed(function () {
|
||||
var
|
||||
bModalVisibility = this.modalVisibility(),
|
||||
|
|
@ -10005,6 +10084,9 @@ PopupsContactsViewModel.prototype.onShow = function ()
|
|||
{
|
||||
kn.routeOff();
|
||||
this.reloadContactList(true);
|
||||
|
||||
this.sKeyScope = RL.data().keyScope();
|
||||
RL.data().keyScope(Enums.KeyState.ContactList);
|
||||
};
|
||||
|
||||
PopupsContactsViewModel.prototype.onHide = function ()
|
||||
|
|
@ -10017,6 +10099,8 @@ PopupsContactsViewModel.prototype.onHide = function ()
|
|||
_.each(this.contacts(), function (oItem) {
|
||||
oItem.checked(false);
|
||||
});
|
||||
|
||||
RL.data().keyScope(this.sKeyScope);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -10936,6 +11020,7 @@ function PopupsAskViewModel()
|
|||
this.fNoAction = null;
|
||||
|
||||
this.bDisabeCloseOnEsc = true;
|
||||
this.sKeyScope = Enums.KeyState.MessageList;
|
||||
|
||||
Knoin.constructorEnd(this);
|
||||
}
|
||||
|
|
@ -10957,22 +11042,22 @@ PopupsAskViewModel.prototype.clearPopup = function ()
|
|||
|
||||
PopupsAskViewModel.prototype.yesClick = function ()
|
||||
{
|
||||
this.cancelCommand();
|
||||
|
||||
if (Utils.isFunc(this.fYesAction))
|
||||
{
|
||||
this.fYesAction.call(null);
|
||||
}
|
||||
|
||||
this.cancelCommand();
|
||||
};
|
||||
|
||||
PopupsAskViewModel.prototype.noClick = function ()
|
||||
{
|
||||
this.cancelCommand();
|
||||
|
||||
if (Utils.isFunc(this.fNoAction))
|
||||
{
|
||||
this.fNoAction.call(null);
|
||||
}
|
||||
|
||||
this.cancelCommand();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -10999,6 +11084,9 @@ PopupsAskViewModel.prototype.onShow = function (sAskDesc, fYesFunc, fNoFunc, sYe
|
|||
{
|
||||
this.yesButton(sNoButton);
|
||||
}
|
||||
|
||||
this.sKeyScope = RL.data().keyScope();
|
||||
RL.data().keyScope(Enums.KeyState.PopupAsk);
|
||||
};
|
||||
|
||||
PopupsAskViewModel.prototype.onFocus = function ()
|
||||
|
|
@ -11008,35 +11096,55 @@ PopupsAskViewModel.prototype.onFocus = function ()
|
|||
|
||||
PopupsAskViewModel.prototype.onHide = function ()
|
||||
{
|
||||
RL.data().keyScope(this.sKeyScope);
|
||||
};
|
||||
|
||||
PopupsAskViewModel.prototype.onBuild = function ()
|
||||
{
|
||||
var self = this;
|
||||
$window.on('keydown', function (oEvent) {
|
||||
var bResult = true;
|
||||
if (oEvent && self.modalVisibility())
|
||||
key('tab, right, left', Enums.KeyState.PopupAsk, _.bind(function () {
|
||||
if (this.modalVisibility())
|
||||
{
|
||||
if (Enums.EventKeyCode.Tab === oEvent.keyCode || Enums.EventKeyCode.Right === oEvent.keyCode || Enums.EventKeyCode.Left === oEvent.keyCode)
|
||||
if (this.yesFocus())
|
||||
{
|
||||
if (self.yesFocus())
|
||||
{
|
||||
self.noFocus(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.yesFocus(true);
|
||||
}
|
||||
|
||||
bResult = false;
|
||||
this.noFocus(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.yesFocus(true);
|
||||
}
|
||||
}
|
||||
|
||||
return bResult;
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}, this));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends KnoinAbstractViewModel
|
||||
*/
|
||||
function PopupsKeyboardShortcutsHelpViewModel()
|
||||
{
|
||||
KnoinAbstractViewModel.call(this, 'Popups', 'PopupsKeyboardShortcutsHelp');
|
||||
|
||||
this.sKeyScope = Enums.KeyState.None;
|
||||
|
||||
Knoin.constructorEnd(this);
|
||||
}
|
||||
|
||||
Utils.extendAsViewModel('PopupsKeyboardShortcutsHelpViewModel', PopupsKeyboardShortcutsHelpViewModel);
|
||||
|
||||
PopupsKeyboardShortcutsHelpViewModel.prototype.onShow = function ()
|
||||
{
|
||||
this.sKeyScope = RL.data().keyScope();
|
||||
RL.data().keyScope(Enums.KeyState.None);
|
||||
};
|
||||
|
||||
PopupsKeyboardShortcutsHelpViewModel.prototype.onHide = function ()
|
||||
{
|
||||
RL.data().keyScope(this.sKeyScope);
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends KnoinAbstractViewModel
|
||||
|
|
@ -11461,11 +11569,19 @@ Utils.extendAsViewModel('MailBoxFolderListViewModel', MailBoxFolderListViewModel
|
|||
MailBoxFolderListViewModel.prototype.onBuild = function (oDom)
|
||||
{
|
||||
oDom
|
||||
.on('click', '.b-folders .b-content', function () {
|
||||
if (RL.data().useKeyboardShortcuts() && RL.data().message.focused())
|
||||
{
|
||||
RL.data().message.focused(false);
|
||||
}
|
||||
})
|
||||
.on('click', '.b-folders .e-item .e-link .e-collapsed-sign', function (oEvent) {
|
||||
var
|
||||
|
||||
var
|
||||
oFolder = ko.dataFor(this),
|
||||
bCollapsed = false
|
||||
;
|
||||
|
||||
if (oFolder && oEvent)
|
||||
{
|
||||
bCollapsed = oFolder.collapsed();
|
||||
|
|
@ -11582,6 +11698,7 @@ function MailBoxMessageListViewModel()
|
|||
|
||||
this.popupVisibility = RL.popupVisibility;
|
||||
|
||||
this.message = oData.message;
|
||||
this.messageList = oData.messageList;
|
||||
this.currentMessage = oData.currentMessage;
|
||||
this.isMessageSelected = oData.isMessageSelected;
|
||||
|
|
@ -11780,13 +11897,6 @@ function MailBoxMessageListViewModel()
|
|||
return oMessage ? oMessage.generateUid() : '';
|
||||
});
|
||||
|
||||
this.selector.on('onDelete', _.bind(function () {
|
||||
if (0 < RL.data().messageListCheckedOrSelected().length)
|
||||
{
|
||||
this.deleteCommand();
|
||||
}
|
||||
}, this));
|
||||
|
||||
RL
|
||||
.sub('mailbox.message-list.selector.go-down', function () {
|
||||
this.selector.goDown();
|
||||
|
|
@ -12106,31 +12216,15 @@ MailBoxMessageListViewModel.prototype.onBuild = function (oDom)
|
|||
return false;
|
||||
});
|
||||
|
||||
this.selector.init(this.oContentVisible, this.oContentScrollable);
|
||||
|
||||
$document.on('keydown', function (oEvent) {
|
||||
|
||||
var
|
||||
bResult = true,
|
||||
iKeyCode = oEvent ? oEvent.keyCode : 0
|
||||
;
|
||||
|
||||
if (oEvent && self.viewModelVisibility() && oData.useKeyboardShortcuts() && !RL.popupVisibility() && !oData.messageFullScreenMode() && !Utils.inFocus())
|
||||
{
|
||||
if (Enums.Layout.NoPreview !== oData.layout() || (!oData.message() && (Enums.EventKeyCode.Delete === iKeyCode || Enums.EventKeyCode.A === iKeyCode)))
|
||||
{
|
||||
if (oEvent.ctrlKey && Enums.EventKeyCode.A === iKeyCode)
|
||||
{
|
||||
self.checkAll(!(self.checkAll() && !self.isIncompleteChecked()));
|
||||
bResult = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bResult;
|
||||
});
|
||||
this.selector.init(this.oContentVisible, this.oContentScrollable, Enums.KeyState.MessageList);
|
||||
|
||||
oDom
|
||||
.on('click', '.messageList .b-message-list-wrapper', function () {
|
||||
if (oData.useKeyboardShortcuts() && self.message.focused())
|
||||
{
|
||||
self.message.focused(false);
|
||||
}
|
||||
})
|
||||
.on('click', '.e-pagenator .e-page', function () {
|
||||
var oPage = ko.dataFor(this);
|
||||
if (oPage)
|
||||
|
|
@ -12191,6 +12285,7 @@ MailBoxMessageListViewModel.prototype.onBuild = function (oDom)
|
|||
}, this).extend({'notify': 'always'});
|
||||
|
||||
this.initUploaderForAppend();
|
||||
this.initShortcuts();
|
||||
|
||||
if (!Globals.bMobileDevice && !!RL.settingsGet('AllowPrefetch') && ifvisible)
|
||||
{
|
||||
|
|
@ -12202,6 +12297,121 @@ MailBoxMessageListViewModel.prototype.onBuild = function (oDom)
|
|||
}
|
||||
};
|
||||
|
||||
MailBoxMessageListViewModel.prototype.initShortcuts = function ()
|
||||
{
|
||||
var
|
||||
self = this,
|
||||
oData = RL.data()
|
||||
;
|
||||
|
||||
// disable print
|
||||
key('ctrl+p, command+p', Enums.KeyState.MessageList, function () {
|
||||
if (oData.useKeyboardShortcuts())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// delete
|
||||
key('delete, shift+delete', Enums.KeyState.MessageList, function (event, handler) {
|
||||
if (oData.useKeyboardShortcuts() && event)
|
||||
{
|
||||
if (0 < RL.data().messageListCheckedOrSelected().length)
|
||||
{
|
||||
if (handler && 'shift+delete' === handler.shortcut)
|
||||
{
|
||||
self.deleteWithoutMoveCommand();
|
||||
}
|
||||
else
|
||||
{
|
||||
self.deleteCommand();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// check all
|
||||
key('ctrl+a, command+a', Enums.KeyState.MessageList, function () {
|
||||
if (oData.useKeyboardShortcuts())
|
||||
{
|
||||
self.checkAll(!(self.checkAll() && !self.isIncompleteChecked()));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// new message (open compose popup)
|
||||
key('c,n', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () {
|
||||
if (oData.useKeyboardShortcuts())
|
||||
{
|
||||
kn.showScreenPopup(PopupsComposeViewModel);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// shortcuts help
|
||||
key('shift+/', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () {
|
||||
if (oData.useKeyboardShortcuts())
|
||||
{
|
||||
kn.showScreenPopup(PopupsKeyboardShortcutsHelpViewModel);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// search input focus
|
||||
key('/', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () {
|
||||
if (oData.useKeyboardShortcuts())
|
||||
{
|
||||
if (self.message())
|
||||
{
|
||||
self.message.focused(false);
|
||||
}
|
||||
|
||||
self.inputMessageListSearchFocus(true);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// cancel search
|
||||
key('esc', Enums.KeyState.MessageList, function () {
|
||||
if (oData.useKeyboardShortcuts() && '' !== self.messageListSearchDesc())
|
||||
{
|
||||
self.cancelSearch();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// change focused state
|
||||
key('tab, enter', Enums.KeyState.MessageList, function () {
|
||||
if (oData.useKeyboardShortcuts())
|
||||
{
|
||||
if (self.message())
|
||||
{
|
||||
self.message.focused(true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
key('ctrl+left, command+left', Enums.KeyState.MessageView, function () {
|
||||
if (oData.useKeyboardShortcuts())
|
||||
{
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
key('ctrl+right, command+right', Enums.KeyState.MessageView, function () {
|
||||
if (oData.useKeyboardShortcuts())
|
||||
{
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
MailBoxMessageListViewModel.prototype.prefetchNextTick = function ()
|
||||
{
|
||||
if (!this.bPrefetch && !ifvisible.now() && this.viewModelVisibility())
|
||||
|
|
@ -12329,6 +12539,7 @@ function MailBoxMessageViewViewModel()
|
|||
|
||||
this.oMessageScrollerDom = null;
|
||||
|
||||
this.keyScope = oData.keyScope;
|
||||
this.message = oData.message;
|
||||
this.messageLoading = oData.messageLoading;
|
||||
this.messageLoadingThrottle = oData.messageLoadingThrottle;
|
||||
|
|
@ -12344,6 +12555,7 @@ function MailBoxMessageViewViewModel()
|
|||
this.fullScreenMode = oData.messageFullScreenMode;
|
||||
|
||||
this.showFullInfo = ko.observable(false);
|
||||
this.messageDomFocused = ko.observable(false);
|
||||
|
||||
this.messageVisibility = ko.computed(function () {
|
||||
return !this.messageLoadingThrottle() && !!this.message();
|
||||
|
|
@ -12376,36 +12588,39 @@ function MailBoxMessageViewViewModel()
|
|||
}, this.messageVisibility);
|
||||
|
||||
this.deleteCommand = Utils.createCommand(this, function () {
|
||||
|
||||
if (this.message())
|
||||
{
|
||||
RL.deleteMessagesFromFolder(Enums.FolderType.Trash,
|
||||
this.message().folderFullNameRaw,
|
||||
[this.message().uid], true);
|
||||
}
|
||||
}, this.messageVisibility);
|
||||
|
||||
this.deleteWithoutMoveCommand = Utils.createCommand(this, function () {
|
||||
if (this.message())
|
||||
{
|
||||
RL.deleteMessagesFromFolder(Enums.FolderType.Trash,
|
||||
RL.data().currentFolderFullNameRaw(),
|
||||
RL.data().messageListCheckedOrSelectedUidsWithSubMails(), false);
|
||||
}
|
||||
}, this.messageVisibility);
|
||||
|
||||
this.archiveCommand = Utils.createCommand(this, function () {
|
||||
|
||||
if (this.message())
|
||||
{
|
||||
RL.deleteMessagesFromFolder(Enums.FolderType.Archive,
|
||||
this.message().folderFullNameRaw,
|
||||
[this.message().uid], true);
|
||||
}
|
||||
|
||||
}, this.messageVisibility);
|
||||
|
||||
this.spamCommand = Utils.createCommand(this, function () {
|
||||
|
||||
if (this.message())
|
||||
{
|
||||
RL.deleteMessagesFromFolder(Enums.FolderType.Spam,
|
||||
this.message().folderFullNameRaw,
|
||||
[this.message().uid], true);
|
||||
}
|
||||
|
||||
}, this.messageVisibility);
|
||||
|
||||
// viewer
|
||||
|
|
@ -12599,29 +12814,14 @@ MailBoxMessageViewViewModel.prototype.onBuild = function (oDom)
|
|||
self = this,
|
||||
oData = RL.data()
|
||||
;
|
||||
|
||||
$document.on('keydown', function (oEvent) {
|
||||
|
||||
var
|
||||
bResult = true,
|
||||
iKeyCode = oEvent ? oEvent.keyCode : 0
|
||||
;
|
||||
|
||||
if (0 < iKeyCode && (Enums.EventKeyCode.Esc === iKeyCode) &&
|
||||
self.viewModelVisibility() && oData.useKeyboardShortcuts() && !Utils.inFocus() && oData.message())
|
||||
this.fullScreenMode.subscribe(function (bValue) {
|
||||
if (bValue)
|
||||
{
|
||||
self.fullScreenMode(false);
|
||||
if (Enums.Layout.NoPreview === oData.layout())
|
||||
{
|
||||
RL.historyBack();
|
||||
}
|
||||
|
||||
bResult = false;
|
||||
self.message.focused(true);
|
||||
}
|
||||
|
||||
return bResult;
|
||||
});
|
||||
|
||||
}, this);
|
||||
|
||||
$('.attachmentsPlace', oDom).magnificPopup({
|
||||
'delegate': '.magnificPopupImage:visible',
|
||||
'type': 'image',
|
||||
|
|
@ -12643,6 +12843,12 @@ MailBoxMessageViewViewModel.prototype.onBuild = function (oDom)
|
|||
});
|
||||
|
||||
oDom
|
||||
.on('click', '.messageView .messageItem', function () {
|
||||
if (oData.useKeyboardShortcuts() && self.message())
|
||||
{
|
||||
self.message.focused(true);
|
||||
}
|
||||
})
|
||||
.on('mousedown', 'a', function (oEvent) {
|
||||
// setup maito protocol
|
||||
return !(oEvent && 3 !== oEvent['which'] && RL.mailToHelper($(this).attr('href')));
|
||||
|
|
@ -12666,8 +12872,171 @@ MailBoxMessageViewViewModel.prototype.onBuild = function (oDom)
|
|||
})
|
||||
;
|
||||
|
||||
this.message.focused.subscribe(function (bValue) {
|
||||
this.messageDomFocused(!!bValue);
|
||||
}, this);
|
||||
|
||||
this.keyScope.subscribe(function (sValue) {
|
||||
if (Enums.KeyState.MessageView === sValue && this.message.focused())
|
||||
{
|
||||
this.messageDomFocused(true);
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.oMessageScrollerDom = oDom.find('.messageItem .content');
|
||||
this.oMessageScrollerDom = this.oMessageScrollerDom && this.oMessageScrollerDom[0] ? this.oMessageScrollerDom : null;
|
||||
|
||||
this.initShortcuts();
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {boolean}
|
||||
*/
|
||||
MailBoxMessageViewViewModel.prototype.escShortcuts = function ()
|
||||
{
|
||||
if (this.viewModelVisibility() && RL.data().useKeyboardShortcuts() && this.message())
|
||||
{
|
||||
if (this.fullScreenMode())
|
||||
{
|
||||
this.fullScreenMode(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.message.focused(false);
|
||||
}
|
||||
|
||||
if (Enums.Layout.NoPreview === RL.data().layout())
|
||||
{
|
||||
RL.historyBack();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
MailBoxMessageViewViewModel.prototype.initShortcuts = function ()
|
||||
{
|
||||
var
|
||||
self = this,
|
||||
oData = RL.data()
|
||||
;
|
||||
|
||||
// exit fullscreen, back
|
||||
key('esc', Enums.KeyState.MessageView, _.bind(this.escShortcuts, this));
|
||||
|
||||
// fullscreen
|
||||
key('enter', Enums.KeyState.MessageView, function () {
|
||||
if (oData.useKeyboardShortcuts())
|
||||
{
|
||||
self.toggleFullScreen();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// reply
|
||||
key('r', Enums.KeyState.MessageView, function () {
|
||||
if (oData.useKeyboardShortcuts())
|
||||
{
|
||||
self.replyCommand();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// replaAll
|
||||
key('a', Enums.KeyState.MessageView, function () {
|
||||
if (oData.useKeyboardShortcuts())
|
||||
{
|
||||
self.replyAllCommand();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// forward
|
||||
key('f', Enums.KeyState.MessageView, function () {
|
||||
if (oData.useKeyboardShortcuts())
|
||||
{
|
||||
self.forwardCommand();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// message information
|
||||
key('i', Enums.KeyState.MessageView, function () {
|
||||
if (oData.useKeyboardShortcuts())
|
||||
{
|
||||
self.showFullInfo(!self.showFullInfo());
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
key('ctrl+left, command+left', Enums.KeyState.MessageView, function () {
|
||||
if (oData.useKeyboardShortcuts())
|
||||
{
|
||||
self.goDownCommand();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
key('ctrl+right, command+right', Enums.KeyState.MessageView, function () {
|
||||
if (oData.useKeyboardShortcuts())
|
||||
{
|
||||
self.goUpCommand();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// print
|
||||
key('ctrl+p, command+p', Enums.KeyState.MessageView, function () {
|
||||
if (oData.useKeyboardShortcuts())
|
||||
{
|
||||
if (self.message())
|
||||
{
|
||||
self.message().printMessage();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// archive
|
||||
// key('delete', Enums.KeyState.MessageView, function () {
|
||||
// if (oData.useKeyboardShortcuts())
|
||||
// {
|
||||
// self.archiveCommand();
|
||||
// return false;
|
||||
// }
|
||||
// });
|
||||
|
||||
// delete
|
||||
key('delete, shift+delete', Enums.KeyState.MessageView, function (event, handler) {
|
||||
if (oData.useKeyboardShortcuts() && event)
|
||||
{
|
||||
self.deleteCommand();
|
||||
if (handler && 'shift+delete' === handler.shortcut)
|
||||
{
|
||||
// self.deleteWithoutMoveCommand();
|
||||
self.deleteCommand();
|
||||
}
|
||||
else
|
||||
{
|
||||
self.deleteCommand();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// change focused state
|
||||
key('tab', Enums.KeyState.MessageView, function () {
|
||||
if (oData.useKeyboardShortcuts())
|
||||
{
|
||||
if (self.message())
|
||||
{
|
||||
self.message.focused(false);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -14241,12 +14610,27 @@ function WebMailDataStorage()
|
|||
this.accountIncLogin = ko.observable('');
|
||||
this.accountOutLogin = ko.observable('');
|
||||
this.projectHash = ko.observable('');
|
||||
|
||||
this.threading = ko.observable(false);
|
||||
this.lastFoldersHash = '';
|
||||
|
||||
this.lastFoldersHash = '';
|
||||
this.remoteSuggestions = false;
|
||||
|
||||
this.keyScope = ko.observable(Enums.KeyState.None);
|
||||
this.keyScope.subscribe(function (sValue) {
|
||||
|
||||
if (Enums.KeyState.Compose === sValue)
|
||||
{
|
||||
Utils.disableKeyFilter();
|
||||
}
|
||||
else
|
||||
{
|
||||
Utils.restoreKeyFilter();
|
||||
}
|
||||
|
||||
// window.console.log(sValue);
|
||||
key.setScope(sValue);
|
||||
});
|
||||
|
||||
// system folders
|
||||
this.sentFolder = ko.observable('');
|
||||
this.draftFolder = ko.observable('');
|
||||
|
|
@ -14461,6 +14845,23 @@ function WebMailDataStorage()
|
|||
this.messageLoading = ko.observable(false);
|
||||
this.messageLoadingThrottle = ko.observable(false).extend({'throttle': 50});
|
||||
|
||||
this.message.focused = ko.observable(false);
|
||||
|
||||
this.message.subscribe(function (oMessage) {
|
||||
if (!oMessage)
|
||||
{
|
||||
this.message.focused(false);
|
||||
}
|
||||
else if (Enums.Layout.NoPreview === this.layout())
|
||||
{
|
||||
this.message.focused(true);
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.message.focused.subscribe(function (bValue) {
|
||||
RL.data().keyScope(bValue ? Enums.KeyState.MessageView : Enums.KeyState.MessageList);
|
||||
});
|
||||
|
||||
this.messageLoading.subscribe(function (bValue) {
|
||||
this.messageLoadingThrottle(bValue);
|
||||
}, this);
|
||||
|
|
@ -17063,6 +17464,13 @@ MailBoxScreen.prototype.setNewTitle = function ()
|
|||
MailBoxScreen.prototype.onShow = function ()
|
||||
{
|
||||
this.setNewTitle();
|
||||
|
||||
RL.data().keyScope(Enums.KeyState.MessageList);
|
||||
};
|
||||
|
||||
MailBoxScreen.prototype.onHide = function ()
|
||||
{
|
||||
RL.data().keyScope(Enums.KeyState.None);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -18752,4 +19160,4 @@ if (window.SimplePace) {
|
|||
window.SimplePace.add(10);
|
||||
}
|
||||
|
||||
}(window, jQuery, ko, crossroads, hasher, moment, Jua, _, ifvisible));
|
||||
}(window, jQuery, ko, crossroads, hasher, moment, Jua, _, ifvisible, key));
|
||||
17
rainloop/v/0.0.0/static/js/app.min.js
vendored
17
rainloop/v/0.0.0/static/js/app.min.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -227,6 +227,314 @@ this.j[c]=i,g.on("click",function(){var a=b.b.d("onDialog");a&&a()}).on("change"
|
|||
j.c=e;j.h=0;j.a={};j.m={};j.q=f;j.e=f;j.on=function(a,b){this.m[a]=b;return this};j.g=function(a,b){this.m[a]&&this.m[a].apply(f,b||[])};j.d=function(a){return this.m[a]||f};j.cancel=function(a){this.e.cancel(a)};j.p=function(){return B.p};j.v=function(a){this.c=!!a};j.k=function(){return this.e.k()};j.s=function(a){this.r(w(),a)};
|
||||
j.r=function(a,b){var c=this.d("onSelect");if(b&&(!c||h!==c(a,b))){this.e.t(a);var g=this.e.u,d=this.e;this.q.defer(function(){return g.apply(q(d)?f:d,Array.prototype.slice.call(arguments))},a,b)}else this.e.cancel(a)};l.Jua=B;
|
||||
|
||||
// keymaster.js
|
||||
// (c) 2011-2013 Thomas Fuchs
|
||||
// keymaster.js may be freely distributed under the MIT license.
|
||||
|
||||
;(function(global){
|
||||
var k,
|
||||
_handlers = {},
|
||||
_mods = { 16: false, 18: false, 17: false, 91: false },
|
||||
_scope = 'all',
|
||||
// modifier keys
|
||||
_MODIFIERS = {
|
||||
'⇧': 16, shift: 16,
|
||||
'⌥': 18, alt: 18, option: 18,
|
||||
'⌃': 17, ctrl: 17, control: 17,
|
||||
'⌘': 91, command: 91
|
||||
},
|
||||
// special keys
|
||||
_MAP = {
|
||||
backspace: 8, tab: 9, clear: 12,
|
||||
enter: 13, 'return': 13,
|
||||
esc: 27, escape: 27, space: 32,
|
||||
left: 37, up: 38,
|
||||
right: 39, down: 40,
|
||||
insert: 45,
|
||||
del: 46, 'delete': 46,
|
||||
home: 36, end: 35,
|
||||
pageup: 33, pagedown: 34,
|
||||
',': 188, '.': 190, '/': 191,
|
||||
'`': 192, '-': 189, '=': 187,
|
||||
';': 186, '\'': 222,
|
||||
'[': 219, ']': 221, '\\': 220
|
||||
},
|
||||
code = function(x){
|
||||
return _MAP[x] || x.toUpperCase().charCodeAt(0);
|
||||
},
|
||||
_downKeys = [];
|
||||
|
||||
for(k=1;k<20;k++) _MAP['f'+k] = 111+k;
|
||||
|
||||
// IE doesn't support Array#indexOf, so have a simple replacement
|
||||
function index(array, item){
|
||||
var i = array.length;
|
||||
while(i--) if(array[i]===item) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// for comparing mods before unassignment
|
||||
function compareArray(a1, a2) {
|
||||
if (a1.length != a2.length) return false;
|
||||
for (var i = 0; i < a1.length; i++) {
|
||||
if (a1[i] !== a2[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
var modifierMap = {
|
||||
16:'shiftKey',
|
||||
18:'altKey',
|
||||
17:'ctrlKey',
|
||||
91:'metaKey'
|
||||
};
|
||||
function updateModifierKey(event) {
|
||||
for(k in _mods) _mods[k] = event[modifierMap[k]];
|
||||
};
|
||||
|
||||
// handle keydown event
|
||||
function dispatch(event) {
|
||||
var key, handler, k, i, modifiersMatch, scope;
|
||||
key = event.keyCode;
|
||||
|
||||
if (index(_downKeys, key) == -1) {
|
||||
_downKeys.push(key);
|
||||
}
|
||||
|
||||
// if a modifier key, set the key.<modifierkeyname> property to true and return
|
||||
if(key == 93 || key == 224) key = 91; // right command on webkit, command on Gecko
|
||||
if(key in _mods) {
|
||||
_mods[key] = true;
|
||||
// 'assignKey' from inside this closure is exported to window.key
|
||||
for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = true;
|
||||
return;
|
||||
}
|
||||
updateModifierKey(event);
|
||||
|
||||
// see if we need to ignore the keypress (filter() can can be overridden)
|
||||
// by default ignore key presses if a select, textarea, or input is focused
|
||||
if(!assignKey.filter.call(this, event)) return;
|
||||
|
||||
// abort if no potentially matching shortcuts found
|
||||
if (!(key in _handlers)) return;
|
||||
|
||||
scope = getScope();
|
||||
|
||||
// for each potential shortcut
|
||||
for (i = 0; i < _handlers[key].length; i++) {
|
||||
handler = _handlers[key][i];
|
||||
|
||||
// see if it's in the current scope
|
||||
if(handler.scope == scope || handler.scope == 'all'){
|
||||
// check if modifiers match if any
|
||||
modifiersMatch = handler.mods.length > 0;
|
||||
for(k in _mods)
|
||||
if((!_mods[k] && index(handler.mods, +k) > -1) ||
|
||||
(_mods[k] && index(handler.mods, +k) == -1)) modifiersMatch = false;
|
||||
// call the handler and stop the event if neccessary
|
||||
if((handler.mods.length == 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91]) || modifiersMatch){
|
||||
if(handler.method(event, handler)===false){
|
||||
if(event.preventDefault) event.preventDefault();
|
||||
else event.returnValue = false;
|
||||
if(event.stopPropagation) event.stopPropagation();
|
||||
if(event.cancelBubble) event.cancelBubble = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// unset modifier keys on keyup
|
||||
function clearModifier(event){
|
||||
var key = event.keyCode, k,
|
||||
i = index(_downKeys, key);
|
||||
|
||||
// remove key from _downKeys
|
||||
if (i >= 0) {
|
||||
_downKeys.splice(i, 1);
|
||||
}
|
||||
|
||||
if(key == 93 || key == 224) key = 91;
|
||||
if(key in _mods) {
|
||||
_mods[key] = false;
|
||||
for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = false;
|
||||
}
|
||||
};
|
||||
|
||||
function resetModifiers() {
|
||||
for(k in _mods) _mods[k] = false;
|
||||
for(k in _MODIFIERS) assignKey[k] = false;
|
||||
};
|
||||
|
||||
// parse and assign shortcut
|
||||
function assignKey(key, scope, method){
|
||||
var keys, mods, bScopeIsArray = false;
|
||||
keys = getKeys(key);
|
||||
if (method === undefined) {
|
||||
method = scope;
|
||||
scope = 'all';
|
||||
}
|
||||
|
||||
bScopeIsArray = !!(typeof scope !== 'string' && scope.length && typeof scope[0] === 'string');
|
||||
|
||||
// for each shortcut
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
// set modifier keys if any
|
||||
mods = [];
|
||||
key = keys[i].split('+');
|
||||
if (key.length > 1){
|
||||
mods = getMods(key);
|
||||
key = [key[key.length-1]];
|
||||
}
|
||||
// convert to keycode and...
|
||||
key = key[0];
|
||||
key = code(key);
|
||||
// ...store handler
|
||||
if (!(key in _handlers)) _handlers[key] = [];
|
||||
|
||||
if (bScopeIsArray) {
|
||||
for (var j = 0; j < scope.length; j++) {
|
||||
_handlers[key].push({ shortcut: keys[i], scope: scope[j], method: method, key: keys[i], mods: mods });
|
||||
}
|
||||
} else {
|
||||
_handlers[key].push({ shortcut: keys[i], scope: scope, method: method, key: keys[i], mods: mods });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// unbind all handlers for given key in current scope
|
||||
function unbindKey(key, scope) {
|
||||
var multipleKeys, keys,
|
||||
mods = [],
|
||||
i, j, obj;
|
||||
|
||||
multipleKeys = getKeys(key);
|
||||
|
||||
for (j = 0; j < multipleKeys.length; j++) {
|
||||
keys = multipleKeys[j].split('+');
|
||||
|
||||
if (keys.length > 1) {
|
||||
mods = getMods(keys);
|
||||
key = keys[keys.length - 1];
|
||||
}
|
||||
|
||||
key = code(key);
|
||||
|
||||
if (scope === undefined) {
|
||||
scope = getScope();
|
||||
}
|
||||
if (!_handlers[key]) {
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < _handlers[key].length; i++) {
|
||||
obj = _handlers[key][i];
|
||||
// only clear handlers if correct scope and mods match
|
||||
if (obj.scope === scope && compareArray(obj.mods, mods)) {
|
||||
_handlers[key][i] = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Returns true if the key with code 'keyCode' is currently down
|
||||
// Converts strings into key codes.
|
||||
function isPressed(keyCode) {
|
||||
if (typeof(keyCode)=='string') {
|
||||
keyCode = code(keyCode);
|
||||
}
|
||||
return index(_downKeys, keyCode) != -1;
|
||||
}
|
||||
|
||||
function getPressedKeyCodes() {
|
||||
return _downKeys.slice(0);
|
||||
}
|
||||
|
||||
function filter(event){
|
||||
var tagName = (event.target || event.srcElement).tagName;
|
||||
// ignore keypressed in any elements that support keyboard data input
|
||||
return !(tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA');
|
||||
}
|
||||
|
||||
// initialize key.<modifier> to false
|
||||
for(k in _MODIFIERS) assignKey[k] = false;
|
||||
|
||||
// set current scope (default 'all')
|
||||
function setScope(scope){ _scope = scope || 'all' };
|
||||
function getScope(){ return _scope || 'all' };
|
||||
|
||||
// delete all handlers for a given scope
|
||||
function deleteScope(scope){
|
||||
var key, handlers, i;
|
||||
|
||||
for (key in _handlers) {
|
||||
handlers = _handlers[key];
|
||||
for (i = 0; i < handlers.length; ) {
|
||||
if (handlers[i].scope === scope) handlers.splice(i, 1);
|
||||
else i++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// abstract key logic for assign and unassign
|
||||
function getKeys(key) {
|
||||
var keys;
|
||||
key = key.replace(/\s/g, '');
|
||||
keys = key.split(',');
|
||||
if ((keys[keys.length - 1]) == '') {
|
||||
keys[keys.length - 2] += ',';
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
// abstract mods logic for assign and unassign
|
||||
function getMods(key) {
|
||||
var mods = key.slice(0, key.length - 1);
|
||||
for (var mi = 0; mi < mods.length; mi++)
|
||||
mods[mi] = _MODIFIERS[mods[mi]];
|
||||
return mods;
|
||||
}
|
||||
|
||||
// cross-browser events
|
||||
function addEvent(object, event, method) {
|
||||
if (object.addEventListener)
|
||||
object.addEventListener(event, method, false);
|
||||
else if(object.attachEvent)
|
||||
object.attachEvent('on'+event, function(){ method(window.event) });
|
||||
};
|
||||
|
||||
// set the handlers globally on document
|
||||
addEvent(document, 'keydown', function(event) { dispatch(event) }); // Passing _scope to a callback to ensure it remains the same by execution. Fixes #48
|
||||
addEvent(document, 'keyup', clearModifier);
|
||||
|
||||
// reset modifiers to false whenever the window is (re)focused.
|
||||
addEvent(window, 'focus', resetModifiers);
|
||||
|
||||
// store previously defined key
|
||||
var previousKey = global.key;
|
||||
|
||||
// restore previously defined key and return reference to our key object
|
||||
function noConflict() {
|
||||
var k = global.key;
|
||||
global.key = previousKey;
|
||||
return k;
|
||||
}
|
||||
|
||||
// set window.key and window.key.set/get/deleteScope, and the default filter
|
||||
global.key = assignKey;
|
||||
global.key.setScope = setScope;
|
||||
global.key.getScope = getScope;
|
||||
global.key.deleteScope = deleteScope;
|
||||
global.key.filter = filter;
|
||||
global.key.isPressed = isPressed;
|
||||
global.key.getPressedKeyCodes = getPressedKeyCodes;
|
||||
global.key.noConflict = noConflict;
|
||||
global.key.unbind = unbindKey;
|
||||
|
||||
if(typeof module !== 'undefined') module.exports = key;
|
||||
|
||||
})(this);
|
||||
|
||||
|
||||
/*!ifvisible.js v1.0.0 (c) 2013 Serkan Yersen | MIT */
|
||||
(function(){"use strict";var a,b,c,d,e,f,g,h,i,j,k,l,m,n;i={},c=document,k=!1,l="active",g=6e4,f=!1,b=function(){var a,b,c,d,e,f;return a=function(){return(65536*(1+Math.random())|0).toString(16).substring(1)},e=function(){return a()+a()+"-"+a()+"-"+a()+"-"+a()+"-"+a()+a()+a()},f={},c="__ceGUID",b=function(a,b,d){return a[c]=void 0,a[c]||(a[c]="ifvisible.object.event.identifier"),f[a[c]]||(f[a[c]]={}),f[a[c]][b]||(f[a[c]][b]=[]),f[a[c]][b].push(d)},d=function(a,b,d){var e,g,h,i,j;if(a[c]&&f[a[c]]&&f[a[c]][b]){for(i=f[a[c]][b],j=[],g=0,h=i.length;h>g;g++)e=i[g],j.push(e(d||{}));return j}},{add:b,fire:d}}(),a=function(){var a;return a=!1,function(b,c,d){return a||(a=b.addEventListener?function(a,b,c){return a.addEventListener(b,c,!1)}:b.attachEvent?function(a,b,c){return a.attachEvent("on"+b,c,!1)}:function(a,b,c){return a["on"+b]=c}),a(b,c,d)}}(),d=function(a,b){var d;return c.createEventObject?a.fireEvent("on"+b,d):(d=c.createEvent("HTMLEvents"),d.initEvent(b,!0,!0),!a.dispatchEvent(d))},h=function(){var a,b,d,e,f;for(e=void 0,f=3,d=c.createElement("div"),a=d.getElementsByTagName("i"),b=function(){return d.innerHTML="<!--[if gt IE "+ ++f+"]><i></i><![endif]-->",a[0]};b(););return f>4?f:e}(),e=!1,n=void 0,"undefined"!=typeof c.hidden?(e="hidden",n="visibilitychange"):"undefined"!=typeof c.mozHidden?(e="mozHidden",n="mozvisibilitychange"):"undefined"!=typeof c.msHidden?(e="msHidden",n="msvisibilitychange"):"undefined"!=typeof c.webkitHidden&&(e="webkitHidden",n="webkitvisibilitychange"),m=function(){var b,d;return b=!1,d=function(){return clearTimeout(b),"active"!==l&&i.wakeup(),f=+new Date,b=setTimeout(function(){return"active"===l?i.idle():void 0},g)},d(),a(c,"mousemove",d),a(c,"keyup",d),a(window,"scroll",d),i.focus(d)},j=function(){var b;return k?!0:(e===!1?(b="blur",9>h&&(b="focusout"),a(window,b,function(){return i.blur()}),a(window,"focus",function(){return i.focus()})):a(c,n,function(){return c[e]?i.blur():i.focus()},!1),k=!0,m())},i={setIdleDuration:function(a){return g=1e3*a},getIdleDuration:function(){return g},getIdleInfo:function(){var a,b;return a=+new Date,b={},"idle"===l?(b.isIdle=!0,b.idleFor=a-f,b.timeLeft=0,b.timeLeftPer=100):(b.isIdle=!1,b.idleFor=a-f,b.timeLeft=f+g-a,b.timeLeftPer=(100-100*b.timeLeft/g).toFixed(2)),b},focus:function(a){return"function"==typeof a?this.on("focus",a):(l="active",b.fire(this,"focus"),b.fire(this,"wakeup"),b.fire(this,"statusChanged",{status:l}))},blur:function(a){return"function"==typeof a?this.on("blur",a):(l="hidden",b.fire(this,"blur"),b.fire(this,"idle"),b.fire(this,"statusChanged",{status:l}))},idle:function(a){return"function"==typeof a?this.on("idle",a):(l="idle",b.fire(this,"idle"),b.fire(this,"statusChanged",{status:l}))},wakeup:function(a){return"function"==typeof a?this.on("wakeup",a):(l="active",b.fire(this,"wakeup"),b.fire(this,"statusChanged",{status:l}))},on:function(a,c){return j(),b.add(this,a,c)},onEvery:function(a,b){var c;return j(),c=setInterval(function(){return"active"===l?b():void 0},1e3*a),{stop:function(){return clearInterval(c)},code:c,callback:b}},now:function(){return j(),"active"===l}},"function"==typeof define&&define.amd?define(function(){return i}):window.ifvisible=i}).call(this);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue