From: zuber Date: Sat, 26 Sep 2009 12:16:19 +0000 (+0200) Subject: Merge branch 'master' into view-refactor X-Git-Url: https://git.mdrn.pl/redakcja.git/commitdiff_plain/80a2c67a898b06c9c28bda89d7aa012676c2a23a?hp=15f3b1ec20246e7935176a743cc95b4863e6ce24 Merge branch 'master' into view-refactor --- diff --git a/project/static/css/master.css b/project/static/css/master.css index b413b2c4..6ba367b0 100644 --- a/project/static/css/master.css +++ b/project/static/css/master.css @@ -35,7 +35,6 @@ body { top: 2.4em; left: 0px; right: 0px; bottom: 0px; overflow: auto; background-color: white; - padding: 0.2em 1em; } ul { @@ -107,8 +106,8 @@ label { /* ========== */ #panels { - position: absolute; - bottom: 0px; left: 0px; right: 0px; top: 0px; + height: 100%; + width: 100%; } .panel-wrap { @@ -343,13 +342,60 @@ text#commit-dialog-message { margin: 0.5em; } -.CodeMirror-line-numbers -{ - text-align: right; - padding-top: 0.4em; - padding-right: 2px; - width: 28px; - font-size: 10pt; - background: black; - color: white; -} \ No newline at end of file +/* ======= */ +/* = New = */ +/* ======= */ +#splitview { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} + +.splitview-splitbar { + width: 5px; + border-left: 1px solid #999; + border-right: 1px solid #999; + height: 100%; + background-color: #CCC; + z-index: 100; +} + +.splitview-overlay { + z-index: 90; + background: #FFF; + opacity: 0.5; +} + +.panel-container { + height: 100%; + position: relative; +} + +.content-view { + position: absolute; + top: 20px; + right: 0; + bottom: 0; + left: 0; + overflow: none; +} + +.xmlview { + height: 100%; +} + +.view-overlay { + z-index: 1000; + background: #FFF; + opacity: 0.8; + text-align: center; + text-valign: center; +} + +.view-overlay p { + display: block; + position: relative; + top: auto; + bottom: auto; + height: 40px; diff --git a/project/static/js/app.js b/project/static/js/app.js new file mode 100644 index 00000000..6e6f0f80 --- /dev/null +++ b/project/static/js/app.js @@ -0,0 +1,285 @@ +/*global Class*/ +var editor; +var panel_hooks; + + +(function(){ + // Classes + var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; + this.Class = function(){}; + Class.extend = function(prop) { + var _super = this.prototype; + initializing = true; + var prototype = new this(); + initializing = false; + for (var name in prop) { + prototype[name] = typeof prop[name] == "function" && + typeof _super[name] == "function" && fnTest.test(prop[name]) ? + (function(name, fn){ + return function() { + var tmp = this._super; + this._super = _super[name]; + var ret = fn.apply(this, arguments); + this._super = tmp; + return ret; + }; + })(name, prop[name]) : + prop[name]; + } + function Class() { + if ( !initializing && this.init ) + this.init.apply(this, arguments); + } + Class.prototype = prototype; + Class.constructor = Class; + Class.extend = arguments.callee; + return Class; + }; + + // Templates + var cache = {}; + + this.render_template = function render_template(str, data){ + // Figure out if we're getting a template, or if we need to + // load the template - and be sure to cache the result. + var fn = !/^[\d\s-_]/.test(str) ? + cache[str] = cache[str] || + render_template(document.getElementById(str).innerHTML) : + + // Generate a reusable function that will serve as a template + // generator (and which will be cached). + new Function("obj", + "var p=[],print=function(){p.push.apply(p,arguments);};" + + + // Introduce the data as local variables using with(){} + "with(obj){p.push('" + + + // Convert the template into pure JavaScript + str + .replace(/[\r\t\n]/g, " ") + .split("<%").join("\t") + .replace(/((^|%>)[^\t]*)'/g, "$1\r") + .replace(/\t=(.*?)%>/g, "',$1,'") + .split("\t").join("');") + .split("%>").join("p.push('") + .split("\r").join("\\'") + + "');}return p.join('');"); + + // Provide some basic currying to the user + return data ? fn( data ) : fn; + }; +})(); + +(function() { + var slice = Array.prototype.slice; + + function update(array, args) { + var arrayLength = array.length, length = args.length; + while (length--) array[arrayLength + length] = args[length]; + return array; + }; + + function merge(array, args) { + array = slice.call(array, 0); + return update(array, args); + }; + + Function.prototype.bind = function(context) { + if (arguments.length < 2 && typeof arguments[0] === 'undefined') { + return this; + } + var __method = this; + var args = slice.call(arguments, 1); + return function() { + var a = merge(args, arguments); + return __method.apply(context, a); + } + } + +})(); + +var panels = []; + +var documentsUrl = '/api/documents/'; + + +var Model = Class.extend({ + observers: {}, + + init: function() {}, + + signal: function(event, data) { + console.log('signal', this, event, data); + if (this.observers[event]) { + for (key in this.observers[event]) { + this.observers[event][key](event, data); + } + }; + return this; + }, + + addObserver: function(observer, event, callback) { + if (!this.observers[event]) { + this.observers[event] = {}; + } + this.observers[event][observer.id] = callback; + return this; + }, + + removeObserver: function(observer, event) { + if (!event) { + for (e in this.observers) { + this.removeObserver(observer, e); + } + } else { + delete this.observers[event][observer.id]; + } + return this; + } +}); + + +var XMLModel = Model.extend({ + parent: null, + data: '', + serverURL: null, + needsReload: false, + + init: function(parent, serverURL) { + this.parent = parent; + this.serverURL = serverURL; + }, + + getData: function() { + if (!this.data) { + this.reload(); + } + return this.data; + }, + + setData: function(data) { + this.data = data; + this.dataChanged(); + }, + + reload: function() { + $.ajax({ + url: this.serverURL, + dataType: 'text', + success: this.reloadSucceeded.bind(this) + }); + }, + + reloadSucceeded: function(data) { + this.data = data; + this.signal('reloaded'); + }, + + dataChanged: function() { + this.parent.modelChanged('xml'); + this.signal('dataChanged'); + }, + + needsReload: function() { + this.needsReload = true; + this.signal('needsReload'); + } +}) + + + +var HTMLModel = Model.extend({ + parent: null, + data: '', + serverURL: null, + needsReload: false, + + init: function(parent, serverURL) { + this.parent = parent; + this.serverURL = serverURL; + }, + + getData: function() { + if (!this.data) { + this.reload(); + } + return this.data; + }, + + setData: function(data) { + console.log('setData'); + if (this.data != data) { + this.data = data; + this.dataChanged(); + } + }, + + reload: function() { + $.ajax({ + url: this.serverURL, + dataType: 'text', + success: this.reloadSucceeded.bind(this) + }); + }, + + reloadSucceeded: function(data) { + this.data = data; + this.signal('reloaded'); + }, + + dataChanged: function() { + this.parent.modelChanged('html'); + }, + + needsReload: function() { + this.needsReload = true; + this.signal('needsReload'); + } +}) + + +var DocumentModel = Model.extend({ + data: null, // name, text_url, latest_rev, latest_shared_rev, parts_url, dc_url, size + xml: null, + html: null, + contentModels: {}, + + init: function() { + this.getData(); + }, + + getData: function() { + console.log('DocumentModel#getData'); + $.ajax({ + cache: false, + url: documentsUrl + fileId, + dataType: 'json', + success: this.successfulGetData.bind(this) + }); + }, + + successfulGetData: function(data) { + console.log('DocumentModel#successfulGetData:', data); + this.data = data; + this.contentModels = { + 'xml': new XMLModel(this, data.text_url) + }; + }, + + modelChanged: function(contentModelName) { + for (modelName in this.contentModels) { + if (!(modelName == contentModelName)) { + this.contentModels[modelName].needsReload(); + } + } + } +}); + +var leftPanelView, rightPanelContainer, doc; + +$(function() { + doc = new DocumentModel(); + var splitView = new SplitView('#splitview', doc); + leftPanelView = new PanelContainerView('#left-panel-container', doc); + rightPanelContainer = new PanelContainerView('#right-panel-container', doc); +}); diff --git a/project/static/js/editor.js b/project/static/js/editor.js index 79b7fa90..6918f9e5 100644 --- a/project/static/js/editor.js +++ b/project/static/js/editor.js @@ -320,30 +320,30 @@ Editor.prototype.loadConfig = function() { }; Editor.prototype.loadPanelOptions = function() { - var self = this; - var totalWidth = 0; - - $('.panel-wrap', self.rootDiv).each(function(index) { - var panelWidth = self.fileOptions.panels[index].ratio * self.rootDiv.width(); - if ($(this).hasClass('last-panel')) { - $(this).css({ - left: totalWidth, - right: 0 - }); - } else { - $(this).css({ - left: totalWidth, - width: panelWidth - }); - totalWidth += panelWidth; - } - $.log('panel:', this, $(this).css('left')); - $('.panel-toolbar option', this).each(function() { - if ($(this).attr('p:panel-name') == self.fileOptions.panels[index].name) { - $(this).parent('select').val($(this).attr('value')); - } - }); - }); + // var self = this; + // var totalWidth = 0; + // + // $('.panel-wrap', self.rootDiv).each(function(index) { + // var panelWidth = self.fileOptions.panels[index].ratio * self.rootDiv.width(); + // if ($(this).hasClass('last-panel')) { + // $(this).css({ + // left: totalWidth, + // right: 0 + // }); + // } else { + // $(this).css({ + // left: totalWidth, + // width: panelWidth + // }); + // totalWidth += panelWidth; + // } + // $.log('panel:', this, $(this).css('left')); + // $('.panel-toolbar option', this).each(function() { + // if ($(this).attr('p:panel-name') == self.fileOptions.panels[index].name) { + // $(this).parent('select').val($(this).attr('value')); + // } + // }); + // }); }; Editor.prototype.savePanelOptions = function() { diff --git a/project/static/js/editor.ui.js b/project/static/js/editor.ui.js index f66d977b..c8d47f66 100755 --- a/project/static/js/editor.ui.js +++ b/project/static/js/editor.ui.js @@ -2,116 +2,116 @@ * UI related Editor methods */ Editor.prototype.setupUI = function() { - // set up the UI visually and attach callbacks +// // set up the UI visually and attach callbacks var self = this; - - var resize_start = function(event, mydata) { - $(document).bind('mousemove', mydata, resize_changed). - bind('mouseup', mydata, resize_stop); - - $('.panel-overlay', mydata.root).css('display', 'block'); - return false; - } - var resize_changed = function(event) { - var old_width = parseInt(event.data.overlay.css('width')); - var delta = event.pageX + event.data.hotspot_x - old_width; - - if(old_width + delta < 12) delta = 12 - old_width; - if(old_width + delta > $(window).width()) - delta = $(window).width() - old_width; - - event.data.overlay.css({ - 'width': old_width + delta - }); - - if(event.data.overlay.next) { - var left = parseInt(event.data.overlay.next.css('left')); - event.data.overlay.next.css('left', left+delta); - } - - return false; - }; - - var resize_stop = function(event) { - $(document).unbind('mousemove', resize_changed).unbind('mouseup', resize_stop); - // $('.panel-content', event.data.root).css('display', 'block'); - var overlays = $('.panel-content-overlay', event.data.root); - $('.panel-content-overlay', event.data.root).each(function(i) { - if( $(this).data('panel').hasClass('last-panel') ) - $(this).data('panel').css({ - 'left': $(this).css('left'), - 'right': $(this).css('right') - }); - else - $(this).data('panel').css({ - 'left': $(this).css('left'), - 'width': $(this).css('width') - }); - }); - $('.panel-overlay', event.data.root).css('display', 'none'); - $(event.data.root).trigger('stopResize'); - }; - - /* - * Prepare panels (overlays & stuff) - */ - /* create an overlay */ - var panel_root = self.rootDiv; - var overlay_root = $("
"); - panel_root.append(overlay_root); - - var prev = null; - - $('*.panel-wrap', panel_root).each( function() - { - var panel = $(this); - var handle = $('.panel-slider', panel); - var overlay = $("
 
"); - overlay_root.append(overlay); - overlay.data('panel', panel); - overlay.data('next', null); - - if (prev) prev.next = overlay; - - if( panel.hasClass('last-panel') ) - { - overlay.css({ - 'left': panel.css('left'), - 'right': panel.css('right') - }); - } - else { - overlay.css({ - 'left': panel.css('left'), - 'width': panel.css('width') - }); - // $.log('Has handle: ' + panel.attr('id')); - overlay.append(handle.clone()); - /* attach the trigger */ - handle.mousedown(function(event) { - var touch_data = { - root: panel_root, - overlay: overlay, - hotspot_x: event.pageX - handle.position().left - }; - - $(this).trigger('hpanel:panel-resize-start', touch_data); - return false; - }); - $('.panel-content', panel).css('right', - (handle.outerWidth() || 10) + 'px'); - $('.panel-content-overlay', panel).css('right', - (handle.outerWidth() || 10) + 'px'); - }; - - prev = overlay; - }); - - panel_root.bind('hpanel:panel-resize-start', resize_start); - self.rootDiv.bind('stopResize', function() { - self.savePanelOptions(); - }); - +// +// var resize_start = function(event, mydata) { +// $(document).bind('mousemove', mydata, resize_changed). +// bind('mouseup', mydata, resize_stop); +// +// $('.panel-overlay', mydata.root).css('display', 'block'); +// return false; +// } +// var resize_changed = function(event) { +// var old_width = parseInt(event.data.overlay.css('width')); +// var delta = event.pageX + event.data.hotspot_x - old_width; +// +// if(old_width + delta < 12) delta = 12 - old_width; +// if(old_width + delta > $(window).width()) +// delta = $(window).width() - old_width; +// +// event.data.overlay.css({ +// 'width': old_width + delta +// }); +// +// if(event.data.overlay.next) { +// var left = parseInt(event.data.overlay.next.css('left')); +// event.data.overlay.next.css('left', left+delta); +// } +// +// return false; +// }; +// +// var resize_stop = function(event) { +// $(document).unbind('mousemove', resize_changed).unbind('mouseup', resize_stop); +// // $('.panel-content', event.data.root).css('display', 'block'); +// var overlays = $('.panel-content-overlay', event.data.root); +// $('.panel-content-overlay', event.data.root).each(function(i) { +// if( $(this).data('panel').hasClass('last-panel') ) +// $(this).data('panel').css({ +// 'left': $(this).css('left'), +// 'right': $(this).css('right') +// }); +// else +// $(this).data('panel').css({ +// 'left': $(this).css('left'), +// 'width': $(this).css('width') +// }); +// }); +// $('.panel-overlay', event.data.root).css('display', 'none'); +// $(event.data.root).trigger('stopResize'); +// }; +// +// /* +// * Prepare panels (overlays & stuff) +// */ +// /* create an overlay */ +// var panel_root = self.rootDiv; +// var overlay_root = $("
"); +// panel_root.append(overlay_root); +// +// var prev = null; +// +// $('*.panel-wrap', panel_root).each( function() +// { +// var panel = $(this); +// var handle = $('.panel-slider', panel); +// var overlay = $("
 
"); +// overlay_root.append(overlay); +// overlay.data('panel', panel); +// overlay.data('next', null); +// +// if (prev) prev.next = overlay; +// +// if( panel.hasClass('last-panel') ) +// { +// overlay.css({ +// 'left': panel.css('left'), +// 'right': panel.css('right') +// }); +// } +// else { +// overlay.css({ +// 'left': panel.css('left'), +// 'width': panel.css('width') +// }); +// // $.log('Has handle: ' + panel.attr('id')); +// overlay.append(handle.clone()); +// /* attach the trigger */ +// handle.mousedown(function(event) { +// var touch_data = { +// root: panel_root, +// overlay: overlay, +// hotspot_x: event.pageX - handle.position().left +// }; +// +// $(this).trigger('hpanel:panel-resize-start', touch_data); +// return false; +// }); +// $('.panel-content', panel).css('right', +// (handle.outerWidth() || 10) + 'px'); +// $('.panel-content-overlay', panel).css('right', +// (handle.outerWidth() || 10) + 'px'); +// }; +// +// prev = overlay; +// }); +// +// panel_root.bind('hpanel:panel-resize-start', resize_start); +// self.rootDiv.bind('stopResize', function() { +// self.savePanelOptions(); +// }); +// /* * Connect panel actions */ @@ -187,8 +187,6 @@ Editor.prototype.setupUI = function() { onShow: $.fbind(self, self.loadSplitDialog) }). jqmAddClose('button.dialog-close-button'); - -// $('#split-dialog'). } Editor.prototype.loadRelatedIssues = function(hash) diff --git a/project/static/js/views/html.js b/project/static/js/views/html.js new file mode 100644 index 00000000..87f2ab7b --- /dev/null +++ b/project/static/js/views/html.js @@ -0,0 +1,17 @@ +/*global View render_template panels */ +var HTMLView = View.extend({ + element: null, + model: null, + template: 'html-view-template', + + init: function(element, model, template) { + this._super(element, model, template); + }, + + dispose: function() { + this._super(); + } +}); + +// Register view +panels['html'] = HTMLView; \ No newline at end of file diff --git a/project/static/js/views/panel_container.js b/project/static/js/views/panel_container.js new file mode 100644 index 00000000..e4950ba8 --- /dev/null +++ b/project/static/js/views/panel_container.js @@ -0,0 +1,34 @@ +/*globals View render_template panels*/ + +var PanelContainerView = View.extend({ + element: null, + model: null, + template: 'panel-container-view-template', + contentView: null, + + init: function(element, model, template) { + this.element = $(element); + this.model = model; + this.template = template || this.template; + + this.element.html(render_template(this.template, {panels: panels})); + $('select', this.element.get(0)).bind('change.panel-container-view', this.selectChanged.bind(this)); + }, + + selectChanged: function(event) { + var value = $('select', this.element.get(0)).val(); + var klass = panels[value]; + if (this.contentView) { + this.contentView.dispose(); + this.contentView = null; + } + this.contentView = new klass($('.content-view', + this.element.get(0)), this.model.contentModels[value]); + }, + + dispose: function() { + $('select', this.element.get(0)).unbind('change.panel-container-view'); + this._super(); + } +}); + diff --git a/project/static/js/views/split.js b/project/static/js/views/split.js new file mode 100644 index 00000000..cc0d361f --- /dev/null +++ b/project/static/js/views/split.js @@ -0,0 +1,106 @@ +/*globals View*/ + +// Split view inspired by jQuery Splitter Plugin http://methvin.com/splitter/ +var SplitView = View.extend({ + splitbarClass: 'splitview-splitbar', + activeClass: 'splitview-active', + overlayClass: 'splitview-overlay', + element: null, + model: null, + zombie: null, + leftViewOffset: 0, + + // Cache + _splitbarWidth: 0, + + init: function(element, model) { + this.element = $(element).css('position', 'relative'); + this.model = model; + this.views = $(">*", this.element[0]).css({ + position: 'absolute', // positioned inside splitter container + 'z-index': 1, // splitbar is positioned above + '-moz-outline-style': 'none', // don't show dotted outline + overflow: 'auto' + }); + + this.leftView = $(this.views[0]); + this.rightView = $(this.views[1]); + this.splitbar = $(this.views[2] || '
') + .insertAfter(this.leftView) + .css({ + position: 'absolute', + 'user-select': 'none', + '-webkit-user-select': 'none', + '-khtml-user-select': 'none', + '-moz-user-select': 'none', + 'z-index': 100 + }) + .attr('unselectable', 'on') + .addClass(this.splitbarClass) + .bind('mousedown.splitview', this.beginResize.bind(this)); + + this._splitbarWidth = this.splitbar.outerWidth(); + + // Solomon's algorithm ;-) + this.resplit(this.element.width() / 2); + }, + + beginResize: function(event) { + this.zombie = this.zombie || this.splitbar.clone(false).insertAfter(this.leftView); + this.overlay = this.overlay || $('
').addClass(this.overlayClass).css({ + position: 'absolute', + width: this.element.width(), + height: this.element.height(), + top: this.element.position().top, + left: this.element.position().left + }).appendTo(this.element); + this.views.css("-webkit-user-select", "none"); // Safari selects A/B text on a move + this.splitbar.addClass(this.activeClass); + this.leftViewOffset = this.leftView[0].offsetWidth - event.pageX; + + $(document) + .bind('mousemove.splitview', this.resizeChanged.bind(this)) + .bind('mouseup.splitview', this.endResize.bind(this)); + }, + + resizeChanged: function(event) { + var newPosition = event.pageX + this.leftViewOffset; + newPosition = Math.max(0, Math.min(newPosition, this.element.width() - this._splitbarWidth)); + this.splitbar.css('left', newPosition); + }, + + endResize: function(event) { + var newPosition = event.pageX + this.leftViewOffset; + this.zombie.remove(); + this.zombie = null; + this.overlay.remove(); + this.overlay = null; + this.resplit(newPosition); + + $(document) + .unbind('mousemove.splitview') + .unbind('mouseup.splitview'); + }, + + resplit: function(newPosition) { + newPosition = Math.max(0, Math.min(newPosition, this.element.width() - this._splitbarWidth)); + this.splitbar.css('left', newPosition); + this.leftView.css({ + left: 0, + width: newPosition + }); + this.rightView.css({ + left: newPosition + this._splitbarWidth, + width: this.element.width() - newPosition - this._splitbarWidth + }); + if (!$.browser.msie) { + this.views.trigger("resize"); + } + }, + + dispose: function() { + this.splitter.unbind('mousedown.splitview'); + this._super(); + } +}); + diff --git a/project/static/js/views/view.js b/project/static/js/views/view.js new file mode 100644 index 00000000..498341e7 --- /dev/null +++ b/project/static/js/views/view.js @@ -0,0 +1,65 @@ +/*globals Class render_template*/ +var View = Class.extend({ + element: null, + model: null, + template: null, + overlayClass: 'view-overlay', + overlay: null, + id: null, + + init: function(element, model, template) { + this.element = $(element); + this.model = model; + this.template = template || this.template; + + if (this.template) { + this.element.html(render_template(this.template, {})); + } + + View.lastId = View.lastId + 1; + this.id = 'view-' + View.lastId; + }, + + // Identyczność + hash: function() { + + }, + + frozen: function() { + return !!this.overlay; + }, + + freeze: function(message) { + this.overlay = this.overlay + || $('
' + message + '
') + .addClass(this.overlayClass) + .css({ + position: 'absolute', + width: this.element.width(), + height: this.element.height(), + top: this.element.position().top, + left: this.element.position().left + }) + .appendTo(this.element.parent()); + + this.overlay.children('div').css({ + position: 'relative', + top: this.overlay.height() / 2 - 20 + }); + }, + + unfreeze: function() { + if (this.frozen()) { + this.overlay.remove(); + this.overlay = null; + } + }, + + dispose: function() { + this.unfreeze(); + this.element.contents().remove(); + } +}); + + +View.lastId = 0; diff --git a/project/static/js/views/xml.js b/project/static/js/views/xml.js new file mode 100644 index 00000000..54abf164 --- /dev/null +++ b/project/static/js/views/xml.js @@ -0,0 +1,62 @@ +/*global View CodeMirror render_template panels */ +var XMLView = View.extend({ + element: null, + model: null, + template: 'xml-view-template', + editor: null, + + init: function(element, model, template) { + this._super(element, model, template); + + this.freeze('Ładowanie edytora...'); + this.editor = new CodeMirror($('.xmlview', this.element).get(0), { + parserfile: 'parsexml.js', + path: "/static/js/lib/codemirror/", + stylesheet: "/static/css/xmlcolors.css", + parserConfig: {useHTMLKludges: false}, + textWrapping: false, + tabMode: 'spaces', + indentUnit: 0, + onChange: this.changed.bind(this), + initCallback: this.editorDidLoad.bind(this) + }); + }, + + changed: function() { + this.model.setData(this.editor.getCode()); + }, + + editorDidLoad: function(editor) { + editor.setCode('Ładowanie edytora...'); + $(editor.frame).css({width: '100%', height: '100%'}); + this.editor.setCode(this.model.getData()); + this.unfreeze(); + this.model + .addObserver(this, 'reloaded', function() { + this.editor.setCode(this.model.getData()); this.unfreeze(); }.bind(this)) + .addObserver(this, 'needsReload', function() { + this.freeze('Niezsynchronizowany'); }.bind(this)) + .addObserver(this, 'dataChanged', this.textDidChange.bind(this)); + + // editor.grabKeys( + // $.fbind(self, self.hotkeyPressed), + // $.fbind(self, self.isHotkey) + // ); + }, + + textDidChange: function(event) { + console.log('textDidChange!'); + if (this.editor.getCode() != this.model.getData()) { + this.editor.setCode(this.model.getData()); + } + }, + + dispose: function() { + this.model.removeObserver(this); + $(this.editor.frame).remove(); + this._super(); + } +}); + +// Register view +panels['xml'] = XMLView; diff --git a/project/templates/explorer/editor.html b/project/templates/explorer/editor.html index 22a60f60..d3c51966 100644 --- a/project/templates/explorer/editor.html +++ b/project/templates/explorer/editor.html @@ -12,9 +12,36 @@ - + + {# App and views #} + + + + + + + + + {# JavaScript templates #} + + + + + {% endblock extrahead %} {% block extrabody %} @@ -57,63 +84,41 @@ {% endblock %} {% block maincontent %} -
- {% for n in panel_list %} -
-
-

+

+
+
+
- - - - - - {# Wydruk #} - -

-
-
- -
- {% endfor %} -
-
-
- - -

Wiadomość nie może być pusta.

- -

- - -

-
-
+
+
+ + +

Wiadomość nie może być pusta.

+ +

+ + +

+
+
-
-
- - +
+
+ + +
{% endblock maincontent %}