Browse Source

Refactor ComponentTextView

pull/415/head
Artur Arseniev 9 years ago
parent
commit
608a1751fa
  1. 92
      src/dom_components/view/ComponentTextView.js
  2. 42
      src/dom_components/view/ComponentView.js
  3. 61
      src/dom_components/view/ComponentsView.js
  4. 6
      src/utils/extender.js

92
src/dom_components/view/ComponentTextView.js

@ -6,18 +6,16 @@ module.exports = ComponentView.extend({
events: { events: {
'dblclick': 'enableEditing', 'dblclick': 'enableEditing',
'change': 'parseRender',
}, },
initialize(o) { initialize(o) {
ComponentView.prototype.initialize.apply(this, arguments); ComponentView.prototype.initialize.apply(this, arguments);
_.bindAll(this,'disableEditing'); this.disableEditing = this.disableEditing.bind(this);
const model = this.model; const model = this.model;
this.listenTo(model, 'focus active', this.enableEditing); this.listenTo(model, 'focus active', this.enableEditing);
this.listenTo(model, 'change:content', this.updateContent); this.listenTo(model, 'change:content', this.updateContent);
this.rte = this.config.rte || ''; this.rte = this.config.rte || '';
this.activeRte = null; this.activeRte = null;
this.em = this.config.em;
}, },
/** /**
@ -26,15 +24,18 @@ module.exports = ComponentView.extend({
* @private * @private
* */ * */
enableEditing(e) { enableEditing(e) {
var editable = this.model.get('editable'); const editable = this.model.get('editable');
if(this.rte && editable) { const rte = this.rte;
if (rte && editable) {
try { try {
this.activeRte = this.rte.attach(this, this.activeRte); this.activeRte = rte.attach(this, this.activeRte);
this.rte.focus(this, this.activeRte); rte.focus(this, this.activeRte);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
} }
} }
this.toggleEvents(1); this.toggleEvents(1);
}, },
@ -44,23 +45,46 @@ module.exports = ComponentView.extend({
* @private * @private
* */ * */
disableEditing(e) { disableEditing(e) {
var model = this.model; const model = this.model;
var editable = model.get('editable'); const editable = model.get('editable');
const rte = this.rte;
if(this.rte && editable) { if (rte && editable) {
try { try {
this.rte.detach(this, this.activeRte); rte.detach(this, this.activeRte);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
} }
var el = this.getChildrenContainer();
// Avoid double content by removing its children components
model.get('components').reset();
model.set('content', el.innerHTML);
}
if(!this.rte.customRte && editable) { const content = this.getChildrenContainer().innerHTML;
this.parseRender(); const comps = model.get('components');
// If there is a custom RTE the content is just baked staticly
// inside 'content'
if (rte.customRte) {
// Avoid double content by removing its children components
comps.reset();
model.set('content', content);
} else {
const clean = model => {
model.set({
highlightable: 0,
removable: 0,
draggable: 0,
copyable: 0,
toolbar: '',
});
model.get('components').each(model => clean(model));
}
// Avoid re-render on reset with silent option
model.set('content', '');
comps.reset();
comps.add(content);
comps.each(model => clean(model));
// With rerender is possible to see changes applied after clean
this.render();
}
} }
this.toggleEvents(); this.toggleEvents();
@ -75,38 +99,6 @@ module.exports = ComponentView.extend({
e.stopPropagation(); e.stopPropagation();
}, },
/**
* Parse content and re-render it
* @private
*/
parseRender() {
const model = this.model;
var el = this.getChildrenContainer();
var comps = model.get('components');
var opts = {silent: true};
const clean = model => {
model.set({
highlightable: 0,
removable: 0,
draggable: 0,
copyable: 0,
toolbar: '',
}, opts);
model.get('components').each(model => clean(model));
}
// Avoid re-render on reset with silent option
comps.reset(null, opts);
comps.add(el.innerHTML, opts);
comps.each(model => clean(model));
model.set('content', '');
this.render();
// As the reset was in silent mode I need to notify
// the navigator about the change
comps.trigger('resetNavigator');
},
/** /**
* Enable/Disable events * Enable/Disable events
* @param {Boolean} enable * @param {Boolean} enable

42
src/dom_components/view/ComponentView.js

@ -1,5 +1,4 @@
const ComponentsView = require('./ComponentsView'); const ComponentsView = require('./ComponentsView');
const $ = Backbone.$;
module.exports = Backbone.View.extend({ module.exports = Backbone.View.extend({
@ -12,15 +11,16 @@ module.exports = Backbone.View.extend({
}, },
initialize(opt) { initialize(opt) {
var model = this.model; const model = this.model;
this.opts = opt || {}; this.opts = opt || {};
this.config = this.opts.config || {}; this.config = this.opts.config || {};
this.em = this.config.em || ''; this.em = this.config.em || '';
this.pfx = this.config.stylePrefix || ''; this.pfx = this.config.stylePrefix || '';
this.ppfx = this.config.pStylePrefix || ''; this.ppfx = this.config.pStylePrefix || '';
this.components = model.get('components'); this.attr = model.get('attributes');
this.attr = model.get("attributes");
this.classe = this.attr.class || []; this.classe = this.attr.class || [];
const $el = this.$el;
const classes = model.get('classes');
this.listenTo(model, 'destroy remove', this.remove); this.listenTo(model, 'destroy remove', this.remove);
this.listenTo(model, 'change:style', this.updateStyle); this.listenTo(model, 'change:style', this.updateStyle);
this.listenTo(model, 'change:attributes', this.updateAttributes); this.listenTo(model, 'change:attributes', this.updateAttributes);
@ -28,26 +28,20 @@ module.exports = Backbone.View.extend({
this.listenTo(model, 'change:state', this.updateState); this.listenTo(model, 'change:state', this.updateState);
this.listenTo(model, 'change:script', this.render); this.listenTo(model, 'change:script', this.render);
this.listenTo(model, 'change', this.handleChange); this.listenTo(model, 'change', this.handleChange);
this.listenTo(model.get('classes'), 'add remove change', this.updateClasses); this.listenTo(classes, 'add remove change', this.updateClasses);
const $el = this.$el;
const el = this.el;
const em = this.em;
$el.data('model', model); $el.data('model', model);
$el.data('collection', this.components); $el.data('collection', model.get('components'));
model.view = this; model.view = this;
classes.length && this.importClasses();
if (em) {
em.data(el, 'model', model);
em.data(el, 'collection', model.get('components'));
}
if(model.get('classes').length)
this.importClasses();
this.init(); this.init();
}, },
remove() {
Backbone.View.prototype.remove.apply(this);
const children = this.childrenView;
children && children.stopListening();
},
/** /**
* Initialize callback * Initialize callback
*/ */
@ -309,15 +303,16 @@ module.exports = Backbone.View.extend({
* @private * @private
*/ */
renderChildren() { renderChildren() {
var view = new ComponentsView({ const container = this.getChildrenContainer();
const view = new ComponentsView({
collection: this.model.get('components'), collection: this.model.get('components'),
config: this.config, config: this.config,
componentTypes: this.opts.componentTypes, componentTypes: this.opts.componentTypes,
}); });
var container = this.getChildrenContainer(); view.render(container);
var childNodes = view.render($(container)).el.childNodes; this.childrenView = view;
childNodes = Array.prototype.slice.call(childNodes); const childNodes = Array.prototype.slice.call(view.el.childNodes);
for (var i = 0, len = childNodes.length ; i < len; i++) { for (var i = 0, len = childNodes.length ; i < len; i++) {
container.appendChild(childNodes.shift()); container.appendChild(childNodes.shift());
@ -348,7 +343,6 @@ module.exports = Backbone.View.extend({
render() { render() {
this.renderAttributes(); this.renderAttributes();
var model = this.model;
this.updateContent(); this.updateContent();
this.renderChildren(); this.renderChildren();
this.updateScript(); this.updateScript();

61
src/dom_components/view/ComponentsView.js

@ -1,12 +1,13 @@
var Backbone = require('backbone'); import { isUndefined } from 'underscore'
module.exports = Backbone.View.extend({ module.exports = Backbone.View.extend({
initialize(o) { initialize(o) {
this.opts = o || {}; this.opts = o || {};
this.config = o.config || {}; this.config = o.config || {};
this.listenTo( this.collection, 'add', this.addTo ); const coll = this.collection;
this.listenTo( this.collection, 'reset', this.render ); this.listenTo(coll, 'add', this.addTo);
this.listenTo(coll, 'reset', this.resetChildren);
}, },
/** /**
@ -17,7 +18,7 @@ module.exports = Backbone.View.extend({
* @private * @private
* */ * */
addTo(model) { addTo(model) {
var i = this.collection.indexOf(model); var i = this.collection.indexOf(model);
this.addToCollection(model, null, i); this.addToCollection(model, null, i);
var em = this.config.em; var em = this.config.em;
@ -42,7 +43,6 @@ module.exports = Backbone.View.extend({
this.compView = require('./ComponentView'); this.compView = require('./ComponentView');
var fragment = fragmentEl || null, var fragment = fragmentEl || null,
viewObject = this.compView; viewObject = this.compView;
//console.log('Add to collection', model, 'Index',i);
var dt = this.opts.componentTypes; var dt = this.opts.componentTypes;
@ -66,44 +66,47 @@ module.exports = Backbone.View.extend({
if(view.model.get('type') == 'textnode') if(view.model.get('type') == 'textnode')
rendered = document.createTextNode(view.model.get('content')); rendered = document.createTextNode(view.model.get('content'));
if(fragment){ if (fragment) {
fragment.appendChild(rendered); fragment.appendChild(rendered);
}else{ } else {
var p = this.$parent; const parent = this.parentEl;
var pc = p.children; const children = parent.childNodes;
if(typeof index != 'undefined'){
var method = 'before'; if (!isUndefined(index)) {
const lastIndex = children.length == index;
// If the added model is the last of collection // If the added model is the last of collection
// need to change the logic of append // need to change the logic of append
if(pc && p.children().length == index){ if (lastIndex) {
index--; index--;
method = 'after';
} }
// In case the added is new in the collection index will be -1 // In case the added is new in the collection index will be -1
if(index < 0) { if (lastIndex || !children.length) {
p.append(rendered); parent.appendChild(rendered);
}else { } else {
if(pc) { parent.insertBefore(rendered, children[index]);
p.children().eq(index)[method](rendered);
}
} }
}else{ } else {
p.append(rendered); parent.appendChild(rendered);
} }
} }
return rendered; return rendered;
}, },
render($p) { resetChildren() {
var fragment = document.createDocumentFragment(); this.parentEl.innerHTML = '';
this.$parent = $p || this.$el; this.collection.each(model => this.addToCollection(model));
this.$el.empty(); },
this.collection.each(function(model){
this.addToCollection(model, fragment);
},this);
this.$el.append(fragment);
render(parent) {
const el = this.el;
const frag = document.createDocumentFragment();
this.parentEl = parent || this.el;
this.collection.each(model => this.addToCollection(model, frag));
el.innerHTML = '';
el.appendChild(frag);
return this; return this;
} }

6
src/utils/extender.js

@ -213,6 +213,12 @@ module.exports = ({$, Backbone}) => {
return this; return this;
} }
fn.remove = function () {
return this.each(node => {
return node.parentNode && node.parentNode.removeChild(node);
});
},
// For spectrum compatibility // For spectrum compatibility
fn.bind = function(ev, h) { fn.bind = function(ev, h) {
return this.on(ev, h); return this.on(ev, h);

Loading…
Cancel
Save