mirror of https://github.com/artf/grapesjs.git
nocodeframeworkdrag-and-dropsite-buildersite-generatortemplate-builderui-builderweb-builderweb-builder-frameworkwebsite-builderno-codepage-builder
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
332 lines
8.4 KiB
332 lines
8.4 KiB
import { isString, isObject, isFunction } from 'underscore';
|
|
const $ = Backbone.$;
|
|
|
|
module.exports = Backbone.View.extend({
|
|
|
|
tagName: 'span',
|
|
|
|
initialize(o) {
|
|
_.bindAll(this, 'startTimer', 'stopTimer', 'showButtons', 'hideButtons','closeOnKeyPress','onDrop', 'initSorter', 'stopDrag');
|
|
var cls = this.model.get('className');
|
|
this.config = o.config || {};
|
|
this.em = this.config.em || {};
|
|
const pfx = this.config.stylePrefix || '';
|
|
const ppfx = this.config.pStylePrefix || '';
|
|
this.pfx = pfx;
|
|
this.ppfx = this.config.pStylePrefix || '';
|
|
this.id = pfx + this.model.get('id');
|
|
this.activeCls = `${pfx}active ${ppfx}four-color`;
|
|
this.disableCls = pfx + 'active';
|
|
this.btnsVisCls = pfx + 'visible';
|
|
this.parentM = o.parentM || null;
|
|
this.className = pfx + 'btn' + (cls ? ' ' + cls : '');
|
|
this.listenTo(this.model, 'change:active updateActive', this.updateActive);
|
|
this.listenTo(this.model, 'checkActive', this.checkActive);
|
|
this.listenTo(this.model, 'change:bntsVis', this.updateBtnsVis);
|
|
this.listenTo(this.model, 'change:attributes', this.updateAttributes);
|
|
this.listenTo(this.model, 'change:className', this.updateClassName);
|
|
this.listenTo(this.model, 'change:disable', this.updateDisable);
|
|
|
|
if(this.model.get('buttons').length){
|
|
this.$el.on('mousedown', this.startTimer);
|
|
this.$el.append($('<div>',{class: pfx + 'arrow-rd'}));
|
|
}
|
|
|
|
if(this.em && this.em.get)
|
|
this.commands = this.em.get('Commands');
|
|
|
|
this.events = {};
|
|
|
|
if(this.model.get('dragDrop')){
|
|
this.events.mousedown = 'initDrag';
|
|
this.em.on('loaded', this.initSorter);
|
|
}else
|
|
this.events.click = 'clicked';
|
|
this.delegateEvents();
|
|
},
|
|
|
|
initSorter() {
|
|
if(this.em.Canvas){
|
|
var canvas = this.em.Canvas;
|
|
this.canvasEl = canvas.getBody();
|
|
this.sorter = new this.em.Utils.Sorter({
|
|
container: this.canvasEl,
|
|
placer: canvas.getPlacerEl(),
|
|
containerSel: '*',
|
|
itemSel: '*',
|
|
pfx: this.ppfx,
|
|
onMove: this.onDrag,
|
|
onEndMove: this.onDrop,
|
|
document: canvas.getFrameEl().contentDocument,
|
|
direction: 'a',
|
|
wmargin: 1,
|
|
nested: 1,
|
|
});
|
|
var offDim = canvas.getOffset();
|
|
this.sorter.offTop = offDim.top;
|
|
this.sorter.offLeft = offDim.left;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Init dragging element
|
|
* @private
|
|
*/
|
|
initDrag() {
|
|
this.model.collection.deactivateAll(this.model.get('context'));
|
|
this.sorter.startSort(this.el);
|
|
this.sorter.setDropContent(this.model.get('options').content);
|
|
this.canvasEl.style.cursor = 'grabbing';
|
|
$(document).on('mouseup', this.stopDrag);
|
|
},
|
|
|
|
/**
|
|
* Stop dragging
|
|
* @private
|
|
*/
|
|
stopDrag() {
|
|
$(document).off('mouseup', this.stopDrag);
|
|
this.sorter.endMove();
|
|
},
|
|
|
|
/**
|
|
* During drag method
|
|
* @private
|
|
*/
|
|
onDrag(e) {},
|
|
|
|
/**
|
|
* During drag method
|
|
* @private
|
|
*/
|
|
onDrop(e) {
|
|
this.canvasEl.style.cursor = 'default';
|
|
},
|
|
|
|
/**
|
|
* Updates class name of the button
|
|
*
|
|
* @return void
|
|
* */
|
|
updateClassName() {
|
|
var cls = this.model.get('className');
|
|
this.$el.attr('class', this.pfx + 'btn' + (cls ? ' ' + cls : ''));
|
|
},
|
|
|
|
/**
|
|
* Updates attributes of the button
|
|
*
|
|
* @return void
|
|
* */
|
|
updateAttributes() {
|
|
this.$el.attr(this.model.get("attributes"));
|
|
},
|
|
|
|
/**
|
|
* Updates visibility of children buttons
|
|
*
|
|
* @return void
|
|
* */
|
|
updateBtnsVis() {
|
|
if(!this.$buttons)
|
|
return;
|
|
|
|
if(this.model.get('bntsVis'))
|
|
this.$buttons.addClass(this.btnsVisCls);
|
|
else
|
|
this.$buttons.removeClass(this.btnsVisCls);
|
|
},
|
|
|
|
/**
|
|
* Start timer for showing children buttons
|
|
*
|
|
* @return void
|
|
* */
|
|
startTimer() {
|
|
this.timeout = setTimeout(this.showButtons, this.config.delayBtnsShow);
|
|
$(document).on('mouseup', this.stopTimer);
|
|
},
|
|
|
|
/**
|
|
* Stop timer for showing children buttons
|
|
*
|
|
* @return void
|
|
* */
|
|
stopTimer() {
|
|
$(document).off('mouseup', this.stopTimer);
|
|
if(this.timeout)
|
|
clearTimeout(this.timeout);
|
|
},
|
|
|
|
/**
|
|
* Show children buttons
|
|
*
|
|
* @return void
|
|
* */
|
|
showButtons() {
|
|
clearTimeout(this.timeout);
|
|
this.model.set('bntsVis', true);
|
|
$(document).on('mousedown', this.hideButtons);
|
|
$(document).on('keypress', this.closeOnKeyPress);
|
|
},
|
|
|
|
/**
|
|
* Hide children buttons
|
|
*
|
|
* @return void
|
|
* */
|
|
hideButtons(e) {
|
|
if(e){ $(e.target).trigger('click'); }
|
|
this.model.set('bntsVis', false);
|
|
$(document).off('mousedown', this.hideButtons);
|
|
$(document).off('keypress', this.closeOnKeyPress);
|
|
},
|
|
|
|
/**
|
|
* Close buttons on ESC key press
|
|
* @param {Object} e Event
|
|
*
|
|
* @return void
|
|
* */
|
|
closeOnKeyPress(e) {
|
|
var key = e.which || e.keyCode;
|
|
if(key == 27)
|
|
this.hideButtons();
|
|
},
|
|
|
|
/**
|
|
* Update active status of the button
|
|
*
|
|
* @return void
|
|
* */
|
|
updateActive() {
|
|
const model = this.model;
|
|
const context = model.get('context');
|
|
const parent = this.parentM;
|
|
let command = {};
|
|
var editor = this.em && this.em.get ? this.em.get('Editor') : null;
|
|
var commandName = model.get('command');
|
|
|
|
if (this.commands && isString(commandName)) {
|
|
command = this.commands.get(commandName) || {};
|
|
} else if (isFunction(commandName)) {
|
|
command = { run: commandName };
|
|
} else if (commandName !== null && isObject(commandName)) {
|
|
command = commandName;
|
|
}
|
|
|
|
if (model.get('active')) {
|
|
model.collection.deactivateAll(context);
|
|
model.set('active', true, { silent: true }).trigger('checkActive');
|
|
parent && parent.set('active', true, { silent: true }).trigger('checkActive');
|
|
|
|
if (command.run) {
|
|
command.run(editor, model, model.get('options'));
|
|
editor.trigger('run:' + commandName);
|
|
}
|
|
|
|
// Disable button if there is no stop method
|
|
!command.stop && model.set('active', false);
|
|
} else {
|
|
this.$el.removeClass(this.activeCls);
|
|
model.collection.deactivateAll(context);
|
|
parent && parent.set('active', false, { silent: true }).trigger('checkActive');
|
|
|
|
if (command.stop) {
|
|
command.stop(editor, model, model.get('options'));
|
|
editor.trigger('stop:' + commandName);
|
|
}
|
|
}
|
|
},
|
|
|
|
updateDisable() {
|
|
if(this.model.get('disable')) {
|
|
this.$el.addClass(this.disableCls);
|
|
} else {
|
|
this.$el.removeClass(this.disableCls);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Update active style status
|
|
*
|
|
* @return void
|
|
* */
|
|
checkActive() {
|
|
if(this.model.get('active'))
|
|
this.$el.addClass(this.activeCls);
|
|
else
|
|
this.$el.removeClass(this.activeCls);
|
|
},
|
|
|
|
/**
|
|
* Triggered when button is clicked
|
|
* @param {Object} e Event
|
|
*
|
|
* @return void
|
|
* */
|
|
clicked(e) {
|
|
if(this.model.get('bntsVis') )
|
|
return;
|
|
|
|
if(this.model.get('disable') )
|
|
return;
|
|
|
|
this.toogleActive();
|
|
},
|
|
|
|
toogleActive() {
|
|
|
|
if(this.parentM)
|
|
this.swapParent();
|
|
|
|
var active = this.model.get('active');
|
|
this.model.set('active', !active);
|
|
|
|
// If the stop is requested
|
|
var command = this.em.get('Commands').get('select-comp');
|
|
|
|
if(active){
|
|
if(this.model.get('runDefaultCommand'))
|
|
this.em.runDefault();
|
|
}else{
|
|
if(this.model.get('stopDefaultCommand'))
|
|
this.em.stopDefault();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Updates parent model swapping properties
|
|
*
|
|
* @return void
|
|
* */
|
|
swapParent() {
|
|
this.parentM.collection.deactivateAll(this.model.get('context'));
|
|
this.parentM.set('attributes', this.model.get('attributes'));
|
|
this.parentM.set('options', this.model.get('options'));
|
|
this.parentM.set('command', this.model.get('command'));
|
|
this.parentM.set('className', this.model.get('className'));
|
|
this.parentM.set('active', true, { silent: true }).trigger('checkActive');
|
|
},
|
|
|
|
render() {
|
|
this.updateAttributes();
|
|
this.$el.attr('class', this.className);
|
|
|
|
if(this.model.get('buttons').length){
|
|
var btnsView = require('./ButtonsView'); //Avoid Circular Dependencies
|
|
var view = new btnsView({
|
|
collection : this.model.get('buttons'),
|
|
config : this.config,
|
|
parentM : this.model
|
|
});
|
|
this.$buttons = view.render().$el;
|
|
this.$buttons.append($('<div>',{class: this.pfx + 'arrow-l'}));
|
|
this.$el.append(this.$buttons); //childNodes avoids wrapping 'div'
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
});
|
|
|