Lepsze obsługiwanie nieudanych merge oraz podawanie w vstorage.all_pages() jedynie...
[redakcja.git] / platforma / static / js / views / gallery.js
1 /*global View render_template panels */
2 var ImageGalleryView = View.extend({
3   _className: 'ImageGalleryView',
4   element: null,
5   model: null,
6   currentPage: -1,
7   pageZoom: 1.0,
8   template: 'image-gallery-view-template',
9   
10   init: function(element, model, parent, template) 
11   {    
12     console.log("init for gallery");
13     var submodel = model.contentModels['gallery'];
14     this._super(element, submodel, template);
15     this.parent = parent;
16
17     console.log("gallery model", this.model);
18        
19     this.model
20       .addObserver(this, 'data', this.modelDataChanged.bind(this))
21       .addObserver(this, 'state', this.modelStateChanged.bind(this));
22    
23     //$('.image-gallery-view', this.element).html(this.model.get('data'));
24     this.modelStateChanged('state', this.model.get('state'));
25     this.model.load();    
26   },
27   
28   modelDataChanged: function(property, value) 
29   {   
30     console.log(this.model.get('state'), value, value.length);
31     if ((this.model.get('state') == 'synced') && (value.length == 0)) {
32       console.log('tutaj');
33       this.render('image-gallery-empty-template');
34     } else {
35       this.render();
36       this.gotoPage(this.currentPage);
37     }
38   },
39
40   gotoPage: function(index) 
41   {
42      if (index < 0) 
43          index = 0;
44     
45      var n = this.$pages.length;
46      if (index >= n) index = n-1;
47
48      if( (this.currentPage == index) )
49          return;
50
51      var cpage = this.$currentPage();
52
53      if(cpage) {
54          var offset = this.pageViewOffset(cpage);
55          this.cleanPage(cpage);
56      }
57      
58      this.currentPage = index;
59
60      cpage = this.$currentPage()
61      this.renderImage(cpage);
62
63      if(offset) {
64          cpage.css({top: offset.y, left: offset.x});
65      }
66
67      var self = this;
68      $('img', cpage).bind('load', function() {
69         if(offset)
70              self.setPageViewOffset(cpage, offset);
71      });
72      
73      cpage.show();
74
75      if(this.currentPage == n-1)
76           this.$nextButton.attr('disabled', 'disabled');
77      else
78           this.$nextButton.removeAttr('disabled');
79
80       if(this.currentPage == 0)
81           this.$prevButton.attr('disabled', 'disabled');
82       else
83           this.$prevButton.removeAttr('disabled');
84
85       this.$pageInput.val( (this.currentPage+1) );
86   },
87   
88   reload: function() {},
89   
90   modelStateChanged: function(property, value) {   
91     if (value == 'loading') {
92       this.freeze('Ładowanie...');
93     } else {
94       if ((value == 'synced') && (this.model.get('data').length == 0)) {
95         this.render('image-gallery-empty-template');
96       }
97       this.unfreeze();
98     }
99   },
100
101   $currentPage: function() {
102       if(this.currentPage >= 0 && this.currentPage < this.$pages.length)
103           return $(this.$pages[this.currentPage]);
104       else
105           return undefined;
106   },    
107
108   cleanPage: function($page) {
109     $page.hide();
110     $('img', $page).unbind();
111     
112     $page.empty();    
113     this.setPageViewOffset($page, {x:0, y:0});
114   },
115
116   pageDragStart: function(event)
117   {      
118       this.dragStart = {x: event.clientX, y: event.clientY};
119       $(window).bind('mousemove.imagedrag', this.pageDrag.bind(this));
120       $(window).bind('mouseup.imagedrag', this.pageDragStop.bind(this));
121       
122       this.$currentPage().css('cursor', 'move');
123
124       return false;
125   },
126
127   pageDrag: function(event)
128   {
129       if(!this.dragStart) return;
130
131       var delta = {
132            x: this.dragStart.x - event.clientX,
133            y: this.dragStart.y - event.clientY };     
134
135       var offset = this.pageViewOffset( $(this.$pages[this.currentPage]) );
136       offset.x -= delta.x;
137       offset.y -= delta.y;
138       this.setPageViewOffset( $(this.$pages[this.currentPage]), offset);
139       
140       this.dragStart = {x: event.clientX, y: event.clientY };     
141       return false;
142   },
143
144   pageDragStop: function(event) {
145       this.$currentPage().css('cursor', 'auto');
146
147       this.dragStart = undefined;
148       $(window).unbind('mousemove.imagedrag');
149       $(window).unbind('mouseup.imagedrag');
150
151       return false;
152   },
153
154   pageViewOffset: function($page) {
155       var left = parseInt($page.css('left'));
156       var top = parseInt($page.css('top'));
157
158       return {x: left, y: top};
159   },
160
161   setPageViewOffset: function($page, offset) {
162       // check if the image will be actually visible
163       // and correct
164       var MARGIN = 30;
165
166
167       var vp_width = this.$pageListRoot.width();
168       var vp_height = this.$pageListRoot.height();
169       
170       var width = $page.outerWidth();
171       var height = $page.outerHeight();
172
173       // console.log(offset, vp_width, vp_height, width, height);
174       if( offset.x+width-MARGIN < 0 ) {
175         // console.log('too much on the left', offset.x, -width)
176         offset.x = -width+MARGIN;
177       }
178       
179       // too much on the right
180       if( offset.x > vp_width-MARGIN) {
181           offset.x = vp_width-MARGIN;
182           // console.log('too much on the right', offset.x, vp_width, width)
183       }
184       
185       if( offset.y+height-MARGIN < 0)
186         offset.y = -height+MARGIN;      
187
188       if( offset.y > vp_height-MARGIN)
189           offset.y = vp_height-MARGIN;               
190       
191       $page.css({left: offset.x, top: offset.y});           
192   },
193
194   reload: function() {
195     this.model.load(true);
196   },
197   
198   renderImage: function(target) 
199   {
200       var source = target.attr('ui:model');
201       var orig_width = parseInt(target.attr('ui:width'));
202       var orig_height = parseInt(target.attr('ui:height'));
203
204       target.html('<img src="' + source
205            + '" width="' + Math.floor(orig_width * this.pageZoom)
206            + '" height="' + Math.floor(orig_height * this.pageZoom)
207            + '" />');
208        
209       $('img', target).
210         css({
211             'user-select': 'none',
212             '-webkit-user-select': 'none',
213             '-khtml-user-select': 'none',
214             '-moz-user-select': 'none'
215         }).
216         attr('unselectable', 'on').
217         mousedown(this.pageDragStart.bind(this));    
218   },
219
220   render: function(template) 
221   {
222     if(!this.model) return;            
223     
224     $('.choose-gallery-button', this.element).unbind();
225     
226     /* first unbind all */    
227     if(this.$nextButton) this.$nextButton.unbind();
228     if(this.$prevButton) this.$prevButton.unbind();
229     if(this.$jumpButton) this.$jumpButton.unbind();
230     if(this.$pageInput) this.$pageInput.unbind();
231
232     if(this.$zoomInButton) this.$zoomInButton.unbind();
233     if(this.$zoomOutButton) this.$zoomOutButton.unbind();
234     if(this.$zoomResetButton) this.$zoomResetButton.unbind();
235     
236     if (!template) {
237       /* render */
238       this._super();
239       
240       /* fetch important parts */
241       this.$pageListRoot = $('.image-gallery-page-list', this.element);
242       this.$pages = $('.image-gallery-page-container', this.$pageListRoot);
243
244       this.$nextButton = $('.image-gallery-next-button', this.element);
245       this.$prevButton = $('.image-gallery-prev-button', this.element);
246       this.$pageInput = $('.image-gallery-current-page', this.element);
247
248       // this.$zoomSelect = $('.image-gallery-current-zoom', this.element);
249       this.$zoomInButton = $('.image-gallery-zoom-in', this.element);
250       this.$zoomOutButton = $('.image-gallery-zoom-out', this.element);
251       this.$zoomResetButton = $('.image-gallery-zoom-reset', this.element);
252
253       /* re-bind events */
254       this.$nextButton.click( this.nextPage.bind(this) );
255       this.$prevButton.click( this.prevPage.bind(this) );
256       this.$pageInput.change( this.jumpToPage.bind(this) );
257
258       // this.$zoomSelect.change( this.zoomChanged.bind(this) );
259       this.$zoomInButton.click( this.zoomInOneStep.bind(this) );
260       this.$zoomOutButton.click( this.zoomOutOneStep.bind(this) );
261       this.$zoomResetButton.click( this.zoomReset.bind(this) );
262
263       this.gotoPage(this.currentPage);
264       this.changePageZoom(this.pageZoom);
265     } else {
266       this._super(template);
267       
268       var self = this;
269       $('.choose-gallery-button', self.element).click(function() {
270         console.log('CLICK CLICK')
271         self.model.setGallery($('#id_subpath', self.element).val());
272       });
273     }
274   },
275
276   jumpToPage: function() {     
277         this.gotoPage(parseInt(this.$pageInput.val())-1);
278   },
279   
280   nextPage: function() {
281       this.gotoPage(this.currentPage + 1);    
282   },
283
284   prevPage: function() {
285       this.gotoPage(this.currentPage - 1);
286   },
287
288   zoomReset: function() {
289       this.changePageZoom(1.0);
290   },
291
292   zoomInOneStep: function() {
293       var zoom = this.pageZoom + 0.1;
294       if(zoom > 3.0) zoom = 3.0;
295       this.changePageZoom(zoom);
296   },
297
298   zoomOutOneStep: function() {
299       var zoom = this.pageZoom - 0.1;
300       if(zoom < 0.3) zoom = 0.3;
301       this.changePageZoom(zoom);
302   },
303
304   changePageZoom: function(value) {
305       var current = this.$currentPage();
306
307       if(!current) return;
308
309       var alpha = value/this.pageZoom;
310       this.pageZoom = value;
311
312       var nwidth = current.attr('ui:width') * this.pageZoom;
313       var nheight = current.attr('ui:height') * this.pageZoom;
314       var off_top = parseInt(current.css('top'));
315       var off_left = parseInt(current.css('left'));
316       
317       var vpx = this.$pageListRoot.width() * 0.5;
318       var vpy = this.$pageListRoot.height() * 0.5;
319       
320       var new_off_left = vpx - alpha*(vpx-off_left);
321       var new_off_top = vpy - alpha*(vpy-off_top);
322                  
323       $('img', current).attr('width', nwidth);
324       $('img', current).attr('height', nheight);
325       
326       this.setPageViewOffset(current, {
327           y: new_off_top, x: new_off_left
328       });
329
330       // this.$zoomSelect.val(this.pageZoom);
331       // console.log('Zoom is now', this.pageZoom);
332   },
333   
334   dispose: function()
335   {
336       console.log("Disposing gallery.");
337       this.model.removeObserver(this);
338       this._super();
339   }
340 });
341
342 // Register view
343 panels['gallery'] = ImageGalleryView;