wip: putting node children into internal container
authorAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Tue, 30 Jul 2013 09:47:54 +0000 (11:47 +0200)
committerAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Mon, 5 Aug 2013 10:20:06 +0000 (12:20 +0200)
not working:
- synchronization of display style between nodeElement main node and
internal container
- clicks on canvas that don't land directly inside container (Chrome)

modules/documentCanvas/canvas/canvas.js
modules/documentCanvas/canvas/canvas.test3.js
modules/documentCanvas/canvas/documentElement.js
modules/documentCanvas/documentCanvas.less
modules/documentCanvas/nodes.less

index 0449a9a..a89a148 100644 (file)
@@ -38,17 +38,22 @@ $.extend(Canvas.prototype, {
                     tag: currentTag.prop('tagName').toLowerCase(),
                     klass: currentTag.attr('class'),
                     meta: meta,
-                    others: others
+                    others: others,
+                    rawChildren: currentTag.contents()
                 });
 
-                element.dom().append(currentTag.contents());
                 ['orig-before', 'orig-after', 'orig-begin', 'orig-end'].forEach(function(attr) {
                     element.data(attr, '');
                 });
                 return element.dom();
             });
 
-            var FIRST_CONTENT_INDEX = 1;
+            var FIRST_CONTENT_INDEX = 0;
+
+            // @@ TODO - refactor!
+            var getNode = function(element) {
+                return element.children('[document-element-content]');
+            }
 
             this.wrapper.find(':not(iframe)').addBack().contents()
                 .filter(function() {return this.nodeType === Node.TEXT_NODE})
@@ -60,8 +65,8 @@ $.extend(Canvas.prototype, {
                         text = {original: el.text(), trimmed: $.trim(el.text())},
                         elParent = el.parent(),
                         hasSpanParent = elParent.attr('wlxml-tag') === 'span',
-                        hasSpanBefore = el.prev().length > 0  && $(el.prev()[0]).attr('wlxml-tag') === 'span',
-                        hasSpanAfter = el.next().length > 0 && $(el.next()[0]).attr('wlxml-tag') === 'span';
+                        hasSpanBefore = el.prev().length > 0  && getNode($(el.prev()[0])).attr('wlxml-tag') === 'span',
+                        hasSpanAfter = el.next().length > 0 && getNode($(el.next()[0])).attr('wlxml-tag') === 'span';
 
                     if(el.parent().hasClass('canvas-widget'))
                         return true; // continue
@@ -74,10 +79,10 @@ $.extend(Canvas.prototype, {
                             target, key;
 
                         if(where === 'above') {
-                            target = prev ? $(prev) : elParent;
+                            target = prev ? $(prev) : elParent.parent();
                             key = prev ? 'orig-after' : 'orig-begin';
                         } else if(where === 'below') {
-                            target = next ? $(next) : elParent;
+                            target = next ? $(next) : elParent.parent();
                             key = next ? 'orig-before' : 'orig-end';
                         } else { throw new Object;}
 
@@ -93,7 +98,7 @@ $.extend(Canvas.prototype, {
                                     + text.trimmed
                                     + (endSpace && (hasSpanParent || hasSpanAfter) ? ' ' : '');
                     } else {
-                        if(text.trimmed.length === 0 && text.original.length > 0 && elParent.contents().length === 2)
+                        if(text.trimmed.length === 0 && text.original.length > 0 && elParent.contents().length === 1)
                             text.transformed = ' ';
                     }
 
index b649b9a..3b14b19 100644 (file)
@@ -19,13 +19,13 @@ describe('Canvas', function() {
                 expect(dom.prop('tagName')).to.equal('DIV', tagName + ' is represented as div');
             });
         });
-        it('has wlxml tag put into wlxml-tag attribute', function() {
+        it('has wlxml tag put into wlxml-tag attribute of its internal container', function() {
             var dom = canvas.fromXML('<section></section>').doc().dom();
-            expect(dom.attr('wlxml-tag')).to.equal('section');
+            expect(dom.children('[document-element-content]').attr('wlxml-tag')).to.equal('section');
         });
-        it('has wlxml class put into wlxml-class, dots replaced with dashes', function() {
+        it('has wlxml class put into wlxml-class attribute of its internal containr, dots replaced with dashes', function() {
             var dom = canvas.fromXML('<section class="some.class"></section>').doc().dom();
-            expect(dom.attr('wlxml-class')).to.equal('some-class');
+            expect(dom.children('[document-element-content]').attr('wlxml-class')).to.equal('some-class');
         });
     });
 
@@ -996,6 +996,15 @@ describe('Canvas', function() {
 
         var getSelection;
 
+        var findTextNode = function(inside, text) {
+            var nodes = inside.find(':not(iframe)').addBack().contents().filter(function() {
+                return this.nodeType === Node.TEXT_NODE && this.data === text;
+            });
+            if(nodes.length)
+                return nodes[0];
+            return null;
+        }
+
         beforeEach(function() {
             getSelection = sinon.stub(window, 'getSelection');
         });
@@ -1007,7 +1016,7 @@ describe('Canvas', function() {
         it('returns position when browser selection collapsed', function() {
             var c = canvas.fromXML('<section>Alice has a cat</section>'),
                 dom = c.doc().dom(),
-                text = $(dom.contents()[1]).contents()[0];
+                text = findTextNode(dom, 'Alice has a cat');
 
             expect(text.nodeType).to.equal(Node.TEXT_NODE, 'correct node selected');
             expect($(text).text()).to.equal('Alice has a cat');
@@ -1042,9 +1051,9 @@ describe('Canvas', function() {
             var c = canvas.fromXML('<section>Alice <span>has</span> a <span>big</span> cat</section>'),
                 dom = c.doc().dom(),
                 text = {
-                    alice: dom.contents()[1],
-                    has: $(dom.contents()[2]).contents()[1],
-                    cat: dom.contents()[5]
+                    alice: findTextNode(dom, 'Alice '),
+                    has: findTextNode(dom, 'has'),
+                    cat: findTextNode(dom, ' cat')
                 },
                 cursor = c.getCursor(),
                 aliceElement = c.getDocumentElement(text.alice),
@@ -1075,11 +1084,11 @@ describe('Canvas', function() {
             var c = canvas.fromXML('<section>Alice <span>has</span> a <span>big</span> cat</section>'),
                 dom = c.doc().dom(),
                 text = {
-                    alice: dom.contents()[1],
-                    has: $(dom.contents()[2]).contents()[1],
-                    a: dom.contents()[3],
-                    big: $(dom.contents()[4]).contents()[1],
-                    cat: dom.contents()[5]
+                    alice: findTextNode(dom, 'Alice '),
+                    has: findTextNode(dom, 'has'),
+                    a: findTextNode(dom, ' a '),
+                    big: findTextNode(dom, 'big'),
+                    cat: findTextNode(dom, ' cat'),
                 },
                 cursor = c.getCursor();
 
index 425978f..1354a84 100644 (file)
@@ -32,7 +32,7 @@ $.extend(DocumentElement, {
 
     fromHTMLElement: function(htmlElement, canvas) {
         var $element = $(htmlElement);
-        if(htmlElement.nodeType === Node.ELEMENT_NODE && $element.attr('wlxml-tag'))
+        if(htmlElement.nodeType === Node.ELEMENT_NODE && $element.attr('document-node-element') !== undefined)
             return DocumentNodeElement.fromHTMLElement(htmlElement, canvas);
         if($element.attr('wlxml-text') !== undefined || (htmlElement.nodeType === Node.TEXT_NODE && $element.parent().attr('wlxml-text') !== undefined))
             return DocumentTextElement.fromHTMLElement(htmlElement, canvas);
@@ -48,7 +48,7 @@ $.extend(DocumentElement.prototype, {
         return this.$element;
     },
     parent: function() {
-        var parents = this.$element.parents('[wlxml-tag]');
+        var parents = this.$element.parents('[document-node-element]');
         if(parents.length)
             return DocumentElement.fromHTMLElement(parents[0], this.canvas);
         return null;
@@ -114,10 +114,12 @@ var DocumentNodeElement = function(htmlElement, canvas) {
 
 $.extend(DocumentNodeElement, {
     createDOM: function(params) {
-        var dom = $('<div>')
-            .attr('wlxml-tag', params.tag);
+        var dom = $('<div document-node-element>'),
+            container = $('<div document-element-content>');
+        
+        container.attr('wlxml-tag', params.tag);
         if(params.klass)
-            dom.attr('wlxml-class', params.klass.replace(/\./g, '-'));
+            container.attr('wlxml-class', params.klass.replace(/\./g, '-'));
         if(params.meta) {
             _.keys(params.meta).forEach(function(key) {
                 dom.attr('wlxml-meta-'+key, params.meta[key]);
@@ -132,6 +134,11 @@ $.extend(DocumentNodeElement, {
         // Make sure widgets aren't navigable with arrow keys
         widgets.find('*').add(widgets).attr('tabindex', -1);
         
+        dom.append(container);
+
+        if(params.rawChildren) {
+            container.append(params.rawChildren);
+        }
         return dom;
     },
 
@@ -151,7 +158,8 @@ var manipulate = function(e, params, action) {
     } else {
         element = DocumentElement.create(params);
     }
-    e.dom()[action](element.dom());
+    var target = action === 'append' ? e._container() : e.dom();
+    target[action](element.dom());
     return element;
 };
 
@@ -159,6 +167,9 @@ DocumentNodeElement.prototype = new DocumentElement();
 
 
 $.extend(DocumentNodeElement.prototype, {
+    _container: function() {
+        return this.dom().children('[document-element-content]');
+    },
     data: function() {
         var dom = this.dom(),
             args = Array.prototype.slice.call(arguments, 0);
@@ -252,13 +263,13 @@ $.extend(DocumentNodeElement.prototype, {
             return toret;
 
 
-        var elementContent = this.dom().contents();
+        var elementContent = this._container().contents();
         var element = this;
         elementContent.each(function(idx) {
             var childElement = DocumentElement.fromHTMLElement(this, element.canvas);
             if(childElement === undefined)
                 return true;
-            if(idx === 1 && elementContent.length > 2 && elementContent[1].nodeType === Node.ELEMENT_NODE && (childElement instanceof DocumentTextElement) && $.trim($(this).text()) === '')
+            if(idx === 0 && elementContent.length > 1 && elementContent[1].nodeType === Node.ELEMENT_NODE && (childElement instanceof DocumentTextElement) && $.trim($(this).text()) === '')
                 return true;
             if(idx > 0 && childElement instanceof DocumentTextElement) {
                 if(toret[toret.length-1] instanceof DocumentNodeElement && $.trim($(this).text()) === '')
@@ -280,13 +291,13 @@ $.extend(DocumentNodeElement.prototype, {
         return toret;
     },
     getWlxmlTag: function() {
-        return this.dom().attr('wlxml-tag');
+        return this._container().attr('wlxml-tag');
     },
     setWlxmlTag: function(tag) {
-        this.dom().attr('wlxml-tag', tag);
+        this._container().attr('wlxml-tag', tag);
     },
     getWlxmlClass: function() {
-        var klass = this.dom().attr('wlxml-class');
+        var klass = this._container().attr('wlxml-class');
         if(klass)
             return klass.replace(/-/g, '.');
         return undefined;
@@ -298,9 +309,9 @@ $.extend(DocumentNodeElement.prototype, {
         }, this);
 
         if(klass)
-            this.dom().attr('wlxml-class', klass.replace(/\./g, '-'));
+            this._container().attr('wlxml-class', klass.replace(/\./g, '-'));
         else
-            this.dom().removeAttr('wlxml-class');
+            this._container().removeAttr('wlxml-class');
     },
     is: function(what) {
         if(what === 'list' && _.contains(['list.items', 'list.items.enum'], this.getWlxmlClass()))
index 8a1dc68..fdc7bab 100644 (file)
@@ -96,4 +96,9 @@
     font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
     padding: 0 5px;
     text-indent: 0;
+}
+
+[document-node-element] {
+    position:relative;
+    border: 1px solid white;
 }
\ No newline at end of file
index 9128290..1b325d6 100644 (file)
     color: blue;
 }
 
-[wlxml-tag=header] [wlxml-class=author] {
+[wlxml-tag=header] [wlxml-class=author] {
     font-size: 14px;
 }
 
-[wlxml-tag=header] [wlxml-class=title] {
+[wlxml-tag=header] [wlxml-class=title] {
     font-size:18px;
 }
 
@@ -74,7 +74,7 @@
 
 [wlxml-class="list-items"] {
 
-    > [wlxml-class="item"] {
+     [wlxml-class="item"] {
         display: list-item;
         margin-left: 10px;
         padding-left: 5px;
@@ -82,7 +82,7 @@
 }
 
 [wlxml-class="item"] {
-    [wlxml-class="list-items"] {
+    [wlxml-class="list-items"] {
         display: block;
     }
 }