2017-01-31 07:50:28 +01:00
|
|
|
const Backbone = require('backbone');
|
|
|
|
const KeyHandler = require('../../comp/key-handler');
|
|
|
|
const Keys = require('../../const/keys');
|
|
|
|
const Alerts = require('../../comp/alerts');
|
|
|
|
const DragDropInfo = require('../../comp/drag-drop-info');
|
|
|
|
const Locale = require('../../util/locale');
|
|
|
|
|
|
|
|
const MenuItemView = Backbone.View.extend({
|
2015-12-16 22:50:45 +01:00
|
|
|
template: require('templates/menu/menu-item.hbs'),
|
2015-10-17 23:49:24 +02:00
|
|
|
|
|
|
|
events: {
|
|
|
|
'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'
|
2015-10-17 23:49:24 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
iconEl: null,
|
|
|
|
itemViews: null,
|
|
|
|
|
2019-08-16 23:05:39 +02:00
|
|
|
initialize: function() {
|
2015-10-17 23:49:24 +02:00
|
|
|
this.itemViews = [];
|
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);
|
2017-01-31 07:50:28 +01:00
|
|
|
const shortcut = this.model.get('shortcut');
|
2015-10-17 23:49:24 +02:00
|
|
|
if (shortcut) {
|
|
|
|
KeyHandler.onKey(shortcut, this.selectItem, this, KeyHandler.SHORTCUT_OPT);
|
|
|
|
if (shortcut !== Keys.DOM_VK_C) {
|
|
|
|
KeyHandler.onKey(shortcut, this.selectItem, this, KeyHandler.SHORTCUT_ACTION);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
render: function() {
|
|
|
|
this.removeInnerViews();
|
|
|
|
this.renderTemplate(this.model.attributes);
|
2016-05-01 17:39:44 +02:00
|
|
|
this.iconEl = this.$el.find('i.menu__item-icon');
|
2017-01-31 07:50:28 +01:00
|
|
|
const items = this.model.get('items');
|
2015-11-21 23:15:51 +01:00
|
|
|
if (items) {
|
2019-08-16 23:05:39 +02:00
|
|
|
items.forEach(function(item) {
|
2015-10-17 23:49:24 +02:00
|
|
|
if (item.get('visible')) {
|
2015-10-31 20:09:32 +01:00
|
|
|
this.insertItem(item);
|
2015-10-17 23:49:24 +02:00
|
|
|
}
|
|
|
|
}, this);
|
|
|
|
}
|
2015-11-21 23:15:51 +01:00
|
|
|
this.$el.toggleClass('menu__item--collapsed', !this.model.get('expanded'));
|
2015-10-31 20:27:31 +01:00
|
|
|
return this;
|
2015-10-17 23:49:24 +02:00
|
|
|
},
|
|
|
|
|
2015-10-31 20:09:32 +01:00
|
|
|
insertItem: function(item) {
|
2019-08-16 23:05:39 +02:00
|
|
|
this.itemViews.push(new MenuItemView({ el: this.$el, model: item }).render());
|
2015-10-31 20:09:32 +01:00
|
|
|
},
|
|
|
|
|
2016-07-17 13:30:38 +02:00
|
|
|
remove: function() {
|
2015-10-17 23:49:24 +02:00
|
|
|
this.removeInnerViews();
|
2017-01-31 07:50:28 +01:00
|
|
|
const shortcut = this.model.get('shortcut');
|
2015-10-17 23:49:24 +02:00
|
|
|
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, arguments);
|
|
|
|
},
|
|
|
|
|
|
|
|
removeInnerViews: function() {
|
2016-07-17 13:30:38 +02:00
|
|
|
this.itemViews.forEach(itemView => itemView.remove());
|
2015-10-17 23:49:24 +02:00
|
|
|
this.itemViews = [];
|
|
|
|
},
|
|
|
|
|
2015-10-27 20:59:04 +01:00
|
|
|
changeTitle: function(model, title) {
|
2019-08-16 23:05:39 +02:00
|
|
|
this.$el
|
|
|
|
.find('.menu__item-title')
|
|
|
|
.first()
|
|
|
|
.text(title || '(no title)');
|
2015-10-31 20:09:32 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
changeIcon: function(model, icon) {
|
|
|
|
this.iconEl[0].className = 'menu__item-icon fa ' + (icon ? 'fa-' + icon : 'menu__item-icon--no-icon');
|
2015-10-27 20:59:04 +01:00
|
|
|
},
|
|
|
|
|
2015-10-17 23:49:24 +02:00
|
|
|
changeActive: function(model, active) {
|
|
|
|
this.$el.toggleClass('menu__item--active', active);
|
|
|
|
},
|
|
|
|
|
|
|
|
changeExpanded: function(model, expanded) {
|
|
|
|
this.$el.toggleClass('menu__item--collapsed', !expanded);
|
2015-12-05 14:04:09 +01:00
|
|
|
this.model.setExpanded(expanded);
|
2015-10-17 23:49:24 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
changeCls: function(model, cls) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const oldCls = model.previousAttributes().cls;
|
2015-10-17 23:49:24 +02:00
|
|
|
if (oldCls) {
|
|
|
|
this.$el.removeClass(oldCls);
|
|
|
|
}
|
|
|
|
this.$el.addClass(cls);
|
|
|
|
},
|
|
|
|
|
|
|
|
mouseover: function(e) {
|
2015-11-08 09:59:46 +01:00
|
|
|
if (!e.button) {
|
|
|
|
this.$el.addClass('menu__item--hover');
|
|
|
|
e.stopPropagation();
|
|
|
|
}
|
2015-10-17 23:49:24 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
mouseout: function(e) {
|
|
|
|
this.$el.removeClass('menu__item--hover');
|
|
|
|
e.stopPropagation();
|
|
|
|
},
|
|
|
|
|
|
|
|
selectItem: function(e) {
|
2015-10-23 22:12:12 +02:00
|
|
|
e.stopPropagation();
|
|
|
|
e.preventDefault();
|
2015-10-17 23:49:24 +02:00
|
|
|
if (this.model.get('active')) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (this.model.get('disabled')) {
|
|
|
|
Alerts.info(this.model.get('disabled'));
|
|
|
|
} else {
|
|
|
|
Backbone.trigger('menu-select', { item: this.model });
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
selectOption: function(e) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const options = this.model.get('options');
|
|
|
|
const value = $(e.target).data('value');
|
2015-10-17 23:49:24 +02:00
|
|
|
if (options && options.length) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const option = options.find(op => op.get('value') === value);
|
2015-10-17 23:49:24 +02:00
|
|
|
if (option) {
|
|
|
|
Backbone.trigger('menu-select', { item: this.model, option: option });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
e.stopImmediatePropagation();
|
|
|
|
e.preventDefault();
|
|
|
|
},
|
|
|
|
|
|
|
|
expandItem: function(e) {
|
|
|
|
if (this.model.toggleExpanded) {
|
|
|
|
this.model.toggleExpanded();
|
|
|
|
}
|
|
|
|
e.stopPropagation();
|
2015-10-31 20:09:32 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
editItem: function(e) {
|
|
|
|
if (this.model.get('active') && this.model.get('editable')) {
|
|
|
|
e.stopPropagation();
|
2016-04-17 22:02:39 +02:00
|
|
|
switch (this.model.get('filterKey')) {
|
|
|
|
case 'tag':
|
|
|
|
Backbone.trigger('edit-tag', this.model);
|
|
|
|
break;
|
|
|
|
case 'group':
|
|
|
|
Backbone.trigger('edit-group', this.model);
|
|
|
|
break;
|
|
|
|
}
|
2015-10-31 20:09:32 +01:00
|
|
|
}
|
2015-11-08 09:59:46 +01:00
|
|
|
},
|
|
|
|
|
2015-11-08 22:25:00 +01:00
|
|
|
emptyTrash: function(e) {
|
|
|
|
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',
|
2015-11-08 22:25:00 +01:00
|
|
|
success: function() {
|
|
|
|
Backbone.trigger('empty-trash');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2016-07-30 20:41:15 +02:00
|
|
|
dropAllowed(e) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const types = e.originalEvent.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') {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
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();
|
|
|
|
if (this.model.get('drag')) {
|
2016-02-17 21:57:12 +01:00
|
|
|
e.originalEvent.dataTransfer.setData('text/group', this.model.id);
|
|
|
|
e.originalEvent.dataTransfer.effectAllowed = 'move';
|
2015-11-08 09:59:46 +01:00
|
|
|
DragDropInfo.dragObject = this.model;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2016-07-30 20:41:15 +02:00
|
|
|
dragover(e) {
|
2015-11-08 09:59:46 +01:00
|
|
|
if (this.model.get('drop') && this.dropAllowed(e)) {
|
2018-08-22 09:59:13 +02:00
|
|
|
e.stopPropagation();
|
2015-11-08 09:59:46 +01:00
|
|
|
e.preventDefault();
|
|
|
|
this.$el.addClass('menu__item--drag');
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2016-07-30 20:41:15 +02:00
|
|
|
dragleave(e) {
|
2015-11-08 09:59:46 +01:00
|
|
|
e.stopPropagation();
|
|
|
|
if (this.model.get('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
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2016-07-30 20:41:15 +02:00
|
|
|
drop(e) {
|
2015-11-08 09:59:46 +01:00
|
|
|
e.stopPropagation();
|
2018-08-23 19:05:34 +02:00
|
|
|
if (this.model.get('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 {
|
2016-07-30 20:41:15 +02:00
|
|
|
if (this.model.get('filterKey') === 'trash') {
|
|
|
|
DragDropInfo.dragObject.moveToTrash();
|
|
|
|
} else {
|
|
|
|
this.model.moveHere(DragDropInfo.dragObject);
|
|
|
|
}
|
2015-11-15 21:26:37 +01:00
|
|
|
}
|
2015-11-08 09:59:46 +01:00
|
|
|
Backbone.trigger('refresh');
|
|
|
|
}
|
2016-07-30 20:41:15 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
dropTopAllowed(e) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const types = e.originalEvent.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;
|
2016-07-30 20:41:15 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
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');
|
|
|
|
}
|
2015-10-17 23:49:24 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
module.exports = MenuItemView;
|