X-Git-Url: https://git.mdrn.pl/fnpeditor.git/blobdiff_plain/b8a6d80a6573772f180b39aaeaf6c3ef48f2c021..e47b0769de4853ef9c027592533804e39f247f44:/modules/visualEditor.js?ds=sidebyside
diff --git a/modules/visualEditor.js b/modules/visualEditor.js
index 702c812..65de452 100644
--- a/modules/visualEditor.js
+++ b/modules/visualEditor.js
@@ -1,5 +1,6 @@
-rng.modules.visualEditor = function(sandbox) {
- var transformations = rng.modules.visualEditor.transformations;
+define(['./visualEditor.transformations'], function(transformations) {
+
+return function(sandbox) {
var view = {
node: $(sandbox.getTemplate('main')()),
@@ -15,8 +16,8 @@ rng.modules.visualEditor = function(sandbox) {
isDirty = true;
});
- this.node.on('mouseover', '[wlxml-tag]', function(e) { $(e.target).addClass('rng-hover')});
- this.node.on('mouseout', '[wlxml-tag]', function(e) { $(e.target).removeClass('rng-hover')});
+ this.node.on('mouseover', '[wlxml-tag]', function(e) { mediator.nodeHovered($(e.target));});
+ this.node.on('mouseout', '[wlxml-tag]', function(e) { mediator.nodeBlured($(e.target));});
this.node.on('click', '[wlxml-tag]', function(e) {
console.log('clicked node type: '+e.target.nodeType);
view._markSelected($(e.target));
@@ -34,12 +35,7 @@ rng.modules.visualEditor = function(sandbox) {
this.node.on('keydown', '#rng-visualEditor-contentWrapper', function(e) {
if(e.which === 13) {
e.preventDefault();
- var anchor = $(window.getSelection().anchorNode);
- if(anchor[0].nodeType === Node.TEXT_NODE)
- anchor = anchor.parent();
- var newNode = anchor.clone().empty();
- anchor.after(newNode);
- view.selectNode(newNode);
+ view.insertNewNode(null, null);
}
});
@@ -72,7 +68,106 @@ rng.modules.visualEditor = function(sandbox) {
}
});
-
+
+
+ var observer = new MutationObserver(function(mutations) {
+ mutations.forEach(function(mutation) {
+ _.each(mutation.addedNodes, function(node) {
+ node = $(node);
+ node.parent().find('[wlxml-tag]').each(function() {
+ tag = $(this);
+ if(!tag.attr('id'))
+ tag.attr('id', 'xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {var r = Math.random()*16|0,v=c=='x'?r:r&0x3|0x8;return v.toString(16);}));
+ });
+ });
+ });
+ });
+ var config = { attributes: true, childList: true, characterData: true, subtree: true };
+ observer.observe(this.node.find('#rng-visualEditor-contentWrapper')[0], config);
+
+ this.gridToggled = false;
+ },
+ _createNode: function(wlxmlTag, wlxmlClass) {
+ var toBlock = ['div', 'document', 'section', 'header'];
+ var htmlTag = _.contains(toBlock, wlxmlTag) ? 'div' : 'span';
+ var toret = $('<' + htmlTag + '>');
+ toret.attr('wlxml-tag', wlxmlTag);
+ if(wlxmlClass)
+ toret.attr('wlxml-class', wlxmlClass);
+ return toret;
+ },
+ insertNewNode: function(wlxmlTag, wlxmlClass) {
+ //TODO: Insert inline
+ var anchor = $(window.getSelection().anchorNode);
+ var anchorOffset = window.getSelection().anchorOffset;
+ if(anchor[0].nodeType === Node.TEXT_NODE)
+ anchor = anchor.parent();
+ if(anchor.text() === '') {
+ var todel = anchor;
+ anchor = anchor.parent();
+ todel.remove();
+ }
+ if(anchorOffset > 0 && anchorOffset < anchor.text().length) {
+ if(wlxmlTag === null && wlxmlClass === null) {
+ return this.splitWithNewNode(anchor);
+ }
+ return this.wrapSelectionWithNewNode(wlxmlTag, wlxmlClass);
+ }
+ var newNode = this._createNode(wlxmlTag || anchor.attr('wlxml-tag'), wlxmlClass || anchor.attr('wlxml-class'));
+ if(anchorOffset === 0)
+ anchor.before(newNode)
+ else
+ anchor.after(newNode);
+ mediator.nodeCreated(newNode);
+ isDirty = true;
+ },
+ wrapSelectionWithNewNode: function(wlxmlTag, wlxmlClass) {
+ var selection = window.getSelection();
+ if(selection.anchorNode === selection.focusNode && selection.anchorNode.nodeType === Node.TEXT_NODE) {
+ var startOffset = selection.anchorOffset;
+ var endOffset = selection.focusOffset;
+ if(startOffset > endOffset) {
+ var tmp = startOffset;
+ startOffset = endOffset;
+ endOffset = tmp;
+ }
+ var node = selection.anchorNode;
+ var prefix = node.data.substr(0, startOffset);
+ var suffix = node.data.substr(endOffset);
+ var core = node.data.substr(startOffset, endOffset - startOffset);
+ var newNode = this._createNode(wlxmlTag, wlxmlClass);
+ newNode.text(core || 'test');
+ $(node).replaceWith(newNode);
+ newNode.before(prefix);
+ newNode.after(suffix);
+ mediator.nodeCreated(newNode);
+ isDirty = true;
+ }
+ },
+ splitWithNewNode: function(node) {
+ var selection = window.getSelection();
+ if(selection.anchorNode === selection.focusNode && selection.anchorNode.nodeType === Node.TEXT_NODE) {
+ var startOffset = selection.anchorOffset;
+ var endOffset = selection.focusOffset;
+ if(startOffset > endOffset) {
+ var tmp = startOffset;
+ startOffset = endOffset;
+ endOffset = tmp;
+ }
+ var anchor = selection.anchorNode;
+ var prefix = anchor.data.substr(0, startOffset);
+ var suffix = anchor.data.substr(endOffset);
+ var prefixNode = this._createNode(node.attr('wlxml-tag'), node.attr('wlxml-class'));
+ var newNode = this._createNode(node.attr('wlxml-tag'), node.attr('wlxml-class'));
+ var suffixNode = this._createNode(node.attr('wlxml-tag'), node.attr('wlxml-class'));
+ prefixNode.text(prefix);
+ suffixNode.text(suffix);
+ node.replaceWith(newNode);
+ newNode.before(prefixNode);
+ newNode.after(suffixNode);
+ mediator.nodeCreated(newNode);
+ isDirty = true;
+ }
},
getMetaData: function() {
var toret = {};
@@ -100,8 +195,12 @@ rng.modules.visualEditor = function(sandbox) {
return this.node.find('#rng-visualEditor-content').html();
},
_markSelected: function(node) {
+ this.dimNode(node);
+
this.node.find('.rng-current').removeClass('rng-current');
+
node.addClass('rng-current');
+
this.currentNode = node;
mediator.nodeSelected(node);
},
@@ -115,6 +214,37 @@ rng.modules.visualEditor = function(sandbox) {
selection.removeAllRanges()
selection.addRange(range);
},
+ selectNodeById: function(id) {
+ var node = this.node.find('#'+id);
+ if(node)
+ this.selectNode(node);
+ },
+ highlightNode: function(node) {
+ if(!this.gridToggled) {
+ node.addClass('rng-hover');
+ var label = node.attr('wlxml-tag');
+ if(node.attr('wlxml-class'))
+ label += ' / ' + node.attr('wlxml-class');
+ var tag = $('
').addClass('rng-visualEditor-nodeHoverTag').text(label);
+ node.append(tag);
+ }
+ },
+ dimNode: function(node) {
+ if(!this.gridToggled) {
+ node.removeClass('rng-hover');
+ node.find('.rng-visualEditor-nodeHoverTag').remove();
+ }
+ },
+ highlightNodeById: function(id) {
+ var node = this.node.find('#'+id);
+ if(node)
+ this.highlightNode(node);
+ },
+ dimNodeById: function(id) {
+ var node = this.node.find('#'+id);
+ if(node)
+ this.dimNode(node);
+ },
selectFirstNode: function() {
var firstNodeWithText = this.node.find('[wlxml-tag]').filter(function() {
return $(this).clone().children().remove().end().text().trim() !== '';
@@ -131,6 +261,13 @@ rng.modules.visualEditor = function(sandbox) {
var newRow = $(sandbox.getTemplate('metaItem')({key: key || '', value: value || ''}));
newRow.appendTo(this.metaTable);
return newRow;
+ },
+ toggleGrid: function(toggle) {
+ this.node.find('[wlxml-tag]').toggleClass('rng-hover', toggle);
+ this.gridToggled = toggle;
+ },
+ toggleTags: function(toggle) {
+
}
};
@@ -141,6 +278,7 @@ rng.modules.visualEditor = function(sandbox) {
var view = this;
this.node.find('#rng-visualEditor-sidebarButtons a').click(function(e) {
e.preventDefault();
+ e.stopPropagation();
var target = $(e.currentTarget);
if(!target.attr('data-content-id'))
return;
@@ -154,29 +292,20 @@ rng.modules.visualEditor = function(sandbox) {
mediator.getCurrentNode().attr('wlxml-'+attr, target.val());
isDirty = true;
});
+
+ view.node.on('click', '.rng-visualEditor-editPaneSurrouding a', function(e) {
+ var target = $(e.target);
+ mediator.nodeDimmedById(target.attr('data-id'));
+ mediator.nodeSelectedById(target.attr('data-id'));
+ });
- view.node.on('change', '.rng-visualEditor-editPaneSelectionForm select', function(e) {
+ view.node.on('mouseenter', '.rng-visualEditor-editPaneSurrouding a', function(e) {
var target = $(e.target);
- var selection = window.getSelection();
- if(selection.anchorNode === selection.focusNode && selection.anchorNode.nodeType === Node.TEXT_NODE) {
- var startOffset = selection.anchorOffset;
- var endOffset = selection.focusOffset;
- if(startOffset > endOffset) {
- var tmp = startOffset;
- startOffset = endOffset;
- endOffset = tmp;
- }
- var node = selection.anchorNode;
- var prefix = node.data.substr(0, startOffset);
- var suffix = node.data.substr(endOffset);
- var core = node.data.substr(startOffset, endOffset - startOffset);
- var newNode = $('' + core + '');
- $(node).replaceWith(newNode);
- newNode.before(prefix);
- newNode.after(suffix);
- mediator.nodeCreated(newNode);
- isDirty = true;
- }
+ mediator.nodeHighlightedById(target.attr('data-id'));
+ });
+ view.node.on('mouseleave', '.rng-visualEditor-editPaneSurrouding a', function(e) {
+ var target = $(e.target);
+ mediator.nodeDimmedById(target.attr('data-id'));
});
},
selectTab: function(id) {
@@ -188,12 +317,89 @@ rng.modules.visualEditor = function(sandbox) {
},
updateEditPane: function(node) {
var pane = this.node.find('#rng-visualEditor-edit');
+ var parentClass = node.parent().attr('wlxml-class');
pane.html( $(sandbox.getTemplate('editPane')({tag: node.attr('wlxml-tag'), klass: node.attr('wlxml-class')})));
+
+ var parent = node.parent('[wlxml-tag]').length ? {
+ repr: node.parent().attr('wlxml-tag') + (parentClass ? ' / ' + parentClass : ''),
+ id: node.parent().attr('id')
+ } : undefined;
+ var children = [];
+ node.children('[wlxml-tag]').each(function() {
+ var child = $(this);
+ var childClass = child.attr('wlxml-class');
+ children.push({repr: child.attr('wlxml-tag') + (childClass ? ' / ' + childClass : ''), id: child.attr('id')});
+ });
+ var naviTemplate = sandbox.getTemplate('editPaneNavigation')({parent: parent, children: children});
+ pane.find('.rng-visualEditor-editPaneSurrouding > div').html($(naviTemplate));
+ },
+ highlightNode: function(id) {
+ var pane = this.node.find('#rng-visualEditor-edit');
+ pane.find('a[data-id="'+id+'"]').addClass('rng-hover');
+ },
+ dimNode: function(id) {
+ var pane = this.node.find('#rng-visualEditor-edit');
+ pane.find('a[data-id="' +id+'"]').removeClass('rng-hover');
+ }
+ }
+
+ var toolbarView = {
+ node: view.node.find('#rng-visualEditor-toolbar'),
+ setup: function() {
+ var view = this;
+
+ view.node.find('button').click(function(e) {
+ var btn = $(e.currentTarget);
+ if(btn.attr('data-btn-type') === 'toggle') {
+ btn.toggleClass('active')
+ mediator.toolbarButtonToggled(btn.attr('data-btn'), btn.hasClass('active'));
+ }
+ if(btn.attr('data-btn-type') === 'cmd') {
+ mediator.toolbarButtonCmd(btn.attr('data-btn'), btn.attr('data-meta'));
+ }
+ });
+ },
+ getOption: function(option) {
+ return this.node.find('.rng-visualEditor-toolbarOption[data-option=' + option +']').val();
+ }
+ }
+
+ var statusBarView = {
+ node: view.node.find('#rng-visualEditor-statusbar'),
+ setup: function() {
+ var view = this;
+ view.node.on('mouseenter', 'a', function(e) {
+ var target = $(e.target);
+ mediator.nodeHighlightedById(target.attr('data-id'));
+ });
+ view.node.on('mouseleave', 'a', function(e) {
+ var target = $(e.target);
+ mediator.nodeDimmedById(target.attr('data-id'));
+ });
+ view.node.on('click', 'a', function(e) {
+ e.preventDefault();
+ mediator.nodeSelectedById($(e.target).attr('data-id'));
+ });
+ },
+
+ showNode: function(node) {
+ this.node.empty();
+ this.node.html(sandbox.getTemplate('statusBarNodeDisplay')({node: node, parents: node.parents('[wlxml-tag]')}));
+ //node.parents('[wlxml-tag]')
+ },
+
+ highlightNode: function(id) {
+ this.node.find('a[data-id="'+id+'"]').addClass('rng-hover');
+ },
+ dimNode: function(id) {
+ this.node.find('a[data-id="' +id+'"]').removeClass('rng-hover');
}
}
view.setup();
sideBarView.setup();
+ toolbarView.setup();
+ statusBarView.setup();
var mediator = {
getCurrentNode: function() {
@@ -201,11 +407,58 @@ rng.modules.visualEditor = function(sandbox) {
},
nodeCreated: function(node) {
view.selectNode(node);
-
},
nodeSelected: function(node) {
sideBarView.updateEditPane(node);
+ statusBarView.showNode(node);
+ },
+ nodeSelectedById: function(id) {
+ view.selectNodeById(id);
+ },
+ nodeHighlightedById: function(id) {
+ view.highlightNodeById(id);
+ },
+ nodeDimmedById: function(id) {
+ view.dimNodeById(id);
+ },
+ toolbarButtonToggled: function(btn, toggle) {
+ if(btn === 'grid')
+ view.toggleGrid(toggle);
+ if(btn === 'tags')
+ view.toggleTags(toggle);
+ },
+ toolbarButtonCmd: function(btn, meta) {
+ if(btn === 'new-node') {
+ var wlxmlTag = toolbarView.getOption('newTag-tag');
+ var wlxmlClass = toolbarView.getOption('newTag-class');
+ if(meta) {
+ var split = meta.split('/');
+ wlxmlTag = split[0];
+ wlxmlClass = split[1];
+ }
+ if(window.getSelection().isCollapsed)
+ view.insertNewNode(wlxmlTag, wlxmlClass);
+ else {
+ this.wrapWithNodeRequest(wlxmlTag, wlxmlClass);
+ }
+
+
+ }
+ },
+ nodeHovered: function(node) {
+ view.highlightNode(node);
+ sideBarView.highlightNode(node.attr('id'));
+ statusBarView.highlightNode(node.attr('id'));
+ },
+ nodeBlured: function(node) {
+ view.dimNode(node);
+ sideBarView.dimNode(node.attr('id'));
+ statusBarView.dimNode(node.attr('id'));
+ },
+ wrapWithNodeRequest: function(wlxmlTag, wlxmlClass) {
+ view.wrapSelectionWithNewNode(wlxmlTag, wlxmlClass);
}
+
}
var isDirty = false;
@@ -242,4 +495,6 @@ rng.modules.visualEditor = function(sandbox) {
}
}
-};
\ No newline at end of file
+};
+
+});
\ No newline at end of file