X-Git-Url: https://git.mdrn.pl/redakcja.git/blobdiff_plain/7a12b550f4a8366c8ace2f9c55706aba7c4b17f7..f0e275b6eeffa2bee768e42ba5528308f81af228:/platforma/static/js/views/html.js?ds=inline diff --git a/platforma/static/js/views/html.js b/platforma/static/js/views/html.js index 3696bdc8..97db6f07 100755 --- a/platforma/static/js/views/html.js +++ b/platforma/static/js/views/html.js @@ -12,20 +12,43 @@ var HTMLView = View.extend({ this.model .addObserver(this, 'data', this.modelDataChanged.bind(this)) .addObserver(this, 'state', this.modelStateChanged.bind(this)); - - $('.htmlview', this.element).html(this.model.get('data')); + + + this.$menuTemplate = $(render_template('html-view-frag-menu-template', this)); this.modelStateChanged('state', this.model.get('state')); - this.model.load(); + this.modelDataChanged('data', this.model.get('data')); + + this.model.load(); + + this.currentOpen = null; + this.currentFocused = null; + this.themeBoxes = []; }, modelDataChanged: function(property, value) { $('.htmlview', this.element).html(value); this.updatePrintLink(); + var self = this; + /* upgrade editable elements */ $("*[x-editable]").each(function() { - var e = $('
'); - e.appendTo(this); - }); + $(this).append( self.$menuTemplate.clone() ); + }); + + var doc_base = $('.htmlview .utwor', this.element); + + /* mark themes */ + $(".theme-ref").each(function() { + var id = $(this).attr('x-theme-class'); + + var end = $("span.theme-end[x-theme-class = " + id+"]"); + var begin = $("span.theme-begin[x-theme-class = " + id+"]"); + + var h = $(this).outerHeight(); + + h = Math.max(h, end.offset().top - begin.offset().top); + $(this).css('height', h); + }); }, updatePrintLink: function() { @@ -40,6 +63,7 @@ var HTMLView = View.extend({ if (value == 'synced' || value == 'dirty') { this.unfreeze(); } else if (value == 'unsynced') { + if(this.currentOpen) this.closeWithoutSave(this.currentOpen); this.freeze('Niezsynchronizowany...'); } else if (value == 'loading') { this.freeze('Åadowanie...'); @@ -86,81 +110,189 @@ var HTMLView = View.extend({ this._super(); }, - itemHover: function(event) + itemClicked: function(event) { + var self = this; + + console.log('click:', event, event.ctrlKey, event.target); var $e = $(event.target); - if( $e.attr('x-editable') == 'editable' ) { - console.log('over:', $e[0]); - $e.css({'background-color': 'grey'}); + + if($e.hasClass('annotation')) + { + if(this.currentOpen) return false; + + var $p = $e.parent(); + if(this.currentFocused) + { + console.log(this.currentFocused, $p); + if($p[0] == this.currentFocused[0]) { + console.log('unfocus of current'); + this.unfocusAnnotation(); + return false; + } + + console.log('switch unfocus'); + this.unfocusAnnotation(); + } + + this.focusAnnotation($p); + return false; } + /* + * Clicking outside of focused area doesn't unfocus by default + * - this greatly simplifies the whole click check + */ + + /* other buttons */ + if($e.hasClass('edit-button')) + this.openForEdit( this.editableFor($e) ); + + if($e.hasClass('accept-button')) + this.closeWithSave( this.editableFor($e) ); + + if($e.hasClass('reject-button')) + this.closeWithoutSave( this.editableFor($e) ); }, - itemClicked: function(event) + unfocusAnnotation: function() { - var self = this; + if(!this.currentFocused) + { + console.log('Redundant unfocus'); + return false; + } + + if(this.currentOpen + && this.currentOpen.is("*[x-annotation-box]") + && this.currentOpen.parent()[0] == this.currentFocused[0]) + { + console.log("Can't unfocus open box"); + return false; + } + + var $box = $("*[x-annotation-box]", this.currentFocused); + $box.css({'display': 'none'}); + // this.currentFocused.removeAttr('x-focused'); + // this.currentFocused.hide(); + this.currentFocused = null; + }, + + focusAnnotation: function($e) { + this.currentFocused = $e; + var $box = $("*[x-annotation-box]", $e); + $box.css({'display': 'block'}); - console.log('click:', event, event.ctrlKey, event.target); - var editableContent = null; - var $e = $(event.target); + // $e.attr('x-focused', 'focused'); + }, - if($e.hasClass('edit-button')) - this.openForEdit($e); + closeWithSave: function($e) { + var $edit = $e.data('edit-overlay'); + var newText = $('textarea', $edit).val(); + + this.model.putXMLPart($e, newText, function($e, html) { + this.renderPart($e, html); + $edit.remove(); + $e.removeAttr('x-open'); + }.bind(this) ); + this.currentOpen = null; }, - openForEdit: function($e) - { - var n = 0; + closeWithoutSave: function($e) { + var $edit = $e.data('edit-overlay'); + $edit.remove(); + $e.removeAttr('x-open'); + this.currentOpen = null; + }, + + renderPart: function($e, html) { + // exceptions aren't good, but I don't have a better idea right now + if($e.attr('x-annotation-box')) { + // replace the whole annotation + var $p = $e.parent(); + $p.html(html); + var $box = $('*[x-annotation-box]', $p); + $box.append( this.$menuTemplate.clone() ); + + if(this.currentFocused && $p[0] == this.currentFocused[0]) + { + this.currentFocused = $p; + $box.css({'display': 'block'}); + } + + return; + } + + $e.html(html); + $e.append( this.$menuTemplate.clone() ); + }, - while( ($e[0] != this.element[0]) && !($e.attr('x-editable')) - && n < 50) + editableFor: function($button) + { + var $e = $button; + var n = 0; + + while( ($e[0] != this.element[0]) && !($e.attr('x-editable')) && n < 50) { // console.log($e, $e.parent(), this.element); $e = $e.parent(); n += 1; } - + if(!$e.attr('x-editable')) - return true; + throw Exception("Click outside of editable") - var $origin = $e; - console.log("editable: ", $e); - - // start edition on this node - var $overlay = $( - '