From 7730486f30b4ba41e2e214185dcceedff7e04b8d Mon Sep 17 00:00:00 2001 From: antelle Date: Mon, 16 Sep 2019 17:43:57 +0200 Subject: [PATCH] move views --- app/scripts/app.js | 2 +- app/scripts/view-engine/resizable.js | 4 +- app/scripts/view-engine/view.js | 33 ++-- app/scripts/views/app-view.js | 193 +++++++++--------- app/scripts/views/list-search-view.js | 129 ++++++------- app/scripts/views/list-view.js | 105 +++++----- app/scripts/views/menu/menu-item-view.js | 95 +++++---- app/scripts/views/menu/menu-section-view.js | 65 ++++--- app/scripts/views/menu/menu-view.js | 57 +++--- app/scripts/views/open-view.js | 204 ++++++++++---------- 10 files changed, 445 insertions(+), 442 deletions(-) diff --git a/app/scripts/app.js b/app/scripts/app.js index 9a13179f..0c422e59 100644 --- a/app/scripts/app.js +++ b/app/scripts/app.js @@ -150,7 +150,7 @@ ready(() => { function showView() { appModel.prepare(); - new AppView({ model: appModel }).render(); + new AppView(appModel).render(); Backbone.trigger('app-ready'); logStartupTime(); } diff --git a/app/scripts/view-engine/resizable.js b/app/scripts/view-engine/resizable.js index 9db57863..32e578a0 100644 --- a/app/scripts/view-engine/resizable.js +++ b/app/scripts/view-engine/resizable.js @@ -16,7 +16,7 @@ const Resizable = { let size = dragInfo.startSize + e.offset; size = Math.max(dragInfo.min, Math.min(dragInfo.max, size)); this.$el[dragInfo.prop](size); - this.trigger('view-resize', size); + this.emit('view-resize', size); Backbone.trigger('page-geometry', { source: 'resizable' }); }, @@ -28,7 +28,7 @@ const Resizable = { this.$el.css(dragInfo.prop, 'auto'); } this.fixSize(dragInfo); - this.trigger('view-resize', null); + this.emit('view-resize', null); Backbone.trigger('page-geometry', { source: 'resizable' }); }, diff --git a/app/scripts/view-engine/view.js b/app/scripts/view-engine/view.js index 95029767..ea64b3c6 100644 --- a/app/scripts/view-engine/view.js +++ b/app/scripts/view-engine/view.js @@ -6,9 +6,10 @@ import { Logger } from 'util/logger'; class View extends EventEmitter { parent = undefined; - replace = false; template = undefined; events = {}; + model = undefined; + options = {}; views = {}; hidden = false; removed = false; @@ -19,13 +20,7 @@ class View extends EventEmitter { super(); this.model = model; - - if (options.parent) { - this.parent = options.parent; - } - if (options.replace) { - this.replace = options.replace; - } + this.options = options; this.setMaxListeners(100); } @@ -55,24 +50,31 @@ class View extends EventEmitter { renderElement(templateData) { const html = this.template(templateData); if (this.el) { - morphdom(this.el, html); + const mountRoot = this.options.ownParent ? this.el.firstChild : this.el; + morphdom(mountRoot, html); } else { - if (this.parent) { - let parent = this.parent; + let parent = this.options.parent || this.parent; + if (parent) { if (typeof parent === 'string') { - parent = document.querySelector(this.parent); + parent = document.querySelector(parent); } if (!parent) { throw new Error(`Error rendering ${this.constructor.name}: parent not found`); } - if (this.replace) { + if (this.options.replace) { Tip.destroyTips(parent); parent.innerHTML = ''; } const el = document.createElement('div'); el.innerHTML = html; - this.el = el.firstChild; - parent.appendChild(this.el); + const root = el.firstChild; + if (this.options.ownParent) { + parent.appendChild(root); + this.el = parent; + } else { + this.el = root; + parent.appendChild(this.el); + } } else { throw new Error( `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) { + // TODO: remove a pending callback model.off(event, callback); } diff --git a/app/scripts/views/app-view.js b/app/scripts/views/app-view.js index 25bb7816..85c7c7ee 100644 --- a/app/scripts/views/app-view.js +++ b/app/scripts/views/app-view.js @@ -1,4 +1,5 @@ import Backbone from 'backbone'; +import { View } from 'view-engine/view'; import { IdleTracker } from 'comp/browser/idle-tracker'; import { KeyHandler } from 'comp/browser/key-handler'; import { Launcher } from 'comp/launcher'; @@ -22,32 +23,31 @@ import { MenuView } from 'views/menu/menu-view'; import { OpenView } from 'views/open-view'; import { SettingsView } from 'views/settings/settings-view'; import { TagView } from 'views/tag-view'; +import template from 'templates/app.hbs'; -const AppView = Backbone.View.extend({ - el: 'body', +class AppView extends View { + parent = 'body'; - template: require('templates/app.hbs'), + template = template; - events: { - 'contextmenu': 'contextMenu', - 'drop': 'drop', - 'dragenter': 'dragover', - 'dragover': 'dragover', + events = { + contextmenu: 'contextMenu', + drop: 'drop', + dragenter: 'dragover', + dragover: 'dragover', 'click a[target=_blank]': 'extLinkClick', - 'mousedown': 'bodyClick' - }, + mousedown: 'bodyClick' + }; - views: null, + titlebarStyle = 'default'; - titlebarStyle: 'default', - - initialize() { - this.views = {}; - this.views.menu = new MenuView({ model: this.model.menu }); + constructor(model) { + super(model); + this.views.menu = new MenuView(this.model.menu, { ownParent: true }); this.views.menuDrag = new DragView('x', { parent: '.app__menu-drag' }); this.views.footer = new FooterView(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.list.dragView = this.views.listDrag; this.views.details = new DetailsView(); @@ -95,13 +95,12 @@ const AppView = Backbone.View.extend({ window.onresize = this.windowResize.bind(this); window.onblur = this.windowBlur.bind(this); - KeyHandler.onKey(Keys.DOM_VK_ESCAPE, this.escPressed, this); - KeyHandler.onKey(Keys.DOM_VK_BACK_SPACE, this.backspacePressed, this); + this.onKey(Keys.DOM_VK_ESCAPE, this.escPressed); + this.onKey(Keys.DOM_VK_BACK_SPACE, this.backspacePressed); if (Launcher && Launcher.devTools) { KeyHandler.onKey( Keys.DOM_VK_I, this.openDevTools, - this, KeyHandler.SHORTCUT_ACTION + KeyHandler.SHORTCUT_OPT ); } @@ -110,7 +109,7 @@ const AppView = Backbone.View.extend({ this.setWindowClass(); this.fixClicksInEdge(); - }, + } setWindowClass() { const getBrowserCssClass = Features.getBrowserCssClass(); @@ -120,7 +119,7 @@ const AppView = Backbone.View.extend({ if (this.titlebarStyle !== 'default') { this.$el.addClass('titlebar-' + this.titlebarStyle); } - }, + } fixClicksInEdge() { // MS Edge doesn't want to handle clicks by default @@ -133,26 +132,24 @@ const AppView = Backbone.View.extend({ .focus(); setTimeout(() => msEdgeScrewer.remove(), 0); } - }, + } render() { - this.$el.html( - this.template({ - beta: this.model.isBeta, - titlebarStyle: this.titlebarStyle - }) - ); + super.render({ + beta: this.model.isBeta, + titlebarStyle: this.titlebarStyle + }); this.panelEl = this.$el.find('.app__panel:first'); this.views.listWrap.render(); - this.views.menu.setElement(this.$el.find('.app__menu')).render(); + this.views.menu.render(); this.views.menuDrag.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.details.setElement(this.$el.find('.app__details')).render(); this.showLastOpenFile(); return this; - }, + } showOpenFile() { this.hideContextMenu(); @@ -167,17 +164,13 @@ const AppView = Backbone.View.extend({ this.hideSettings(); this.hideOpenFile(); this.hideKeyChange(); - this.views.open = new OpenView({ model: this.model }); - this.views.open.setElement(this.$el.find('.app__body')).render(); - this.views.open.on( - 'close', - () => { - Backbone.trigger('closed-open-view'); - }, - this - ); - this.views.open.on('close', this.showEntries, this); - }, + this.views.open = new OpenView(this.model); + this.views.open.render(); + this.views.open.on('close', () => { + Backbone.trigger('closed-open-view'); + }); + this.views.open.on('close', () => this.showEntries()); + } showLastOpenFile() { this.showOpenFile(); @@ -186,14 +179,14 @@ const AppView = Backbone.View.extend({ this.views.open.currentSelectedIndex = 0; this.views.open.showOpenFileInfo(lastOpenFile); } - }, + } launcherOpenFile(file) { if (file && file.data && /\.kdbx$/i.test(file.data)) { this.showOpenFile(); this.views.open.showOpenLocalFile(file.data, file.key); } - }, + } updateApp() { if ( @@ -203,7 +196,7 @@ const AppView = Backbone.View.extend({ ) { window.location.reload(); } - }, + } showEntries() { this.views.menu.show(); @@ -217,14 +210,14 @@ const AppView = Backbone.View.extend({ this.hideOpenFile(); this.hideSettings(); this.hideKeyChange(); - }, + } hideOpenFile() { if (this.views.open) { this.views.open.remove(); this.views.open = null; } - }, + } hidePanelView() { if (this.views.panel) { @@ -232,7 +225,7 @@ const AppView = Backbone.View.extend({ this.views.panel = null; this.panelEl.addClass('hide'); } - }, + } showPanelView(view) { this.views.listWrap.hide(); @@ -243,7 +236,7 @@ const AppView = Backbone.View.extend({ view.render(); this.views.panel = view; this.panelEl.removeClass('hide'); - }, + } hideSettings() { if (this.views.settings) { @@ -251,14 +244,14 @@ const AppView = Backbone.View.extend({ this.views.settings.remove(); this.views.settings = null; } - }, + } hideKeyChange() { if (this.views.keyChange) { this.views.keyChange.hide(); this.views.keyChange = null; } - }, + } showSettings(selectedMenuItem) { this.model.menu.setMenu('settings'); @@ -278,15 +271,15 @@ const AppView = Backbone.View.extend({ } this.model.menu.select({ item: selectedMenuItem }); this.views.menu.switchVisibility(false); - }, + } showEditGroup(group) { this.showPanelView(new GrpView(group)); - }, + } showEditTag() { this.showPanelView(new TagView(this.model)); - }, + } showKeyChange(file, viewConfig) { if (Alerts.alertDisplayed) { @@ -310,7 +303,7 @@ const AppView = Backbone.View.extend({ this.views.keyChange.render(); this.views.keyChange.on('accept', this.keyChangeAccept.bind(this)); this.views.keyChange.on('cancel', this.showEntries.bind(this)); - }, + } fileListUpdated() { if (this.model.files.hasOpenFiles()) { @@ -319,7 +312,7 @@ const AppView = Backbone.View.extend({ this.showOpenFile(); } this.fixClicksInEdge(); - }, + } showFileSettings(e) { const menuItem = this.model.menu.filesSection @@ -334,7 +327,7 @@ const AppView = Backbone.View.extend({ } else { this.showSettings(menuItem); } - }, + } toggleOpenFile() { if (this.views.open) { @@ -344,7 +337,7 @@ const AppView = Backbone.View.extend({ } else { this.showOpenFile(); } - }, + } beforeUnload(e) { const exitEvent = { @@ -419,70 +412,70 @@ const AppView = Backbone.View.extend({ Launcher.minimizeApp(); return Launcher.preventExit(e); } - }, + } windowResize() { Backbone.trigger('page-geometry', { source: 'window' }); - }, + } windowBlur(e) { if (e.target === window) { Backbone.trigger('page-blur'); } - }, + } enterFullScreen() { this.$el.addClass('fullscreen'); - }, + } leaveFullScreen() { this.$el.removeClass('fullscreen'); - }, + } escPressed() { if (this.views.open && this.model.files.hasOpenFiles()) { this.showEntries(); } - }, + } backspacePressed(e) { if (e.target === document.body) { e.preventDefault(); } - }, + } openDevTools() { if (Launcher && Launcher.devTools) { Launcher.openDevTools(); } - }, + } selectAll() { this.menuSelect({ item: this.model.menu.allItemsSection.get('items').first() }); - }, + } menuSelect(opt) { this.model.menu.select(opt); if (this.views.panel && !this.views.panel.isHidden()) { this.showEntries(); } - }, + } userIdle() { this.lockWorkspace(true); - }, + } osLocked() { if (this.model.settings.get('lockOnOsLock')) { this.lockWorkspace(true); } - }, + } appMinimized() { if (this.model.settings.get('lockOnMinimize')) { this.lockWorkspace(true); } - }, + } lockWorkspace(autoInit) { if (Alerts.alertDisplayed) { @@ -518,7 +511,7 @@ const AppView = Backbone.View.extend({ } else { this.closeAllFilesAndShowFirst(); } - }, + } handleAutoSaveTimer() { if (this.model.settings.get('autoSaveInterval') !== 0) { @@ -531,7 +524,7 @@ const AppView = Backbone.View.extend({ this.model.settings.get('autoSaveInterval') * 1000 * 60 ); } - }, + } saveAndLock(complete) { let pendingCallbacks = 0; @@ -574,7 +567,7 @@ const AppView = Backbone.View.extend({ } } } - }, + } closeAllFilesAndShowFirst() { 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); } } - }, + } saveAll() { this.model.files.forEach(function(file) { this.model.syncFile(file); }, this); - }, + } syncAllByTimer() { if (this.model.settings.get('autoSave')) { this.saveAll(); } - }, + } remoteKeyChanged(e) { this.showKeyChange(e.file, { remote: true }); - }, + } keyChangePending(e) { this.showKeyChange(e.file, { expired: true }); - }, + } keyChangeAccept(e) { this.showEntries(); @@ -632,7 +625,7 @@ const AppView = Backbone.View.extend({ } }); } - }, + } toggleSettings(page) { let menuItem = page ? this.model.menu[page + 'Section'] : null; @@ -658,16 +651,16 @@ const AppView = Backbone.View.extend({ this.model.menu.select({ item: menuItem }); } } - }, + } toggleMenu() { this.views.menu.switchVisibility(); - }, + } toggleDetails(visible) { this.$el.find('.app').toggleClass('app--details-visible', visible); this.views.menu.switchVisibility(false); - }, + } editGroup(group) { if (group && !(this.views.panel instanceof GrpView)) { @@ -675,7 +668,7 @@ const AppView = Backbone.View.extend({ } else { this.showEntries(); } - }, + } editTag(tag) { if (tag && !(this.views.panel instanceof TagView)) { @@ -684,7 +677,7 @@ const AppView = Backbone.View.extend({ } else { this.showEntries(); } - }, + } editGeneratorPresets() { if (!(this.views.panel instanceof GeneratorPresetsView)) { @@ -695,17 +688,17 @@ const AppView = Backbone.View.extend({ } else { this.showEntries(); } - }, + } isContextMenuAllowed(e) { return ['input', 'textarea'].indexOf(e.target.tagName.toLowerCase()) < 0; - }, + } contextMenu(e) { if (this.isContextMenuAllowed(e)) { e.preventDefault(); } - }, + } showContextMenu(e) { if (e.options && this.isContextMenuAllowed(e)) { @@ -723,19 +716,19 @@ const AppView = Backbone.View.extend({ menu.on('select', e => this.contextMenuSelect(e)); this.views.contextMenu = menu; } - }, + } hideContextMenu() { if (this.views.contextMenu) { this.views.contextMenu.remove(); delete this.views.contextMenu; } - }, + } contextMenuSelect(e) { this.hideContextMenu(); Backbone.trigger('context-menu-select', e); - }, + } showSingleInstanceAlert() { this.hideOpenFile(); @@ -747,24 +740,24 @@ const AppView = Backbone.View.extend({ click: false, buttons: [] }); - }, + } dragover(e) { e.preventDefault(); e.originalEvent.dataTransfer.dropEffect = 'none'; - }, + } drop(e) { e.preventDefault(); - }, + } setTheme() { SettingsManager.setTheme(this.model.settings.get('theme')); - }, + } setFontSize() { SettingsManager.setFontSize(this.model.settings.get('fontSize')); - }, + } setLocale() { SettingsManager.setLocale(this.model.settings.get('locale')); @@ -773,19 +766,19 @@ const AppView = Backbone.View.extend({ this.showSettings(); } this.$el.find('.app__beta:first').text(Locale.appBeta); - }, + } extLinkClick(e) { if (Launcher) { e.preventDefault(); Launcher.openLink(e.target.href); } - }, + } bodyClick(e) { IdleTracker.regUserAction(); Backbone.trigger('click', e); } -}); +} export { AppView }; diff --git a/app/scripts/views/list-search-view.js b/app/scripts/views/list-search-view.js index 6743bf29..e23664ef 100644 --- a/app/scripts/views/list-search-view.js +++ b/app/scripts/views/list-search-view.js @@ -1,4 +1,5 @@ import Backbone from 'backbone'; +import { View } from 'view-engine/view'; import { Shortcuts } from 'comp/app/shortcuts'; import { KeyHandler } from 'comp/browser/key-handler'; import { Keys } from 'const/keys'; @@ -7,11 +8,14 @@ import { Features } from 'util/features'; import { StringFormat } from 'util/formatting/string-format'; import { Locale } from 'util/locale'; import { DropdownView } from 'views/dropdown-view'; +import template from 'templates/list-search.hbs'; -const ListSearchView = Backbone.View.extend({ - template: require('templates/list-search.hbs'), +class ListSearchView extends View { + parent = '.list__header'; - events: { + template = template; + + events = { 'keydown .list__search-field': 'inputKeyDown', 'keypress .list__search-field': 'inputKeyPress', 'input .list__search-field': 'inputChange', @@ -21,18 +25,17 @@ const ListSearchView = Backbone.View.extend({ 'click .list__search-icon-search': 'advancedSearchClick', 'click .list__search-btn-menu': 'toggleMenu', 'change .list__search-adv input[type=checkbox]': 'toggleAdvCheck' - }, + }; - views: null, + inputEl = null; + sortOptions = null; + sortIcons = null; + createOptions = null; + advancedSearchEnabled = false; + advancedSearch = null; - inputEl: null, - sortOptions: null, - sortIcons: null, - createOptions: null, - advancedSearchEnabled: false, - advancedSearch: null, - - initialize() { + constructor(model) { + super(model); this.sortOptions = [ { value: 'title', @@ -116,24 +119,16 @@ const ListSearchView = Backbone.View.extend({ this.advancedSearch = _.extend({}, this.model.advancedSearch); } this.setLocale(); - KeyHandler.onKey(Keys.DOM_VK_F, this.findKeyPress, this, KeyHandler.SHORTCUT_ACTION); - KeyHandler.onKey(Keys.DOM_VK_N, this.newKeyPress, this, KeyHandler.SHORTCUT_OPT); - KeyHandler.onKey(Keys.DOM_VK_DOWN, this.downKeyPress, this); - KeyHandler.onKey(Keys.DOM_VK_UP, this.upKeyPress, this); + this.onKey(Keys.DOM_VK_F, this.findKeyPress, KeyHandler.SHORTCUT_ACTION); + this.onKey(Keys.DOM_VK_N, this.newKeyPress, KeyHandler.SHORTCUT_OPT); + this.onKey(Keys.DOM_VK_DOWN, this.downKeyPress); + this.onKey(Keys.DOM_VK_UP, this.upKeyPress); this.listenTo(this, 'show', this.viewShown); this.listenTo(this, 'hide', this.viewHidden); this.listenTo(Backbone, 'filter', this.filterChanged); this.listenTo(Backbone, 'set-locale', this.setLocale); 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() { this.sortOptions.forEach(opt => { @@ -150,27 +145,29 @@ const ListSearchView = Backbone.View.extend({ { value: 'entry', icon: 'key', text: StringFormat.capFirst(Locale.entry) + entryDesc }, { value: 'group', icon: 'folder', text: StringFormat.capFirst(Locale.group) } ]; - this.render(); - }, + if (this.el) { + this.render(); + } + } pageBlur() { this.inputEl.blur(); - }, + } viewShown() { this.listenTo(KeyHandler, 'keypress', this.documentKeyPress); - }, + } viewHidden() { this.stopListening(KeyHandler, 'keypress', this.documentKeyPress); - }, + } render() { let searchVal; if (this.inputEl) { searchVal = this.inputEl.val(); } - this.renderTemplate({ + super.render({ adv: this.advancedSearch, advEnabled: this.advancedSearchEnabled }); @@ -179,7 +176,7 @@ const ListSearchView = Backbone.View.extend({ this.inputEl.val(searchVal); } return this; - }, + } inputKeyDown(e) { switch (e.which) { @@ -200,22 +197,22 @@ const ListSearchView = Backbone.View.extend({ return; } e.preventDefault(); - }, + } inputKeyPress(e) { e.stopPropagation(); - }, + } inputChange() { Backbone.trigger('add-filter', { text: this.inputEl.val() }); - }, + } inputFocus(e) { $(e.target).select(); - }, + } documentKeyPress(e) { - if (this._hidden) { + if (this.hidden) { return; } const code = e.charCode; @@ -227,35 +224,35 @@ const ListSearchView = Backbone.View.extend({ this.inputEl[0].setSelectionRange(1, 1); this.inputChange(); e.preventDefault(); - }, + } findKeyPress(e) { - if (!this._hidden) { + if (!this.hidden) { e.preventDefault(); this.hideSearchOptions(); this.inputEl.select().focus(); } - }, + } newKeyPress(e) { - if (!this._hidden) { + if (!this.hidden) { e.preventDefault(); this.hideSearchOptions(); - this.trigger('create-entry'); + this.emit('create-entry'); } - }, + } downKeyPress(e) { e.preventDefault(); this.hideSearchOptions(); - this.trigger('select-next'); - }, + this.emit('select-next'); + } upKeyPress(e) { e.preventDefault(); this.hideSearchOptions(); - this.trigger('select-prev'); - }, + this.emit('select-prev'); + } filterChanged(filter) { this.hideSearchOptions(); @@ -272,22 +269,22 @@ const ListSearchView = Backbone.View.extend({ this.advancedSearchEnabled = adv; this.$el.find('.list__search-adv').toggleClass('hide', !this.advancedSearchEnabled); } - }, + } createOptionsClick(e) { e.stopImmediatePropagation(); if (e.shiftKey) { this.hideSearchOptions(); - this.trigger('create-entry'); + this.emit('create-entry'); return; } this.toggleCreateOptions(); - }, + } sortOptionsClick(e) { this.toggleSortOptions(); e.stopImmediatePropagation(); - }, + } advancedSearchClick() { this.advancedSearchEnabled = !this.advancedSearchEnabled; @@ -299,17 +296,17 @@ const ListSearchView = Backbone.View.extend({ advanced = this.model.advancedSearch; } Backbone.trigger('add-filter', { advanced }); - }, + } toggleMenu() { Backbone.trigger('toggle-menu'); - }, + } toggleAdvCheck(e) { const setting = $(e.target).data('id'); this.advancedSearch[setting] = e.target.checked; Backbone.trigger('add-filter', { advanced: this.advancedSearch }); - }, + } hideSearchOptions() { if (this.views.searchDropdown) { @@ -319,7 +316,7 @@ const ListSearchView = Backbone.View.extend({ .find('.list__search-btn-sort,.list__search-btn-new') .removeClass('sel--active'); } - }, + } toggleSortOptions() { if (this.views.searchDropdown && this.views.searchDropdown.isSort) { @@ -343,7 +340,7 @@ const ListSearchView = Backbone.View.extend({ options: this.sortOptions }); this.views.searchDropdown = view; - }, + } toggleCreateOptions() { if (this.views.searchDropdown && this.views.searchDropdown.isCreate) { @@ -365,7 +362,7 @@ const ListSearchView = Backbone.View.extend({ options: this.createOptions.concat(this.getCreateEntryTemplateOptions()) }); this.views.searchDropdown = view; - }, + } getCreateEntryTemplateOptions() { const entryTemplates = this.model.getEntryTemplates(); @@ -390,35 +387,35 @@ const ListSearchView = Backbone.View.extend({ text: StringFormat.capFirst(Locale.template) }); return options; - }, + } sortDropdownSelect(e) { this.hideSearchOptions(); Backbone.trigger('set-sort', e.item); - }, + } createDropdownSelect(e) { this.hideSearchOptions(); switch (e.item) { case 'entry': - this.trigger('create-entry'); + this.emit('create-entry'); break; case 'group': - this.trigger('create-group'); + this.emit('create-group'); break; case 'tmpl': - this.trigger('create-template'); + this.emit('create-template'); break; default: 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) { return str.replace('{}', '→'); } -}); +} export { ListSearchView }; diff --git a/app/scripts/views/list-view.js b/app/scripts/views/list-view.js index e5050381..eda754b2 100644 --- a/app/scripts/views/list-view.js +++ b/app/scripts/views/list-view.js @@ -1,4 +1,5 @@ import Backbone from 'backbone'; +import { View } from 'view-engine/view'; import { EntryCollection } from 'collections/entry-collection'; import { DragDropInfo } from 'comp/app/drag-drop-info'; import { Alerts } from 'comp/ui/alerts'; @@ -10,27 +11,30 @@ import { Resizable } from 'view-engine/resizable'; import { Scrollable } from 'view-engine/scrollable'; import { DropdownView } from 'views/dropdown-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({ - template: require('templates/list.hbs'), - emptyTemplate: require('templates/list-empty.hbs'), +class ListView extends View { + parent = '.app__list'; - events: { + template = template; + + emptyTemplate = emptyTemplate; + + events = { 'click .list__item': 'itemClick', 'click .list__table-options': 'tableOptionsClick', 'dragstart .list__item': 'itemDragStart' - }, + }; - views: null, + minWidth = 200; + minHeight = 200; + maxWidth = 500; + maxHeight = 500; - minWidth: 200, - minHeight: 200, - maxWidth: 500, - maxHeight: 500, + itemsEl = null; - itemsEl: null, - - tableColumns: [ + tableColumns = [ { val: 'title', name: 'title', enabled: true }, { val: 'user', name: 'user', enabled: true }, { val: 'url', name: 'website', enabled: true }, @@ -38,12 +42,13 @@ const ListView = Backbone.View.extend({ { val: 'notes', name: 'notes', enabled: true }, { val: 'groupName', name: 'group', enabled: false }, { val: 'fileName', name: 'file', enabled: false } - ], + ]; + + constructor(model) { + super(model); - initialize() { this.initScroll(); - this.views = {}; - this.views.search = new ListSearchView({ model: this.model }); + this.views.search = new ListSearchView(this.model); this.listenTo(this.views.search, 'select-prev', this.selectPrev); this.listenTo(this.views.search, 'select-next', this.selectNext); @@ -62,13 +67,13 @@ const ListView = Backbone.View.extend({ this.readTableColumnsEnabled(); this.items = new EntryCollection(); - }, + } render() { if (!this.itemsEl) { - this.$el.html(this.template()); + super.render(); 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.createScroll({ @@ -105,7 +110,7 @@ const ListView = Backbone.View.extend({ } this.pageResized(); return this; - }, + } getItemsTemplate() { if (this.model.settings.get('tableView')) { @@ -113,11 +118,11 @@ const ListView = Backbone.View.extend({ } else { return this.renderPlainItems; } - }, + } renderPlainItems(itemsHtml) { return itemsHtml.items; - }, + } getItemTemplate() { if (this.model.settings.get('tableView')) { @@ -125,11 +130,11 @@ const ListView = Backbone.View.extend({ } else { return require('templates/list-item-short.hbs'); } - }, + } getDescField() { return this.model.sort.replace('-', ''); - }, + } itemClick(e) { const id = $(e.target) @@ -140,33 +145,33 @@ const ListView = Backbone.View.extend({ this.selectItem(item); } Backbone.trigger('toggle-details', true); - }, + } selectPrev() { const ix = this.items.indexOf(this.items.get(this.model.activeEntryId)); if (ix > 0) { this.selectItem(this.items.at(ix - 1)); } - }, + } selectNext() { const ix = this.items.indexOf(this.items.get(this.model.activeEntryId)); if (ix < this.items.length - 1) { this.selectItem(this.items.at(ix + 1)); } - }, + } createEntry(arg) { const newEntry = this.model.createNewEntry(arg); this.items.unshift(newEntry); this.render(); this.selectItem(newEntry); - }, + } createGroup() { const newGroup = this.model.createNewGroup(); Backbone.trigger('edit-group', newGroup); - }, + } createTemplate() { if (!this.model.settings.get('templateHelpShown')) { @@ -189,7 +194,7 @@ const ListView = Backbone.View.extend({ this.items.unshift(templateEntry); this.render(); this.selectItem(templateEntry); - }, + } selectItem(item) { this.model.activeEntryId = item.id; @@ -205,25 +210,25 @@ const ListView = Backbone.View.extend({ } else if (itemRect.bottom > listRect.bottom) { listEl.scrollTop += itemRect.bottom - listRect.bottom; } - }, + } viewShown() { this.views.search.show(); - }, + } viewHidden() { this.views.search.hide(); - }, + } setTableView() { const isTable = this.model.settings.get('tableView'); this.dragView.setCoord(isTable ? 'y' : 'x'); this.setDefaultSize(); - }, + } setDefaultSize() { this.setSize(this.model.settings.get('listViewWidth')); - }, + } setSize(size) { this.$el.css({ width: 'auto', height: 'auto' }); @@ -232,27 +237,27 @@ const ListView = Backbone.View.extend({ } else { this.$el.css('flex', null); } - }, + } viewResized(size) { this.setSize(size); this.throttleSetViewSizeSetting(size); - }, + } - throttleSetViewSizeSetting: _.throttle(size => { + throttleSetViewSizeSetting = _.throttle(size => { AppSettingsModel.instance.set('listViewWidth', size); - }, 1000), + }, 1000); filterChanged(filter) { this.items = filter.entries; this.render(); - }, + } entryUpdated() { const scrollTop = this.itemsEl[0].scrollTop; this.render(); this.itemsEl[0].scrollTop = scrollTop; - }, + } itemDragStart(e) { e.stopPropagation(); @@ -262,7 +267,7 @@ const ListView = Backbone.View.extend({ e.originalEvent.dataTransfer.setData('text/entry', id); e.originalEvent.dataTransfer.effectAllowed = 'move'; DragDropInfo.dragObject = this.items.get(id); - }, + } tableOptionsClick(e) { e.stopImmediatePropagation(); @@ -287,14 +292,14 @@ const ListView = Backbone.View.extend({ options }); this.views.optionsDropdown = view; - }, + } hideOptionsDropdown() { if (this.views.optionsDropdown) { this.views.optionsDropdown.remove(); delete this.views.optionsDropdown; } - }, + } optionsDropdownSelect(e) { 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'); this.render(); this.saveTableColumnsEnabled(); - }, + } readTableColumnsEnabled() { const tableViewColumns = AppSettingsModel.instance.get('tableViewColumns'); @@ -311,7 +316,7 @@ const ListView = Backbone.View.extend({ col.enabled = tableViewColumns.indexOf(col.name) >= 0; }); } - }, + } saveTableColumnsEnabled() { const tableViewColumns = this.tableColumns @@ -319,9 +324,9 @@ const ListView = Backbone.View.extend({ .map(column => column.name); AppSettingsModel.instance.set('tableViewColumns', tableViewColumns); } -}); +} -_.extend(ListView.prototype, Resizable); -_.extend(ListView.prototype, Scrollable); +Object.assign(ListView.prototype, Resizable); +Object.assign(ListView.prototype, Scrollable); export { ListView }; diff --git a/app/scripts/views/menu/menu-item-view.js b/app/scripts/views/menu/menu-item-view.js index 3c3c7f89..94c9f47d 100644 --- a/app/scripts/views/menu/menu-item-view.js +++ b/app/scripts/views/menu/menu-item-view.js @@ -1,14 +1,16 @@ import Backbone from 'backbone'; +import { View } from 'view-engine/view'; import { DragDropInfo } from 'comp/app/drag-drop-info'; import { KeyHandler } from 'comp/browser/key-handler'; import { Alerts } from 'comp/ui/alerts'; import { Keys } from 'const/keys'; import { Locale } from 'util/locale'; +import template from 'templates/menu/menu-item.hbs'; -const MenuItemView = Backbone.View.extend({ - template: require('templates/menu/menu-item.hbs'), +class MenuItemView extends View { + template = template; - events: { + events = { 'mouseover': 'mouseover', 'mouseout': 'mouseout', 'click .menu__item-option': 'selectOption', @@ -22,12 +24,13 @@ const MenuItemView = Backbone.View.extend({ 'drop': 'drop', 'dragover .menu__item-drag-top': 'dragoverTop', 'dragleave .menu__item-drag-top': 'dragleaveTop' - }, + }; - iconEl: null, - itemViews: null, + iconEl = null; + itemViews = null; - initialize() { + constructor(model, options) { + super(model, options); this.itemViews = []; this.listenTo(this.model, 'change:title', this.changeTitle); this.listenTo(this.model, 'change:icon', this.changeIcon); @@ -39,70 +42,62 @@ const MenuItemView = Backbone.View.extend({ this.listenTo(this.model, 'insert', this.insertItem); const shortcut = this.model.get('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) { - KeyHandler.onKey(shortcut, this.selectItem, this, KeyHandler.SHORTCUT_ACTION); + this.onKey(shortcut, this.selectItem, KeyHandler.SHORTCUT_ACTION); } } - }, + this.once('remove', () => { + this.removeInnerViews(); + }); + } render() { this.removeInnerViews(); - this.renderTemplate(this.model.attributes); + super.render(this.model.attributes); this.iconEl = this.$el.find('.menu__item-icon'); const items = this.model.get('items'); if (items) { - items.forEach(function(item) { + items.forEach(item => { if (item.get('visible')) { this.insertItem(item); } - }, this); + }); } this.$el.toggleClass('menu__item--collapsed', !this.model.get('expanded')); - return this; - }, + } insertItem(item) { - this.itemViews.push(new MenuItemView({ el: this.$el, model: item }).render()); - }, - - 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); - }, + const itemView = new MenuItemView(item, { parent: this.el }); + itemView.render(); + this.itemViews.push(itemView); + } removeInnerViews() { this.itemViews.forEach(itemView => itemView.remove()); this.itemViews = []; - }, + } changeTitle(model, title) { this.$el .find('.menu__item-title') .first() .text(title || '(no title)'); - }, + } changeIcon(model, icon) { this.iconEl[0].className = 'menu__item-icon fa ' + (icon ? 'fa-' + icon : 'menu__item-icon--no-icon'); - }, + } changeActive(model, active) { this.$el.toggleClass('menu__item--active', active); - }, + } changeExpanded(model, expanded) { this.$el.toggleClass('menu__item--collapsed', !expanded); this.model.setExpanded(expanded); - }, + } changeCls(model, cls) { const oldCls = model.previousAttributes().cls; @@ -110,19 +105,19 @@ const MenuItemView = Backbone.View.extend({ this.$el.removeClass(oldCls); } this.$el.addClass(cls); - }, + } mouseover(e) { if (!e.button) { this.$el.addClass('menu__item--hover'); e.stopPropagation(); } - }, + } mouseout(e) { this.$el.removeClass('menu__item--hover'); e.stopPropagation(); - }, + } selectItem(e) { e.stopPropagation(); @@ -135,7 +130,7 @@ const MenuItemView = Backbone.View.extend({ } else { Backbone.trigger('menu-select', { item: this.model }); } - }, + } selectOption(e) { const options = this.model.get('options'); @@ -148,14 +143,14 @@ const MenuItemView = Backbone.View.extend({ } e.stopImmediatePropagation(); e.preventDefault(); - }, + } expandItem(e) { if (this.model.toggleExpanded) { this.model.toggleExpanded(); } e.stopPropagation(); - }, + } editItem(e) { if (this.model.get('active') && this.model.get('editable')) { @@ -169,7 +164,7 @@ const MenuItemView = Backbone.View.extend({ break; } } - }, + } emptyTrash(e) { e.stopPropagation(); @@ -181,7 +176,7 @@ const MenuItemView = Backbone.View.extend({ Backbone.trigger('empty-trash'); } }); - }, + } dropAllowed(e) { const types = e.originalEvent.dataTransfer.types; @@ -191,7 +186,7 @@ const MenuItemView = Backbone.View.extend({ } } return false; - }, + } dragstart(e) { e.stopPropagation(); @@ -200,7 +195,7 @@ const MenuItemView = Backbone.View.extend({ e.originalEvent.dataTransfer.effectAllowed = 'move'; DragDropInfo.dragObject = this.model; } - }, + } dragover(e) { if (this.model.get('drop') && this.dropAllowed(e)) { @@ -208,14 +203,14 @@ const MenuItemView = Backbone.View.extend({ e.preventDefault(); this.$el.addClass('menu__item--drag'); } - }, + } dragleave(e) { e.stopPropagation(); if (this.model.get('drop') && this.dropAllowed(e)) { this.$el.removeClass('menu__item--drag menu__item--drag-top'); } - }, + } drop(e) { e.stopPropagation(); @@ -233,7 +228,7 @@ const MenuItemView = Backbone.View.extend({ } Backbone.trigger('refresh'); } - }, + } dropTopAllowed(e) { const types = e.originalEvent.dataTransfer.types; @@ -243,19 +238,19 @@ const MenuItemView = Backbone.View.extend({ } } return false; - }, + } dragoverTop(e) { if (this.dropTopAllowed(e)) { this.$el.addClass('menu__item--drag-top'); } - }, + } dragleaveTop(e) { if (this.dropTopAllowed(e)) { this.$el.removeClass('menu__item--drag-top'); } } -}); +} export { MenuItemView }; diff --git a/app/scripts/views/menu/menu-section-view.js b/app/scripts/views/menu/menu-section-view.js index ea3da560..9a3491d7 100644 --- a/app/scripts/views/menu/menu-section-view.js +++ b/app/scripts/views/menu/menu-section-view.js @@ -1,31 +1,36 @@ -import Backbone from 'backbone'; +import { View } from 'view-engine/view'; import { AppSettingsModel } from 'models/app-settings-model'; import { Resizable } from 'view-engine/resizable'; import { Scrollable } from 'view-engine/scrollable'; import { MenuItemView } from 'views/menu/menu-item-view'; +import template from 'templates/menu/menu-section.hbs'; -const MenuSectionView = Backbone.View.extend({ - template: require('templates/menu/menu-section.hbs'), +class MenuSectionView extends View { + template = template; - events: {}, + events = {}; - itemViews: null, + itemViews = null; - minHeight: 55, - maxHeight() { - return this.$el.parent().height() - 116; - }, - autoHeight: 'auto', + minHeight = 55; + autoHeigh = 'auto'; - initialize() { + constructor(model, options) { + super(model, options); this.itemViews = []; this.listenTo(this.model, 'change-items', this.itemsChanged); this.listenTo(this, 'view-resize', this.viewResized); - }, + this.once('remove', () => { + if (this.scroll) { + this.scroll.dispose(); + } + this.removeInnerViews(); + }); + } render() { 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; if (this.model.get('scrollable')) { this.initScroll(); @@ -38,11 +43,11 @@ const MenuSectionView = Backbone.View.extend({ } else { this.removeInnerViews(); } - this.model.get('items').forEach(function(item) { - const itemView = new MenuItemView({ el: this.itemsEl, model: item }); + this.model.get('items').forEach(item => { + const itemView = new MenuItemView(item, { parent: this.itemsEl[0] }); itemView.render(); this.itemViews.push(itemView); - }, this); + }); if (this.model.get('drag')) { const height = AppSettingsModel.instance.get('tagsViewHeight'); if (typeof height === 'number') { @@ -51,36 +56,32 @@ const MenuSectionView = Backbone.View.extend({ } } this.pageResized(); - }, + } - remove() { - if (this.scroll) { - this.scroll.dispose(); - } - this.removeInnerViews(); - Backbone.View.prototype.remove.apply(this); - }, + maxHeight() { + return this.$el.parent().height() - 116; + } removeInnerViews() { this.itemViews.forEach(itemView => itemView.remove()); this.itemViews = []; - }, + } itemsChanged() { this.render(); - }, + } viewResized(size) { this.$el.css('flex', '0 0 ' + (size ? size + 'px' : 'auto')); this.saveViewHeight(size); - }, + } - saveViewHeight: _.throttle(size => { + saveViewHeight = _.throttle(size => { AppSettingsModel.instance.set('tagsViewHeight', size); - }, 1000) -}); + }, 1000); +} -_.extend(MenuSectionView.prototype, Resizable); -_.extend(MenuSectionView.prototype, Scrollable); +Object.assign(MenuSectionView.prototype, Resizable); +Object.assign(MenuSectionView.prototype, Scrollable); export { MenuSectionView }; diff --git a/app/scripts/views/menu/menu-view.js b/app/scripts/views/menu/menu-view.js index 98353761..5260da9f 100644 --- a/app/scripts/views/menu/menu-view.js +++ b/app/scripts/views/menu/menu-view.js @@ -1,49 +1,50 @@ import Backbone from 'backbone'; +import { View } from 'view-engine/view'; import { KeyHandler } from 'comp/browser/key-handler'; import { Keys } from 'const/keys'; import { AppSettingsModel } from 'models/app-settings-model'; import { Resizable } from 'view-engine/resizable'; import { DragView } from 'views/drag-view'; import { MenuSectionView } from 'views/menu/menu-section-view'; +import template from 'templates/menu/menu.hbs'; -const MenuView = Backbone.View.extend({ - template: require('templates/menu/menu.hbs'), +class MenuView extends View { + parent = '.app__menu'; - events: {}, + template = template; - sectionViews: [], + events = {}; - minWidth: 130, - maxWidth: 300, + sectionViews = []; - initialize() { + minWidth = 130; + maxWidth = 300; + + constructor(model, options) { + super(model, options); this.listenTo(this.model, 'change:sections', this.menuChanged); this.listenTo(this, 'view-resize', this.viewResized); - KeyHandler.onKey( + this.onKey( Keys.DOM_VK_UP, this.selectPreviousSection, - this, KeyHandler.SHORTCUT_ACTION + KeyHandler.SHORTCUT_OPT ); - KeyHandler.onKey( + this.onKey( Keys.DOM_VK_DOWN, this.selectNextSection, - this, KeyHandler.SHORTCUT_ACTION + KeyHandler.SHORTCUT_OPT ); - }, - - remove() { - this.sectionViews.forEach(sectionView => sectionView.remove()); - this.sectionViews = []; - Backbone.View.prototype.remove.apply(this); - }, + this.once('remove', () => { + this.sectionViews.forEach(sectionView => sectionView.remove()); + this.sectionViews = []; + }); + } render() { - this.$el.html(this.template()); + super.render(); const sectionsEl = this.$el.find('.menu'); 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(); if (section.get('drag')) { const dragEl = $('
') @@ -60,29 +61,29 @@ const MenuView = Backbone.View.extend({ this.$el.width(AppSettingsModel.instance.get('menuViewWidth')); } return this; - }, + } menuChanged() { this.render(); - }, + } - viewResized: _.throttle(size => { + viewResized = _.throttle(size => { AppSettingsModel.instance.set('menuViewWidth', size); - }, 1000), + }, 1000); switchVisibility(visible) { this.$el.toggleClass('menu-visible', visible); - }, + } selectPreviousSection() { Backbone.trigger('select-previous-menu-item'); - }, + } selectNextSection() { Backbone.trigger('select-next-menu-item'); } -}); +} -_.extend(MenuView.prototype, Resizable); +Object.assign(MenuView.prototype, Resizable); export { MenuView }; diff --git a/app/scripts/views/open-view.js b/app/scripts/views/open-view.js index 18fab0d4..de08f7a9 100644 --- a/app/scripts/views/open-view.js +++ b/app/scripts/views/open-view.js @@ -1,5 +1,6 @@ import Backbone from 'backbone'; import kdbxweb from 'kdbxweb'; +import { View } from 'view-engine/view'; import { Storage } from 'storage'; import { DropboxChooser } from 'comp/app/dropbox-chooser'; import { FocusDetector } from 'comp/browser/focus-detector'; @@ -16,13 +17,16 @@ import { Logger } from 'util/logger'; import { InputFx } from 'util/ui/input-fx'; import { OpenConfigView } from 'views/open-config-view'; import { StorageFileListView } from 'views/storage-file-list-view'; +import template from 'templates/open.hbs'; const logger = new Logger('open-view'); -const OpenView = Backbone.View.extend({ - template: require('templates/open.hbs'), +class OpenView extends View { + parent = '.app__body'; - events: { + template = template; + + events = { 'change .open__file-ctrl': 'fileSelected', 'click .open__icon-open': 'openFile', 'click .open__icon-new': 'createNew', @@ -30,7 +34,7 @@ const OpenView = Backbone.View.extend({ 'click .open__icon-more': 'toggleMore', 'click .open__icon-storage': 'openStorage', 'click .open__icon-settings': 'openSettings', - 'click .open__pass-input[readonly]': 'openFile', + 'click .open__pass-input': 'passInputClick', 'input .open__pass-input': 'inputInput', 'keydown .open__pass-input': 'inputKeydown', 'keyup .open__pass-input': 'inputKeyup', @@ -38,39 +42,34 @@ const OpenView = Backbone.View.extend({ 'click .open__pass-enter-btn': 'openDb', 'click .open__settings-key-file': 'openKeyFile', 'click .open__last-item': 'openLast', - 'dragover': 'dragover', - 'dragleave': 'dragleave', - 'drop': 'drop' - }, + dragover: 'dragover', + dragleave: 'dragleave', + drop: 'drop' + }; - views: null, - params: null, - passwordInput: null, - busy: false, - currentSelectedIndex: -1, + params = null; - initialize() { - this.views = {}; - this.params = { - id: null, - name: '', - storage: null, - path: null, - keyFileName: null, - keyFileData: null, - keyFilePath: null, - fileData: null, - rev: null - }; + passwordInput = null; + + busy = false; + + currentSelectedIndex = -1; + + constructor(model) { + super(model); + this.resetParams(); this.passwordInput = new SecureInput(); - KeyHandler.onKey(Keys.DOM_VK_Z, this.undoKeyPress, this, KeyHandler.SHORTCUT_ACTION); - KeyHandler.onKey(Keys.DOM_VK_TAB, this.tabKeyPress, this); - KeyHandler.onKey(Keys.DOM_VK_ENTER, this.enterKeyPress, this); - KeyHandler.onKey(Keys.DOM_VK_RETURN, this.enterKeyPress, this); - KeyHandler.onKey(Keys.DOM_VK_DOWN, this.moveOpenFileSelectionDown, this); - KeyHandler.onKey(Keys.DOM_VK_UP, this.moveOpenFileSelectionUp, this); + this.onKey(Keys.DOM_VK_Z, this.undoKeyPress, KeyHandler.SHORTCUT_ACTION); + this.onKey(Keys.DOM_VK_TAB, this.tabKeyPress); + this.onKey(Keys.DOM_VK_ENTER, this.enterKeyPress); + this.onKey(Keys.DOM_VK_RETURN, this.enterKeyPress); + this.onKey(Keys.DOM_VK_DOWN, this.moveOpenFileSelectionDown); + this.onKey(Keys.DOM_VK_UP, this.moveOpenFileSelectionUp); this.listenTo(Backbone, 'main-window-focus', this.windowFocused.bind(this)); - }, + this.once('reset', () => { + this.passwordInput.reset(); + }); + } render() { if (this.dragTimeout) { @@ -90,7 +89,7 @@ const OpenView = Backbone.View.extend({ !this.model.settings.get('canOpen') && !this.model.settings.get('canCreate') && !(this.model.settings.get('canOpenDemo') && !this.model.settings.get('demoOpened')); - this.renderTemplate({ + super.render({ lastOpenFiles: this.getLastOpenFiles(), canOpenKeyFromDropbox: !Launcher && Storage.dropbox.enabled, demoOpened: this.model.settings.get('demoOpened'), @@ -106,17 +105,31 @@ const OpenView = Backbone.View.extend({ this.inputEl = this.$el.find('.open__pass-input'); this.passwordInput.setElement(this.inputEl); return this; - }, + } + + resetParams() { + this.params = { + id: null, + name: '', + storage: null, + path: null, + keyFileName: null, + keyFileData: null, + keyFilePath: null, + fileData: null, + rev: null + }; + } windowFocused() { this.inputEl.focus(); - }, + } focusInput(focusOnMobile) { if (FocusDetector.hasFocus() && (focusOnMobile || !Features.isMobile)) { this.inputEl.focus(); } - }, + } getLastOpenFiles() { return this.model.fileInfos.map(f => { @@ -136,7 +149,7 @@ const OpenView = Backbone.View.extend({ iconSvg: storage ? storage.iconSvg : undefined }; }); - }, + } getDisplayedPath(fileInfo) { const storage = fileInfo.get('storage'); @@ -144,18 +157,7 @@ const OpenView = Backbone.View.extend({ return fileInfo.get('path'); } 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() { if (this.model.settings.get('skipOpenLocalWarn')) { @@ -179,7 +181,7 @@ const OpenView = Backbone.View.extend({ } } }); - }, + } fileSelected(e) { const file = e.target.files[0]; @@ -190,7 +192,7 @@ const OpenView = Backbone.View.extend({ } }); } - }, + } processFile(file, complete) { const reader = new FileReader(); @@ -264,7 +266,7 @@ const OpenView = Backbone.View.extend({ } else { reader.readAsArrayBuffer(file); } - }, + } getOpenFileFormat(fileData) { if (fileData.byteLength < 8) { @@ -290,7 +292,7 @@ const OpenView = Backbone.View.extend({ } else { return undefined; } - }, + } displayOpenFile() { this.$el.addClass('open--file'); @@ -298,7 +300,7 @@ const OpenView = Backbone.View.extend({ this.inputEl[0].removeAttribute('readonly'); this.inputEl[0].setAttribute('placeholder', Locale.openPassFor + ' ' + this.params.name); this.focusInput(); - }, + } displayOpenKeyFile() { this.$el.toggleClass('open--key-file', !!this.params.keyFileName); @@ -306,7 +308,7 @@ const OpenView = Backbone.View.extend({ .find('.open__settings-key-file-name') .text(this.params.keyFileName || this.params.keyFilePath || Locale.openKeyFile); this.focusInput(); - }, + } setFile(file, keyFile, fileReadyCallback) { this.reading = 'fileData'; @@ -319,7 +321,13 @@ const OpenView = Backbone.View.extend({ fileReadyCallback(); } }); - }, + } + + passInputClick(e) { + if (e.target.readOnly) { + this.openFile(); + } + } openFile() { if (this.model.settings.get('canOpen') === false) { @@ -329,7 +337,7 @@ const OpenView = Backbone.View.extend({ this.closeConfig(); this.openAny('fileData'); } - }, + } openKeyFile(e) { if ($(e.target).hasClass('open__settings-key-file-dropbox')) { @@ -345,7 +353,7 @@ const OpenView = Backbone.View.extend({ this.openAny('keyFileData'); } } - }, + } openKeyFileFromDropbox() { if (!this.busy) { @@ -358,7 +366,7 @@ const OpenView = Backbone.View.extend({ this.displayOpenKeyFile(); }).choose(); } - }, + } openAny(reading, ext) { this.reading = reading; @@ -380,7 +388,7 @@ const OpenView = Backbone.View.extend({ } else { fileInput.click(); } - }, + } openLast(e) { if (this.busy) { @@ -414,14 +422,14 @@ const OpenView = Backbone.View.extend({ const fileInfo = this.model.fileInfos.get(id); this.showOpenFileInfo(fileInfo, true); - }, + } removeFile(id) { this.model.removeFileInfo(id); this.$el.find('.open__last-item[data-id="' + id + '"]').remove(); - this.initialize(); + this.resetParams(); this.render(); - }, + } inputKeydown(e) { const code = e.keyCode || e.which; @@ -430,14 +438,14 @@ const OpenView = Backbone.View.extend({ } else if (code === Keys.DOM_VK_CAPS_LOCK) { this.toggleCapsLockWarning(false); } - }, + } inputKeyup(e) { const code = e.keyCode || e.which; if (code === Keys.DOM_VK_CAPS_LOCK) { this.toggleCapsLockWarning(false); } - }, + } inputKeypress(e) { const charCode = e.keyCode || e.which; @@ -447,11 +455,11 @@ const OpenView = Backbone.View.extend({ if (lower !== upper && !e.shiftKey) { this.toggleCapsLockWarning(ch !== lower); } - }, + } toggleCapsLockWarning(on) { this.$el.find('.open__pass-warning').toggleClass('invisible', !on); - }, + } dragover(e) { if (this.model.settings.get('canOpen') === false) { @@ -474,7 +482,7 @@ const OpenView = Backbone.View.extend({ if (!this.$el.hasClass('open--drag')) { this.$el.addClass('open--drag'); } - }, + } dragleave() { if (this.model.settings.get('canOpen') === false) { @@ -486,7 +494,7 @@ const OpenView = Backbone.View.extend({ this.dragTimeout = setTimeout(() => { this.$el.removeClass('open--drag'); }, 100); - }, + } drop(e) { if (this.model.settings.get('canOpen') === false) { @@ -516,22 +524,22 @@ const OpenView = Backbone.View.extend({ this.setFile(xmlFile, null, this.showLocalFileAlert.bind(this)); } } - }, + } undoKeyPress(e) { e.preventDefault(); - }, + } tabKeyPress() { this.$el.addClass('open--show-focus'); - }, + } enterKeyPress(e) { const el = this.$el.find('[tabindex]:focus'); if (el.length) { el.trigger('click', e); } - }, + } showOpenFileInfo(fileInfo, fileWasClicked) { if (this.busy || !fileInfo) { @@ -554,7 +562,7 @@ const OpenView = Backbone.View.extend({ if (fileWasClicked) { this.focusInput(true); } - }, + } showOpenLocalFile(path, keyFilePath) { if (this.busy) { @@ -574,7 +582,7 @@ const OpenView = Backbone.View.extend({ this.params.keyFileData = null; this.displayOpenKeyFile(); } - }, + } openFileWithFingerprint(fileInfo) { if (!fileInfo.has('fingerprint')) { @@ -588,29 +596,29 @@ const OpenView = Backbone.View.extend({ this.openDb(); }); } - }, + } createDemo() { if (!this.busy) { this.closeConfig(); if (!this.model.createDemoFile()) { - this.trigger('close'); + this.emit('close'); } if (!this.model.settings.get('demoOpened')) { this.model.settings.set('demoOpened', true); } } - }, + } createNew() { if (!this.busy) { this.model.createNewFile(); } - }, + } openDb() { if (this.params.id && this.model.files.get(this.params.id)) { - this.trigger('close'); + this.emit('close'); return; } if (this.busy || !this.params.name) { @@ -623,7 +631,7 @@ const OpenView = Backbone.View.extend({ this.afterPaint( this.model.openFile.bind(this.model, this.params, this.openDbComplete.bind(this)) ); - }, + } openDbComplete(err) { this.busy = false; @@ -650,9 +658,9 @@ const OpenView = Backbone.View.extend({ }); } } else { - this.trigger('close'); + this.emit('close'); } - }, + } importDbWithXml() { if (this.busy || !this.params.name) { @@ -670,7 +678,7 @@ const OpenView = Backbone.View.extend({ this.openDbComplete(err); }) ); - }, + } toggleMore() { if (this.busy) { @@ -678,11 +686,11 @@ const OpenView = Backbone.View.extend({ } this.closeConfig(); this.$el.find('.open__icons--lower').toggleClass('hide'); - }, + } openSettings() { Backbone.trigger('toggle-settings'); - }, + } openStorage(e) { if (this.busy) { @@ -704,7 +712,7 @@ const OpenView = Backbone.View.extend({ } else { Alerts.notImplemented(); } - }, + } listStorage(storage, config) { if (this.busy) { @@ -778,7 +786,7 @@ const OpenView = Backbone.View.extend({ view: listView }); }); - }, + } openStorageFile(storage, file) { if (this.busy) { @@ -791,7 +799,7 @@ const OpenView = Backbone.View.extend({ this.params.rev = file.rev; this.params.fileData = null; this.displayOpenFile(); - }, + } showConfig(storage) { if (this.busy) { @@ -817,7 +825,7 @@ const OpenView = Backbone.View.extend({ this.views.openConfig.render(); this.$el.find('.open__pass-area').addClass('hide'); this.$el.find('.open__icons--lower').addClass('hide'); - }, + } closeConfig() { if (this.busy) { @@ -831,7 +839,7 @@ const OpenView = Backbone.View.extend({ this.$el.find('.open__pass-area').removeClass('hide'); this.$el.find('.open__config').addClass('hide'); this.focusInput(); - }, + } applyConfig(config) { if (this.busy || !config) { @@ -854,7 +862,7 @@ const OpenView = Backbone.View.extend({ } else { storage.stat(path, opts, this.storageStatComplete.bind(this, req)); } - }, + } storageApplyConfigComplete(req, err) { if (this.storageWaitId !== req.waitId) { @@ -868,7 +876,7 @@ const OpenView = Backbone.View.extend({ } else { this.closeConfig(); } - }, + } storageStatComplete(req, err, stat) { if (this.storageWaitId !== req.waitId) { @@ -890,7 +898,7 @@ const OpenView = Backbone.View.extend({ this.params.fileData = null; this.displayOpenFile(); } - }, + } moveOpenFileSelection(steps) { const lastOpenFiles = this.getLastOpenFiles(); @@ -911,15 +919,15 @@ const OpenView = Backbone.View.extend({ if (fileInfo && Launcher && Launcher.fingerprints) { this.openFileWithFingerprint(fileInfo); } - }, + } moveOpenFileSelectionDown() { this.moveOpenFileSelection(1); - }, + } moveOpenFileSelectionUp() { this.moveOpenFileSelection(-1); } -}); +} export { OpenView };