move views

This commit is contained in:
antelle 2019-09-16 17:43:57 +02:00
parent ad0963e412
commit 7730486f30
10 changed files with 445 additions and 442 deletions

View File

@ -150,7 +150,7 @@ ready(() => {
function showView() { function showView() {
appModel.prepare(); appModel.prepare();
new AppView({ model: appModel }).render(); new AppView(appModel).render();
Backbone.trigger('app-ready'); Backbone.trigger('app-ready');
logStartupTime(); logStartupTime();
} }

View File

@ -16,7 +16,7 @@ const Resizable = {
let size = dragInfo.startSize + e.offset; let size = dragInfo.startSize + e.offset;
size = Math.max(dragInfo.min, Math.min(dragInfo.max, size)); size = Math.max(dragInfo.min, Math.min(dragInfo.max, size));
this.$el[dragInfo.prop](size); this.$el[dragInfo.prop](size);
this.trigger('view-resize', size); this.emit('view-resize', size);
Backbone.trigger('page-geometry', { source: 'resizable' }); Backbone.trigger('page-geometry', { source: 'resizable' });
}, },
@ -28,7 +28,7 @@ const Resizable = {
this.$el.css(dragInfo.prop, 'auto'); this.$el.css(dragInfo.prop, 'auto');
} }
this.fixSize(dragInfo); this.fixSize(dragInfo);
this.trigger('view-resize', null); this.emit('view-resize', null);
Backbone.trigger('page-geometry', { source: 'resizable' }); Backbone.trigger('page-geometry', { source: 'resizable' });
}, },

View File

@ -6,9 +6,10 @@ import { Logger } from 'util/logger';
class View extends EventEmitter { class View extends EventEmitter {
parent = undefined; parent = undefined;
replace = false;
template = undefined; template = undefined;
events = {}; events = {};
model = undefined;
options = {};
views = {}; views = {};
hidden = false; hidden = false;
removed = false; removed = false;
@ -19,13 +20,7 @@ class View extends EventEmitter {
super(); super();
this.model = model; this.model = model;
this.options = options;
if (options.parent) {
this.parent = options.parent;
}
if (options.replace) {
this.replace = options.replace;
}
this.setMaxListeners(100); this.setMaxListeners(100);
} }
@ -55,24 +50,31 @@ class View extends EventEmitter {
renderElement(templateData) { renderElement(templateData) {
const html = this.template(templateData); const html = this.template(templateData);
if (this.el) { if (this.el) {
morphdom(this.el, html); const mountRoot = this.options.ownParent ? this.el.firstChild : this.el;
morphdom(mountRoot, html);
} else { } else {
if (this.parent) { let parent = this.options.parent || this.parent;
let parent = this.parent; if (parent) {
if (typeof parent === 'string') { if (typeof parent === 'string') {
parent = document.querySelector(this.parent); parent = document.querySelector(parent);
} }
if (!parent) { if (!parent) {
throw new Error(`Error rendering ${this.constructor.name}: parent not found`); throw new Error(`Error rendering ${this.constructor.name}: parent not found`);
} }
if (this.replace) { if (this.options.replace) {
Tip.destroyTips(parent); Tip.destroyTips(parent);
parent.innerHTML = ''; parent.innerHTML = '';
} }
const el = document.createElement('div'); const el = document.createElement('div');
el.innerHTML = html; el.innerHTML = html;
this.el = el.firstChild; const root = el.firstChild;
parent.appendChild(this.el); if (this.options.ownParent) {
parent.appendChild(root);
this.el = parent;
} else {
this.el = root;
parent.appendChild(this.el);
}
} else { } else {
throw new Error( throw new Error(
`Error rendering ${this.constructor.name}: I don't know how to insert the view` `Error rendering ${this.constructor.name}: I don't know how to insert the view`
@ -145,6 +147,7 @@ class View extends EventEmitter {
} }
stopListening(model, event, callback) { stopListening(model, event, callback) {
// TODO: remove a pending callback
model.off(event, callback); model.off(event, callback);
} }

View File

@ -1,4 +1,5 @@
import Backbone from 'backbone'; import Backbone from 'backbone';
import { View } from 'view-engine/view';
import { IdleTracker } from 'comp/browser/idle-tracker'; import { IdleTracker } from 'comp/browser/idle-tracker';
import { KeyHandler } from 'comp/browser/key-handler'; import { KeyHandler } from 'comp/browser/key-handler';
import { Launcher } from 'comp/launcher'; import { Launcher } from 'comp/launcher';
@ -22,32 +23,31 @@ import { MenuView } from 'views/menu/menu-view';
import { OpenView } from 'views/open-view'; import { OpenView } from 'views/open-view';
import { SettingsView } from 'views/settings/settings-view'; import { SettingsView } from 'views/settings/settings-view';
import { TagView } from 'views/tag-view'; import { TagView } from 'views/tag-view';
import template from 'templates/app.hbs';
const AppView = Backbone.View.extend({ class AppView extends View {
el: 'body', parent = 'body';
template: require('templates/app.hbs'), template = template;
events: { events = {
'contextmenu': 'contextMenu', contextmenu: 'contextMenu',
'drop': 'drop', drop: 'drop',
'dragenter': 'dragover', dragenter: 'dragover',
'dragover': 'dragover', dragover: 'dragover',
'click a[target=_blank]': 'extLinkClick', 'click a[target=_blank]': 'extLinkClick',
'mousedown': 'bodyClick' mousedown: 'bodyClick'
}, };
views: null, titlebarStyle = 'default';
titlebarStyle: 'default', constructor(model) {
super(model);
initialize() { this.views.menu = new MenuView(this.model.menu, { ownParent: true });
this.views = {};
this.views.menu = new MenuView({ model: this.model.menu });
this.views.menuDrag = new DragView('x', { parent: '.app__menu-drag' }); this.views.menuDrag = new DragView('x', { parent: '.app__menu-drag' });
this.views.footer = new FooterView(this.model); this.views.footer = new FooterView(this.model);
this.views.listWrap = new ListWrapView(this.model); this.views.listWrap = new ListWrapView(this.model);
this.views.list = new ListView({ model: this.model }); this.views.list = new ListView(this.model);
this.views.listDrag = new DragView('x', { parent: '.app__list-drag' }); this.views.listDrag = new DragView('x', { parent: '.app__list-drag' });
this.views.list.dragView = this.views.listDrag; this.views.list.dragView = this.views.listDrag;
this.views.details = new DetailsView(); this.views.details = new DetailsView();
@ -95,13 +95,12 @@ const AppView = Backbone.View.extend({
window.onresize = this.windowResize.bind(this); window.onresize = this.windowResize.bind(this);
window.onblur = this.windowBlur.bind(this); window.onblur = this.windowBlur.bind(this);
KeyHandler.onKey(Keys.DOM_VK_ESCAPE, this.escPressed, this); this.onKey(Keys.DOM_VK_ESCAPE, this.escPressed);
KeyHandler.onKey(Keys.DOM_VK_BACK_SPACE, this.backspacePressed, this); this.onKey(Keys.DOM_VK_BACK_SPACE, this.backspacePressed);
if (Launcher && Launcher.devTools) { if (Launcher && Launcher.devTools) {
KeyHandler.onKey( KeyHandler.onKey(
Keys.DOM_VK_I, Keys.DOM_VK_I,
this.openDevTools, this.openDevTools,
this,
KeyHandler.SHORTCUT_ACTION + KeyHandler.SHORTCUT_OPT KeyHandler.SHORTCUT_ACTION + KeyHandler.SHORTCUT_OPT
); );
} }
@ -110,7 +109,7 @@ const AppView = Backbone.View.extend({
this.setWindowClass(); this.setWindowClass();
this.fixClicksInEdge(); this.fixClicksInEdge();
}, }
setWindowClass() { setWindowClass() {
const getBrowserCssClass = Features.getBrowserCssClass(); const getBrowserCssClass = Features.getBrowserCssClass();
@ -120,7 +119,7 @@ const AppView = Backbone.View.extend({
if (this.titlebarStyle !== 'default') { if (this.titlebarStyle !== 'default') {
this.$el.addClass('titlebar-' + this.titlebarStyle); this.$el.addClass('titlebar-' + this.titlebarStyle);
} }
}, }
fixClicksInEdge() { fixClicksInEdge() {
// MS Edge doesn't want to handle clicks by default // MS Edge doesn't want to handle clicks by default
@ -133,26 +132,24 @@ const AppView = Backbone.View.extend({
.focus(); .focus();
setTimeout(() => msEdgeScrewer.remove(), 0); setTimeout(() => msEdgeScrewer.remove(), 0);
} }
}, }
render() { render() {
this.$el.html( super.render({
this.template({ beta: this.model.isBeta,
beta: this.model.isBeta, titlebarStyle: this.titlebarStyle
titlebarStyle: this.titlebarStyle });
})
);
this.panelEl = this.$el.find('.app__panel:first'); this.panelEl = this.$el.find('.app__panel:first');
this.views.listWrap.render(); this.views.listWrap.render();
this.views.menu.setElement(this.$el.find('.app__menu')).render(); this.views.menu.render();
this.views.menuDrag.render(); this.views.menuDrag.render();
this.views.footer.render(); this.views.footer.render();
this.views.list.setElement(this.$el.find('.app__list')).render(); this.views.list.render();
this.views.listDrag.render(); this.views.listDrag.render();
this.views.details.setElement(this.$el.find('.app__details')).render(); this.views.details.setElement(this.$el.find('.app__details')).render();
this.showLastOpenFile(); this.showLastOpenFile();
return this; return this;
}, }
showOpenFile() { showOpenFile() {
this.hideContextMenu(); this.hideContextMenu();
@ -167,17 +164,13 @@ const AppView = Backbone.View.extend({
this.hideSettings(); this.hideSettings();
this.hideOpenFile(); this.hideOpenFile();
this.hideKeyChange(); this.hideKeyChange();
this.views.open = new OpenView({ model: this.model }); this.views.open = new OpenView(this.model);
this.views.open.setElement(this.$el.find('.app__body')).render(); this.views.open.render();
this.views.open.on( this.views.open.on('close', () => {
'close', Backbone.trigger('closed-open-view');
() => { });
Backbone.trigger('closed-open-view'); this.views.open.on('close', () => this.showEntries());
}, }
this
);
this.views.open.on('close', this.showEntries, this);
},
showLastOpenFile() { showLastOpenFile() {
this.showOpenFile(); this.showOpenFile();
@ -186,14 +179,14 @@ const AppView = Backbone.View.extend({
this.views.open.currentSelectedIndex = 0; this.views.open.currentSelectedIndex = 0;
this.views.open.showOpenFileInfo(lastOpenFile); this.views.open.showOpenFileInfo(lastOpenFile);
} }
}, }
launcherOpenFile(file) { launcherOpenFile(file) {
if (file && file.data && /\.kdbx$/i.test(file.data)) { if (file && file.data && /\.kdbx$/i.test(file.data)) {
this.showOpenFile(); this.showOpenFile();
this.views.open.showOpenLocalFile(file.data, file.key); this.views.open.showOpenLocalFile(file.data, file.key);
} }
}, }
updateApp() { updateApp() {
if ( if (
@ -203,7 +196,7 @@ const AppView = Backbone.View.extend({
) { ) {
window.location.reload(); window.location.reload();
} }
}, }
showEntries() { showEntries() {
this.views.menu.show(); this.views.menu.show();
@ -217,14 +210,14 @@ const AppView = Backbone.View.extend({
this.hideOpenFile(); this.hideOpenFile();
this.hideSettings(); this.hideSettings();
this.hideKeyChange(); this.hideKeyChange();
}, }
hideOpenFile() { hideOpenFile() {
if (this.views.open) { if (this.views.open) {
this.views.open.remove(); this.views.open.remove();
this.views.open = null; this.views.open = null;
} }
}, }
hidePanelView() { hidePanelView() {
if (this.views.panel) { if (this.views.panel) {
@ -232,7 +225,7 @@ const AppView = Backbone.View.extend({
this.views.panel = null; this.views.panel = null;
this.panelEl.addClass('hide'); this.panelEl.addClass('hide');
} }
}, }
showPanelView(view) { showPanelView(view) {
this.views.listWrap.hide(); this.views.listWrap.hide();
@ -243,7 +236,7 @@ const AppView = Backbone.View.extend({
view.render(); view.render();
this.views.panel = view; this.views.panel = view;
this.panelEl.removeClass('hide'); this.panelEl.removeClass('hide');
}, }
hideSettings() { hideSettings() {
if (this.views.settings) { if (this.views.settings) {
@ -251,14 +244,14 @@ const AppView = Backbone.View.extend({
this.views.settings.remove(); this.views.settings.remove();
this.views.settings = null; this.views.settings = null;
} }
}, }
hideKeyChange() { hideKeyChange() {
if (this.views.keyChange) { if (this.views.keyChange) {
this.views.keyChange.hide(); this.views.keyChange.hide();
this.views.keyChange = null; this.views.keyChange = null;
} }
}, }
showSettings(selectedMenuItem) { showSettings(selectedMenuItem) {
this.model.menu.setMenu('settings'); this.model.menu.setMenu('settings');
@ -278,15 +271,15 @@ const AppView = Backbone.View.extend({
} }
this.model.menu.select({ item: selectedMenuItem }); this.model.menu.select({ item: selectedMenuItem });
this.views.menu.switchVisibility(false); this.views.menu.switchVisibility(false);
}, }
showEditGroup(group) { showEditGroup(group) {
this.showPanelView(new GrpView(group)); this.showPanelView(new GrpView(group));
}, }
showEditTag() { showEditTag() {
this.showPanelView(new TagView(this.model)); this.showPanelView(new TagView(this.model));
}, }
showKeyChange(file, viewConfig) { showKeyChange(file, viewConfig) {
if (Alerts.alertDisplayed) { if (Alerts.alertDisplayed) {
@ -310,7 +303,7 @@ const AppView = Backbone.View.extend({
this.views.keyChange.render(); this.views.keyChange.render();
this.views.keyChange.on('accept', this.keyChangeAccept.bind(this)); this.views.keyChange.on('accept', this.keyChangeAccept.bind(this));
this.views.keyChange.on('cancel', this.showEntries.bind(this)); this.views.keyChange.on('cancel', this.showEntries.bind(this));
}, }
fileListUpdated() { fileListUpdated() {
if (this.model.files.hasOpenFiles()) { if (this.model.files.hasOpenFiles()) {
@ -319,7 +312,7 @@ const AppView = Backbone.View.extend({
this.showOpenFile(); this.showOpenFile();
} }
this.fixClicksInEdge(); this.fixClicksInEdge();
}, }
showFileSettings(e) { showFileSettings(e) {
const menuItem = this.model.menu.filesSection const menuItem = this.model.menu.filesSection
@ -334,7 +327,7 @@ const AppView = Backbone.View.extend({
} else { } else {
this.showSettings(menuItem); this.showSettings(menuItem);
} }
}, }
toggleOpenFile() { toggleOpenFile() {
if (this.views.open) { if (this.views.open) {
@ -344,7 +337,7 @@ const AppView = Backbone.View.extend({
} else { } else {
this.showOpenFile(); this.showOpenFile();
} }
}, }
beforeUnload(e) { beforeUnload(e) {
const exitEvent = { const exitEvent = {
@ -419,70 +412,70 @@ const AppView = Backbone.View.extend({
Launcher.minimizeApp(); Launcher.minimizeApp();
return Launcher.preventExit(e); return Launcher.preventExit(e);
} }
}, }
windowResize() { windowResize() {
Backbone.trigger('page-geometry', { source: 'window' }); Backbone.trigger('page-geometry', { source: 'window' });
}, }
windowBlur(e) { windowBlur(e) {
if (e.target === window) { if (e.target === window) {
Backbone.trigger('page-blur'); Backbone.trigger('page-blur');
} }
}, }
enterFullScreen() { enterFullScreen() {
this.$el.addClass('fullscreen'); this.$el.addClass('fullscreen');
}, }
leaveFullScreen() { leaveFullScreen() {
this.$el.removeClass('fullscreen'); this.$el.removeClass('fullscreen');
}, }
escPressed() { escPressed() {
if (this.views.open && this.model.files.hasOpenFiles()) { if (this.views.open && this.model.files.hasOpenFiles()) {
this.showEntries(); this.showEntries();
} }
}, }
backspacePressed(e) { backspacePressed(e) {
if (e.target === document.body) { if (e.target === document.body) {
e.preventDefault(); e.preventDefault();
} }
}, }
openDevTools() { openDevTools() {
if (Launcher && Launcher.devTools) { if (Launcher && Launcher.devTools) {
Launcher.openDevTools(); Launcher.openDevTools();
} }
}, }
selectAll() { selectAll() {
this.menuSelect({ item: this.model.menu.allItemsSection.get('items').first() }); this.menuSelect({ item: this.model.menu.allItemsSection.get('items').first() });
}, }
menuSelect(opt) { menuSelect(opt) {
this.model.menu.select(opt); this.model.menu.select(opt);
if (this.views.panel && !this.views.panel.isHidden()) { if (this.views.panel && !this.views.panel.isHidden()) {
this.showEntries(); this.showEntries();
} }
}, }
userIdle() { userIdle() {
this.lockWorkspace(true); this.lockWorkspace(true);
}, }
osLocked() { osLocked() {
if (this.model.settings.get('lockOnOsLock')) { if (this.model.settings.get('lockOnOsLock')) {
this.lockWorkspace(true); this.lockWorkspace(true);
} }
}, }
appMinimized() { appMinimized() {
if (this.model.settings.get('lockOnMinimize')) { if (this.model.settings.get('lockOnMinimize')) {
this.lockWorkspace(true); this.lockWorkspace(true);
} }
}, }
lockWorkspace(autoInit) { lockWorkspace(autoInit) {
if (Alerts.alertDisplayed) { if (Alerts.alertDisplayed) {
@ -518,7 +511,7 @@ const AppView = Backbone.View.extend({
} else { } else {
this.closeAllFilesAndShowFirst(); this.closeAllFilesAndShowFirst();
} }
}, }
handleAutoSaveTimer() { handleAutoSaveTimer() {
if (this.model.settings.get('autoSaveInterval') !== 0) { if (this.model.settings.get('autoSaveInterval') !== 0) {
@ -531,7 +524,7 @@ const AppView = Backbone.View.extend({
this.model.settings.get('autoSaveInterval') * 1000 * 60 this.model.settings.get('autoSaveInterval') * 1000 * 60
); );
} }
}, }
saveAndLock(complete) { saveAndLock(complete) {
let pendingCallbacks = 0; let pendingCallbacks = 0;
@ -574,7 +567,7 @@ const AppView = Backbone.View.extend({
} }
} }
} }
}, }
closeAllFilesAndShowFirst() { closeAllFilesAndShowFirst() {
let fileToShow = this.model.files.find(file => !file.get('demo') && !file.get('created')); let fileToShow = this.model.files.find(file => !file.get('demo') && !file.get('created'));
@ -592,27 +585,27 @@ const AppView = Backbone.View.extend({
this.views.open.showOpenFileInfo(fileInfo); this.views.open.showOpenFileInfo(fileInfo);
} }
} }
}, }
saveAll() { saveAll() {
this.model.files.forEach(function(file) { this.model.files.forEach(function(file) {
this.model.syncFile(file); this.model.syncFile(file);
}, this); }, this);
}, }
syncAllByTimer() { syncAllByTimer() {
if (this.model.settings.get('autoSave')) { if (this.model.settings.get('autoSave')) {
this.saveAll(); this.saveAll();
} }
}, }
remoteKeyChanged(e) { remoteKeyChanged(e) {
this.showKeyChange(e.file, { remote: true }); this.showKeyChange(e.file, { remote: true });
}, }
keyChangePending(e) { keyChangePending(e) {
this.showKeyChange(e.file, { expired: true }); this.showKeyChange(e.file, { expired: true });
}, }
keyChangeAccept(e) { keyChangeAccept(e) {
this.showEntries(); this.showEntries();
@ -632,7 +625,7 @@ const AppView = Backbone.View.extend({
} }
}); });
} }
}, }
toggleSettings(page) { toggleSettings(page) {
let menuItem = page ? this.model.menu[page + 'Section'] : null; let menuItem = page ? this.model.menu[page + 'Section'] : null;
@ -658,16 +651,16 @@ const AppView = Backbone.View.extend({
this.model.menu.select({ item: menuItem }); this.model.menu.select({ item: menuItem });
} }
} }
}, }
toggleMenu() { toggleMenu() {
this.views.menu.switchVisibility(); this.views.menu.switchVisibility();
}, }
toggleDetails(visible) { toggleDetails(visible) {
this.$el.find('.app').toggleClass('app--details-visible', visible); this.$el.find('.app').toggleClass('app--details-visible', visible);
this.views.menu.switchVisibility(false); this.views.menu.switchVisibility(false);
}, }
editGroup(group) { editGroup(group) {
if (group && !(this.views.panel instanceof GrpView)) { if (group && !(this.views.panel instanceof GrpView)) {
@ -675,7 +668,7 @@ const AppView = Backbone.View.extend({
} else { } else {
this.showEntries(); this.showEntries();
} }
}, }
editTag(tag) { editTag(tag) {
if (tag && !(this.views.panel instanceof TagView)) { if (tag && !(this.views.panel instanceof TagView)) {
@ -684,7 +677,7 @@ const AppView = Backbone.View.extend({
} else { } else {
this.showEntries(); this.showEntries();
} }
}, }
editGeneratorPresets() { editGeneratorPresets() {
if (!(this.views.panel instanceof GeneratorPresetsView)) { if (!(this.views.panel instanceof GeneratorPresetsView)) {
@ -695,17 +688,17 @@ const AppView = Backbone.View.extend({
} else { } else {
this.showEntries(); this.showEntries();
} }
}, }
isContextMenuAllowed(e) { isContextMenuAllowed(e) {
return ['input', 'textarea'].indexOf(e.target.tagName.toLowerCase()) < 0; return ['input', 'textarea'].indexOf(e.target.tagName.toLowerCase()) < 0;
}, }
contextMenu(e) { contextMenu(e) {
if (this.isContextMenuAllowed(e)) { if (this.isContextMenuAllowed(e)) {
e.preventDefault(); e.preventDefault();
} }
}, }
showContextMenu(e) { showContextMenu(e) {
if (e.options && this.isContextMenuAllowed(e)) { if (e.options && this.isContextMenuAllowed(e)) {
@ -723,19 +716,19 @@ const AppView = Backbone.View.extend({
menu.on('select', e => this.contextMenuSelect(e)); menu.on('select', e => this.contextMenuSelect(e));
this.views.contextMenu = menu; this.views.contextMenu = menu;
} }
}, }
hideContextMenu() { hideContextMenu() {
if (this.views.contextMenu) { if (this.views.contextMenu) {
this.views.contextMenu.remove(); this.views.contextMenu.remove();
delete this.views.contextMenu; delete this.views.contextMenu;
} }
}, }
contextMenuSelect(e) { contextMenuSelect(e) {
this.hideContextMenu(); this.hideContextMenu();
Backbone.trigger('context-menu-select', e); Backbone.trigger('context-menu-select', e);
}, }
showSingleInstanceAlert() { showSingleInstanceAlert() {
this.hideOpenFile(); this.hideOpenFile();
@ -747,24 +740,24 @@ const AppView = Backbone.View.extend({
click: false, click: false,
buttons: [] buttons: []
}); });
}, }
dragover(e) { dragover(e) {
e.preventDefault(); e.preventDefault();
e.originalEvent.dataTransfer.dropEffect = 'none'; e.originalEvent.dataTransfer.dropEffect = 'none';
}, }
drop(e) { drop(e) {
e.preventDefault(); e.preventDefault();
}, }
setTheme() { setTheme() {
SettingsManager.setTheme(this.model.settings.get('theme')); SettingsManager.setTheme(this.model.settings.get('theme'));
}, }
setFontSize() { setFontSize() {
SettingsManager.setFontSize(this.model.settings.get('fontSize')); SettingsManager.setFontSize(this.model.settings.get('fontSize'));
}, }
setLocale() { setLocale() {
SettingsManager.setLocale(this.model.settings.get('locale')); SettingsManager.setLocale(this.model.settings.get('locale'));
@ -773,19 +766,19 @@ const AppView = Backbone.View.extend({
this.showSettings(); this.showSettings();
} }
this.$el.find('.app__beta:first').text(Locale.appBeta); this.$el.find('.app__beta:first').text(Locale.appBeta);
}, }
extLinkClick(e) { extLinkClick(e) {
if (Launcher) { if (Launcher) {
e.preventDefault(); e.preventDefault();
Launcher.openLink(e.target.href); Launcher.openLink(e.target.href);
} }
}, }
bodyClick(e) { bodyClick(e) {
IdleTracker.regUserAction(); IdleTracker.regUserAction();
Backbone.trigger('click', e); Backbone.trigger('click', e);
} }
}); }
export { AppView }; export { AppView };

View File

@ -1,4 +1,5 @@
import Backbone from 'backbone'; import Backbone from 'backbone';
import { View } from 'view-engine/view';
import { Shortcuts } from 'comp/app/shortcuts'; import { Shortcuts } from 'comp/app/shortcuts';
import { KeyHandler } from 'comp/browser/key-handler'; import { KeyHandler } from 'comp/browser/key-handler';
import { Keys } from 'const/keys'; import { Keys } from 'const/keys';
@ -7,11 +8,14 @@ import { Features } from 'util/features';
import { StringFormat } from 'util/formatting/string-format'; import { StringFormat } from 'util/formatting/string-format';
import { Locale } from 'util/locale'; import { Locale } from 'util/locale';
import { DropdownView } from 'views/dropdown-view'; import { DropdownView } from 'views/dropdown-view';
import template from 'templates/list-search.hbs';
const ListSearchView = Backbone.View.extend({ class ListSearchView extends View {
template: require('templates/list-search.hbs'), parent = '.list__header';
events: { template = template;
events = {
'keydown .list__search-field': 'inputKeyDown', 'keydown .list__search-field': 'inputKeyDown',
'keypress .list__search-field': 'inputKeyPress', 'keypress .list__search-field': 'inputKeyPress',
'input .list__search-field': 'inputChange', 'input .list__search-field': 'inputChange',
@ -21,18 +25,17 @@ const ListSearchView = Backbone.View.extend({
'click .list__search-icon-search': 'advancedSearchClick', 'click .list__search-icon-search': 'advancedSearchClick',
'click .list__search-btn-menu': 'toggleMenu', 'click .list__search-btn-menu': 'toggleMenu',
'change .list__search-adv input[type=checkbox]': 'toggleAdvCheck' 'change .list__search-adv input[type=checkbox]': 'toggleAdvCheck'
}, };
views: null, inputEl = null;
sortOptions = null;
sortIcons = null;
createOptions = null;
advancedSearchEnabled = false;
advancedSearch = null;
inputEl: null, constructor(model) {
sortOptions: null, super(model);
sortIcons: null,
createOptions: null,
advancedSearchEnabled: false,
advancedSearch: null,
initialize() {
this.sortOptions = [ this.sortOptions = [
{ {
value: 'title', value: 'title',
@ -116,24 +119,16 @@ const ListSearchView = Backbone.View.extend({
this.advancedSearch = _.extend({}, this.model.advancedSearch); this.advancedSearch = _.extend({}, this.model.advancedSearch);
} }
this.setLocale(); this.setLocale();
KeyHandler.onKey(Keys.DOM_VK_F, this.findKeyPress, this, KeyHandler.SHORTCUT_ACTION); this.onKey(Keys.DOM_VK_F, this.findKeyPress, KeyHandler.SHORTCUT_ACTION);
KeyHandler.onKey(Keys.DOM_VK_N, this.newKeyPress, this, KeyHandler.SHORTCUT_OPT); this.onKey(Keys.DOM_VK_N, this.newKeyPress, KeyHandler.SHORTCUT_OPT);
KeyHandler.onKey(Keys.DOM_VK_DOWN, this.downKeyPress, this); this.onKey(Keys.DOM_VK_DOWN, this.downKeyPress);
KeyHandler.onKey(Keys.DOM_VK_UP, this.upKeyPress, this); this.onKey(Keys.DOM_VK_UP, this.upKeyPress);
this.listenTo(this, 'show', this.viewShown); this.listenTo(this, 'show', this.viewShown);
this.listenTo(this, 'hide', this.viewHidden); this.listenTo(this, 'hide', this.viewHidden);
this.listenTo(Backbone, 'filter', this.filterChanged); this.listenTo(Backbone, 'filter', this.filterChanged);
this.listenTo(Backbone, 'set-locale', this.setLocale); this.listenTo(Backbone, 'set-locale', this.setLocale);
this.listenTo(Backbone, 'page-blur', this.pageBlur); this.listenTo(Backbone, 'page-blur', this.pageBlur);
}, }
remove() {
KeyHandler.offKey(Keys.DOM_VK_F, this.findKeyPress, this);
KeyHandler.offKey(Keys.DOM_VK_N, this.newKeyPress, this);
KeyHandler.offKey(Keys.DOM_VK_DOWN, this.downKeyPress, this);
KeyHandler.offKey(Keys.DOM_VK_UP, this.upKeyPress, this);
Backbone.View.prototype.remove.apply(this);
},
setLocale() { setLocale() {
this.sortOptions.forEach(opt => { this.sortOptions.forEach(opt => {
@ -150,27 +145,29 @@ const ListSearchView = Backbone.View.extend({
{ value: 'entry', icon: 'key', text: StringFormat.capFirst(Locale.entry) + entryDesc }, { value: 'entry', icon: 'key', text: StringFormat.capFirst(Locale.entry) + entryDesc },
{ value: 'group', icon: 'folder', text: StringFormat.capFirst(Locale.group) } { value: 'group', icon: 'folder', text: StringFormat.capFirst(Locale.group) }
]; ];
this.render(); if (this.el) {
}, this.render();
}
}
pageBlur() { pageBlur() {
this.inputEl.blur(); this.inputEl.blur();
}, }
viewShown() { viewShown() {
this.listenTo(KeyHandler, 'keypress', this.documentKeyPress); this.listenTo(KeyHandler, 'keypress', this.documentKeyPress);
}, }
viewHidden() { viewHidden() {
this.stopListening(KeyHandler, 'keypress', this.documentKeyPress); this.stopListening(KeyHandler, 'keypress', this.documentKeyPress);
}, }
render() { render() {
let searchVal; let searchVal;
if (this.inputEl) { if (this.inputEl) {
searchVal = this.inputEl.val(); searchVal = this.inputEl.val();
} }
this.renderTemplate({ super.render({
adv: this.advancedSearch, adv: this.advancedSearch,
advEnabled: this.advancedSearchEnabled advEnabled: this.advancedSearchEnabled
}); });
@ -179,7 +176,7 @@ const ListSearchView = Backbone.View.extend({
this.inputEl.val(searchVal); this.inputEl.val(searchVal);
} }
return this; return this;
}, }
inputKeyDown(e) { inputKeyDown(e) {
switch (e.which) { switch (e.which) {
@ -200,22 +197,22 @@ const ListSearchView = Backbone.View.extend({
return; return;
} }
e.preventDefault(); e.preventDefault();
}, }
inputKeyPress(e) { inputKeyPress(e) {
e.stopPropagation(); e.stopPropagation();
}, }
inputChange() { inputChange() {
Backbone.trigger('add-filter', { text: this.inputEl.val() }); Backbone.trigger('add-filter', { text: this.inputEl.val() });
}, }
inputFocus(e) { inputFocus(e) {
$(e.target).select(); $(e.target).select();
}, }
documentKeyPress(e) { documentKeyPress(e) {
if (this._hidden) { if (this.hidden) {
return; return;
} }
const code = e.charCode; const code = e.charCode;
@ -227,35 +224,35 @@ const ListSearchView = Backbone.View.extend({
this.inputEl[0].setSelectionRange(1, 1); this.inputEl[0].setSelectionRange(1, 1);
this.inputChange(); this.inputChange();
e.preventDefault(); e.preventDefault();
}, }
findKeyPress(e) { findKeyPress(e) {
if (!this._hidden) { if (!this.hidden) {
e.preventDefault(); e.preventDefault();
this.hideSearchOptions(); this.hideSearchOptions();
this.inputEl.select().focus(); this.inputEl.select().focus();
} }
}, }
newKeyPress(e) { newKeyPress(e) {
if (!this._hidden) { if (!this.hidden) {
e.preventDefault(); e.preventDefault();
this.hideSearchOptions(); this.hideSearchOptions();
this.trigger('create-entry'); this.emit('create-entry');
} }
}, }
downKeyPress(e) { downKeyPress(e) {
e.preventDefault(); e.preventDefault();
this.hideSearchOptions(); this.hideSearchOptions();
this.trigger('select-next'); this.emit('select-next');
}, }
upKeyPress(e) { upKeyPress(e) {
e.preventDefault(); e.preventDefault();
this.hideSearchOptions(); this.hideSearchOptions();
this.trigger('select-prev'); this.emit('select-prev');
}, }
filterChanged(filter) { filterChanged(filter) {
this.hideSearchOptions(); this.hideSearchOptions();
@ -272,22 +269,22 @@ const ListSearchView = Backbone.View.extend({
this.advancedSearchEnabled = adv; this.advancedSearchEnabled = adv;
this.$el.find('.list__search-adv').toggleClass('hide', !this.advancedSearchEnabled); this.$el.find('.list__search-adv').toggleClass('hide', !this.advancedSearchEnabled);
} }
}, }
createOptionsClick(e) { createOptionsClick(e) {
e.stopImmediatePropagation(); e.stopImmediatePropagation();
if (e.shiftKey) { if (e.shiftKey) {
this.hideSearchOptions(); this.hideSearchOptions();
this.trigger('create-entry'); this.emit('create-entry');
return; return;
} }
this.toggleCreateOptions(); this.toggleCreateOptions();
}, }
sortOptionsClick(e) { sortOptionsClick(e) {
this.toggleSortOptions(); this.toggleSortOptions();
e.stopImmediatePropagation(); e.stopImmediatePropagation();
}, }
advancedSearchClick() { advancedSearchClick() {
this.advancedSearchEnabled = !this.advancedSearchEnabled; this.advancedSearchEnabled = !this.advancedSearchEnabled;
@ -299,17 +296,17 @@ const ListSearchView = Backbone.View.extend({
advanced = this.model.advancedSearch; advanced = this.model.advancedSearch;
} }
Backbone.trigger('add-filter', { advanced }); Backbone.trigger('add-filter', { advanced });
}, }
toggleMenu() { toggleMenu() {
Backbone.trigger('toggle-menu'); Backbone.trigger('toggle-menu');
}, }
toggleAdvCheck(e) { toggleAdvCheck(e) {
const setting = $(e.target).data('id'); const setting = $(e.target).data('id');
this.advancedSearch[setting] = e.target.checked; this.advancedSearch[setting] = e.target.checked;
Backbone.trigger('add-filter', { advanced: this.advancedSearch }); Backbone.trigger('add-filter', { advanced: this.advancedSearch });
}, }
hideSearchOptions() { hideSearchOptions() {
if (this.views.searchDropdown) { if (this.views.searchDropdown) {
@ -319,7 +316,7 @@ const ListSearchView = Backbone.View.extend({
.find('.list__search-btn-sort,.list__search-btn-new') .find('.list__search-btn-sort,.list__search-btn-new')
.removeClass('sel--active'); .removeClass('sel--active');
} }
}, }
toggleSortOptions() { toggleSortOptions() {
if (this.views.searchDropdown && this.views.searchDropdown.isSort) { if (this.views.searchDropdown && this.views.searchDropdown.isSort) {
@ -343,7 +340,7 @@ const ListSearchView = Backbone.View.extend({
options: this.sortOptions options: this.sortOptions
}); });
this.views.searchDropdown = view; this.views.searchDropdown = view;
}, }
toggleCreateOptions() { toggleCreateOptions() {
if (this.views.searchDropdown && this.views.searchDropdown.isCreate) { if (this.views.searchDropdown && this.views.searchDropdown.isCreate) {
@ -365,7 +362,7 @@ const ListSearchView = Backbone.View.extend({
options: this.createOptions.concat(this.getCreateEntryTemplateOptions()) options: this.createOptions.concat(this.getCreateEntryTemplateOptions())
}); });
this.views.searchDropdown = view; this.views.searchDropdown = view;
}, }
getCreateEntryTemplateOptions() { getCreateEntryTemplateOptions() {
const entryTemplates = this.model.getEntryTemplates(); const entryTemplates = this.model.getEntryTemplates();
@ -390,35 +387,35 @@ const ListSearchView = Backbone.View.extend({
text: StringFormat.capFirst(Locale.template) text: StringFormat.capFirst(Locale.template)
}); });
return options; return options;
}, }
sortDropdownSelect(e) { sortDropdownSelect(e) {
this.hideSearchOptions(); this.hideSearchOptions();
Backbone.trigger('set-sort', e.item); Backbone.trigger('set-sort', e.item);
}, }
createDropdownSelect(e) { createDropdownSelect(e) {
this.hideSearchOptions(); this.hideSearchOptions();
switch (e.item) { switch (e.item) {
case 'entry': case 'entry':
this.trigger('create-entry'); this.emit('create-entry');
break; break;
case 'group': case 'group':
this.trigger('create-group'); this.emit('create-group');
break; break;
case 'tmpl': case 'tmpl':
this.trigger('create-template'); this.emit('create-template');
break; break;
default: default:
if (this.entryTemplates[e.item]) { if (this.entryTemplates[e.item]) {
this.trigger('create-entry', { template: this.entryTemplates[e.item] }); this.emit('create-entry', { template: this.entryTemplates[e.item] });
} }
} }
}, }
addArrow(str) { addArrow(str) {
return str.replace('{}', '&rarr;'); return str.replace('{}', '&rarr;');
} }
}); }
export { ListSearchView }; export { ListSearchView };

View File

@ -1,4 +1,5 @@
import Backbone from 'backbone'; import Backbone from 'backbone';
import { View } from 'view-engine/view';
import { EntryCollection } from 'collections/entry-collection'; import { EntryCollection } from 'collections/entry-collection';
import { DragDropInfo } from 'comp/app/drag-drop-info'; import { DragDropInfo } from 'comp/app/drag-drop-info';
import { Alerts } from 'comp/ui/alerts'; import { Alerts } from 'comp/ui/alerts';
@ -10,27 +11,30 @@ import { Resizable } from 'view-engine/resizable';
import { Scrollable } from 'view-engine/scrollable'; import { Scrollable } from 'view-engine/scrollable';
import { DropdownView } from 'views/dropdown-view'; import { DropdownView } from 'views/dropdown-view';
import { ListSearchView } from 'views/list-search-view'; import { ListSearchView } from 'views/list-search-view';
import template from 'templates/list.hbs';
import emptyTemplate from 'templates/list-empty.hbs';
const ListView = Backbone.View.extend({ class ListView extends View {
template: require('templates/list.hbs'), parent = '.app__list';
emptyTemplate: require('templates/list-empty.hbs'),
events: { template = template;
emptyTemplate = emptyTemplate;
events = {
'click .list__item': 'itemClick', 'click .list__item': 'itemClick',
'click .list__table-options': 'tableOptionsClick', 'click .list__table-options': 'tableOptionsClick',
'dragstart .list__item': 'itemDragStart' 'dragstart .list__item': 'itemDragStart'
}, };
views: null, minWidth = 200;
minHeight = 200;
maxWidth = 500;
maxHeight = 500;
minWidth: 200, itemsEl = null;
minHeight: 200,
maxWidth: 500,
maxHeight: 500,
itemsEl: null, tableColumns = [
tableColumns: [
{ val: 'title', name: 'title', enabled: true }, { val: 'title', name: 'title', enabled: true },
{ val: 'user', name: 'user', enabled: true }, { val: 'user', name: 'user', enabled: true },
{ val: 'url', name: 'website', enabled: true }, { val: 'url', name: 'website', enabled: true },
@ -38,12 +42,13 @@ const ListView = Backbone.View.extend({
{ val: 'notes', name: 'notes', enabled: true }, { val: 'notes', name: 'notes', enabled: true },
{ val: 'groupName', name: 'group', enabled: false }, { val: 'groupName', name: 'group', enabled: false },
{ val: 'fileName', name: 'file', enabled: false } { val: 'fileName', name: 'file', enabled: false }
], ];
constructor(model) {
super(model);
initialize() {
this.initScroll(); this.initScroll();
this.views = {}; this.views.search = new ListSearchView(this.model);
this.views.search = new ListSearchView({ model: this.model });
this.listenTo(this.views.search, 'select-prev', this.selectPrev); this.listenTo(this.views.search, 'select-prev', this.selectPrev);
this.listenTo(this.views.search, 'select-next', this.selectNext); this.listenTo(this.views.search, 'select-next', this.selectNext);
@ -62,13 +67,13 @@ const ListView = Backbone.View.extend({
this.readTableColumnsEnabled(); this.readTableColumnsEnabled();
this.items = new EntryCollection(); this.items = new EntryCollection();
}, }
render() { render() {
if (!this.itemsEl) { if (!this.itemsEl) {
this.$el.html(this.template()); super.render();
this.itemsEl = this.$el.find('.list__items>.scroller'); this.itemsEl = this.$el.find('.list__items>.scroller');
this.views.search.setElement(this.$el.find('.list__header')).render(); this.views.search.render();
this.setTableView(); this.setTableView();
this.createScroll({ this.createScroll({
@ -105,7 +110,7 @@ const ListView = Backbone.View.extend({
} }
this.pageResized(); this.pageResized();
return this; return this;
}, }
getItemsTemplate() { getItemsTemplate() {
if (this.model.settings.get('tableView')) { if (this.model.settings.get('tableView')) {
@ -113,11 +118,11 @@ const ListView = Backbone.View.extend({
} else { } else {
return this.renderPlainItems; return this.renderPlainItems;
} }
}, }
renderPlainItems(itemsHtml) { renderPlainItems(itemsHtml) {
return itemsHtml.items; return itemsHtml.items;
}, }
getItemTemplate() { getItemTemplate() {
if (this.model.settings.get('tableView')) { if (this.model.settings.get('tableView')) {
@ -125,11 +130,11 @@ const ListView = Backbone.View.extend({
} else { } else {
return require('templates/list-item-short.hbs'); return require('templates/list-item-short.hbs');
} }
}, }
getDescField() { getDescField() {
return this.model.sort.replace('-', ''); return this.model.sort.replace('-', '');
}, }
itemClick(e) { itemClick(e) {
const id = $(e.target) const id = $(e.target)
@ -140,33 +145,33 @@ const ListView = Backbone.View.extend({
this.selectItem(item); this.selectItem(item);
} }
Backbone.trigger('toggle-details', true); Backbone.trigger('toggle-details', true);
}, }
selectPrev() { selectPrev() {
const ix = this.items.indexOf(this.items.get(this.model.activeEntryId)); const ix = this.items.indexOf(this.items.get(this.model.activeEntryId));
if (ix > 0) { if (ix > 0) {
this.selectItem(this.items.at(ix - 1)); this.selectItem(this.items.at(ix - 1));
} }
}, }
selectNext() { selectNext() {
const ix = this.items.indexOf(this.items.get(this.model.activeEntryId)); const ix = this.items.indexOf(this.items.get(this.model.activeEntryId));
if (ix < this.items.length - 1) { if (ix < this.items.length - 1) {
this.selectItem(this.items.at(ix + 1)); this.selectItem(this.items.at(ix + 1));
} }
}, }
createEntry(arg) { createEntry(arg) {
const newEntry = this.model.createNewEntry(arg); const newEntry = this.model.createNewEntry(arg);
this.items.unshift(newEntry); this.items.unshift(newEntry);
this.render(); this.render();
this.selectItem(newEntry); this.selectItem(newEntry);
}, }
createGroup() { createGroup() {
const newGroup = this.model.createNewGroup(); const newGroup = this.model.createNewGroup();
Backbone.trigger('edit-group', newGroup); Backbone.trigger('edit-group', newGroup);
}, }
createTemplate() { createTemplate() {
if (!this.model.settings.get('templateHelpShown')) { if (!this.model.settings.get('templateHelpShown')) {
@ -189,7 +194,7 @@ const ListView = Backbone.View.extend({
this.items.unshift(templateEntry); this.items.unshift(templateEntry);
this.render(); this.render();
this.selectItem(templateEntry); this.selectItem(templateEntry);
}, }
selectItem(item) { selectItem(item) {
this.model.activeEntryId = item.id; this.model.activeEntryId = item.id;
@ -205,25 +210,25 @@ const ListView = Backbone.View.extend({
} else if (itemRect.bottom > listRect.bottom) { } else if (itemRect.bottom > listRect.bottom) {
listEl.scrollTop += itemRect.bottom - listRect.bottom; listEl.scrollTop += itemRect.bottom - listRect.bottom;
} }
}, }
viewShown() { viewShown() {
this.views.search.show(); this.views.search.show();
}, }
viewHidden() { viewHidden() {
this.views.search.hide(); this.views.search.hide();
}, }
setTableView() { setTableView() {
const isTable = this.model.settings.get('tableView'); const isTable = this.model.settings.get('tableView');
this.dragView.setCoord(isTable ? 'y' : 'x'); this.dragView.setCoord(isTable ? 'y' : 'x');
this.setDefaultSize(); this.setDefaultSize();
}, }
setDefaultSize() { setDefaultSize() {
this.setSize(this.model.settings.get('listViewWidth')); this.setSize(this.model.settings.get('listViewWidth'));
}, }
setSize(size) { setSize(size) {
this.$el.css({ width: 'auto', height: 'auto' }); this.$el.css({ width: 'auto', height: 'auto' });
@ -232,27 +237,27 @@ const ListView = Backbone.View.extend({
} else { } else {
this.$el.css('flex', null); this.$el.css('flex', null);
} }
}, }
viewResized(size) { viewResized(size) {
this.setSize(size); this.setSize(size);
this.throttleSetViewSizeSetting(size); this.throttleSetViewSizeSetting(size);
}, }
throttleSetViewSizeSetting: _.throttle(size => { throttleSetViewSizeSetting = _.throttle(size => {
AppSettingsModel.instance.set('listViewWidth', size); AppSettingsModel.instance.set('listViewWidth', size);
}, 1000), }, 1000);
filterChanged(filter) { filterChanged(filter) {
this.items = filter.entries; this.items = filter.entries;
this.render(); this.render();
}, }
entryUpdated() { entryUpdated() {
const scrollTop = this.itemsEl[0].scrollTop; const scrollTop = this.itemsEl[0].scrollTop;
this.render(); this.render();
this.itemsEl[0].scrollTop = scrollTop; this.itemsEl[0].scrollTop = scrollTop;
}, }
itemDragStart(e) { itemDragStart(e) {
e.stopPropagation(); e.stopPropagation();
@ -262,7 +267,7 @@ const ListView = Backbone.View.extend({
e.originalEvent.dataTransfer.setData('text/entry', id); e.originalEvent.dataTransfer.setData('text/entry', id);
e.originalEvent.dataTransfer.effectAllowed = 'move'; e.originalEvent.dataTransfer.effectAllowed = 'move';
DragDropInfo.dragObject = this.items.get(id); DragDropInfo.dragObject = this.items.get(id);
}, }
tableOptionsClick(e) { tableOptionsClick(e) {
e.stopImmediatePropagation(); e.stopImmediatePropagation();
@ -287,14 +292,14 @@ const ListView = Backbone.View.extend({
options options
}); });
this.views.optionsDropdown = view; this.views.optionsDropdown = view;
}, }
hideOptionsDropdown() { hideOptionsDropdown() {
if (this.views.optionsDropdown) { if (this.views.optionsDropdown) {
this.views.optionsDropdown.remove(); this.views.optionsDropdown.remove();
delete this.views.optionsDropdown; delete this.views.optionsDropdown;
} }
}, }
optionsDropdownSelect(e) { optionsDropdownSelect(e) {
const col = _.find(this.tableColumns, c => c.val === e.item); const col = _.find(this.tableColumns, c => c.val === e.item);
@ -302,7 +307,7 @@ const ListView = Backbone.View.extend({
e.el.find('i:first').toggleClass('fa-check-square-o fa-square-o'); e.el.find('i:first').toggleClass('fa-check-square-o fa-square-o');
this.render(); this.render();
this.saveTableColumnsEnabled(); this.saveTableColumnsEnabled();
}, }
readTableColumnsEnabled() { readTableColumnsEnabled() {
const tableViewColumns = AppSettingsModel.instance.get('tableViewColumns'); const tableViewColumns = AppSettingsModel.instance.get('tableViewColumns');
@ -311,7 +316,7 @@ const ListView = Backbone.View.extend({
col.enabled = tableViewColumns.indexOf(col.name) >= 0; col.enabled = tableViewColumns.indexOf(col.name) >= 0;
}); });
} }
}, }
saveTableColumnsEnabled() { saveTableColumnsEnabled() {
const tableViewColumns = this.tableColumns const tableViewColumns = this.tableColumns
@ -319,9 +324,9 @@ const ListView = Backbone.View.extend({
.map(column => column.name); .map(column => column.name);
AppSettingsModel.instance.set('tableViewColumns', tableViewColumns); AppSettingsModel.instance.set('tableViewColumns', tableViewColumns);
} }
}); }
_.extend(ListView.prototype, Resizable); Object.assign(ListView.prototype, Resizable);
_.extend(ListView.prototype, Scrollable); Object.assign(ListView.prototype, Scrollable);
export { ListView }; export { ListView };

View File

@ -1,14 +1,16 @@
import Backbone from 'backbone'; import Backbone from 'backbone';
import { View } from 'view-engine/view';
import { DragDropInfo } from 'comp/app/drag-drop-info'; import { DragDropInfo } from 'comp/app/drag-drop-info';
import { KeyHandler } from 'comp/browser/key-handler'; import { KeyHandler } from 'comp/browser/key-handler';
import { Alerts } from 'comp/ui/alerts'; import { Alerts } from 'comp/ui/alerts';
import { Keys } from 'const/keys'; import { Keys } from 'const/keys';
import { Locale } from 'util/locale'; import { Locale } from 'util/locale';
import template from 'templates/menu/menu-item.hbs';
const MenuItemView = Backbone.View.extend({ class MenuItemView extends View {
template: require('templates/menu/menu-item.hbs'), template = template;
events: { events = {
'mouseover': 'mouseover', 'mouseover': 'mouseover',
'mouseout': 'mouseout', 'mouseout': 'mouseout',
'click .menu__item-option': 'selectOption', 'click .menu__item-option': 'selectOption',
@ -22,12 +24,13 @@ const MenuItemView = Backbone.View.extend({
'drop': 'drop', 'drop': 'drop',
'dragover .menu__item-drag-top': 'dragoverTop', 'dragover .menu__item-drag-top': 'dragoverTop',
'dragleave .menu__item-drag-top': 'dragleaveTop' 'dragleave .menu__item-drag-top': 'dragleaveTop'
}, };
iconEl: null, iconEl = null;
itemViews: null, itemViews = null;
initialize() { constructor(model, options) {
super(model, options);
this.itemViews = []; this.itemViews = [];
this.listenTo(this.model, 'change:title', this.changeTitle); this.listenTo(this.model, 'change:title', this.changeTitle);
this.listenTo(this.model, 'change:icon', this.changeIcon); this.listenTo(this.model, 'change:icon', this.changeIcon);
@ -39,70 +42,62 @@ const MenuItemView = Backbone.View.extend({
this.listenTo(this.model, 'insert', this.insertItem); this.listenTo(this.model, 'insert', this.insertItem);
const shortcut = this.model.get('shortcut'); const shortcut = this.model.get('shortcut');
if (shortcut) { if (shortcut) {
KeyHandler.onKey(shortcut, this.selectItem, this, KeyHandler.SHORTCUT_OPT); this.onKey(shortcut, this.selectItem, KeyHandler.SHORTCUT_OPT);
if (shortcut !== Keys.DOM_VK_C) { if (shortcut !== Keys.DOM_VK_C) {
KeyHandler.onKey(shortcut, this.selectItem, this, KeyHandler.SHORTCUT_ACTION); this.onKey(shortcut, this.selectItem, KeyHandler.SHORTCUT_ACTION);
} }
} }
}, this.once('remove', () => {
this.removeInnerViews();
});
}
render() { render() {
this.removeInnerViews(); this.removeInnerViews();
this.renderTemplate(this.model.attributes); super.render(this.model.attributes);
this.iconEl = this.$el.find('.menu__item-icon'); this.iconEl = this.$el.find('.menu__item-icon');
const items = this.model.get('items'); const items = this.model.get('items');
if (items) { if (items) {
items.forEach(function(item) { items.forEach(item => {
if (item.get('visible')) { if (item.get('visible')) {
this.insertItem(item); this.insertItem(item);
} }
}, this); });
} }
this.$el.toggleClass('menu__item--collapsed', !this.model.get('expanded')); this.$el.toggleClass('menu__item--collapsed', !this.model.get('expanded'));
return this; }
},
insertItem(item) { insertItem(item) {
this.itemViews.push(new MenuItemView({ el: this.$el, model: item }).render()); const itemView = new MenuItemView(item, { parent: this.el });
}, itemView.render();
this.itemViews.push(itemView);
remove() { }
this.removeInnerViews();
const shortcut = this.model.get('shortcut');
if (shortcut) {
KeyHandler.offKey(shortcut, this.selectItem, this, KeyHandler.SHORTCUT_OPT);
if (shortcut !== Keys.DOM_VK_C) {
KeyHandler.offKey(shortcut, this.selectItem, this, KeyHandler.SHORTCUT_ACTION);
}
}
Backbone.View.prototype.remove.apply(this);
},
removeInnerViews() { removeInnerViews() {
this.itemViews.forEach(itemView => itemView.remove()); this.itemViews.forEach(itemView => itemView.remove());
this.itemViews = []; this.itemViews = [];
}, }
changeTitle(model, title) { changeTitle(model, title) {
this.$el this.$el
.find('.menu__item-title') .find('.menu__item-title')
.first() .first()
.text(title || '(no title)'); .text(title || '(no title)');
}, }
changeIcon(model, icon) { changeIcon(model, icon) {
this.iconEl[0].className = this.iconEl[0].className =
'menu__item-icon fa ' + (icon ? 'fa-' + icon : 'menu__item-icon--no-icon'); 'menu__item-icon fa ' + (icon ? 'fa-' + icon : 'menu__item-icon--no-icon');
}, }
changeActive(model, active) { changeActive(model, active) {
this.$el.toggleClass('menu__item--active', active); this.$el.toggleClass('menu__item--active', active);
}, }
changeExpanded(model, expanded) { changeExpanded(model, expanded) {
this.$el.toggleClass('menu__item--collapsed', !expanded); this.$el.toggleClass('menu__item--collapsed', !expanded);
this.model.setExpanded(expanded); this.model.setExpanded(expanded);
}, }
changeCls(model, cls) { changeCls(model, cls) {
const oldCls = model.previousAttributes().cls; const oldCls = model.previousAttributes().cls;
@ -110,19 +105,19 @@ const MenuItemView = Backbone.View.extend({
this.$el.removeClass(oldCls); this.$el.removeClass(oldCls);
} }
this.$el.addClass(cls); this.$el.addClass(cls);
}, }
mouseover(e) { mouseover(e) {
if (!e.button) { if (!e.button) {
this.$el.addClass('menu__item--hover'); this.$el.addClass('menu__item--hover');
e.stopPropagation(); e.stopPropagation();
} }
}, }
mouseout(e) { mouseout(e) {
this.$el.removeClass('menu__item--hover'); this.$el.removeClass('menu__item--hover');
e.stopPropagation(); e.stopPropagation();
}, }
selectItem(e) { selectItem(e) {
e.stopPropagation(); e.stopPropagation();
@ -135,7 +130,7 @@ const MenuItemView = Backbone.View.extend({
} else { } else {
Backbone.trigger('menu-select', { item: this.model }); Backbone.trigger('menu-select', { item: this.model });
} }
}, }
selectOption(e) { selectOption(e) {
const options = this.model.get('options'); const options = this.model.get('options');
@ -148,14 +143,14 @@ const MenuItemView = Backbone.View.extend({
} }
e.stopImmediatePropagation(); e.stopImmediatePropagation();
e.preventDefault(); e.preventDefault();
}, }
expandItem(e) { expandItem(e) {
if (this.model.toggleExpanded) { if (this.model.toggleExpanded) {
this.model.toggleExpanded(); this.model.toggleExpanded();
} }
e.stopPropagation(); e.stopPropagation();
}, }
editItem(e) { editItem(e) {
if (this.model.get('active') && this.model.get('editable')) { if (this.model.get('active') && this.model.get('editable')) {
@ -169,7 +164,7 @@ const MenuItemView = Backbone.View.extend({
break; break;
} }
} }
}, }
emptyTrash(e) { emptyTrash(e) {
e.stopPropagation(); e.stopPropagation();
@ -181,7 +176,7 @@ const MenuItemView = Backbone.View.extend({
Backbone.trigger('empty-trash'); Backbone.trigger('empty-trash');
} }
}); });
}, }
dropAllowed(e) { dropAllowed(e) {
const types = e.originalEvent.dataTransfer.types; const types = e.originalEvent.dataTransfer.types;
@ -191,7 +186,7 @@ const MenuItemView = Backbone.View.extend({
} }
} }
return false; return false;
}, }
dragstart(e) { dragstart(e) {
e.stopPropagation(); e.stopPropagation();
@ -200,7 +195,7 @@ const MenuItemView = Backbone.View.extend({
e.originalEvent.dataTransfer.effectAllowed = 'move'; e.originalEvent.dataTransfer.effectAllowed = 'move';
DragDropInfo.dragObject = this.model; DragDropInfo.dragObject = this.model;
} }
}, }
dragover(e) { dragover(e) {
if (this.model.get('drop') && this.dropAllowed(e)) { if (this.model.get('drop') && this.dropAllowed(e)) {
@ -208,14 +203,14 @@ const MenuItemView = Backbone.View.extend({
e.preventDefault(); e.preventDefault();
this.$el.addClass('menu__item--drag'); this.$el.addClass('menu__item--drag');
} }
}, }
dragleave(e) { dragleave(e) {
e.stopPropagation(); e.stopPropagation();
if (this.model.get('drop') && this.dropAllowed(e)) { if (this.model.get('drop') && this.dropAllowed(e)) {
this.$el.removeClass('menu__item--drag menu__item--drag-top'); this.$el.removeClass('menu__item--drag menu__item--drag-top');
} }
}, }
drop(e) { drop(e) {
e.stopPropagation(); e.stopPropagation();
@ -233,7 +228,7 @@ const MenuItemView = Backbone.View.extend({
} }
Backbone.trigger('refresh'); Backbone.trigger('refresh');
} }
}, }
dropTopAllowed(e) { dropTopAllowed(e) {
const types = e.originalEvent.dataTransfer.types; const types = e.originalEvent.dataTransfer.types;
@ -243,19 +238,19 @@ const MenuItemView = Backbone.View.extend({
} }
} }
return false; return false;
}, }
dragoverTop(e) { dragoverTop(e) {
if (this.dropTopAllowed(e)) { if (this.dropTopAllowed(e)) {
this.$el.addClass('menu__item--drag-top'); this.$el.addClass('menu__item--drag-top');
} }
}, }
dragleaveTop(e) { dragleaveTop(e) {
if (this.dropTopAllowed(e)) { if (this.dropTopAllowed(e)) {
this.$el.removeClass('menu__item--drag-top'); this.$el.removeClass('menu__item--drag-top');
} }
} }
}); }
export { MenuItemView }; export { MenuItemView };

View File

@ -1,31 +1,36 @@
import Backbone from 'backbone'; import { View } from 'view-engine/view';
import { AppSettingsModel } from 'models/app-settings-model'; import { AppSettingsModel } from 'models/app-settings-model';
import { Resizable } from 'view-engine/resizable'; import { Resizable } from 'view-engine/resizable';
import { Scrollable } from 'view-engine/scrollable'; import { Scrollable } from 'view-engine/scrollable';
import { MenuItemView } from 'views/menu/menu-item-view'; import { MenuItemView } from 'views/menu/menu-item-view';
import template from 'templates/menu/menu-section.hbs';
const MenuSectionView = Backbone.View.extend({ class MenuSectionView extends View {
template: require('templates/menu/menu-section.hbs'), template = template;
events: {}, events = {};
itemViews: null, itemViews = null;
minHeight: 55, minHeight = 55;
maxHeight() { autoHeigh = 'auto';
return this.$el.parent().height() - 116;
},
autoHeight: 'auto',
initialize() { constructor(model, options) {
super(model, options);
this.itemViews = []; this.itemViews = [];
this.listenTo(this.model, 'change-items', this.itemsChanged); this.listenTo(this.model, 'change-items', this.itemsChanged);
this.listenTo(this, 'view-resize', this.viewResized); this.listenTo(this, 'view-resize', this.viewResized);
}, this.once('remove', () => {
if (this.scroll) {
this.scroll.dispose();
}
this.removeInnerViews();
});
}
render() { render() {
if (!this.itemsEl) { if (!this.itemsEl) {
this.renderTemplate(this.model.attributes); super.render(this.model.attributes);
this.itemsEl = this.model.get('scrollable') ? this.$el.find('.scroller') : this.$el; this.itemsEl = this.model.get('scrollable') ? this.$el.find('.scroller') : this.$el;
if (this.model.get('scrollable')) { if (this.model.get('scrollable')) {
this.initScroll(); this.initScroll();
@ -38,11 +43,11 @@ const MenuSectionView = Backbone.View.extend({
} else { } else {
this.removeInnerViews(); this.removeInnerViews();
} }
this.model.get('items').forEach(function(item) { this.model.get('items').forEach(item => {
const itemView = new MenuItemView({ el: this.itemsEl, model: item }); const itemView = new MenuItemView(item, { parent: this.itemsEl[0] });
itemView.render(); itemView.render();
this.itemViews.push(itemView); this.itemViews.push(itemView);
}, this); });
if (this.model.get('drag')) { if (this.model.get('drag')) {
const height = AppSettingsModel.instance.get('tagsViewHeight'); const height = AppSettingsModel.instance.get('tagsViewHeight');
if (typeof height === 'number') { if (typeof height === 'number') {
@ -51,36 +56,32 @@ const MenuSectionView = Backbone.View.extend({
} }
} }
this.pageResized(); this.pageResized();
}, }
remove() { maxHeight() {
if (this.scroll) { return this.$el.parent().height() - 116;
this.scroll.dispose(); }
}
this.removeInnerViews();
Backbone.View.prototype.remove.apply(this);
},
removeInnerViews() { removeInnerViews() {
this.itemViews.forEach(itemView => itemView.remove()); this.itemViews.forEach(itemView => itemView.remove());
this.itemViews = []; this.itemViews = [];
}, }
itemsChanged() { itemsChanged() {
this.render(); this.render();
}, }
viewResized(size) { viewResized(size) {
this.$el.css('flex', '0 0 ' + (size ? size + 'px' : 'auto')); this.$el.css('flex', '0 0 ' + (size ? size + 'px' : 'auto'));
this.saveViewHeight(size); this.saveViewHeight(size);
}, }
saveViewHeight: _.throttle(size => { saveViewHeight = _.throttle(size => {
AppSettingsModel.instance.set('tagsViewHeight', size); AppSettingsModel.instance.set('tagsViewHeight', size);
}, 1000) }, 1000);
}); }
_.extend(MenuSectionView.prototype, Resizable); Object.assign(MenuSectionView.prototype, Resizable);
_.extend(MenuSectionView.prototype, Scrollable); Object.assign(MenuSectionView.prototype, Scrollable);
export { MenuSectionView }; export { MenuSectionView };

View File

@ -1,49 +1,50 @@
import Backbone from 'backbone'; import Backbone from 'backbone';
import { View } from 'view-engine/view';
import { KeyHandler } from 'comp/browser/key-handler'; import { KeyHandler } from 'comp/browser/key-handler';
import { Keys } from 'const/keys'; import { Keys } from 'const/keys';
import { AppSettingsModel } from 'models/app-settings-model'; import { AppSettingsModel } from 'models/app-settings-model';
import { Resizable } from 'view-engine/resizable'; import { Resizable } from 'view-engine/resizable';
import { DragView } from 'views/drag-view'; import { DragView } from 'views/drag-view';
import { MenuSectionView } from 'views/menu/menu-section-view'; import { MenuSectionView } from 'views/menu/menu-section-view';
import template from 'templates/menu/menu.hbs';
const MenuView = Backbone.View.extend({ class MenuView extends View {
template: require('templates/menu/menu.hbs'), parent = '.app__menu';
events: {}, template = template;
sectionViews: [], events = {};
minWidth: 130, sectionViews = [];
maxWidth: 300,
initialize() { minWidth = 130;
maxWidth = 300;
constructor(model, options) {
super(model, options);
this.listenTo(this.model, 'change:sections', this.menuChanged); this.listenTo(this.model, 'change:sections', this.menuChanged);
this.listenTo(this, 'view-resize', this.viewResized); this.listenTo(this, 'view-resize', this.viewResized);
KeyHandler.onKey( this.onKey(
Keys.DOM_VK_UP, Keys.DOM_VK_UP,
this.selectPreviousSection, this.selectPreviousSection,
this,
KeyHandler.SHORTCUT_ACTION + KeyHandler.SHORTCUT_OPT KeyHandler.SHORTCUT_ACTION + KeyHandler.SHORTCUT_OPT
); );
KeyHandler.onKey( this.onKey(
Keys.DOM_VK_DOWN, Keys.DOM_VK_DOWN,
this.selectNextSection, this.selectNextSection,
this,
KeyHandler.SHORTCUT_ACTION + KeyHandler.SHORTCUT_OPT KeyHandler.SHORTCUT_ACTION + KeyHandler.SHORTCUT_OPT
); );
}, this.once('remove', () => {
this.sectionViews.forEach(sectionView => sectionView.remove());
remove() { this.sectionViews = [];
this.sectionViews.forEach(sectionView => sectionView.remove()); });
this.sectionViews = []; }
Backbone.View.prototype.remove.apply(this);
},
render() { render() {
this.$el.html(this.template()); super.render();
const sectionsEl = this.$el.find('.menu'); const sectionsEl = this.$el.find('.menu');
this.model.get('sections').forEach(function(section) { this.model.get('sections').forEach(function(section) {
const sectionView = new MenuSectionView({ el: sectionsEl, model: section }); const sectionView = new MenuSectionView(section, { parent: sectionsEl[0] });
sectionView.render(); sectionView.render();
if (section.get('drag')) { if (section.get('drag')) {
const dragEl = $('<div/>') const dragEl = $('<div/>')
@ -60,29 +61,29 @@ const MenuView = Backbone.View.extend({
this.$el.width(AppSettingsModel.instance.get('menuViewWidth')); this.$el.width(AppSettingsModel.instance.get('menuViewWidth'));
} }
return this; return this;
}, }
menuChanged() { menuChanged() {
this.render(); this.render();
}, }
viewResized: _.throttle(size => { viewResized = _.throttle(size => {
AppSettingsModel.instance.set('menuViewWidth', size); AppSettingsModel.instance.set('menuViewWidth', size);
}, 1000), }, 1000);
switchVisibility(visible) { switchVisibility(visible) {
this.$el.toggleClass('menu-visible', visible); this.$el.toggleClass('menu-visible', visible);
}, }
selectPreviousSection() { selectPreviousSection() {
Backbone.trigger('select-previous-menu-item'); Backbone.trigger('select-previous-menu-item');
}, }
selectNextSection() { selectNextSection() {
Backbone.trigger('select-next-menu-item'); Backbone.trigger('select-next-menu-item');
} }
}); }
_.extend(MenuView.prototype, Resizable); Object.assign(MenuView.prototype, Resizable);
export { MenuView }; export { MenuView };

View File

@ -1,5 +1,6 @@
import Backbone from 'backbone'; import Backbone from 'backbone';
import kdbxweb from 'kdbxweb'; import kdbxweb from 'kdbxweb';
import { View } from 'view-engine/view';
import { Storage } from 'storage'; import { Storage } from 'storage';
import { DropboxChooser } from 'comp/app/dropbox-chooser'; import { DropboxChooser } from 'comp/app/dropbox-chooser';
import { FocusDetector } from 'comp/browser/focus-detector'; import { FocusDetector } from 'comp/browser/focus-detector';
@ -16,13 +17,16 @@ import { Logger } from 'util/logger';
import { InputFx } from 'util/ui/input-fx'; import { InputFx } from 'util/ui/input-fx';
import { OpenConfigView } from 'views/open-config-view'; import { OpenConfigView } from 'views/open-config-view';
import { StorageFileListView } from 'views/storage-file-list-view'; import { StorageFileListView } from 'views/storage-file-list-view';
import template from 'templates/open.hbs';
const logger = new Logger('open-view'); const logger = new Logger('open-view');
const OpenView = Backbone.View.extend({ class OpenView extends View {
template: require('templates/open.hbs'), parent = '.app__body';
events: { template = template;
events = {
'change .open__file-ctrl': 'fileSelected', 'change .open__file-ctrl': 'fileSelected',
'click .open__icon-open': 'openFile', 'click .open__icon-open': 'openFile',
'click .open__icon-new': 'createNew', 'click .open__icon-new': 'createNew',
@ -30,7 +34,7 @@ const OpenView = Backbone.View.extend({
'click .open__icon-more': 'toggleMore', 'click .open__icon-more': 'toggleMore',
'click .open__icon-storage': 'openStorage', 'click .open__icon-storage': 'openStorage',
'click .open__icon-settings': 'openSettings', 'click .open__icon-settings': 'openSettings',
'click .open__pass-input[readonly]': 'openFile', 'click .open__pass-input': 'passInputClick',
'input .open__pass-input': 'inputInput', 'input .open__pass-input': 'inputInput',
'keydown .open__pass-input': 'inputKeydown', 'keydown .open__pass-input': 'inputKeydown',
'keyup .open__pass-input': 'inputKeyup', 'keyup .open__pass-input': 'inputKeyup',
@ -38,39 +42,34 @@ const OpenView = Backbone.View.extend({
'click .open__pass-enter-btn': 'openDb', 'click .open__pass-enter-btn': 'openDb',
'click .open__settings-key-file': 'openKeyFile', 'click .open__settings-key-file': 'openKeyFile',
'click .open__last-item': 'openLast', 'click .open__last-item': 'openLast',
'dragover': 'dragover', dragover: 'dragover',
'dragleave': 'dragleave', dragleave: 'dragleave',
'drop': 'drop' drop: 'drop'
}, };
views: null, params = null;
params: null,
passwordInput: null,
busy: false,
currentSelectedIndex: -1,
initialize() { passwordInput = null;
this.views = {};
this.params = { busy = false;
id: null,
name: '', currentSelectedIndex = -1;
storage: null,
path: null, constructor(model) {
keyFileName: null, super(model);
keyFileData: null, this.resetParams();
keyFilePath: null,
fileData: null,
rev: null
};
this.passwordInput = new SecureInput(); this.passwordInput = new SecureInput();
KeyHandler.onKey(Keys.DOM_VK_Z, this.undoKeyPress, this, KeyHandler.SHORTCUT_ACTION); this.onKey(Keys.DOM_VK_Z, this.undoKeyPress, KeyHandler.SHORTCUT_ACTION);
KeyHandler.onKey(Keys.DOM_VK_TAB, this.tabKeyPress, this); this.onKey(Keys.DOM_VK_TAB, this.tabKeyPress);
KeyHandler.onKey(Keys.DOM_VK_ENTER, this.enterKeyPress, this); this.onKey(Keys.DOM_VK_ENTER, this.enterKeyPress);
KeyHandler.onKey(Keys.DOM_VK_RETURN, this.enterKeyPress, this); this.onKey(Keys.DOM_VK_RETURN, this.enterKeyPress);
KeyHandler.onKey(Keys.DOM_VK_DOWN, this.moveOpenFileSelectionDown, this); this.onKey(Keys.DOM_VK_DOWN, this.moveOpenFileSelectionDown);
KeyHandler.onKey(Keys.DOM_VK_UP, this.moveOpenFileSelectionUp, this); this.onKey(Keys.DOM_VK_UP, this.moveOpenFileSelectionUp);
this.listenTo(Backbone, 'main-window-focus', this.windowFocused.bind(this)); this.listenTo(Backbone, 'main-window-focus', this.windowFocused.bind(this));
}, this.once('reset', () => {
this.passwordInput.reset();
});
}
render() { render() {
if (this.dragTimeout) { if (this.dragTimeout) {
@ -90,7 +89,7 @@ const OpenView = Backbone.View.extend({
!this.model.settings.get('canOpen') && !this.model.settings.get('canOpen') &&
!this.model.settings.get('canCreate') && !this.model.settings.get('canCreate') &&
!(this.model.settings.get('canOpenDemo') && !this.model.settings.get('demoOpened')); !(this.model.settings.get('canOpenDemo') && !this.model.settings.get('demoOpened'));
this.renderTemplate({ super.render({
lastOpenFiles: this.getLastOpenFiles(), lastOpenFiles: this.getLastOpenFiles(),
canOpenKeyFromDropbox: !Launcher && Storage.dropbox.enabled, canOpenKeyFromDropbox: !Launcher && Storage.dropbox.enabled,
demoOpened: this.model.settings.get('demoOpened'), demoOpened: this.model.settings.get('demoOpened'),
@ -106,17 +105,31 @@ const OpenView = Backbone.View.extend({
this.inputEl = this.$el.find('.open__pass-input'); this.inputEl = this.$el.find('.open__pass-input');
this.passwordInput.setElement(this.inputEl); this.passwordInput.setElement(this.inputEl);
return this; return this;
}, }
resetParams() {
this.params = {
id: null,
name: '',
storage: null,
path: null,
keyFileName: null,
keyFileData: null,
keyFilePath: null,
fileData: null,
rev: null
};
}
windowFocused() { windowFocused() {
this.inputEl.focus(); this.inputEl.focus();
}, }
focusInput(focusOnMobile) { focusInput(focusOnMobile) {
if (FocusDetector.hasFocus() && (focusOnMobile || !Features.isMobile)) { if (FocusDetector.hasFocus() && (focusOnMobile || !Features.isMobile)) {
this.inputEl.focus(); this.inputEl.focus();
} }
}, }
getLastOpenFiles() { getLastOpenFiles() {
return this.model.fileInfos.map(f => { return this.model.fileInfos.map(f => {
@ -136,7 +149,7 @@ const OpenView = Backbone.View.extend({
iconSvg: storage ? storage.iconSvg : undefined iconSvg: storage ? storage.iconSvg : undefined
}; };
}); });
}, }
getDisplayedPath(fileInfo) { getDisplayedPath(fileInfo) {
const storage = fileInfo.get('storage'); const storage = fileInfo.get('storage');
@ -144,18 +157,7 @@ const OpenView = Backbone.View.extend({
return fileInfo.get('path'); return fileInfo.get('path');
} }
return null; return null;
}, }
remove() {
this.passwordInput.reset();
KeyHandler.offKey(Keys.DOM_VK_Z, this.undoKeyPress, this);
KeyHandler.offKey(Keys.DOM_VK_TAB, this.tabKeyPress, this);
KeyHandler.offKey(Keys.DOM_VK_ENTER, this.enterKeyPress, this);
KeyHandler.offKey(Keys.DOM_VK_RETURN, this.enterKeyPress, this);
KeyHandler.offKey(Keys.DOM_VK_DOWN, this.moveOpenFileSelectionDown, this);
KeyHandler.offKey(Keys.DOM_VK_UP, this.moveOpenFileSelectionUp, this);
Backbone.View.prototype.remove.apply(this);
},
showLocalFileAlert() { showLocalFileAlert() {
if (this.model.settings.get('skipOpenLocalWarn')) { if (this.model.settings.get('skipOpenLocalWarn')) {
@ -179,7 +181,7 @@ const OpenView = Backbone.View.extend({
} }
} }
}); });
}, }
fileSelected(e) { fileSelected(e) {
const file = e.target.files[0]; const file = e.target.files[0];
@ -190,7 +192,7 @@ const OpenView = Backbone.View.extend({
} }
}); });
} }
}, }
processFile(file, complete) { processFile(file, complete) {
const reader = new FileReader(); const reader = new FileReader();
@ -264,7 +266,7 @@ const OpenView = Backbone.View.extend({
} else { } else {
reader.readAsArrayBuffer(file); reader.readAsArrayBuffer(file);
} }
}, }
getOpenFileFormat(fileData) { getOpenFileFormat(fileData) {
if (fileData.byteLength < 8) { if (fileData.byteLength < 8) {
@ -290,7 +292,7 @@ const OpenView = Backbone.View.extend({
} else { } else {
return undefined; return undefined;
} }
}, }
displayOpenFile() { displayOpenFile() {
this.$el.addClass('open--file'); this.$el.addClass('open--file');
@ -298,7 +300,7 @@ const OpenView = Backbone.View.extend({
this.inputEl[0].removeAttribute('readonly'); this.inputEl[0].removeAttribute('readonly');
this.inputEl[0].setAttribute('placeholder', Locale.openPassFor + ' ' + this.params.name); this.inputEl[0].setAttribute('placeholder', Locale.openPassFor + ' ' + this.params.name);
this.focusInput(); this.focusInput();
}, }
displayOpenKeyFile() { displayOpenKeyFile() {
this.$el.toggleClass('open--key-file', !!this.params.keyFileName); this.$el.toggleClass('open--key-file', !!this.params.keyFileName);
@ -306,7 +308,7 @@ const OpenView = Backbone.View.extend({
.find('.open__settings-key-file-name') .find('.open__settings-key-file-name')
.text(this.params.keyFileName || this.params.keyFilePath || Locale.openKeyFile); .text(this.params.keyFileName || this.params.keyFilePath || Locale.openKeyFile);
this.focusInput(); this.focusInput();
}, }
setFile(file, keyFile, fileReadyCallback) { setFile(file, keyFile, fileReadyCallback) {
this.reading = 'fileData'; this.reading = 'fileData';
@ -319,7 +321,13 @@ const OpenView = Backbone.View.extend({
fileReadyCallback(); fileReadyCallback();
} }
}); });
}, }
passInputClick(e) {
if (e.target.readOnly) {
this.openFile();
}
}
openFile() { openFile() {
if (this.model.settings.get('canOpen') === false) { if (this.model.settings.get('canOpen') === false) {
@ -329,7 +337,7 @@ const OpenView = Backbone.View.extend({
this.closeConfig(); this.closeConfig();
this.openAny('fileData'); this.openAny('fileData');
} }
}, }
openKeyFile(e) { openKeyFile(e) {
if ($(e.target).hasClass('open__settings-key-file-dropbox')) { if ($(e.target).hasClass('open__settings-key-file-dropbox')) {
@ -345,7 +353,7 @@ const OpenView = Backbone.View.extend({
this.openAny('keyFileData'); this.openAny('keyFileData');
} }
} }
}, }
openKeyFileFromDropbox() { openKeyFileFromDropbox() {
if (!this.busy) { if (!this.busy) {
@ -358,7 +366,7 @@ const OpenView = Backbone.View.extend({
this.displayOpenKeyFile(); this.displayOpenKeyFile();
}).choose(); }).choose();
} }
}, }
openAny(reading, ext) { openAny(reading, ext) {
this.reading = reading; this.reading = reading;
@ -380,7 +388,7 @@ const OpenView = Backbone.View.extend({
} else { } else {
fileInput.click(); fileInput.click();
} }
}, }
openLast(e) { openLast(e) {
if (this.busy) { if (this.busy) {
@ -414,14 +422,14 @@ const OpenView = Backbone.View.extend({
const fileInfo = this.model.fileInfos.get(id); const fileInfo = this.model.fileInfos.get(id);
this.showOpenFileInfo(fileInfo, true); this.showOpenFileInfo(fileInfo, true);
}, }
removeFile(id) { removeFile(id) {
this.model.removeFileInfo(id); this.model.removeFileInfo(id);
this.$el.find('.open__last-item[data-id="' + id + '"]').remove(); this.$el.find('.open__last-item[data-id="' + id + '"]').remove();
this.initialize(); this.resetParams();
this.render(); this.render();
}, }
inputKeydown(e) { inputKeydown(e) {
const code = e.keyCode || e.which; const code = e.keyCode || e.which;
@ -430,14 +438,14 @@ const OpenView = Backbone.View.extend({
} else if (code === Keys.DOM_VK_CAPS_LOCK) { } else if (code === Keys.DOM_VK_CAPS_LOCK) {
this.toggleCapsLockWarning(false); this.toggleCapsLockWarning(false);
} }
}, }
inputKeyup(e) { inputKeyup(e) {
const code = e.keyCode || e.which; const code = e.keyCode || e.which;
if (code === Keys.DOM_VK_CAPS_LOCK) { if (code === Keys.DOM_VK_CAPS_LOCK) {
this.toggleCapsLockWarning(false); this.toggleCapsLockWarning(false);
} }
}, }
inputKeypress(e) { inputKeypress(e) {
const charCode = e.keyCode || e.which; const charCode = e.keyCode || e.which;
@ -447,11 +455,11 @@ const OpenView = Backbone.View.extend({
if (lower !== upper && !e.shiftKey) { if (lower !== upper && !e.shiftKey) {
this.toggleCapsLockWarning(ch !== lower); this.toggleCapsLockWarning(ch !== lower);
} }
}, }
toggleCapsLockWarning(on) { toggleCapsLockWarning(on) {
this.$el.find('.open__pass-warning').toggleClass('invisible', !on); this.$el.find('.open__pass-warning').toggleClass('invisible', !on);
}, }
dragover(e) { dragover(e) {
if (this.model.settings.get('canOpen') === false) { if (this.model.settings.get('canOpen') === false) {
@ -474,7 +482,7 @@ const OpenView = Backbone.View.extend({
if (!this.$el.hasClass('open--drag')) { if (!this.$el.hasClass('open--drag')) {
this.$el.addClass('open--drag'); this.$el.addClass('open--drag');
} }
}, }
dragleave() { dragleave() {
if (this.model.settings.get('canOpen') === false) { if (this.model.settings.get('canOpen') === false) {
@ -486,7 +494,7 @@ const OpenView = Backbone.View.extend({
this.dragTimeout = setTimeout(() => { this.dragTimeout = setTimeout(() => {
this.$el.removeClass('open--drag'); this.$el.removeClass('open--drag');
}, 100); }, 100);
}, }
drop(e) { drop(e) {
if (this.model.settings.get('canOpen') === false) { if (this.model.settings.get('canOpen') === false) {
@ -516,22 +524,22 @@ const OpenView = Backbone.View.extend({
this.setFile(xmlFile, null, this.showLocalFileAlert.bind(this)); this.setFile(xmlFile, null, this.showLocalFileAlert.bind(this));
} }
} }
}, }
undoKeyPress(e) { undoKeyPress(e) {
e.preventDefault(); e.preventDefault();
}, }
tabKeyPress() { tabKeyPress() {
this.$el.addClass('open--show-focus'); this.$el.addClass('open--show-focus');
}, }
enterKeyPress(e) { enterKeyPress(e) {
const el = this.$el.find('[tabindex]:focus'); const el = this.$el.find('[tabindex]:focus');
if (el.length) { if (el.length) {
el.trigger('click', e); el.trigger('click', e);
} }
}, }
showOpenFileInfo(fileInfo, fileWasClicked) { showOpenFileInfo(fileInfo, fileWasClicked) {
if (this.busy || !fileInfo) { if (this.busy || !fileInfo) {
@ -554,7 +562,7 @@ const OpenView = Backbone.View.extend({
if (fileWasClicked) { if (fileWasClicked) {
this.focusInput(true); this.focusInput(true);
} }
}, }
showOpenLocalFile(path, keyFilePath) { showOpenLocalFile(path, keyFilePath) {
if (this.busy) { if (this.busy) {
@ -574,7 +582,7 @@ const OpenView = Backbone.View.extend({
this.params.keyFileData = null; this.params.keyFileData = null;
this.displayOpenKeyFile(); this.displayOpenKeyFile();
} }
}, }
openFileWithFingerprint(fileInfo) { openFileWithFingerprint(fileInfo) {
if (!fileInfo.has('fingerprint')) { if (!fileInfo.has('fingerprint')) {
@ -588,29 +596,29 @@ const OpenView = Backbone.View.extend({
this.openDb(); this.openDb();
}); });
} }
}, }
createDemo() { createDemo() {
if (!this.busy) { if (!this.busy) {
this.closeConfig(); this.closeConfig();
if (!this.model.createDemoFile()) { if (!this.model.createDemoFile()) {
this.trigger('close'); this.emit('close');
} }
if (!this.model.settings.get('demoOpened')) { if (!this.model.settings.get('demoOpened')) {
this.model.settings.set('demoOpened', true); this.model.settings.set('demoOpened', true);
} }
} }
}, }
createNew() { createNew() {
if (!this.busy) { if (!this.busy) {
this.model.createNewFile(); this.model.createNewFile();
} }
}, }
openDb() { openDb() {
if (this.params.id && this.model.files.get(this.params.id)) { if (this.params.id && this.model.files.get(this.params.id)) {
this.trigger('close'); this.emit('close');
return; return;
} }
if (this.busy || !this.params.name) { if (this.busy || !this.params.name) {
@ -623,7 +631,7 @@ const OpenView = Backbone.View.extend({
this.afterPaint( this.afterPaint(
this.model.openFile.bind(this.model, this.params, this.openDbComplete.bind(this)) this.model.openFile.bind(this.model, this.params, this.openDbComplete.bind(this))
); );
}, }
openDbComplete(err) { openDbComplete(err) {
this.busy = false; this.busy = false;
@ -650,9 +658,9 @@ const OpenView = Backbone.View.extend({
}); });
} }
} else { } else {
this.trigger('close'); this.emit('close');
} }
}, }
importDbWithXml() { importDbWithXml() {
if (this.busy || !this.params.name) { if (this.busy || !this.params.name) {
@ -670,7 +678,7 @@ const OpenView = Backbone.View.extend({
this.openDbComplete(err); this.openDbComplete(err);
}) })
); );
}, }
toggleMore() { toggleMore() {
if (this.busy) { if (this.busy) {
@ -678,11 +686,11 @@ const OpenView = Backbone.View.extend({
} }
this.closeConfig(); this.closeConfig();
this.$el.find('.open__icons--lower').toggleClass('hide'); this.$el.find('.open__icons--lower').toggleClass('hide');
}, }
openSettings() { openSettings() {
Backbone.trigger('toggle-settings'); Backbone.trigger('toggle-settings');
}, }
openStorage(e) { openStorage(e) {
if (this.busy) { if (this.busy) {
@ -704,7 +712,7 @@ const OpenView = Backbone.View.extend({
} else { } else {
Alerts.notImplemented(); Alerts.notImplemented();
} }
}, }
listStorage(storage, config) { listStorage(storage, config) {
if (this.busy) { if (this.busy) {
@ -778,7 +786,7 @@ const OpenView = Backbone.View.extend({
view: listView view: listView
}); });
}); });
}, }
openStorageFile(storage, file) { openStorageFile(storage, file) {
if (this.busy) { if (this.busy) {
@ -791,7 +799,7 @@ const OpenView = Backbone.View.extend({
this.params.rev = file.rev; this.params.rev = file.rev;
this.params.fileData = null; this.params.fileData = null;
this.displayOpenFile(); this.displayOpenFile();
}, }
showConfig(storage) { showConfig(storage) {
if (this.busy) { if (this.busy) {
@ -817,7 +825,7 @@ const OpenView = Backbone.View.extend({
this.views.openConfig.render(); this.views.openConfig.render();
this.$el.find('.open__pass-area').addClass('hide'); this.$el.find('.open__pass-area').addClass('hide');
this.$el.find('.open__icons--lower').addClass('hide'); this.$el.find('.open__icons--lower').addClass('hide');
}, }
closeConfig() { closeConfig() {
if (this.busy) { if (this.busy) {
@ -831,7 +839,7 @@ const OpenView = Backbone.View.extend({
this.$el.find('.open__pass-area').removeClass('hide'); this.$el.find('.open__pass-area').removeClass('hide');
this.$el.find('.open__config').addClass('hide'); this.$el.find('.open__config').addClass('hide');
this.focusInput(); this.focusInput();
}, }
applyConfig(config) { applyConfig(config) {
if (this.busy || !config) { if (this.busy || !config) {
@ -854,7 +862,7 @@ const OpenView = Backbone.View.extend({
} else { } else {
storage.stat(path, opts, this.storageStatComplete.bind(this, req)); storage.stat(path, opts, this.storageStatComplete.bind(this, req));
} }
}, }
storageApplyConfigComplete(req, err) { storageApplyConfigComplete(req, err) {
if (this.storageWaitId !== req.waitId) { if (this.storageWaitId !== req.waitId) {
@ -868,7 +876,7 @@ const OpenView = Backbone.View.extend({
} else { } else {
this.closeConfig(); this.closeConfig();
} }
}, }
storageStatComplete(req, err, stat) { storageStatComplete(req, err, stat) {
if (this.storageWaitId !== req.waitId) { if (this.storageWaitId !== req.waitId) {
@ -890,7 +898,7 @@ const OpenView = Backbone.View.extend({
this.params.fileData = null; this.params.fileData = null;
this.displayOpenFile(); this.displayOpenFile();
} }
}, }
moveOpenFileSelection(steps) { moveOpenFileSelection(steps) {
const lastOpenFiles = this.getLastOpenFiles(); const lastOpenFiles = this.getLastOpenFiles();
@ -911,15 +919,15 @@ const OpenView = Backbone.View.extend({
if (fileInfo && Launcher && Launcher.fingerprints) { if (fileInfo && Launcher && Launcher.fingerprints) {
this.openFileWithFingerprint(fileInfo); this.openFileWithFingerprint(fileInfo);
} }
}, }
moveOpenFileSelectionDown() { moveOpenFileSelectionDown() {
this.moveOpenFileSelection(1); this.moveOpenFileSelection(1);
}, }
moveOpenFileSelectionUp() { moveOpenFileSelectionUp() {
this.moveOpenFileSelection(-1); this.moveOpenFileSelection(-1);
} }
}); }
export { OpenView }; export { OpenView };