wip: Experimenting with new approach - dividing visualEditor module
authorAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Wed, 5 Jun 2013 13:04:50 +0000 (15:04 +0200)
committerAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Wed, 5 Jun 2013 13:04:50 +0000 (15:04 +0200)
21 files changed:
fnpjs/layout.js [new file with mode: 0644]
fnpjs/vbox.js [new file with mode: 0644]
modules.js
modules/documentCanvas/documentCanvas.js [new file with mode: 0644]
modules/documentCanvas/template.html [new file with mode: 0644]
modules/documentCanvas/transformations.js [new file with mode: 0644]
modules/metadataEditor/metadataEditor.js [new file with mode: 0644]
modules/metadataEditor/metadataEditor.less [new file with mode: 0644]
modules/metadataEditor/templates/item.html [new file with mode: 0644]
modules/metadataEditor/templates/main.html [new file with mode: 0644]
modules/metadataEditor/transformations.js [new file with mode: 0644]
modules/nodeFamilyTree/nodeFamilyTree.js [new file with mode: 0644]
modules/nodeFamilyTree/template.html [new file with mode: 0644]
modules/nodePane/nodePane.js [new file with mode: 0644]
modules/nodePane/nodePane.less [new file with mode: 0644]
modules/nodePane/template.html [new file with mode: 0644]
modules/rng.js
modules/rng2/layout.html [new file with mode: 0644]
modules/rng2/layout.less [new file with mode: 0644]
modules/rng2/rng2.js [new file with mode: 0644]
rng.js

diff --git a/fnpjs/layout.js b/fnpjs/layout.js
new file mode 100644 (file)
index 0000000..a7c27fe
--- /dev/null
@@ -0,0 +1,18 @@
+define(['libs/jquery-1.9.1.min', 'libs/underscore-min'], function($ ,_) {\r
+    'use strict';\r
+      \r
+    var Layout = function(template) {\r
+        this.dom = $(_.template(template)());\r
+        \r
+    };\r
+    \r
+    Layout.prototype.setView = function(place, view) {\r
+        this.dom.find('[fnpjs-place=' + place + ']').append(view);\r
+    };\r
+    \r
+    Layout.prototype.getAsView = function() {\r
+        return this.dom\r
+    };\r
+    \r
+    return {Layout: Layout};\r
+});
\ No newline at end of file
diff --git a/fnpjs/vbox.js b/fnpjs/vbox.js
new file mode 100644 (file)
index 0000000..a7a5a67
--- /dev/null
@@ -0,0 +1,13 @@
+define(['libs/jquery-1.9.1.min', './layout'], function($, layout) {\r
+    \r
+    var VBox = function() {};\r
+    \r
+    VBox.prototype = new layout.Layout('<div class="fnpjs-vbox"></div>');\r
+    VBox.prototype.appendView = function(view) {\r
+        var item = $('<div>').addClass('fnpjs-vbox-item').append(view);\r
+        this.dom.append(item);\r
+    }\r
+    \r
+    return {VBox: VBox};\r
+    \r
+});
\ No newline at end of file
index 309faf1..32010a0 100644 (file)
@@ -10,5 +10,12 @@ define(function(require) {
         sourceEditor: require('modules/sourceEditor'),\r
         tabsManager: require('modules/tabsManager'),\r
         visualEditor: require('modules/visualEditor'),\r
+        \r
+        documentCanvas: require('modules/documentCanvas/documentCanvas'),\r
+        nodePane: require('modules/nodePane/nodePane'),\r
+        metadataEditor: require('modules/metadataEditor/metadataEditor'),\r
+        nodeFamilyTree: require('modules/nodeFamilyTree/nodeFamilyTree'),\r
+        \r
+        rng2: require('modules/rng2/rng2')\r
     }\r
 });
\ No newline at end of file
diff --git a/modules/documentCanvas/documentCanvas.js b/modules/documentCanvas/documentCanvas.js
new file mode 100644 (file)
index 0000000..7e7fdf0
--- /dev/null
@@ -0,0 +1,255 @@
+// Module that implements main WYSIWIG edit area\r
+\r
+define([\r
+'libs/underscore-min',\r
+'./transformations', \r
+'libs/text!./template.html'], function(_, transformations, template) {\r
+\r
+\r
+\r
+return function(sandbox) {\r
+\r
+    var view = {\r
+        node: $(_.template(template)()),\r
+        currentNode: null,\r
+        setup: function() {\r
+            var view = this;\r
+\r
+            this.node.find('#rng-module-documentCanvas-content').on('keyup', function() {\r
+                //isDirty = true;\r
+                sandbox.publish('contentChanged');\r
+            });\r
+\r
+            this.node.on('mouseover', '[wlxml-tag]', function(e) { sandbox.publish('nodeHovered', $(e.target)); });\r
+            this.node.on('mouseout', '[wlxml-tag]', function(e) { sandbox.publish('nodeBlured', $(e.target)); });\r
+            this.node.on('click', '[wlxml-tag]', function(e) {\r
+                console.log('clicked node type: '+e.target.nodeType);\r
+                view._markSelected($(e.target));\r
+            });\r
+\r
+            this.node.on('keyup', '#rng-module-documentCanvas-contentWrapper', function(e) {\r
+                var anchor = $(window.getSelection().anchorNode);\r
+                if(anchor[0].nodeType === Node.TEXT_NODE)\r
+                    anchor = anchor.parent();\r
+                if(!anchor.is('[wlxml-tag]'))\r
+                    return;\r
+                view._markSelected(anchor);\r
+            });\r
+            \r
+            this.node.on('keydown', '#rng-module-documentCanvas-contentWrapper', function(e) {\r
+                if(e.which === 13) { \r
+                    e.preventDefault();\r
+                    view.insertNewNode(null, null);\r
+                }\r
+            });\r
+            \r
+            \r
+            var observer = new MutationObserver(function(mutations) {\r
+              mutations.forEach(function(mutation) {\r
+                _.each(mutation.addedNodes, function(node) {\r
+                    node = $(node);\r
+                    node.parent().find('[wlxml-tag]').each(function() {\r
+                        tag = $(this);\r
+                        if(!tag.attr('id'))\r
+                            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);}));\r
+                    });\r
+                });\r
+              });    \r
+            });\r
+            var config = { attributes: true, childList: true, characterData: true, subtree: true };\r
+            observer.observe(this.node.find('#rng-module-documentCanvas-contentWrapper')[0], config);\r
+            \r
+            this.gridToggled = false;\r
+        },\r
+        _createNode: function(wlxmlTag, wlxmlClass) {\r
+            var toBlock = ['div', 'document', 'section', 'header'];\r
+            var htmlTag = _.contains(toBlock, wlxmlTag) ? 'div' : 'span';\r
+            var toret = $('<' + htmlTag + '>');\r
+            toret.attr('wlxml-tag', wlxmlTag);\r
+            if(wlxmlClass)\r
+                toret.attr('wlxml-class', wlxmlClass);\r
+            return toret;\r
+        },\r
+        insertNewNode: function(wlxmlTag, wlxmlClass) {\r
+            //TODO: Insert inline\r
+            var anchor = $(window.getSelection().anchorNode);\r
+            var anchorOffset = window.getSelection().anchorOffset;\r
+            if(anchor[0].nodeType === Node.TEXT_NODE)\r
+                anchor = anchor.parent();\r
+            if(anchor.text() === '') {\r
+                var todel = anchor;\r
+                anchor = anchor.parent();\r
+                todel.remove();\r
+            }\r
+            if(anchorOffset > 0 && anchorOffset < anchor.text().length) {\r
+                if(wlxmlTag === null && wlxmlClass === null) {\r
+                    return this.splitWithNewNode(anchor);\r
+                }\r
+                return this.wrapSelectionWithNewNode(wlxmlTag, wlxmlClass);\r
+            }\r
+            var newNode = this._createNode(wlxmlTag || anchor.attr('wlxml-tag'), wlxmlClass || anchor.attr('wlxml-class'));\r
+            if(anchorOffset === 0)\r
+                anchor.before(newNode)\r
+            else\r
+                anchor.after(newNode);\r
+            mediator.nodeCreated(newNode);\r
+            //isDirty = true;\r
+            sandbox.publish('contentChanged');\r
+        },\r
+        wrapSelectionWithNewNode: function(wlxmlTag, wlxmlClass) {\r
+            var selection = window.getSelection();\r
+            if(selection.anchorNode === selection.focusNode && selection.anchorNode.nodeType === Node.TEXT_NODE) {\r
+                var startOffset = selection.anchorOffset;\r
+                var endOffset = selection.focusOffset;\r
+                if(startOffset > endOffset) {\r
+                    var tmp = startOffset;\r
+                    startOffset = endOffset;\r
+                    endOffset = tmp;\r
+                }\r
+                var node = selection.anchorNode;\r
+                var prefix = node.data.substr(0, startOffset);\r
+                var suffix = node.data.substr(endOffset);\r
+                var core = node.data.substr(startOffset, endOffset - startOffset);\r
+                var newNode = this._createNode(wlxmlTag, wlxmlClass);\r
+                newNode.text(core || 'test');\r
+                $(node).replaceWith(newNode);\r
+                newNode.before(prefix);\r
+                newNode.after(suffix);\r
+                mediator.nodeCreated(newNode);\r
+                //isDirty = true;\r
+                sandbox.publish('contentChanged');\r
+            }\r
+        },\r
+        splitWithNewNode: function(node) {\r
+            var selection = window.getSelection();\r
+            if(selection.anchorNode === selection.focusNode && selection.anchorNode.nodeType === Node.TEXT_NODE) {\r
+                var startOffset = selection.anchorOffset;\r
+                var endOffset = selection.focusOffset;\r
+                if(startOffset > endOffset) {\r
+                    var tmp = startOffset;\r
+                    startOffset = endOffset;\r
+                    endOffset = tmp;\r
+                }\r
+                var anchor = selection.anchorNode;\r
+                var prefix = anchor.data.substr(0, startOffset);\r
+                var suffix = anchor.data.substr(endOffset);\r
+                var prefixNode = this._createNode(node.attr('wlxml-tag'), node.attr('wlxml-class'));\r
+                var newNode = this._createNode(node.attr('wlxml-tag'), node.attr('wlxml-class'));\r
+                var suffixNode = this._createNode(node.attr('wlxml-tag'), node.attr('wlxml-class'));\r
+                prefixNode.text(prefix);\r
+                suffixNode.text(suffix);\r
+                node.replaceWith(newNode);\r
+                newNode.before(prefixNode);\r
+                newNode.after(suffixNode);\r
+                mediator.nodeCreated(newNode);\r
+                //isDirty = true;\r
+                sandbox.publish('contentChanged');\r
+            }\r
+        },\r
+        setBody: function(HTMLTree) {\r
+            this.node.find('#rng-module-documentCanvas-content').html(HTMLTree);\r
+        },\r
+        getBody: function() {\r
+            return this.node.find('#rng-module-documentCanvas-content').html();\r
+        }, \r
+        _markSelected: function(node) {\r
+            this.dimNode(node);\r
+            \r
+            this.node.find('.rng-current').removeClass('rng-current');\r
+            \r
+            node.addClass('rng-current');\r
+\r
+            this.currentNode = node;\r
+            sandbox.publish('nodeSelected', node);\r
+            \r
+        },\r
+        selectNode: function(node) {\r
+            view._markSelected(node);\r
+            var range = document.createRange();\r
+            range.selectNodeContents(node[0]);\r
+            range.collapse(false);\r
+\r
+            var selection = document.getSelection();\r
+            selection.removeAllRanges()\r
+            selection.addRange(range);\r
+        },\r
+        selectNodeById: function(id) {\r
+            var node = this.node.find('#'+id);\r
+            if(node)\r
+                this.selectNode(node);\r
+        },\r
+        highlightNode: function(node) {\r
+            if(!this.gridToggled) {\r
+                node.addClass('rng-hover');\r
+                var label = node.attr('wlxml-tag');\r
+                if(node.attr('wlxml-class'))\r
+                    label += ' / ' + node.attr('wlxml-class');\r
+                var tag = $('<div>').addClass('rng-visualEditor-nodeHoverTag').text(label);\r
+                node.append(tag);\r
+            }\r
+        },\r
+        dimNode: function(node) {\r
+            if(!this.gridToggled) {\r
+                node.removeClass('rng-hover');\r
+                node.find('.rng-visualEditor-nodeHoverTag').remove();\r
+            }\r
+        },\r
+        highlightNodeById: function(id) {\r
+            var node = this.node.find('#'+id);\r
+            if(node)\r
+                this.highlightNode(node);\r
+        },\r
+        dimNodeById: function(id) {\r
+            var node = this.node.find('#'+id);\r
+            if(node)\r
+                this.dimNode(node);\r
+        },\r
+        selectFirstNode: function() {\r
+            var firstNodeWithText = this.node.find('[wlxml-tag]').filter(function() {\r
+                return $(this).clone().children().remove().end().text().trim() !== '';\r
+            }).first();\r
+            var node;\r
+            if(firstNodeWithText.length)\r
+                node = $(firstNodeWithText[0])\r
+            else {\r
+                node = this.node.find('[wlxml-class|="p"]')\r
+            }\r
+            this.selectNode(node);\r
+        },\r
+        toggleGrid: function(toggle) {\r
+            this.node.find('[wlxml-tag]').toggleClass('rng-hover', toggle);\r
+            this.gridToggled = toggle;\r
+        }\r
+    };\r
+    \r
+    view.setup();\r
+\r
+    /* public api */\r
+    return {\r
+        start: function() { sandbox.publish('ready'); },\r
+        getView: function() { return view.node; },\r
+        setDocument: function(xml) {\r
+            var transformed = transformations.fromXML.getDocumentDescription(xml);\r
+            view.setBody(transformed.HTMLTree);\r
+            view.selectFirstNode();\r
+            //isDirty = false;\r
+        },\r
+        modifyCurrentNode: function(attr, value) {\r
+            if(view.currentNode)\r
+                view.currentNode.attr('wlxml-'+attr, value);\r
+        },\r
+        highlightNode: function(id) {\r
+            view.highlightNodeById(id);\r
+        },\r
+        dimNode: function(id) {\r
+            view.dimNodeById(id);\r
+        },\r
+        selectNode: function(id) {\r
+            view.selectNodeById(id);\r
+        }\r
+        \r
+    }\r
+    \r
+};\r
+\r
+});
\ No newline at end of file
diff --git a/modules/documentCanvas/template.html b/modules/documentCanvas/template.html
new file mode 100644 (file)
index 0000000..b4d7dd7
--- /dev/null
@@ -0,0 +1,8 @@
+<div id="rng-module-documentCanvas">\r
+    <div id="rng-module-documentCanvas-mainArea">\r
+        <div id="rng-module-documentCanvas-contentWrapper">\r
+            <div id="rng-module-documentCanvas-content" contenteditable="true">\r
+            </div>\r
+        </div>\r
+    </div>\r
+</div>
\ No newline at end of file
diff --git a/modules/documentCanvas/transformations.js b/modules/documentCanvas/transformations.js
new file mode 100644 (file)
index 0000000..cd20d2b
--- /dev/null
@@ -0,0 +1,108 @@
+define(['libs/jquery-1.9.1.min'], function($) {\r
+\r
+    var transformations = {};\r
+\r
+    transformations.fromXML = {\r
+        getHTMLTree: function(xml) {\r
+            var inner = $(xml).clone();\r
+            var toret = $('<div></div>');\r
+            toret.append(inner);\r
+            \r
+            var toBlock = ['div', 'section', 'header'];\r
+            var toInline = ['aside', 'span'];\r
+            \r
+            var transform = function(tags, replacingTagName) {\r
+                tags.forEach(function(tagName) {\r
+                    tagName = tagName.toLowerCase();\r
+                    console.log('running ' + tagName);\r
+                    toret.find(tagName).replaceWith(function() {\r
+                        var currentTag = $(this);\r
+                        if(currentTag.attr('wlxml-tag'))\r
+                            return;\r
+                        var toret = $('<' + replacingTagName + '>').attr('wlxml-tag', tagName);\r
+                        toret.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);}));\r
+                        for(var i = 0; i < this.attributes.length; i++) {\r
+                            var attr = this.attributes.item(i);\r
+                            var value = attr.name === 'class' ? attr.value.replace(/\./g, '-') : attr.value;\r
+                            toret.attr('wlxml-' + attr.name, value)\r
+                        }\r
+                        toret.append(currentTag.contents());\r
+                        return toret;\r
+                    });\r
+                });\r
+            }\r
+            \r
+            transform(toBlock, 'div');\r
+            transform(toInline, 'span');\r
+\r
+            return toret.children();\r
+        },\r
+        getMetaData: function(xml) {\r
+            var toret = {};\r
+            $(xml).find('metadata').children().each(function() {\r
+                var node = $(this);\r
+                toret[this.nodeName.split(':')[1].toLowerCase()] = node.text();\r
+            })\r
+            return toret;\r
+        },\r
+        getDocumentDescription: function(xml) {\r
+            return {\r
+                HTMLTree: this.getHTMLTree(xml),\r
+                metadata: this.getMetaData(xml)\r
+            }\r
+        }\r
+    }\r
+\r
+    transformations.toXML = {\r
+        getXML: function(documentDescription) {\r
+            \r
+            var inner = $(documentDescription.HTMLTree);\r
+            var toret = $('<div></div>');\r
+            toret.append(inner);\r
+            \r
+            toret.find('div, span').replaceWith(function() {\r
+                var div = $(this);\r
+                var tagName = div.attr('wlxml-tag');\r
+                var toret = $('<'+tagName+'>');\r
+                                   \r
+                for(var i = 0; i < this.attributes.length; i++) {\r
+                    var attr = this.attributes.item(i);\r
+                    var split = attr.name.split('-')\r
+                    console.log(split);\r
+                    if(split[0] !== 'wlxml' || (split.length > 1 && split[1] === 'tag')) \r
+                        continue;\r
+                    var wlxmlName = split.splice(1).join('-');\r
+                    var value = wlxmlName === 'class' ? attr.value.replace(/-/g, '.') : attr.value;\r
+                    console.log(name + ': ' + value);\r
+                    toret.attr(wlxmlName, value);\r
+                }\r
+                    \r
+                toret.append(div.contents());\r
+                return toret;\r
+            });\r
+            \r
+            var meta = $('<metadata></metadata>\n');\r
+            _.each(_.keys(documentDescription.metadata), function(key) {\r
+                meta.append('\n\t<dc:'+key+'>' + documentDescription.metadata[key] + '</dc:'+key+'>');\r
+            });\r
+            meta.append('\n');\r
+            \r
+            var metadata = toret.find('metadata');\r
+            if(metadata.length === 0) {\r
+                var section = toret.find('section');\r
+                section = section.length ? $(section[0]) : null;\r
+                if(section) {\r
+                    section.prepend(meta)\r
+                }\r
+            } else {\r
+                metadata.replaceWith(meta);\r
+            }\r
+            \r
+            \r
+            return vkbeautify.xml(toret.html());\r
+        }\r
+    }\r
+\r
+    return transformations;\r
+\r
+});
\ No newline at end of file
diff --git a/modules/metadataEditor/metadataEditor.js b/modules/metadataEditor/metadataEditor.js
new file mode 100644 (file)
index 0000000..5c3e4fc
--- /dev/null
@@ -0,0 +1,90 @@
+define([\r
+'libs/jquery-1.9.1.min',\r
+'libs/underscore-min',\r
+'./transformations',\r
+'libs/text!./templates/main.html',\r
+'libs/text!./templates/item.html'\r
+], function($, _, transformations, mainTemplate, itemTemplate) {\r
+\r
+'use strict';\r
+\r
+return function(sandbox) {\r
+\r
+    \r
+    var view = {\r
+        node: $(_.template(mainTemplate)()),\r
+        setup: function() {\r
+            var metaTable = this.metaTable = this.node.find('table');\r
+            \r
+            this.node.find('.rng-module-metadataEditor-addBtn').click(function() {\r
+                var newRow = view._addMetaRow('', '');\r
+                $(newRow.find('td div')[0]).focus();\r
+                //isDirty = true;\r
+            });\r
+            \r
+            this.metaTable.on('click', '.rng-visualEditor-metaRemoveBtn', function(e) {\r
+                $(e.target).closest('tr').remove();\r
+                //isDirty = true;\r
+            });\r
+            \r
+            this.metaTable.on('keydown', '[contenteditable]', function(e) {\r
+                console.log(e.which);\r
+                if(e.which === 13) { \r
+                    if($(document.activeElement).hasClass('rng-module-metadataEditor-metaItemKey')) {\r
+                        metaTable.find('.rng-module-metadataEditor-metaItemValue').focus();\r
+                    } else {\r
+                        var input = $('<input>');\r
+                        input.appendTo('body').focus()\r
+                        view.node.find('.rng-module-metadataEditor-addBtn').focus();\r
+                        input.remove();\r
+                    }\r
+                    e.preventDefault();\r
+                }\r
+                \r
+            });\r
+        },\r
+        getMetaData: function() {\r
+            var toret = {};\r
+            this.node.find('tr').each(function() {\r
+                var tr = $(this);\r
+                var inputs = $(this).find('td [contenteditable]');\r
+                var key = $(inputs[0]).text();\r
+                var value = $(inputs[1]).text();\r
+                toret[key] = value;\r
+            });\r
+            return toret;\r
+        },\r
+        setMetadata: function(metadata) {\r
+            var view = this;\r
+            this.metaTable.find('tr').remove();\r
+            _.each(_.keys(metadata), function(key) {    \r
+                view._addMetaRow(key, metadata[key]);\r
+            });\r
+        },\r
+        _addMetaRow: function(key, value) {\r
+            var newRow = $(_.template(itemTemplate)({key: key || '', value: value || ''}));\r
+            newRow.appendTo(this.metaTable);\r
+            return newRow;\r
+        }\r
+    }\r
+    \r
+    view.setup();\r
+    \r
+    return {\r
+        start: function() {\r
+            sandbox.publish('ready');\r
+        },\r
+        setMetadata: function(xml) {\r
+            view.setMetadata(transformations.getMetadata(xml));\r
+        },\r
+        getMetadata: function() {\r
+            return view.getMetadata();\r
+        },\r
+        getView: function() {\r
+            return view.node;\r
+        }\r
+        \r
+    };\r
+}\r
+\r
+});
\ No newline at end of file
diff --git a/modules/metadataEditor/metadataEditor.less b/modules/metadataEditor/metadataEditor.less
new file mode 100644 (file)
index 0000000..8a9446c
--- /dev/null
@@ -0,0 +1,32 @@
+.rng-module-metadataEditor {\r
+\r
+    table {\r
+        margin-bottom:10px;\r
+    \r
+        [contenteditable] {\r
+            cursor: pointer;\r
+        }\r
+\r
+        li:last-child {\r
+            border-bottom: none !important;\r
+        }\r
+\r
+        tr td:nth-child(1){\r
+            width: 20%;\r
+        }\r
+\r
+        tr td:nth-child(2)  {\r
+            width:80%;\r
+        }\r
+    }\r
+\r
+    .rng-module-metadataEditor-addBtn {\r
+        float:right;\r
+        margin-right:6px;\r
+    }\r
+\r
+    .btn {\r
+        padding:3px;\r
+        line-height:10px;\r
+    }\r
+}
\ No newline at end of file
diff --git a/modules/metadataEditor/templates/item.html b/modules/metadataEditor/templates/item.html
new file mode 100644 (file)
index 0000000..ef91cab
--- /dev/null
@@ -0,0 +1,5 @@
+<tr>\r
+    <td><div contenteditable="true" class="rng-module-metadataEditor-metaItemKey"><%= key %></div></td>\r
+    <td><div contenteditable="true" class="rng-module-metadataEditor-metaItemValue"><%= value %></div></td>\r
+    <td><button class="rng-visualEditor-metaRemoveBtn btn btn-mini btn-danger">x</button></td>\r
+</tr>
\ No newline at end of file
diff --git a/modules/metadataEditor/templates/main.html b/modules/metadataEditor/templates/main.html
new file mode 100644 (file)
index 0000000..e163cbb
--- /dev/null
@@ -0,0 +1,8 @@
+<div class="rng-module-metadataEditor">\r
+    <fieldset>\r
+    <legend>Meta dane</legend>\r
+    <table class="table table-condensed table-bordered">\r
+    </table>\r
+    <button class="rng-module-metadataEditor-addBtn btn btn-mini btn-info">+</button></td>\r
+    </fieldset>\r
+</div>
\ No newline at end of file
diff --git a/modules/metadataEditor/transformations.js b/modules/metadataEditor/transformations.js
new file mode 100644 (file)
index 0000000..a6fea3f
--- /dev/null
@@ -0,0 +1,22 @@
+define(['libs/jquery-1.9.1.min'], function($) {\r
+\r
+    return {\r
+        getMetadata: function(xml) {\r
+            var toret = {};\r
+            $(xml).find('metadata').children().each(function() {\r
+                var node = $(this);\r
+                toret[this.nodeName.split(':')[1].toLowerCase()] = node.text();\r
+            })\r
+            return toret;\r
+        },\r
+        getXML: function(metadata) {\r
+            var meta = $('<metadata></metadata>\n');\r
+            _.each(_.keys(metadata), function(key) {\r
+                meta.append('\n\t<dc:'+key+'>' + metadata[key] + '</dc:'+key+'>');\r
+            });\r
+            meta.append('\n');\r
+            return vkbeautify.xml(meta.html());\r
+        }\r
+    }\r
+\r
+});
\ No newline at end of file
diff --git a/modules/nodeFamilyTree/nodeFamilyTree.js b/modules/nodeFamilyTree/nodeFamilyTree.js
new file mode 100644 (file)
index 0000000..68ab8f0
--- /dev/null
@@ -0,0 +1,62 @@
+define([\r
+'libs/jquery-1.9.1.min',\r
+'libs/underscore-min',\r
+'libs/text!./template.html'\r
+], function($, _, templateSrc) {\r
+\r
+'use strict';\r
+\r
+return function(sandbox) {\r
+    \r
+    var template = _.template(templateSrc);\r
+    \r
+    var view = {\r
+        dom: $('<div>' + template({children: null, parent: null}) + '</div>'),\r
+        setup: function() {\r
+            this.dom.on('click', 'a', function(e) {\r
+                var target = $(e.target);\r
+                sandbox.publish('nodeSelected', target.attr('data-id'));\r
+            });\r
+            \r
+            this.dom.on('mouseenter', 'a', function(e) {\r
+                var target = $(e.target);\r
+                sandbox.publish('nodeEntered', target.attr('data-id'));\r
+            });\r
+            this.dom.on('mouseleave', 'a', function(e) {\r
+                var target = $(e.target);\r
+                sandbox.publish('nodeLeft', target.attr('data-id'));\r
+            });\r
+        },\r
+        setNode: function(node) {\r
+            var parentClass = node.parent().attr('wlxml-class');\r
+            var parent = node.parent('[wlxml-tag]').length ? {\r
+                repr: node.parent().attr('wlxml-tag') + (parentClass ? ' / ' + parentClass : ''),\r
+                id: node.parent().attr('id')\r
+            } : undefined;\r
+            var children = [];\r
+            node.children('[wlxml-tag]').each(function() {\r
+                var child = $(this);\r
+                var childClass = child.attr('wlxml-class');\r
+                children.push({repr: child.attr('wlxml-tag') + (childClass ? ' / ' + childClass : ''), id: child.attr('id')});\r
+            });\r
+            this.dom.empty();\r
+            this.dom.append($(template({parent: parent, children: children})));\r
+        }\r
+    }\r
+    \r
+    view.setup();\r
+    \r
+    return {\r
+        start: function() {\r
+            sandbox.publish('ready');\r
+        },\r
+        setNode: function(node) {\r
+            view.setNode(node);\r
+        },\r
+        getView: function() {\r
+            return view.dom;\r
+        }\r
+    };\r
+};\r
+\r
+});
\ No newline at end of file
diff --git a/modules/nodeFamilyTree/template.html b/modules/nodeFamilyTree/template.html
new file mode 100644 (file)
index 0000000..252d234
--- /dev/null
@@ -0,0 +1,19 @@
+<div id="rng-module-nodeFamilyTree">\r
+    <table class="table table-bordered">\r
+        <tr>\r
+            <td>powyżej</td>\r
+            <td><% if(parent) { %><a href="#" class="rng-module-nodeFamilyTree-parent" data-id="<%= parent.id %>"><%= parent.repr %></a><% } else { %>-<% } %></td>\r
+        </tr>\r
+        <tr>\r
+            <td rowspan="0">poniżej</td>\r
+            <td>\r
+                <ul>\r
+                <% if(!children || children.length === 0) { %>-<% } else { %>\r
+                    <% children.forEach(function(child) { %>\r
+                        <li><a href="#" data-id="<%= child.id %>"><%= child.repr %></a></li>\r
+                    <% }); %>\r
+                <% } %>\r
+                </ul>\r
+            </td>\r
+        </tr>\r
+</div>
\ No newline at end of file
diff --git a/modules/nodePane/nodePane.js b/modules/nodePane/nodePane.js
new file mode 100644 (file)
index 0000000..47777b7
--- /dev/null
@@ -0,0 +1,35 @@
+define([\r
+'libs/text!./template.html',\r
+'libs/jquery-1.9.1.min',\r
+'libs/underscore-min',\r
+\r
+], function(templateSrc, $, _) {\r
+\r
+return function(sandbox) {\r
+    \r
+    view = $(_.template(templateSrc)());\r
+    \r
+    view.on('change', 'select', function(e) {\r
+        var target = $(e.target);\r
+        var attr = target.attr('class').split('-')[2].split('nodePane')[1].substr(0,3) === 'Tag' ? 'tag' : 'class';\r
+        sandbox.publish('nodeChanged', attr, target.val());\r
+    });\r
+    \r
+    return {\r
+        start: function() {\r
+            sandbox.publish('ready');\r
+        },\r
+        getView: function() {\r
+            return view;\r
+        },\r
+        setNode: function(node) {\r
+            var tag = node.attr('wlxml-tag');\r
+            var klass = node.attr('wlxml-class');\r
+            view.find('.rng-module-nodePane-tagSelect').val(tag);\r
+            view.find('.rng-module-nodePane-classSelect').val(klass);\r
+        }\r
+    }\r
+    \r
+}\r
+\r
+});
\ No newline at end of file
diff --git a/modules/nodePane/nodePane.less b/modules/nodePane/nodePane.less
new file mode 100644 (file)
index 0000000..5dfd252
--- /dev/null
@@ -0,0 +1,9 @@
+.rng-module-nodePane {\r
+    label {\r
+        width: 50px;\r
+        display: inline-block;\r
+    }\r
+    select {\r
+        width: 100px;\r
+    }\r
+}
\ No newline at end of file
diff --git a/modules/nodePane/template.html b/modules/nodePane/template.html
new file mode 100644 (file)
index 0000000..4d5caf6
--- /dev/null
@@ -0,0 +1,23 @@
+<div class="rng-module-nodePane">\r
+    <fieldset>\r
+        <legend>Current node</legend>\r
+        <div>\r
+            <label>Tag</label>\r
+            <select class="rng-module-nodePane-tagSelect">\r
+                <% var options = ['', 'section', 'header', 'div', 'span', 'aside']; %>\r
+                <% options.forEach(function(option) { %>\r
+                    <option value="<%= option %>" <% if(option === '') { %>selected<% } %>><%= option %></option>\r
+                <% }); %>\r
+            </select>\r
+        </div>\r
+        <div>\r
+            <label>Klasa</label>\r
+            <select  class="rng-module-nodePane-classSelect">\r
+                <% var options = ['', 'author', 'title', 'cite', 'cite.code', 'cite.code.xml', 'list', 'list.items', 'item', 'uri', 'p', 'footnote', 'todo', 'emp', 'emph.tech'] %>\r
+                <% options.forEach(function(option) { %>\r
+                    <option value="<%= option.replace(/\./g, '-') %>" <% if(option === '') { %>selected<% } %>><%= option %></option>\r
+                <% }); %>\r
+            </select>\r
+        </div>\r
+    </fieldset>\r
+</div>
\ No newline at end of file
index 6068d4d..0106f03 100644 (file)
@@ -32,7 +32,7 @@ return function(sandbox) {
     eventHandlers.tabsManager = {\r
         ready: function() {\r
             sandbox.getModule('skelton').setMainView(sandbox.getModule('tabsManager').getView());\r
-            _.each(['visualEditor', 'sourceEditor'], function(moduleName) {\r
+            _.each(['visualEditor', 'sourceEditor', 'rng2'], function(moduleName) {\r
                 sandbox.getModule(moduleName).start();\r
             });\r
         },\r
@@ -84,6 +84,12 @@ return function(sandbox) {
         }\r
     }\r
     \r
+    eventHandlers.rng2 = {\r
+        ready: function() {\r
+           addTab('rng2 test', 'rng2test', sandbox.getModule('rng2').getView());\r
+           \r
+        }\r
+    }\r
     \r
     /* api */\r
     \r
@@ -92,7 +98,9 @@ return function(sandbox) {
             sandbox.getModule('data').start();\r
         },\r
         handleEvent: function(moduleName, eventName, args) {\r
-            if(eventHandlers[moduleName] && eventHandlers[moduleName][eventName]) {\r
+            if('')\r
+                wysiwigHandler.handleEvent(moduleName, eventName, args);\r
+            else if(eventHandlers[moduleName] && eventHandlers[moduleName][eventName]) {\r
                 eventHandlers[moduleName][eventName].apply(eventHandlers, args);\r
             }\r
         }\r
diff --git a/modules/rng2/layout.html b/modules/rng2/layout.html
new file mode 100644 (file)
index 0000000..f98ca07
--- /dev/null
@@ -0,0 +1,6 @@
+<div>\r
+    <div class="rng-module-rng2-left" fnpjs-place="leftColumn"></div>\r
+    <div class="rng-module-rng2-right" fnpjs-place="rightColumn"></div>\r
+    <div style="clear:both;"></div>\r
+    <div class="rng-module-rng2-statusBar" fnpjs-place="statusBar"></div>\r
+</div>
\ No newline at end of file
diff --git a/modules/rng2/layout.less b/modules/rng2/layout.less
new file mode 100644 (file)
index 0000000..9b603dd
--- /dev/null
@@ -0,0 +1,53 @@
+\r
+.rng-module-rng2-left {\r
+    float: left;\r
+    width: 600px;\r
+}\r
+\r
+.rng-module-rng2-right {\r
+    float: right;\r
+    position: relative;\r
+    width: 258px;\r
+    margin-left: 50px;\r
+\r
+    border-width: 1px 1px 1px 1px;\r
+    border-style: solid;\r
+    border-color: #ddd;\r
+    padding: 5px 15px;\r
+    \r
+    p, td, label, input, select {\r
+        font-size: 11px;\r
+        line-height:13px;\r
+    }\r
+    \r
+    select {\r
+        -webkit-appearance: button;\r
+        -moz-appearance: button;\r
+        appearance: button;\r
+        height: auto;\r
+        line-height: 14px;\r
+    }\r
+    \r
+    legend {\r
+        font-size:11px;\r
+        height:30px;\r
+    }\r
+    \r
+    \r
+    .rng-view-tabs-tabBar {\r
+        position:absolute;\r
+        top:-1px;\r
+        right:-50px;\r
+        border-width: 1px 1px 1px 0px;\r
+        border-style: solid;\r
+        border-color: #ddd;\r
+        padding: 5px;\r
+        background: #ededed;\r
+    }\r
+    \r
+    label + select {\r
+        position:relative;\r
+        top: 5px;\r
+    }\r
+\r
+}
\ No newline at end of file
diff --git a/modules/rng2/rng2.js b/modules/rng2/rng2.js
new file mode 100644 (file)
index 0000000..e488e1b
--- /dev/null
@@ -0,0 +1,104 @@
+define([\r
+'fnpjs/layout',\r
+'fnpjs/vbox',\r
+'views/tabs/tabs',\r
+'libs/text!./layout.html',\r
+],\r
+function(layout, vbox, tabs, layoutTemplate) {\r
+\r
+'use strict';\r
+\r
+return function(sandbox) {    \r
+    var view = new layout.Layout(layoutTemplate);\r
+    \r
+    var sidebar = new tabs.View({stacked: true});\r
+    sidebar.render();\r
+    \r
+    var box = new vbox.VBox();\r
+    \r
+    \r
+    view.setView('rightColumn', sidebar.$el);\r
+    \r
+    var eventHandlers = {};\r
+    \r
+    eventHandlers.documentCanvas = {\r
+        ready: function() {\r
+            sandbox.getModule('documentCanvas').setDocument(sandbox.getModule('data').getDocument());\r
+            view.setView('leftColumn', sandbox.getModule('documentCanvas').getView());\r
+        },\r
+        \r
+        nodeSelected: function(node) {\r
+            sandbox.getModule('nodePane').setNode(node);\r
+            sandbox.getModule('nodeFamilyTree').setNode(node);\r
+        },\r
+        \r
+        contentChanged: function() {\r
+        \r
+        },\r
+        \r
+        nodeHovered: function(node) {\r
+            \r
+        },\r
+        \r
+        nodeBlured: function(node) {\r
+        \r
+        }\r
+    };\r
+\r
+    eventHandlers.nodePane = {\r
+        ready: function() {\r
+            //sidebar.addTab({icon: 'pencil'}, 'nodePane', sandbox.getModule('nodePane').getView());\r
+            box.appendView(sandbox.getModule('nodePane').getView());\r
+            sidebar.addTab({icon: 'pencil'}, 'edit', box.getAsView());\r
+        },\r
+        \r
+        nodeChanged: function(attr, value) {\r
+            sandbox.getModule('documentCanvas').modifyCurrentNode(attr, value);\r
+        }\r
+    };\r
+    \r
+    eventHandlers.metadataEditor = {\r
+        ready: function() {\r
+            sandbox.getModule('metadataEditor').setMetadata(sandbox.getModule('data').getDocument());\r
+            sidebar.addTab({icon: 'info-sign'}, 'metadataEditor', sandbox.getModule('metadataEditor').getView());\r
+        }\r
+    };\r
+    \r
+    eventHandlers.nodeFamilyTree = {\r
+        ready: function() {\r
+            //sidebar.addTab({icon: 'home'}, 'family', sandbox.getModule('nodeFamilyTree').getView());\r
+            box.appendView(sandbox.getModule('nodeFamilyTree').getView());\r
+        },\r
+        nodeEntered: function(id) {\r
+            sandbox.getModule('documentCanvas').highlightNode(id);\r
+        },\r
+        nodeLeft: function(id) {\r
+            sandbox.getModule('documentCanvas').dimNode(id);\r
+        },\r
+        nodeSelected: function(id) {\r
+            sandbox.getModule('documentCanvas').selectNode(id);\r
+        }\r
+    }\r
+    \r
+    \r
+    \r
+    return {\r
+        start: function() {\r
+            sandbox.getModule('documentCanvas').start();\r
+            sandbox.getModule('nodePane').start();\r
+            sandbox.getModule('metadataEditor').start();\r
+            sandbox.getModule('nodeFamilyTree').start();\r
+            \r
+            sandbox.publish('ready');\r
+        },\r
+        handleEvent: function(moduleName, eventName, args) {\r
+            if(eventHandlers[moduleName] && eventHandlers[moduleName][eventName]) {\r
+                eventHandlers[moduleName][eventName].apply(eventHandlers, args);\r
+            }\r
+        },\r
+        getView: function() { return view.getAsView(); }\r
+        \r
+    }\r
+}\r
+\r
+});
\ No newline at end of file
diff --git a/rng.js b/rng.js
index e30a633..57d5818 100644 (file)
--- a/rng.js
+++ b/rng.js
@@ -3,6 +3,7 @@ define({
     initModules: ['rng'],
     permissions: {
         'skelton': ['getDOM'],
-        'rng': ['getModule', 'handleEvents']
+        'rng': ['getModule', 'handleEvents'],
+        'rng2': ['getModule', 'handleEvents']
     }
 });
\ No newline at end of file