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