6 var hash = "#advanced-view-editor";
8 var website = openerp.website;
9 website.templates.push('/website/static/src/xml/website.ace.xml');
11 website.ready().then(function () {
12 if (window.location.hash.indexOf(hash) >= 0) {
21 globalEditor = new website.ace.ViewEditor(this);
22 globalEditor.appendTo($(document.body));
26 website.EditorBar.include({
27 events: _.extend({}, website.EditorBar.prototype.events, {
28 'click a[data-action=ace]': 'launch',
35 website.ace.XmlDocument = openerp.Class.extend({
36 init: function (text) {
39 isWellFormed: function () {
40 if (document.implementation.createDocument) {
41 var dom = new DOMParser().parseFromString(this.xml, "text/xml");
42 return dom.getElementsByTagName("parsererror").length === 0;
43 } else if (window.ActiveXObject) {
45 var msDom = new ActiveXObject("Microsoft.XMLDOM");
47 return !msDom.loadXML(this.xml);
52 return vkbeautify.xml(this.xml, 4);
56 website.ace.ViewOption = openerp.Widget.extend({
57 template: 'website.ace_view_option',
58 init: function (parent, options) {
59 this.view_id = options.id;
60 this.view_name = options.name;
65 website.ace.ViewEditor = openerp.Widget.extend({
66 template: 'website.ace_view_editor',
68 'change #ace-view-list': 'displaySelectedView',
69 'click button[data-action=save]': 'saveViews',
70 'click button[data-action=format]': 'formatXml',
71 'click button[data-action=close]': 'close',
73 init: function (parent) {
79 self.aceEditor = ace.edit(self.$('#ace-view-editor')[0]);
80 self.aceEditor.setTheme("ace/theme/monokai");
81 var viewId = $(document.documentElement).data('view-xmlid');
82 openerp.jsonRpc('/website/customize_template_get', 'call', {
85 }).then(function (views) {
86 self.loadViews.call(self, views);
90 loadViews: function (views) {
92 var activeViews = _.filter(views, function (view) {
95 var $viewList = self.$('#ace-view-list');
96 _.each(activeViews, function (view) {
98 new website.ace.ViewOption(self, view).appendTo($viewList);
99 self.loadView(view.id);
103 loadView: function (id) {
104 var viewId = parseInt(id, 10);
106 openerp.jsonRpc('/web/dataset/call', 'call', {
109 args: [[viewId], ['arch'], website.get_context()],
110 }).then(function(result) {
111 var editingSession = self.buffers[viewId] = new ace.EditSession(result[0].arch);;
112 editingSession.setMode("ace/mode/xml");
113 editingSession.setUndoManager(new ace.UndoManager());
114 editingSession.on("change", function () {
115 setTimeout(function () {
116 var $option = self.$('#ace-view-list').find('[value='+viewId+']');
117 var bufferName = $option.text();
118 var dirtyMarker = " (unsaved changes)";
119 var isDirty = editingSession.getUndoManager().hasUndo();
120 if (isDirty && bufferName.indexOf(dirtyMarker) < 0) {
121 $option.text(bufferName + dirtyMarker);
122 } else if (!isDirty && bufferName.indexOf(dirtyMarker) > 0) {
123 $option.text(bufferName.substring(0, bufferName.indexOf(dirtyMarker)));
127 if (viewId === self.selectedViewId()) {
128 self.displayView.call(self, viewId);
132 selectedViewId: function () {
133 return parseInt(this.$('#ace-view-list').val(), 10);
135 displayView: function (id) {
136 var viewId = parseInt(id, 10);
137 var editingSession = this.buffers[viewId];
138 if (editingSession) {
139 this.aceEditor.setSession(editingSession);
142 displaySelectedView: function () {
143 this.displayView(this.selectedViewId());
146 formatXml: function () {
147 var xml = new website.ace.XmlDocument(this.aceEditor.getValue());
148 this.aceEditor.setValue(xml.format());
150 saveViews: function () {
152 var toSave = _.filter(_.map(self.buffers, function (editingSession, viewId) {
154 id: parseInt(viewId, 10),
155 isDirty: editingSession.getUndoManager().hasUndo(),
156 text: editingSession.getValue(),
158 }), function (session) {
159 return session.isDirty;
161 var requests = _.map(toSave, self.saveView);
162 $.when.apply($, requests).then(function () {
163 self.reloadPage.call(self);
164 }).fail(function () {
165 self.displayError.call(self);
168 saveView: function (session) {
169 var xml = new website.ace.XmlDocument(session.text);
170 if (xml.isWellFormed()) {
171 return openerp.jsonRpc('/web/dataset/call', 'call', {
174 args: [[session.id], { 'arch': xml.xml }, website.get_context()],
177 return $.Deferred().fail("Malformed XML document");
180 updateHash: function () {
181 window.location.hash = hash + "?view=" + this.selectedViewId();
183 reloadPage: function () {
185 window.location.reload();
187 displayError: function (error) {
188 // TODO Improve feedback (e.g. update 'Save' button + tooltip)
192 this.$el.removeClass('oe_ace_closed').addClass('oe_ace_open');
193 var curentHash = window.location.hash;
194 var indexOfView = curentHash.indexOf("?view=");
195 if (indexOfView >= 0) {
196 var viewId = parseInt(curentHash.substring(indexOfView + 6, curentHash.length), 10);
197 this.$('#ace-view-list').val(viewId).change();
199 window.location.hash = hash;
203 window.location.hash = "";
205 this.$el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function () {
207 self.destroy.call(self);
208 }).removeClass('oe_ace_open').addClass('oe_ace_closed');