keeweb/app/scripts/views/menu/menu-item-view.js

258 lines
7.4 KiB
JavaScript
Raw Normal View History

2019-09-16 22:57:56 +02:00
import { Events } from 'framework/events';
2019-09-16 20:42:33 +02:00
import { View } from 'framework/views/view';
2019-09-15 14:16:32 +02:00
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';
2019-09-16 17:43:57 +02:00
import template from 'templates/menu/menu-item.hbs';
2017-01-31 07:50:28 +01:00
2019-09-16 17:43:57 +02:00
class MenuItemView extends View {
template = template;
2015-10-17 23:49:24 +02:00
2019-09-16 17:43:57 +02:00
events = {
2015-10-17 23:49:24 +02:00
'mouseover': 'mouseover',
'mouseout': 'mouseout',
'click .menu__item-option': 'selectOption',
'click': 'selectItem',
2015-10-31 20:09:32 +01:00
'dblclick': 'expandItem',
2015-11-08 09:59:46 +01:00
'click .menu__item-edit': 'editItem',
2015-11-08 22:25:00 +01:00
'click .menu__item-empty-trash': 'emptyTrash',
2015-11-08 09:59:46 +01:00
'dragstart': 'dragstart',
'dragover': 'dragover',
'dragleave': 'dragleave',
2016-07-30 20:41:15 +02:00
'drop': 'drop',
'dragover .menu__item-drag-top': 'dragoverTop',
'dragleave .menu__item-drag-top': 'dragleaveTop'
2019-09-16 17:43:57 +02:00
};
2015-10-17 23:49:24 +02:00
2019-09-16 17:43:57 +02:00
iconEl = null;
2019-09-16 20:54:14 +02:00
itemViews = [];
2015-10-17 23:49:24 +02:00
2019-09-16 17:43:57 +02:00
constructor(model, options) {
super(model, options);
2015-10-27 20:59:04 +01:00
this.listenTo(this.model, 'change:title', this.changeTitle);
2015-10-31 20:09:32 +01:00
this.listenTo(this.model, 'change:icon', this.changeIcon);
2015-11-21 23:15:51 +01:00
this.listenTo(this.model, 'change:customIconId', this.render);
2015-10-17 23:49:24 +02:00
this.listenTo(this.model, 'change:active', this.changeActive);
this.listenTo(this.model, 'change:expanded', this.changeExpanded);
this.listenTo(this.model, 'change:cls', this.changeCls);
2015-10-31 20:09:32 +01:00
this.listenTo(this.model, 'delete', this.remove);
this.listenTo(this.model, 'insert', this.insertItem);
2019-09-18 23:37:57 +02:00
const shortcut = this.model.shortcut;
2015-10-17 23:49:24 +02:00
if (shortcut) {
2019-09-16 17:43:57 +02:00
this.onKey(shortcut, this.selectItem, KeyHandler.SHORTCUT_OPT);
2015-10-17 23:49:24 +02:00
if (shortcut !== Keys.DOM_VK_C) {
2019-09-16 17:43:57 +02:00
this.onKey(shortcut, this.selectItem, KeyHandler.SHORTCUT_ACTION);
2015-10-17 23:49:24 +02:00
}
}
2019-09-16 17:43:57 +02:00
this.once('remove', () => {
this.removeInnerViews();
});
}
2015-10-17 23:49:24 +02:00
2019-08-18 10:17:09 +02:00
render() {
2015-10-17 23:49:24 +02:00
this.removeInnerViews();
2019-09-30 19:36:16 +02:00
super.render(this.model);
2019-09-19 17:42:53 +02:00
if (this.model.options) {
window.model = this.model;
}
2019-09-15 20:09:28 +02:00
this.iconEl = this.$el.find('.menu__item-icon');
2019-09-18 23:37:57 +02:00
const items = this.model.items;
2015-11-21 23:15:51 +01:00
if (items) {
2020-06-01 16:53:51 +02:00
items.forEach((item) => {
2019-09-18 23:37:57 +02:00
if (item.visible) {
2015-10-31 20:09:32 +01:00
this.insertItem(item);
2015-10-17 23:49:24 +02:00
}
2019-09-16 17:43:57 +02:00
});
2015-10-17 23:49:24 +02:00
}
2019-09-18 23:37:57 +02:00
this.$el.toggleClass('menu__item--collapsed', !this.model.expanded);
2019-09-16 17:43:57 +02:00
}
2015-10-17 23:49:24 +02:00
2019-08-18 10:17:09 +02:00
insertItem(item) {
2019-09-16 17:43:57 +02:00
const itemView = new MenuItemView(item, { parent: this.el });
itemView.render();
this.itemViews.push(itemView);
}
2015-10-17 23:49:24 +02:00
2019-08-18 10:17:09 +02:00
removeInnerViews() {
2020-06-01 16:53:51 +02:00
this.itemViews.forEach((itemView) => itemView.remove());
2015-10-17 23:49:24 +02:00
this.itemViews = [];
2019-09-16 17:43:57 +02:00
}
2015-10-17 23:49:24 +02:00
2019-08-18 10:17:09 +02:00
changeTitle(model, title) {
2019-08-16 23:05:39 +02:00
this.$el
.find('.menu__item-title')
.first()
.text(title || '(no title)');
2019-09-16 17:43:57 +02:00
}
2015-10-31 20:09:32 +01:00
2019-08-18 10:17:09 +02:00
changeIcon(model, icon) {
2019-08-18 08:05:38 +02:00
this.iconEl[0].className =
'menu__item-icon fa ' + (icon ? 'fa-' + icon : 'menu__item-icon--no-icon');
2019-09-16 17:43:57 +02:00
}
2015-10-27 20:59:04 +01:00
2019-08-18 10:17:09 +02:00
changeActive(model, active) {
2015-10-17 23:49:24 +02:00
this.$el.toggleClass('menu__item--active', active);
2019-09-16 17:43:57 +02:00
}
2015-10-17 23:49:24 +02:00
2019-08-18 10:17:09 +02:00
changeExpanded(model, expanded) {
2015-10-17 23:49:24 +02:00
this.$el.toggleClass('menu__item--collapsed', !expanded);
2015-12-05 14:04:09 +01:00
this.model.setExpanded(expanded);
2019-09-16 17:43:57 +02:00
}
2015-10-17 23:49:24 +02:00
2019-09-19 17:42:53 +02:00
changeCls(model, cls, oldCls) {
2015-10-17 23:49:24 +02:00
if (oldCls) {
this.$el.removeClass(oldCls);
}
this.$el.addClass(cls);
2019-09-16 17:43:57 +02:00
}
2015-10-17 23:49:24 +02:00
2019-08-18 10:17:09 +02:00
mouseover(e) {
2015-11-08 09:59:46 +01:00
if (!e.button) {
this.$el.addClass('menu__item--hover');
e.stopPropagation();
}
2019-09-16 17:43:57 +02:00
}
2015-10-17 23:49:24 +02:00
2019-08-18 10:17:09 +02:00
mouseout(e) {
2015-10-17 23:49:24 +02:00
this.$el.removeClass('menu__item--hover');
e.stopPropagation();
2019-09-16 17:43:57 +02:00
}
2015-10-17 23:49:24 +02:00
2019-08-18 10:17:09 +02:00
selectItem(e) {
2015-10-23 22:12:12 +02:00
e.stopPropagation();
e.preventDefault();
2019-09-18 23:37:57 +02:00
if (this.model.active) {
2015-10-17 23:49:24 +02:00
return;
}
2019-09-18 23:37:57 +02:00
if (this.model.disabled) {
Alerts.info(this.model.disabled);
2015-10-17 23:49:24 +02:00
} else {
2019-09-16 22:57:56 +02:00
Events.emit('menu-select', { item: this.model });
2015-10-17 23:49:24 +02:00
}
2019-09-16 17:43:57 +02:00
}
2015-10-17 23:49:24 +02:00
2019-08-18 10:17:09 +02:00
selectOption(e) {
2019-09-18 23:37:57 +02:00
const options = this.model.options;
2017-01-31 07:50:28 +01:00
const value = $(e.target).data('value');
2015-10-17 23:49:24 +02:00
if (options && options.length) {
2020-06-01 16:53:51 +02:00
const option = options.find((op) => op.value === value);
2015-10-17 23:49:24 +02:00
if (option) {
2019-09-16 22:57:56 +02:00
Events.emit('menu-select', { item: this.model, option });
2015-10-17 23:49:24 +02:00
}
}
e.stopImmediatePropagation();
e.preventDefault();
2019-09-16 17:43:57 +02:00
}
2015-10-17 23:49:24 +02:00
2019-08-18 10:17:09 +02:00
expandItem(e) {
2015-10-17 23:49:24 +02:00
if (this.model.toggleExpanded) {
this.model.toggleExpanded();
}
e.stopPropagation();
2019-09-16 17:43:57 +02:00
}
2015-10-31 20:09:32 +01:00
2019-08-18 10:17:09 +02:00
editItem(e) {
2019-09-18 23:37:57 +02:00
if (this.model.active && this.model.editable) {
2015-10-31 20:09:32 +01:00
e.stopPropagation();
2019-09-18 23:37:57 +02:00
switch (this.model.filterKey) {
2016-04-17 22:02:39 +02:00
case 'tag':
2019-09-16 22:57:56 +02:00
Events.emit('edit-tag', this.model);
2016-04-17 22:02:39 +02:00
break;
case 'group':
2019-09-16 22:57:56 +02:00
Events.emit('edit-group', this.model);
2016-04-17 22:02:39 +02:00
break;
}
2015-10-31 20:09:32 +01:00
}
2019-09-16 17:43:57 +02:00
}
2015-11-08 09:59:46 +01:00
2019-08-18 10:17:09 +02:00
emptyTrash(e) {
2015-11-08 22:25:00 +01:00
e.stopPropagation();
Alerts.yesno({
2015-12-17 19:25:25 +01:00
header: Locale.menuEmptyTrashAlert,
body: Locale.menuEmptyTrashAlertBody,
2015-11-09 19:15:39 +01:00
icon: 'minus-circle',
2019-08-18 10:17:09 +02:00
success() {
2019-09-16 22:57:56 +02:00
Events.emit('empty-trash');
2015-11-08 22:25:00 +01:00
}
});
2019-09-16 17:43:57 +02:00
}
2015-11-08 22:25:00 +01:00
2016-07-30 20:41:15 +02:00
dropAllowed(e) {
2019-09-16 21:49:21 +02:00
const types = e.dataTransfer.types;
2016-09-12 21:16:14 +02:00
for (let i = 0; i < types.length; i++) {
if (types[i] === 'text/group' || types[i] === 'text/entry') {
2020-05-05 17:46:07 +02:00
return DragDropInfo.dragObject && !DragDropInfo.dragObject.readOnly;
2016-09-12 21:16:14 +02:00
}
}
return false;
2019-09-16 17:43:57 +02:00
}
2015-11-08 09:59:46 +01:00
2016-07-30 20:41:15 +02:00
dragstart(e) {
2015-11-08 09:59:46 +01:00
e.stopPropagation();
2019-09-18 23:37:57 +02:00
if (this.model.drag) {
2019-09-16 21:49:21 +02:00
e.dataTransfer.setData('text/group', this.model.id);
e.dataTransfer.effectAllowed = 'move';
2015-11-08 09:59:46 +01:00
DragDropInfo.dragObject = this.model;
}
2019-09-16 17:43:57 +02:00
}
2015-11-08 09:59:46 +01:00
2016-07-30 20:41:15 +02:00
dragover(e) {
2019-09-18 23:37:57 +02:00
if (this.model.drop && this.dropAllowed(e)) {
e.stopPropagation();
2015-11-08 09:59:46 +01:00
e.preventDefault();
this.$el.addClass('menu__item--drag');
}
2019-09-16 17:43:57 +02:00
}
2015-11-08 09:59:46 +01:00
2016-07-30 20:41:15 +02:00
dragleave(e) {
2015-11-08 09:59:46 +01:00
e.stopPropagation();
2019-09-18 23:37:57 +02:00
if (this.model.drop && this.dropAllowed(e)) {
2016-07-30 20:41:15 +02:00
this.$el.removeClass('menu__item--drag menu__item--drag-top');
2015-11-08 09:59:46 +01:00
}
2019-09-16 17:43:57 +02:00
}
2015-11-08 09:59:46 +01:00
2016-07-30 20:41:15 +02:00
drop(e) {
2015-11-08 09:59:46 +01:00
e.stopPropagation();
2019-09-18 23:37:57 +02:00
if (this.model.drop && this.dropAllowed(e)) {
2017-01-31 07:50:28 +01:00
const isTop = this.$el.hasClass('menu__item--drag-top');
2016-07-30 20:41:15 +02:00
this.$el.removeClass('menu__item--drag menu__item--drag-top');
if (isTop) {
this.model.moveToTop(DragDropInfo.dragObject);
2015-11-15 21:26:37 +01:00
} else {
2019-09-18 23:37:57 +02:00
if (this.model.filterKey === 'trash') {
2016-07-30 20:41:15 +02:00
DragDropInfo.dragObject.moveToTrash();
} else {
this.model.moveHere(DragDropInfo.dragObject);
}
2015-11-15 21:26:37 +01:00
}
2019-09-16 22:57:56 +02:00
Events.emit('refresh');
2015-11-08 09:59:46 +01:00
}
2019-09-16 17:43:57 +02:00
}
2016-07-30 20:41:15 +02:00
dropTopAllowed(e) {
2019-09-16 21:49:21 +02:00
const types = e.dataTransfer.types;
2016-09-12 21:16:14 +02:00
for (let i = 0; i < types.length; i++) {
if (types[i] === 'text/group') {
return true;
}
}
return false;
2019-09-16 17:43:57 +02:00
}
2016-07-30 20:41:15 +02:00
dragoverTop(e) {
if (this.dropTopAllowed(e)) {
this.$el.addClass('menu__item--drag-top');
}
2019-09-16 17:43:57 +02:00
}
2016-07-30 20:41:15 +02:00
dragleaveTop(e) {
if (this.dropTopAllowed(e)) {
this.$el.removeClass('menu__item--drag-top');
}
2015-10-17 23:49:24 +02:00
}
2019-09-16 17:43:57 +02:00
}
2015-10-17 23:49:24 +02:00
2019-09-15 14:16:32 +02:00
export { MenuItemView };