From e459e4567cc578abd5d7e02e70a01ec9464f474d Mon Sep 17 00:00:00 2001 From: Lukasz Rekucki Date: Mon, 9 Nov 2009 15:16:01 +0100 Subject: [PATCH] Poprawki w motywach. Ukrywanie DC. Minimalna wysokosc pola tekstowego do edycji --- platforma/static/css/html.css | 34 +++-- platforma/static/js/models.js | 89 +++++++++--- platforma/static/js/views/html.js | 166 ++++++++++++++++++----- platforma/static/xsl/html2wl_client.xsl | 9 +- platforma/static/xsl/wl2html_client.xsl | 22 ++- platforma/templates/explorer/editor.html | 3 +- 6 files changed, 246 insertions(+), 77 deletions(-) diff --git a/platforma/static/css/html.css b/platforma/static/css/html.css index acbeac2c..682e905e 100755 --- a/platforma/static/css/html.css +++ b/platforma/static/css/html.css @@ -9,6 +9,10 @@ padding-left: 55px; } +.htmlview *[x-node='rdf:RDF'] { + display: none; +} + .htmlview * { position: relative; } @@ -230,18 +234,22 @@ } .htmlview .motyw { - position: absolute; - right: -8em; + /* position: absolute; */ + + float: right; + left: auto; + clear: right; + + width: 10em; - min-width: 5em; - max-width: 8em; - font-weight: normal; font-size: 10pt; font-variant: normal; text-decoration: none; - padding: 0.2em 0.2em 0.2em 0.5em; + padding: 0.2em; + + background-color: #efefef; border: 1px solid gray; border-left: 2px dotted gray; @@ -299,7 +307,7 @@ padding: 3px 5px; text-decoration: none; - z-index: 11; + z-index: 1000; } @@ -339,10 +347,10 @@ } /* focused editable element */ -/* .htmlview *[x-editable]:hover -{ - -} */ +.htmlview *[x-editable]:hover +{ + z-index: 900; +} .htmlview *[x-editable][x-open] { @@ -394,6 +402,7 @@ padding: 2px; cursor: pointer; border-bottom: 1px solid black; + } .context-menu *:last-child { @@ -402,7 +411,7 @@ } .context-menu *:hover { - background-color: orange; + background-color: orange; } /* @@ -415,6 +424,7 @@ .default-menu:hover { opacity: 1; + z-index: 5000; } .htmlview *[x-annotation-box] > .default-menu { diff --git a/platforma/static/js/models.js b/platforma/static/js/models.js index 59a285a1..dae64d8a 100755 --- a/platforma/static/js/models.js +++ b/platforma/static/js/models.js @@ -98,7 +98,7 @@ Editor.HTMLModel = Editor.Model.extend({ return false; }, - asWLML: function(element) + asWLML: function(element, inner) { console.log("Source", element); var doc = this.parser.parseFromString(this.serializer.serializeToString(element), 'text/xml'); @@ -111,30 +111,81 @@ Editor.HTMLModel = Editor.Model.extend({ } console.log("Transformed", doc, " to: ", result.documentElement); - return this.serializer.serializeToString(result.documentElement); + if(inner) { + var children = result.documentElement.childNodes; + var buf = ''; + + for(var i=0; i < children.length; i++) + buf += this.serializer.serializeToString(children.item(i)); + + return buf; + } + + return this.serializer.serializeToString(result.documentElement); + }, + + innerAsWLML: function(elem) + { + return this.asWLML(elem, true); + }, + + updateInnerWithWLML: function($element, innerML) + { + var e = $element.clone().html('')[0]; + var s = this.asWLML(e); + // hurray for dirty hacks :P + s = s.replace(/>%<\//, '>'+innerML+''); - var chunk = this.parser.parseFromString(""+text+"", "text/xml"); - - var errors = $('parsererror', chunk); + try { + var chunk = this.parser.parseFromString(""+text+"", "text/xml"); + } catch(e) { + console.log('Caught parse exception.'); + return "

Źle sformatowana zawartość:" + e.toString() + "

"; + } - // check if chunk is parsable - if(errors.length > 0) - throw {text: errors.text(), html: errors.html()}; + var parseError = chunk.getElementsByTagName('parsererror'); + console.log("Errors:", parseError); - var result = this.htmlXSL.transformToFragment(chunk, document); + if(parseError.length > 0) + { + console.log("Parse errors.") + return this.serializer.serializeToString(parseError.item(0)); + } - console.log("RESULT", this.serializer.serializeToString(result)); + console.log("Transforming to HTML"); + var result = this.htmlXSL.transformToFragment(chunk, $element[0].ownerDocument).firstChild; - if(!result) - throw "WLML->HTML transformation failed."; - - $element.replaceWith(result); - this.set('state', 'dirty'); + if(!result) { + return "Błąd aplikacji - nie udało się wygenerować nowego widoku HTML."; + } + + var errors = result.getElementsByTagName('error'); + if(errors.length > 0) + { + var errorMessage = 'Wystąpiły błędy:"; + return errorMessage; + } + + try { + $element.replaceWith(result); + this.set('state', 'dirty'); + return false; + } catch(e) { + return "Błąd podczas wstawiania tekstu: '" + e.toString() + "'"; + } }, createXSLT: function(xslt_doc) { @@ -151,7 +202,9 @@ Editor.HTMLModel = Editor.Model.extend({ if(this.wlmlXSL && this.htmlXSL && this.rawText) this.loadSuccess(); } catch(e) { - this.loadingFailed(); + console.log(e); + this.set('error', e.toString() ); + this.set('state', 'error'); } }, @@ -163,7 +216,9 @@ Editor.HTMLModel = Editor.Model.extend({ if(this.wlmlXSL && this.htmlXSL && this.rawText) this.loadSuccess(); } catch(e) { - this.loadingFailed(); + console.log(e); + this.set('error', e.toString() ); + this.set('state', 'error'); } }, diff --git a/platforma/static/js/views/html.js b/platforma/static/js/views/html.js index 0b1234ce..cc42be24 100755 --- a/platforma/static/js/views/html.js +++ b/platforma/static/js/views/html.js @@ -105,19 +105,18 @@ var HTMLView = View.extend({ this.$printLink = $('.htmlview-toolbar .html-print-link', this.element); this.$docbase = $('.htmlview', this.element); this.$addThemeButton = $('.htmlview-toolbar .html-add-motive', this.element); - - this.$debugButton = $('.htmlview-toolbar .html-serialize', this.element); + // this.$debugButton = $('.htmlview-toolbar .html-serialize', this.element); this.updatePrintLink(); this.$docbase.bind('click', this.itemClicked.bind(this)); this.$addThemeButton.click( this.addTheme.bind(this) ); - this.$debugButton.click( this.serialized.bind(this) ); + // this.$debugButton.click( this.serialized.bind(this) ); }, - serialized: function() { + /* serialized: function() { this.model.set('state', 'dirty'); console.log( this.model.serializer.serializeToString(this.model.get('data')) ); - }, + }, */ renderPart: function($e, html) { // exceptions aren't good, but I don't have a better idea right now @@ -186,15 +185,18 @@ var HTMLView = View.extend({ * - this greatly simplifies the whole click check */ - if( $e.hasClass('theme-ref') ) + if( $e.hasClass('motyw') ) { console.log($e); - this.selectTheme($e.attr('x-theme-class')); + this.selectTheme($e.attr('theme-class')); return false; } /* other buttons */ try { + if($e.hasClass('delete-button')) + this.deleteElement( this.editableFor($e) ); + if($e.hasClass('edit-button')) this.openForEdit( this.editableFor($e) ); @@ -204,7 +206,7 @@ var HTMLView = View.extend({ if($e.hasClass('reject-button')) this.closeWithoutSave( this.editableFor($e) ); } catch(e) { - messageCenter.addMessage('error', "wlsave", 'Błąd:' + e.text); + messageCenter.addMessage('error', "wlsave", 'Błąd:' + e.toString()); } return false; @@ -248,10 +250,16 @@ var HTMLView = View.extend({ closeWithSave: function($e) { var $edit = $e.data('edit-overlay'); var newText = $('textarea', $edit).val(); - - this.model.updateWithWLML($e, newText); - $edit.remove(); - this.currentOpen = null; + var errors = null; + + errors = this.model.updateInnerWithWLML($e, newText); + + if(errors) + messageCenter.addMessage('error', 'render', errors); + else { + $edit.remove(); + this.currentOpen = null; + } }, closeWithoutSave: function($e) { @@ -305,6 +313,8 @@ var HTMLView = View.extend({ // start edition on this node var $overlay = $('
'); + + h = Math.max(h, 2*parseInt($box.css('line-height'))); $overlay.css({ position: 'absolute', @@ -315,7 +325,7 @@ var HTMLView = View.extend({ }); try { - $('textarea', $overlay).val( this.model.asWLML($origin[0]) ); + $('textarea', $overlay).val( this.model.innerAsWLML($origin[0]) ); if($origin.is(".annotation-inline-box")) { @@ -347,6 +357,62 @@ var HTMLView = View.extend({ return false; }, + + deleteElement: function($editable) + { + var relatedThemes = $("*[x-node='begin'], *[x-node='end']", $editable); + + var themeMarks = relatedThemes.map(function() { + return $(".motyw[theme-class='"+$(this).attr('theme-class')+"']"); + }); + + if($editable.is("*.motyw")) + { + console.log($editable); + var selector = "[theme-class='"+$editable.attr('theme-class')+"']"; + relatedThemes = relatedThemes.add("*[x-node='begin']"+selector+", *[x-node='end']"+selector); + } + + console.log(relatedThemes, themeMarks); + + var del = confirm("Usunięcie elementu jest nieodwracalne.\n" + +" Czy na pewno chcesz usunąć ten element, wraz z zawartymi motywami ?\n"); + + if(del) { + relatedThemes.remove(); + themeMarks.remove(); + $editable.remove(); + } + }, + + // Theme related stuff + verifyThemeInsertPoint: function(node) { + + if(node.nodeType == 3) { // Text Node + node = node.parentNode; + } + + if(node.nodeType != 1) return false; + + console.log('Selection point:', node); + + node = $(node); + var xtype = node.attr('x-node'); + + if(!xtype || (xtype.search(':') >= 0) || + xtype == 'motyw' || xtype == 'begin' || xtype == 'end') + return false; + + // this is hopefully redundant + //if(! node.is('*.utwor *') ) + // return false; + + // don't allow themes inside annotations + if( node.is('*[x-annotation-box] *') ) + return false; + + return true; + }, addTheme: function() { @@ -355,19 +421,37 @@ var HTMLView = View.extend({ console.log("Range count:", n); - if(n == 0) + if(n == 0) { window.alert("Nie zaznaczono żadnego obszaru"); + return false; + } // for now allow only 1 range - if(n > 1) + if(n > 1) { window.alert("Zaznacz jeden obszar"); - + return false; + } // from this point, we will assume that the ranges are disjoint for(var i=0; i < n; i++) { var range = selection.getRangeAt(i); console.log(i, range.startContainer, range.endContainer); + + // verify if the start/end points make even sense - + // they must be inside a x-node (otherwise they will be discarded) + // and the x-node must be a main text + if(! this.verifyThemeInsertPoint(range.startContainer) ) { + window.alert("Motyw nie może się zaczynać w tym miejscu."); + return false; + } + + if(! this.verifyThemeInsertPoint(range.endContainer) ) { + window.alert("Motyw nie może się kończyć w tym miejscu."); + return false; + } + + var date = (new Date()).getTime(); var random = Math.floor(4000000000*Math.random()); var id = (''+date) + '-' + (''+random); @@ -378,38 +462,52 @@ var HTMLView = View.extend({ spoint.setStart(range.startContainer, range.startOffset); epoint.setStart(range.endContainer, range.endOffset); - // insert theme-ref - - var elem = $('Nowy motyw'); - elem.attr('x-attr-qname-'+id, 'id'); - elem.attr('x-attr-value-'+id, 'm'+id); - spoint.insertNode(elem[0]); + var mtag, btag, etag, errors; + + // insert theme-ref + mtag = $(''); + spoint.insertNode(mtag[0]); + errors = this.model.updateWithWLML(mtag, 'Nowy Motyw'); + if(errors) { + messageCenter.addMessage('error', null, 'Błąd przy dodawaniu motywu :' + errors); + return false; + } // insert theme-begin - elem = $(''); - elem.attr('x-attr-qname-'+id, 'id'); - elem.attr('x-attr-value-'+id, 'b'+id); - spoint.insertNode(elem[0]); + btag = $(''); + spoint.insertNode(btag[0]); + errors = this.model.updateWithWLML(btag, ''); + if(errors) { + mtag.remove(); + messageCenter.addMessage('error', null, 'Błąd przy dodawaniu motywu :' + errors); + return false; + } + - elem = $(''); - elem.attr('x-attr-qname-'+id, 'id'); - elem.attr('x-attr-value-'+id, 'e'+id); - epoint.insertNode(elem[0]); + etag = $(''); + epoint.insertNode(etag[0]); + result = this.model.updateWithWLML(etag, ''); + if(errors) { + btag.remove(); + mtag.remove(); + messageCenter.addMessage('error', null, 'Błąd przy dodawaniu motywu :' + errors); + return false; + } } - //selection.removeAllRanges(); + selection.removeAllRanges(); }, selectTheme: function(themeId) { - var selection = document.getSelection(); + var selection = window.getSelection(); // remove current selection selection.removeAllRanges(); var range = document.createRange(); - var s = $('#m'+themeId)[0]; - var e = $('#e'+themeId)[0]; + var s = $(".motyw[theme-class='"+themeId+"']")[0]; + var e = $(".end[theme-class='"+themeId+"']")[0]; console.log('Selecting range:', themeId, range, s, e); if(s && e) { diff --git a/platforma/static/xsl/html2wl_client.xsl b/platforma/static/xsl/html2wl_client.xsl index 726a404a..3ee2f9ef 100755 --- a/platforma/static/xsl/html2wl_client.xsl +++ b/platforma/static/xsl/html2wl_client.xsl @@ -7,12 +7,11 @@ xmlns:dc="http://purl.org/dc/elements/1.1/" > - + - @@ -86,8 +85,8 @@ / - - - + + + \ No newline at end of file diff --git a/platforma/static/xsl/wl2html_client.xsl b/platforma/static/xsl/wl2html_client.xsl index 234ea5cf..72ac7771 100755 --- a/platforma/static/xsl/wl2html_client.xsl +++ b/platforma/static/xsl/wl2html_client.xsl @@ -5,7 +5,7 @@ - + @@ -660,6 +660,9 @@ + + + @@ -673,6 +676,9 @@ + + + @@ -680,7 +686,10 @@ - + + + + @@ -715,18 +724,17 @@ - - Unmatched tag - + Unknown tag: Edit + Delete - OK - Cancel + Accept + Close diff --git a/platforma/templates/explorer/editor.html b/platforma/templates/explorer/editor.html index 2e8a6b4b..a3ee0450 100755 --- a/platforma/templates/explorer/editor.html +++ b/platforma/templates/explorer/editor.html @@ -64,8 +64,7 @@