Browse Source

Update text component and the html parser

pull/36/head
Artur Arseniev 9 years ago
parent
commit
5e5977c83a
  1. 36
      src/demo.js
  2. 8
      src/dom_components/main.js
  3. 6
      src/dom_components/model/ComponentImage.js
  4. 17
      src/dom_components/model/ComponentTextNode.js
  5. 2
      src/dom_components/model/Components.js
  6. 9
      src/dom_components/view/ComponentTextNodeView.js
  7. 31
      src/dom_components/view/ComponentTextView.js
  8. 2
      src/dom_components/view/ComponentView.js
  9. 3
      src/dom_components/view/ComponentsView.js
  10. 20
      src/parser/model/ParserHtml.js
  11. 35
      src/rich_text_editor/config/config.js
  12. 13
      src/rich_text_editor/view/CommandButtonsView.js
  13. 17
      src/rich_text_editor/view/TextEditorView.js

36
src/demo.js

@ -9,27 +9,31 @@ require(['config/require-config'], function() {
noticeOnUnload: 0,
container : '#gjs',
height: '100%',
fromElement: true,
/*
//fromElement: true,
components: [{
type: 'text',
style:{
width:'100px',
height:'100px'
},
traits: ['title']
},{
style:{
width:'150px',
height:'100px'
height:'100px',
margin: '50px auto',
},
traits: [{name:'title', value: "myTitleTest"}]
},{
type: 'image'
},{
type: 'link',
content: 'mylink',
traits: ['title'],
components: [{
type: 'textnode',
content: 'text node row',
},{
type: 'textnode',
content: ', another text node',
},{
type: 'link',
content: 'someLink',
},{
type: 'textnode',
content: " More text node --- ",
}],
}],
*/
storageManager:{
autoload: 0,
},

8
src/dom_components/main.js

@ -58,14 +58,14 @@ define(function(require) {
model: require('./model/ComponentImage'),
view: require('./view/ComponentImageView'),
},
'text': {
model: require('./model/ComponentText'),
view: require('./view/ComponentTextView'),
},
'textnode': {
model: require('./model/ComponentTextNode'),
view: require('./view/ComponentTextNodeView'),
},
'text': {
model: require('./model/ComponentText'),
view: require('./view/ComponentTextView'),
},
'default': {
model: Component,
view: ComponentView,

6
src/dom_components/model/ComponentImage.js

@ -67,8 +67,10 @@ define(['./Component'],
isComponent: function(el) {
var result = '';
if(el.tagName == 'IMG'){
result = {type: 'image'};
result.src = el.src;
result = {
type: 'image',
src: el.src
};
}
return result;
},

17
src/dom_components/model/ComponentTextNode.js

@ -7,5 +7,22 @@ define(['./Component'],
droppable: false,
}),
toHTML: function() {
return this.get('content');
},
}, {
isComponent: function(el) {
var result = '';
if(el.nodeType === 3){
result = {
type: 'textnode',
content: el.textContent
};
}
return result;
},
});
});

2
src/dom_components/model/Components.js

@ -51,6 +51,8 @@ define([ 'backbone', 'require'],
if(parsed.css && cssc){
var added = cssc.addCollection(parsed.css);
}
console.log('Parsed from add', models);
}
return Backbone.Collection.prototype.add.apply(this, [models, opt]);

9
src/dom_components/view/ComponentTextNodeView.js

@ -1,12 +1,5 @@
define(['backbone'],
function (Backbone) {
return Backbone.View.extend({
render: function() {
this.el.innerHTML = this.model.get('content');
return this;
},
});
return Backbone.View.extend({});
});

31
src/dom_components/view/ComponentTextView.js

@ -4,7 +4,8 @@ define(['backbone', './ComponentView'],
return ComponentView.extend({
events: {
'dblclick' : 'enableEditing',
'dblclick': 'enableEditing',
'change': 'parseRender',
},
initialize: function(o){
@ -14,6 +15,20 @@ define(['backbone', './ComponentView'],
this.rte = this.config.rte || '';
},
/**
* Parse content and re-render it
* @private
*/
parseRender: function(){
var comps = this.model.get('components');
var opts = {silent: true};
// Avoid re-render on reset with silent option
comps.reset(null, opts);
comps.add(this.$el.html(), opts);
this.model.set('content', '');
this.render();
},
/**
* Enable the component to be editable
* @param {Event} e
@ -34,7 +49,8 @@ define(['backbone', './ComponentView'],
if(this.rte)
this.rte.detach(this);
this.toggleEvents();
this.updateContents();
//this.updateContents();
this.parseRender();
},
/**
@ -48,10 +64,11 @@ define(['backbone', './ComponentView'],
/**
* Update contents of the element
* TODO to remove
* @private
**/
updateContents: function(){
this.model.set('content', this.el.innerHTML);
//this.model.set('content', this.el.innerHTML);
},
/**
@ -62,16 +79,12 @@ define(['backbone', './ComponentView'],
var method = enable ? 'on' : 'off';
// The ownerDocument is from the frame
var elDocs = [this.el.ownerDocument, document, this.rte];
$(elDocs).off('mousedown', this.disableEditing);
$(elDocs)[method]('mousedown', this.disableEditing);
// Avoid closing edit mode on component click
this.$el.off('mousedown', this.disablePropagation);
this.$el[method]('mousedown', this.disablePropagation);
},
render: function() {
this.updateAttributes();
this.updateClasses();
this.el.innerHTML = this.model.get('content');
return this;
},
});
});

2
src/dom_components/view/ComponentView.js

@ -179,7 +179,7 @@ define(['backbone', './ComponentsView'],
this.updateClasses();
this.$el.html(this.model.get('content'));
var view = new ComponentsView({
collection: this.components,
collection: this.model.get('components'),
config: this.config,
defaultTypes: this.opts.defaultTypes,
componentTypes: this.opts.componentTypes,

3
src/dom_components/view/ComponentsView.js

@ -36,6 +36,7 @@ function(Backbone, require) {
this.compView = require('./ComponentView');
var fragment = fragmentEl || null,
viewObject = this.compView;
//console.log('Add to collection', model, 'Index',i);
var dt = this.opts.defaultTypes;
var ct = this.opts.componentTypes;
@ -50,6 +51,8 @@ function(Backbone, require) {
componentTypes: ct,
});
var rendered = view.render().el;
if(view.model.get('type') == 'textnode')
rendered = document.createTextNode(view.model.get('content'));
if(fragment){
fragment.appendChild(rendered);

20
src/parser/model/ParserHtml.js

@ -97,10 +97,7 @@ define(function(require) {
model.style = this.parseStyle(nodeValue);
else if(nodeName == 'class')
model.classes = this.parseClass(nodeValue);
else if(nodeName == 'src' && model.tagName == 'img'){
model.type = 'image';
model.src = nodeValue;
}else
else
model.attributes[nodeName] = nodeValue;
}
@ -110,7 +107,9 @@ define(function(require) {
// Avoid infinite text nodes nesting
var firstChild = node.childNodes[0];
if(nodeChild === 1 && firstChild.nodeType === 3){
model.type = 'text';
if(!model.type){
model.type = 'text';
}
model.content = firstChild.nodeValue;
}else{
var parsed = this.parseNode(node);
@ -128,19 +127,22 @@ define(function(require) {
var prevIsText = prevSib && prevSib.type == 'text' && prevSib.tagName == TEXT_NODE;
// Find text nodes
if(!model.tagName && node.nodeType === 3){
/*
if(model.type == 'textnode'){
// Pass content to the previous model if it's a text node
if(prevIsText){
prevSib.content += node.nodeValue;
continue;
}
// Make it text node only the content is not empty
// Make it text node only if the content is not empty
if(node.nodeValue.trim()){
console.log('part 1', model);
model.type = 'text';
model.tagName = TEXT_NODE;
model.content = node.nodeValue;
}
}
*/
// Check if it's a text node and if it could be moved to the prevous model
if(c.textTags.indexOf(model.tagName) >= 0){
@ -156,8 +158,8 @@ define(function(require) {
}
}
// If tagName is still empty do not push it
if(!model.tagName)
// If tagName is still empty and is not a textnode, do not push it
if(!model.tagName && model.type != 'textnode')
continue;
result.push(model);

35
src/rich_text_editor/config/config.js

@ -4,24 +4,29 @@ define(function () {
toolbarId : 'toolbar',
containerId : 'wrapper',
commands : [{
command: 'bold',
title: 'Bold',
class: 'fa fa-bold',
command: 'bold',
title: 'Bold',
class: 'fa fa-bold',
},{
command: 'italic',
title: 'Italic',
class: 'fa fa-italic',
command: 'italic',
title: 'Italic',
class: 'fa fa-italic',
},{
command: 'underline',
title: 'Underline',
class: 'fa fa-underline',
command: 'underline',
title: 'Underline',
class: 'fa fa-underline',
},{
command: 'strikethrough',
title: 'Strikethrough',
class: 'fa fa-strikethrough',
group: 'format'
command: 'strikethrough',
title: 'Strikethrough',
class: 'fa fa-strikethrough',
group: 'format'
},{
command: 'insertHTML',
title: 'Link',
class: 'fa fa-link',
args: '<a href="">${content}</a>',
}/*,{
command: 'fontSize',
command: 'fontSize',
options: [
{name: 'Huge', value: '7'},
{name: 'Normal', value: '5'},
@ -29,4 +34,4 @@ define(function () {
]
}*/],
};
});
});

13
src/rich_text_editor/view/CommandButtonsView.js

@ -38,13 +38,16 @@ define(['backbone','./CommandButtonView', './CommandButtonSelectView'],
viewObj = CommandButtonSelectView;
break;
}
var args = model.get('args');
var attrs = {
'title': model.get('title'),
'data-edit': model.get('command'),
};
if(args)
attrs['data-args'] = args;
var view = new viewObj({
model: model,
attributes: {
'title': model.get('title'),
'data-edit': model.get('command'),
},
attributes: attrs,
}, this.config);
var rendered = view.render().el;

17
src/rich_text_editor/view/TextEditorView.js

@ -45,6 +45,7 @@ define(['jquery'],
editor.get(0).ownerDocument.execCommand("styleWithCSS", false, true);
editor.get(0).ownerDocument.execCommand(command, 0, args);
updateToolbar();
editor.trigger('change');
},
/*
bindHotkeys = function (hotKeys) {
@ -112,7 +113,16 @@ define(['jquery'],
toolbar.find(toolbarBtnSelector).unbind().click(function () {
restoreSelection();
//editor.focus(); // cause defocus on selects
editor.get(0).ownerDocument.execCommand($(this).data(options.commandRole));
var doc = editor.get(0).ownerDocument;
var el = $(this);
var comm = el.data(options.commandRole);
var args = el.data('args');
if(args){
args = args.replace('${content}', doc.getSelection());
execCommand(comm, args);
}else{
doc.execCommand(comm);
}
saveSelection();
});
toolbar.find('[data-toggle=dropdown]').click(restoreSelection);
@ -124,11 +134,9 @@ define(['jquery'],
editor.focus();
execCommand($(this).data(options.commandRole), newValue);
}
console.log('change isolated2 ', newValue);
saveSelection();
});
toolbar.find('input[type=text]'+dName,', select'+dName).on('webkitspeechchange change', function () {
console.log('on changed ', newValue);
var newValue = this.value; /* ugly but prevents fake double-calls due to selection restoration */
this.value = '';
restoreSelection();
@ -138,10 +146,8 @@ define(['jquery'],
}
saveSelection();
}).on('focus', function () {
console.log('on focus ');
var input = $(this);
if (!input.data(options.selectionMarker)) {
console.log('i have no ', options.selectionMarker);
markSelection(input, options.selectionColor);
input.focus();
}
@ -228,4 +234,3 @@ define(['jquery'],
return $;
});

Loading…
Cancel
Save