Merge branch 'master' of stigma.nowoczesnapolska.org.pl:platforma
[redakcja.git] / platforma / static / js / views / html.js
1 /*global View render_template panels */
2 var HTMLView = View.extend({
3     _className: 'HTMLView',
4     element: null,
5     model: null,
6     template: 'html-view-template',
7   
8     init: function(element, model, parent, template) {
9         this._super(element, model, template);
10         this.parent = parent;
11     
12         this.model
13         .addObserver(this, 'data', this.modelDataChanged.bind(this))        
14         .addObserver(this, 'state', this.modelStateChanged.bind(this));
15       
16         $('.htmlview', this.element).html(this.model.get('data'));
17
18         this.$menuTemplate = $(render_template('html-view-frag-menu-template', this));
19         
20         this.modelStateChanged('state', this.model.get('state'));
21         this.model.load();
22
23         this.currentOpen = null;
24     },
25
26     modelDataChanged: function(property, value) {
27         $('.htmlview', this.element).html(value);
28         this.updatePrintLink();
29         var self = this;
30         
31         $("*[x-editable]").each(function() {
32             $(this).append( self.$menuTemplate.clone() );
33         });
34     },
35
36     updatePrintLink: function() {
37         var base = this.$printLink.attr('ui:baseref');
38         this.$printLink.attr('href', base + "?user="+this.model.document.get('user')+"&revision=" + this.model.get('revision'));
39     },
40   
41     modelStateChanged: function(property, value) 
42     {
43         var self = $(this);
44
45         if (value == 'synced' || value == 'dirty') {
46             this.unfreeze();
47         } else if (value == 'unsynced') {
48             if(this.currentOpen) this.closeWithoutSave(this.currentOpen);
49             this.freeze('Niezsynchronizowany...');
50         } else if (value == 'loading') {
51             this.freeze('Ɓadowanie...');
52         } else if (value == 'saving') {
53             this.freeze('Zapisywanie...');
54         } else if (value == 'error') {
55             this.freeze(this.model.get('error'));
56             $('.xml-editor-ref', this.overlay).click(
57             function(event) {
58                 console.log("Sending scroll rq.", this);
59                 try {
60                     var href = $(this).attr('href').split('-');
61                     var line = parseInt(href[1]);
62                     var column = parseInt(href[2]);
63                     
64                     $(document).trigger('xml-scroll-request', {line:line, column:column});
65                 } catch(e) {
66                     console.log(e);
67                 }
68                 
69                 return false;
70             });
71         }
72     },
73
74     render: function() {
75         this.element.unbind('click');
76
77         if(this.$printLink) this.$printLink.unbind();
78         this._super();
79         this.$printLink = $('.html-print-link', this.element);
80         this.updatePrintLink();
81
82         this.element.bind('click', this.itemClicked.bind(this));
83         // this.element.bind('mouseover', this.itemHover.bind(this));
84     },
85   
86     reload: function() {
87         this.model.load(true);
88     },
89   
90     dispose: function() {
91         this.model.removeObserver(this);
92         this._super();
93     },
94
95     itemClicked: function(event) 
96     {
97         var self = this;
98         
99         console.log('click:', event, event.ctrlKey, event.target);        
100         var $e = $(event.target);
101
102         if($e.hasClass('edit-button'))
103             this.openForEdit( this.editableFor($e) );
104
105         if($e.hasClass('accept-button'))
106             this.closeWithSave( this.editableFor($e) );
107
108         if($e.hasClass('reject-button'))
109             this.closeWithoutSave( this.editableFor($e) );
110     },
111
112     closeWithSave: function($e) {
113         var $edit = $e.data('edit-overlay');
114         var newText = $('textarea', $edit).val();
115
116         this.model.putXMLPart($e, newText, function($e, html) {
117             this.renderPart($e, html);
118             $edit.remove();
119             $e.removeAttr('x-open');            
120         }.bind(this) );
121         this.currentOpen = null;
122     },
123
124     closeWithoutSave: function($e) {
125         var $edit = $e.data('edit-overlay');
126         $edit.remove();
127         $e.removeAttr('x-open');
128         this.currentOpen = null;
129     },
130
131     renderPart: function($e, html) {
132             $e.html(html);
133             $e.append( this.$menuTemplate.clone() );
134     },
135
136     editableFor: function($button) 
137     {
138         var $e = $button;
139         var n = 0;
140         
141         while( ($e[0] != this.element[0]) && !($e.attr('x-editable')) && n < 50)
142         {
143             // console.log($e, $e.parent(), this.element);
144             $e = $e.parent();
145             n += 1;
146         }
147
148         if(!$e.attr('x-editable'))
149             throw Exception("Click outside of editable")
150
151         return $e;
152     },
153
154     openForEdit: function($origin)
155     {       
156         if(this.currentOpen && this.currentOpen != $origin) {
157             this.closeWithSave(this.currentOpen);
158             
159         }
160     
161         // start edition on this node       
162         var $overlay = $('<div class="html-editarea"><textarea></textarea></div>');
163
164         var x = $origin[0].offsetLeft;
165         var y = $origin[0].offsetTop;
166         var w = $origin.outerWidth();
167         var h = $origin.innerHeight();
168         
169         $overlay.css({position: 'absolute', height: h, left: x, top: y, width: '95%'});
170         
171             $origin.offsetParent().append($overlay);
172             $origin.data('edit-overlay', $overlay);
173                      
174             this.model.getXMLPart($origin, function(path, data) {
175                 $('textarea', $overlay).val(data);
176             });
177
178             this.currentOpen = $origin;
179             $origin.attr('x-open', 'open');
180         
181         
182         return false;
183     }
184   
185 });
186
187 // Register view
188 panels['html'] = HTMLView;