bookmarks/js/views/BookmarkCard.js

174 lines
4.6 KiB
JavaScript

import _ from 'underscore';
import Backbone from 'backbone';
import interact from 'interactjs';
import isTouchDevice from '../utils/IsTouchscreen';
import Tags from '../models/Tags';
import TagsNavigationView from './TagsNavigation';
import templateString from '../templates/BookmarkCard.html';
const Marionette = Backbone.Marionette;
const Radio = Backbone.Radio;
export default Marionette.View.extend({
template: _.template(templateString),
className: 'bookmark-card',
ui: {
link: 'h2 > a',
checkbox: '.selectbox',
actionsMenu: '.popovermenu',
actionsToggle: '.toggle-actions'
},
regions: {
tags: '.tags'
},
events: {
click: 'open',
'click @ui.link': 'clickLink',
'click @ui.checkbox': 'select',
'click @ui.actionsToggle': 'toggleActions',
'click .menu-filter-add': 'select',
'click .menu-filter-remove': 'select',
'click .menu-delete': 'delete',
'click .menu-details': 'open',
'click .menu-move': 'move',
contextmenu: 'preventRightClick'
},
initialize: function(opts) {
this.app = opts.app;
this.listenTo(this.model, 'change', this.render);
this.listenTo(this.model, 'select', this.onSelect);
this.listenTo(this.model, 'unselect', this.onUnselect);
// when bulk selection is active, the cards not being dragged directly
// get their events through the models
this.listenTo(this.model, 'dragstart', this.onDragStart);
this.listenTo(this.model, 'dragmove', this.onDragMove);
this.listenTo(this.model, 'dragend', this.onDragEnd);
this.listenTo(this.model, 'dropped', this.onDropped);
this.listenTo(this.app.tags, 'sync', this.render);
this.listenTo(Radio.channel('documentClicked'), 'click', this.closeActions);
this.interactable = interact(this.el).draggable({
onstart: this.onDragStart.bind(this),
onend: this.onDragEnd.bind(this),
onmove: this.onDragMove.bind(this),
hold: isTouchDevice() ? 500 : 0
});
this.interactable.model = this.model;
},
onRender: function() {
var that = this;
this.$el.css(
'background-image',
'url(bookmark/' + this.model.get('id') + '/image)'
);
this.$el.css('background-color', this.model.getColor());
this.$el.prop('title', t('bookmarks', 'Open details'));
var tags = new Tags(
this.model.get('tags').map(function(id) {
return that.app.tags.findWhere({ name: id });
})
);
this.showChildView('tags', new TagsNavigationView({ collection: tags }));
this.$('.checkbox').prop('checked', this.$el.hasClass('active'));
},
clickLink: function(e) {
if (e && e.target === this.getUI('actionsToggle')[0]) {
return;
}
this.model.clickLink();
},
open: function(e) {
if (
e &&
(this.getUI('actionsToggle')[0] === e.target ||
this.getUI('link')[0] === e.target ||
$.contains(this.$('.tags')[0], e.target))
) {
return;
}
if (this.$el.closest('.selection-active').length) {
this.select(e);
e.preventDefault();
return;
}
if (e) {
e.stopPropagation();
}
Radio.channel('details').trigger('show', this.model);
},
toggleActions: function() {
this.getUI('actionsMenu')
.toggleClass('open')
.toggleClass('closed');
},
closeActions: function(e) {
if (e && this.getUI('actionsToggle')[0] === e.target) {
return;
}
this.getUI('actionsMenu')
.removeClass('open')
.addClass('closed');
},
select: function(e) {
e.stopPropagation();
if (this.$el.hasClass('active')) {
this.model.trigger('unselect', this.model);
} else {
this.model.trigger('select', this.model);
}
},
onSelect: function() {
this.$el.addClass('active');
this.render();
},
onUnselect: function() {
this.$el.removeClass('active');
this.render();
},
delete: function() {
this.model.destroy();
},
onDragStart: function(e, propagate) {
this.$el.addClass('dragging');
if (propagate !== false) {
this.app.selectedBookmarks.forEach(function(bm) {
bm.trigger('dragstart', e, false);
});
}
},
onDragMove: function(e, propagate) {
this.$el.offset({ top: e.pageY + 20, left: e.pageX + 20 });
if (propagate !== false) {
this.app.selectedBookmarks.forEach(function(bm, i) {
bm.trigger(
'dragmove',
{ pageY: e.pageY + 10 * (i + 1), pageX: e.pageX + 10 * (i + 1) },
false
);
});
}
},
onDragEnd: function(e, propagate) {
this.$el.removeClass('dragging');
this.$el.css({ position: 'relative', top: 0, left: 0 });
if (propagate !== false) {
this.app.selectedBookmarks.forEach(function(bm) {
bm.trigger('dragend', e, false);
});
}
},
onDropped: function() {
var that = this;
this.$el.hide();
},
onDestroy: function() {
this.interactable.unset();
},
preventRightClick: function(e) {
e.preventDefault();
}
});