mirror of https://github.com/artf/grapesjs.git
5 changed files with 295 additions and 302 deletions
File diff suppressed because one or more lines are too long
@ -1,40 +1,38 @@ |
|||||
define(['Navigator'], function(Layers) { |
define(['Navigator'], function(Layers) { |
||||
/** |
/** |
||||
* @class OpenStyleManager |
* @class OpenStyleManager |
||||
* @private |
* @private |
||||
* */ |
* */ |
||||
return { |
return { |
||||
|
|
||||
run: function(em, sender) |
run: function(em, sender) { |
||||
{ |
if(!this.$layers) { |
||||
if(!this.$layers){ |
var collection = em.DomComponents.getComponent().get('components'), |
||||
var collection = em.DomComponents.getComponent().get('components'), |
config = em.getConfig(), |
||||
config = em.getConfig(), |
panels = em.Panels, |
||||
panels = em.Panels, |
lyStylePfx = config.layers.stylePrefix || 'nv-'; |
||||
lyStylePfx = config.layers.stylePrefix || 'nv-'; |
|
||||
|
|
||||
config.layers.stylePrefix = config.stylePrefix + lyStylePfx; |
config.layers.stylePrefix = config.stylePrefix + lyStylePfx; |
||||
config.layers.pStylePrefix = config.stylePrefix; |
config.layers.pStylePrefix = config.stylePrefix; |
||||
config.layers.em = em.editor; |
config.layers.em = em.editor; |
||||
config.layers.opened = em.editor.get('opened'); |
config.layers.opened = em.editor.get('opened'); |
||||
var layers = new Layers(collection, config.layers); |
var layers = new Layers(collection, config.layers); |
||||
this.$layers = layers.render(); |
this.$layers = layers.render(); |
||||
|
|
||||
// Check if panel exists otherwise crate it
|
// Check if panel exists otherwise crate it
|
||||
if(!panels.getPanel('views-container')) |
if(!panels.getPanel('views-container')) |
||||
this.panel = panels.addPanel({id: 'views-container'}); |
this.panel = panels.addPanel({id: 'views-container'}); |
||||
else |
else |
||||
this.panel = panels.getPanel('views-container'); |
this.panel = panels.getPanel('views-container'); |
||||
|
|
||||
this.panel.set('appendContent', this.$layers).trigger('change:appendContent'); |
this.panel.set('appendContent', this.$layers).trigger('change:appendContent'); |
||||
} |
} |
||||
this.$layers.show(); |
this.$layers.show(); |
||||
}, |
}, |
||||
|
|
||||
stop: function() |
stop: function() { |
||||
{ |
if(this.$layers) |
||||
if(this.$layers) |
this.$layers.hide(); |
||||
this.$layers.hide(); |
} |
||||
} |
}; |
||||
}; |
}); |
||||
}); |
|
||||
|
|||||
@ -1,292 +1,287 @@ |
|||||
define(['backbone', 'text!./../template/item.html','require'], |
define(['backbone', 'text!./../template/item.html','require'], function (Backbone, ItemTemplate, require) { |
||||
function (Backbone, ItemTemplate, require) { |
return Backbone.View.extend({ |
||||
/** |
|
||||
* @class ItemView |
|
||||
* */ |
|
||||
|
|
||||
return Backbone.View.extend({ |
template: _.template(ItemTemplate), |
||||
|
|
||||
template: _.template(ItemTemplate), |
initialize: function(o) { |
||||
|
this.opt = o; |
||||
|
this.config = o.config; |
||||
|
this.em = o.config.em; |
||||
|
this.ppfx = this.em.get('Config').stylePrefix; |
||||
|
this.sorter = o.sorter || {}; |
||||
|
this.pfx = this.config.stylePrefix; |
||||
|
if(typeof this.model.get('open') == 'undefined') |
||||
|
this.model.set('open',false); |
||||
|
this.listenTo(this.model.components, 'remove add change reset', this.checkChildren); |
||||
|
this.listenTo(this.model, 'destroy remove', this.remove); |
||||
|
this.listenTo(this.model, 'change:status', this.updateStatus); |
||||
|
this.listenTo(this.model, 'change:open', this.updateOpening); |
||||
|
this.className = this.pfx + 'item no-select'; |
||||
|
this.editBtnCls = this.pfx + 'nav-item-edit'; |
||||
|
this.inputNameCls = this.ppfx + 'nav-comp-name'; |
||||
|
this.caretCls = this.ppfx + 'nav-item-caret'; |
||||
|
this.titleCls = this.pfx + 'title'; |
||||
|
this.customNameProp = 'custom-name'; |
||||
|
this.events = {}; |
||||
|
this.events['click > #'+this.pfx+'btn-eye'] = 'toggleVisibility'; |
||||
|
this.events['click .' + this.caretCls] = 'toggleOpening'; |
||||
|
this.events['click .' + this.titleCls] = 'handleSelect'; |
||||
|
this.events['click .' + this.editBtnCls] = 'handleEdit'; |
||||
|
this.events['blur .' + this.inputNameCls] = 'handleEditEnd'; |
||||
|
|
||||
initialize: function(o) { |
this.$el.data('model', this.model); |
||||
this.opt = o; |
this.$el.data('collection', this.model.get('components')); |
||||
this.config = o.config; |
|
||||
this.em = o.config.em; |
|
||||
this.ppfx = this.em.get('Config').stylePrefix; |
|
||||
this.sorter = o.sorter || {}; |
|
||||
this.pfx = this.config.stylePrefix; |
|
||||
if(typeof this.model.get('open') == 'undefined') |
|
||||
this.model.set('open',false); |
|
||||
this.listenTo(this.model.components, 'remove add change reset', this.checkChildren); |
|
||||
this.listenTo(this.model, 'destroy remove', this.remove); |
|
||||
this.listenTo(this.model, 'change:status', this.updateStatus); |
|
||||
this.listenTo(this.model, 'change:open', this.updateOpening); |
|
||||
this.className = this.pfx + 'item no-select'; |
|
||||
this.editBtnCls = this.pfx + 'nav-item-edit'; |
|
||||
this.inputNameCls = this.ppfx + 'nav-comp-name'; |
|
||||
this.caretCls = this.ppfx + 'nav-item-caret'; |
|
||||
this.titleCls = this.pfx + 'title'; |
|
||||
this.customNameProp = 'custom-name'; |
|
||||
this.events = {}; |
|
||||
this.events['click > #'+this.pfx+'btn-eye'] = 'toggleVisibility'; |
|
||||
this.events['click .' + this.caretCls] = 'toggleOpening'; |
|
||||
this.events['click .' + this.titleCls] = 'handleSelect'; |
|
||||
this.events['click .' + this.editBtnCls] = 'handleEdit'; |
|
||||
this.events['blur .' + this.inputNameCls] = 'handleEditEnd'; |
|
||||
|
|
||||
this.$el.data('model', this.model); |
if(o.config.sortable) |
||||
this.$el.data('collection', this.model.get('components')); |
this.events['mousedown > #'+this.pfx+'move'] = 'startSort'; |
||||
|
|
||||
if(o.config.sortable) |
this.delegateEvents(); |
||||
this.events['mousedown > #'+this.pfx+'move'] = 'startSort'; |
}, |
||||
|
|
||||
this.delegateEvents(); |
/** |
||||
}, |
* Handle the edit of the component name |
||||
|
*/ |
||||
|
handleEdit: function(e) { |
||||
|
e.stopPropagation(); |
||||
|
var inputName = this.getInputName(); |
||||
|
inputName.readOnly = false; |
||||
|
inputName.focus(); |
||||
|
}, |
||||
|
|
||||
/** |
/** |
||||
* Handle the edit of the component name |
* Handle with the end of editing of the component name |
||||
*/ |
*/ |
||||
handleEdit: function(e) { |
handleEditEnd: function (e) { |
||||
e.stopPropagation(); |
e.stopPropagation(); |
||||
var inputName = this.getInputName(); |
var inputName = this.getInputName(); |
||||
inputName.readOnly = false; |
inputName.readOnly = true; |
||||
inputName.focus(); |
this.model.set(this.customNameProp, inputName.value); |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Handle with the end of editing of the component name |
* Get the input containing the name of the component |
||||
*/ |
* @return {HTMLElement} |
||||
handleEditEnd: function (e) { |
*/ |
||||
e.stopPropagation(); |
getInputName: function () { |
||||
var inputName = this.getInputName(); |
if(!this.inputName) { |
||||
inputName.readOnly = true; |
this.inputName = this.el.querySelector('.' + this.inputNameCls); |
||||
this.model.set(this.customNameProp, inputName.value); |
} |
||||
}, |
return this.inputName; |
||||
|
}, |
||||
|
|
||||
/** |
/** |
||||
* Get the input containing the name of the component |
* Update item opening |
||||
* @return {HTMLElement} |
* |
||||
*/ |
* @return void |
||||
getInputName: function () { |
* */ |
||||
if(!this.inputName) { |
updateOpening: function (){ |
||||
this.inputName = this.el.querySelector('.' + this.inputNameCls); |
var opened = this.opt.opened || {}; |
||||
} |
var model = this.model; |
||||
return this.inputName; |
if(model.get('open')){ |
||||
}, |
this.$el.addClass("open"); |
||||
|
this.$caret.addClass('fa-chevron-down'); |
||||
|
opened[model.cid] = model; |
||||
|
}else{ |
||||
|
this.$el.removeClass("open"); |
||||
|
this.$caret.removeClass('fa-chevron-down'); |
||||
|
delete opened[model.cid]; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
/** |
/** |
||||
* Update item opening |
* Toggle item opening |
||||
* |
* @param {Object} e |
||||
* @return void |
* |
||||
* */ |
* @return void |
||||
updateOpening: function (){ |
* */ |
||||
var opened = this.opt.opened || {}; |
toggleOpening: function(e){ |
||||
var model = this.model; |
e.stopPropagation(); |
||||
if(model.get('open')){ |
|
||||
this.$el.addClass("open"); |
|
||||
this.$caret.addClass('fa-chevron-down'); |
|
||||
opened[model.cid] = model; |
|
||||
}else{ |
|
||||
this.$el.removeClass("open"); |
|
||||
this.$caret.removeClass('fa-chevron-down'); |
|
||||
delete opened[model.cid]; |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
if(!this.model.components.length) |
||||
* Toggle item opening |
return; |
||||
* @param {Object} e |
|
||||
* |
|
||||
* @return void |
|
||||
* */ |
|
||||
toggleOpening: function(e){ |
|
||||
e.stopPropagation(); |
|
||||
|
|
||||
if(!this.model.components.length) |
this.model.set('open', !this.model.get('open') ); |
||||
return; |
}, |
||||
|
|
||||
this.model.set('open', !this.model.get('open') ); |
/** |
||||
}, |
* Handle component selection |
||||
|
* @return {[type]} [description] |
||||
|
*/ |
||||
|
handleSelect: function (e) { |
||||
|
e.stopPropagation(); |
||||
|
var em = this.em; |
||||
|
|
||||
/** |
if(em){ |
||||
* Handle component selection |
var model = em.get('selectedComponent'); |
||||
* @return {[type]} [description] |
if(model){ |
||||
*/ |
model.set('status', ''); |
||||
handleSelect: function (e) { |
} |
||||
e.stopPropagation(); |
this.model.set('status', 'selected'); |
||||
|
em.set('selectedComponent', this.model); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
// Selection
|
/** |
||||
if(this.em){ |
* Delegate to sorter |
||||
var md = this.em.get('selectedComponent'); |
* @param Event |
||||
if(md){ |
* */ |
||||
md.set('status',''); |
startSort: function(e){ |
||||
this.model.set('status','selected'); |
if (this.sorter) { |
||||
this.em.set('selectedComponent', this.model); |
this.sorter.startSort(e.target); |
||||
} |
} |
||||
} |
}, |
||||
}, |
|
||||
|
|
||||
/** |
/** |
||||
* Delegate to sorter |
* Freeze item |
||||
* @param Event |
* @return void |
||||
* */ |
* */ |
||||
startSort: function(e){ |
freeze: function(){ |
||||
if (this.sorter) { |
this.$el.addClass(this.pfx + 'opac50'); |
||||
//this.sorter.startMove(this, e);
|
this.model.set('open',0); |
||||
this.sorter.startSort(e.target); |
}, |
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
/** |
||||
* Freeze item |
* Unfreeze item |
||||
* @return void |
* @return void |
||||
* */ |
* */ |
||||
freeze: function(){ |
unfreeze: function(){ |
||||
this.$el.addClass(this.pfx + 'opac50'); |
this.$el.removeClass(this.pfx + 'opac50'); |
||||
this.model.set('open',0); |
}, |
||||
}, |
|
||||
|
|
||||
/** |
/** |
||||
* Unfreeze item |
* Update item on status change |
||||
* @return void |
* @param Event |
||||
* */ |
* */ |
||||
unfreeze: function(){ |
updateStatus: function(e) { |
||||
this.$el.removeClass(this.pfx + 'opac50'); |
var status = this.model.get('status'); |
||||
}, |
var cls = this.pfx + 'selected'; |
||||
|
var el = this.$el; |
||||
|
switch(status) { |
||||
|
case 'selected': |
||||
|
el.addClass(cls); |
||||
|
break; |
||||
|
case 'moving': |
||||
|
break; |
||||
|
default: |
||||
|
el.removeClass(cls); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
/** |
/** |
||||
* Update item on status change |
* Toggle visibility |
||||
* @param Event |
* @param Event |
||||
* */ |
* |
||||
updateStatus: function(e) |
* @return void |
||||
{ |
* */ |
||||
var s = this.model.get('status'), |
toggleVisibility: function(e){ |
||||
pfx = this.pfx; |
if(!this.$eye) |
||||
switch(s) { |
this.$eye = this.$el.find('> #'+this.pfx+'btn-eye'); |
||||
case 'selected': |
|
||||
this.$el.addClass(pfx + 'selected'); |
|
||||
break; |
|
||||
case 'moving': |
|
||||
break; |
|
||||
default: |
|
||||
this.$el.removeClass(pfx + 'selected'); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
var cCss = _.clone(this.model.get('style')), |
||||
* Toggle visibility |
hClass = this.pfx + 'hide'; |
||||
* @param Event |
if(this.isVisible()){ |
||||
* |
this.$el.addClass(hClass); |
||||
* @return void |
this.$eye.addClass('fa-eye-slash'); |
||||
* */ |
cCss.display = 'none'; |
||||
toggleVisibility: function(e){ |
}else{ |
||||
if(!this.$eye) |
this.$el.removeClass(hClass); |
||||
this.$eye = this.$el.find('> #'+this.pfx+'btn-eye'); |
this.$eye.removeClass('fa-eye-slash'); |
||||
|
delete cCss.display; |
||||
|
} |
||||
|
this.model.set('style', cCss); |
||||
|
}, |
||||
|
|
||||
var cCss = _.clone(this.model.get('style')), |
/** |
||||
hClass = this.pfx + 'hide'; |
* Check if component is visible |
||||
if(this.isVisible()){ |
* |
||||
this.$el.addClass(hClass); |
* @return bool |
||||
this.$eye.addClass('fa-eye-slash'); |
* */ |
||||
cCss.display = 'none'; |
isVisible: function(){ |
||||
}else{ |
var css = this.model.get('style'), |
||||
this.$el.removeClass(hClass); |
pr = css.display; |
||||
this.$eye.removeClass('fa-eye-slash'); |
if(pr && pr == 'none' ) |
||||
delete cCss.display; |
return; |
||||
} |
return 1; |
||||
this.model.set('style', cCss); |
}, |
||||
}, |
|
||||
|
|
||||
/** |
/** |
||||
* Check if component is visible |
* Update item aspect after children changes |
||||
* |
* |
||||
* @return bool |
* @return void |
||||
* */ |
* */ |
||||
isVisible: function(){ |
checkChildren: function(){ |
||||
var css = this.model.get('style'), |
var c = this.countChildren(this.model), |
||||
pr = css.display; |
pfx = this.pfx, |
||||
if(pr && pr == 'none' ) |
tC = '> .' + pfx + 'title-c > .' + pfx + 'title'; |
||||
return; |
if(!this.$counter) |
||||
return 1; |
this.$counter = this.$el.find('> #' + pfx + 'counter'); |
||||
}, |
if(c){ |
||||
|
this.$el.find(tC).removeClass(pfx + 'no-chld'); |
||||
|
this.$counter.html(c); |
||||
|
}else{ |
||||
|
this.$el.find(tC).addClass(pfx + 'no-chld'); |
||||
|
this.$counter.empty(); |
||||
|
this.model.set('open',0); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
/** |
/** |
||||
* Update item aspect after children changes |
* Count children inside model |
||||
* |
* @param {Object} model |
||||
* @return void |
* @return {number} |
||||
* */ |
* @private |
||||
checkChildren: function(){ |
*/ |
||||
var c = this.countChildren(this.model), |
countChildren: function(model){ |
||||
pfx = this.pfx, |
var count = 0; |
||||
tC = '> .' + pfx + 'title-c > .' + pfx + 'title'; |
model.components.each(function(m){ |
||||
if(!this.$counter) |
var isCountable = this.opt.isCountable; |
||||
this.$counter = this.$el.find('> #' + pfx + 'counter'); |
var hide = this.config.hideTextnode; |
||||
if(c){ |
if(isCountable && !isCountable(m, hide)) |
||||
this.$el.find(tC).removeClass(pfx + 'no-chld'); |
return; |
||||
this.$counter.html(c); |
count++; |
||||
}else{ |
}, this); |
||||
this.$el.find(tC).addClass(pfx + 'no-chld'); |
return count; |
||||
this.$counter.empty(); |
}, |
||||
this.model.set('open',0); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
render: function(){ |
||||
* Count children inside model |
var pfx = this.pfx; |
||||
* @param {Object} model |
var vis = this.isVisible(); |
||||
* @return {number} |
var count = this.countChildren(this.model); |
||||
* @private |
|
||||
*/ |
|
||||
countChildren: function(model){ |
|
||||
var count = 0; |
|
||||
model.components.each(function(m){ |
|
||||
var isCountable = this.opt.isCountable; |
|
||||
var hide = this.config.hideTextnode; |
|
||||
if(isCountable && !isCountable(m, hide)) |
|
||||
return; |
|
||||
count++; |
|
||||
}, this); |
|
||||
return count; |
|
||||
}, |
|
||||
|
|
||||
render: function(){ |
this.$el.html( this.template({ |
||||
var pfx = this.pfx; |
title: this.model.get(this.customNameProp) || this.model.getName(), |
||||
var vis = this.isVisible(); |
addClass: (count ? '' : pfx+'no-chld'), |
||||
var count = this.countChildren(this.model); |
editBtnCls: this.editBtnCls, |
||||
|
inputNameCls: this.inputNameCls, |
||||
|
caretCls: this.caretCls, |
||||
|
count: count, |
||||
|
visible: vis, |
||||
|
hidable: this.config.hidable, |
||||
|
prefix: pfx, |
||||
|
ppfx: this.ppfx |
||||
|
})); |
||||
|
|
||||
this.$el.html( this.template({ |
if(typeof ItemsView == 'undefined') |
||||
title: this.model.get(this.customNameProp) || this.model.getName(), |
ItemsView = require('./ItemsView'); |
||||
addClass: (count ? '' : pfx+'no-chld'), |
this.$components = new ItemsView({ |
||||
editBtnCls: this.editBtnCls, |
collection : this.model.components, |
||||
inputNameCls: this.inputNameCls, |
config: this.config, |
||||
caretCls: this.caretCls, |
sorter: this.sorter, |
||||
count: count, |
opened: this.opt.opened, |
||||
visible: vis, |
parent: this.model |
||||
hidable: this.config.hidable, |
}).render().$el; |
||||
prefix: pfx, |
this.$el.find('.'+ pfx +'children').html(this.$components); |
||||
ppfx: this.ppfx |
this.$caret = this.$el.find('> .' + pfx + 'title-c > .' + pfx + 'title > #' + pfx + 'caret'); |
||||
})); |
if(!this.model.get('draggable') || !this.config.sortable){ |
||||
|
this.$el.find('> #' + pfx + 'move').detach(); |
||||
|
} |
||||
|
if(!vis) |
||||
|
this.className += ' ' + pfx + 'hide'; |
||||
|
this.$el.attr('class', _.result(this, 'className')); |
||||
|
this.updateOpening(); |
||||
|
this.updateStatus(); |
||||
|
return this; |
||||
|
}, |
||||
|
|
||||
if(typeof ItemsView == 'undefined') |
}); |
||||
ItemsView = require('./ItemsView'); |
|
||||
this.$components = new ItemsView({ |
|
||||
collection : this.model.components, |
|
||||
config: this.config, |
|
||||
sorter: this.sorter, |
|
||||
opened: this.opt.opened, |
|
||||
parent: this.model |
|
||||
}).render().$el; |
|
||||
this.$el.find('.'+ pfx +'children').html(this.$components); |
|
||||
this.$caret = this.$el.find('> .' + pfx + 'title-c > .' + pfx + 'title > #' + pfx + 'caret'); |
|
||||
if(!this.model.get('draggable') || !this.config.sortable){ |
|
||||
this.$el.find('> #' + pfx + 'move').detach(); |
|
||||
} |
|
||||
if(!vis) |
|
||||
this.className += ' ' + pfx + 'hide'; |
|
||||
this.$el.attr('class', _.result(this, 'className')); |
|
||||
this.updateOpening(); |
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
Loading…
Reference in new issue