Galeria skanów z przewijaniem, bez zoom'a.
[redakcja.git] / project / 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   template: 'image-gallery-view-template',
7   
8   init: function(element, model, parent, template) 
9   {
10     this.currentPage = -1;
11     
12     this._super(element, model, template);
13     this.parent = parent;
14        
15     this.model
16       .addObserver(this, 'data', this.modelDataChanged.bind(this))
17       .addObserver(this, 'state', this.modelStateChanged.bind(this));
18       
19     //$('.image-gallery-view', this.element).html(this.model.get('data'));
20     this.modelStateChanged('state', this.model.get('state'));
21     this.model.load();
22   },
23   
24   modelDataChanged: function(property, value) 
25   {    
26     if( property == 'data')
27     {
28         this.render();
29         this.gotoPage(this.currentPage);
30     }   
31   },
32
33   gotoPage: function(index) 
34   {
35      if (index < 0) 
36          index = 0;
37     
38      var n = this.$pages.length;
39      if (index >= n) index = n-1;
40
41      if( (this.currentPage == index) )
42          return;
43
44      var cpage = this.$currentPage();
45
46      if(cpage) {
47          var offset = this.pageViewOffset(cpage);
48          this.cleanPage(cpage);
49      }
50      
51      this.currentPage = index;
52
53      cpage = this.$currentPage()
54      this.renderImage(cpage, cpage.attr('ui:model'));
55
56      if(offset) {
57          cpage.css({top: offset.y, left: offset.x});
58      }
59
60      var self = this;
61      $('img', cpage).bind('load', function() {
62         if(offset)
63              self.setPageViewOffset(cpage, offset);
64      });
65      
66      cpage.show();
67
68      if(this.currentPage == n-1)
69           this.$nextButton.attr('disabled', 'disabled');
70      else
71           this.$nextButton.removeAttr('disabled');
72
73       if(this.currentPage == 0)
74           this.$prevButton.attr('disabled', 'disabled');
75       else
76           this.$prevButton.removeAttr('disabled');
77
78       this.$pageInput.val( (this.currentPage+1) );
79   },
80   
81   modelStateChanged: function(property, value) {
82     if (value == 'synced' || value == 'dirty') {
83       this.parent.unfreeze();
84     } else if (value == 'unsynced') {
85       this.parent.freeze('Niezsynchronizowany...');
86     } else if (value == 'loading') {
87       this.parent.freeze('Ładowanie...');
88     } else if (value == 'saving') {
89       this.parent.freeze('Zapisywanie...');
90     }
91   },
92
93   $currentPage: function() {
94       if(this.currentPage >= 0 && this.currentPage < this.$pages.length)
95           return $(this.$pages[this.currentPage]);
96       else
97           return undefined;
98   },    
99
100   cleanPage: function($page) {
101     $page.hide();
102     $('img', $page).unbind();
103     
104     $page.empty();
105     
106     this.setPageViewOffset($page, {x:0, y:0});
107   },
108
109   pageDragStart: function(event)
110   {      
111       this.dragStart = {x: event.clientX, y: event.clientY};
112       $(window).bind('mousemove.imagedrag', this.pageDrag.bind(this));
113       $(window).bind('mouseup.imagedrag', this.pageDragStop.bind(this));
114       
115       this.$currentPage().css('cursor', 'move');
116
117       return false;
118   },
119
120   pageDrag: function(event)
121   {
122       if(!this.dragStart) return;
123
124       var delta = {
125            x: this.dragStart.x - event.clientX,
126            y: this.dragStart.y - event.clientY };     
127
128       var offset = this.pageViewOffset( $(this.$pages[this.currentPage]) );
129       offset.x -= delta.x;
130       offset.y -= delta.y;
131       this.setPageViewOffset( $(this.$pages[this.currentPage]), offset);
132       
133       this.dragStart = {x: event.clientX, y: event.clientY };     
134       return false;
135   },
136
137   pageDragStop: function(event) {
138       this.$currentPage().css('cursor', 'auto');
139
140       this.dragStart = undefined;
141       $(window).unbind('mousemove.imagedrag');
142       $(window).unbind('mouseup.imagedrag');
143
144       return false;
145   },
146
147   pageViewOffset: function($page) {
148       var left = parseInt($page.css('left'));
149       var top = parseInt($page.css('top'));
150
151       return {x: left, y: top};
152   },
153
154   setPageViewOffset: function($page, offset) {
155       // check if the image will be actually visible
156       // and correct
157       var MARGIN = 30;
158
159       var vp_width = this.$pageListRoot.width();
160       var vp_height = this.$pageListRoot.height();
161       
162       var width = $page.outerWidth();
163       var height = $page.outerHeight();      
164
165       if( offset.x+width-MARGIN < 0 ) {
166         // console.log('too much on the left', offset.x, -width)
167         offset.x = -width+MARGIN;
168       }
169       
170       // too much on the right
171       if( offset.x > vp_width-MARGIN) {
172           offset.x = vp_width-MARGIN;
173           // console.log('too much on the right', offset.x, vp_width, width)
174       }
175
176       
177       if( offset.y+height-MARGIN < 0)
178         offset.y = -height+MARGIN;      
179
180       if( offset.y > vp_height-MARGIN)
181           offset.y = vp_height-MARGIN;               
182       
183       $page.css({left: offset.x, top: offset.y});           
184   }, 
185   
186   renderImage: function(target, source) {
187       target.html('<img src="'+source+'" />');
188       $('img', target).
189         css({
190             'user-select': 'none',
191             '-webkit-user-select': 'none',
192             '-khtml-user-select': 'none',
193             '-moz-user-select': 'none',
194         }).
195         attr('unselectable', 'on').
196         mousedown(this.pageDragStart.bind(this));
197   },
198
199   render: function() {
200       /* first unbind all */
201       
202       // this.pageListElement
203       if(this.$nextButton) this.$nextButton.unbind();
204       if(this.$prevButton) this.$prevButton.unbind();
205       if(this.$jumpButton) this.$jumpButton.unbind();
206
207       /* render */
208       this.element.html(render_template(this.template, this));
209
210       /* fetch important parts */
211       this.$pageListRoot = $('.image-gallery-page-list', this.element);
212       this.$pages = $('.image-gallery-page-container', this.$pageListRoot);
213
214       this.$nextButton = $('.image-gallery-next-button', this.element);
215       this.$prevButton = $('.image-gallery-prev-button', this.element);
216       this.$pageInput = $('.image-gallery-current-page', this.element);
217
218       /* re-bind events */
219       this.$nextButton.click( this.nextPage.bind(this) );
220       this.$prevButton.click( this.prevPage.bind(this) );
221
222       this.$pageInput.change( this.jumpToPage.bind(this) );
223   },
224
225   jumpToPage: function() {     
226         this.gotoPage(parseInt(this.$pageInput.val())-1);
227   },
228   
229   nextPage: function() {
230       this.gotoPage(this.currentPage + 1);    
231   },
232
233   prevPage: function() {
234       this.gotoPage(this.currentPage - 1);
235   },
236   
237   dispose: function() {
238     this.model.removeObserver(this);
239     this._super();
240   }
241 });
242
243 // Register view
244 panels['gallery'] = ImageGalleryView;