0840aa5faf843f45a4b765444d74a4ebd1ca9e22
[wolnelektury.git] / apps / wolnelektury_core / static / js / picture.js
1
2 (function($) {
3     $.widget('wl.pictureviewer', {
4
5         options: {
6             steps: 6, // steps of zoom
7             max: -1, // max zoom in percent
8             plus_button: undefined,
9             minus_button: undefined,
10             height: 500, // height to scale to initially
11         },
12
13
14         _create: function() {
15             var self = this;
16             /* Calibrate */
17             self._zoom = 0;
18
19             // the initial thumbnailed picture
20
21
22             var img = self.element.find('img.initial').get(0);
23
24             self.initial_size = [ 
25                 img.naturalWidth,
26                 img.naturalHeight
27             ];
28
29             self.element.width(self.initial_size[0]);
30             self.element.height(self.initial_size[1]);
31             
32             self.initial_position = self.element.offset();
33
34             var original = self.element.find('img.original').get(0);
35             self._original = false;
36             self.original_loeaded = undefined; // callback
37             self._original_loaded = false;
38
39             self.spinner = $("#spinner").progressSpin();
40
41             $(original).load(function() {
42                 self._original_loaded = true;
43                 self.spinner.stop();
44                 var cb = self.original_loaded;
45                 self.original_loaded = undefined;
46                 if (cb)
47                     cb()
48             });
49             
50             if (self.options.max <= 0) {
51                 self.options.max = original.naturalWidth
52                     * 100 / self.initial_size[0];
53             }
54
55             self.element.css({
56                 'margin': 0,
57             });
58
59             self.element.offset(self.initial_position);
60             //      self.element.draggable({containment:"parent"});
61
62             if (self.options.plus_button)
63                 self.options.plus_button.click(
64                     function(ev) { self.zoom(1); });
65             if (self.options.minus_button)
66                 self.options.minus_button.click(
67                     function(ev) { self.zoom(-1); });
68
69             self.options.areas_links.hover(function() {
70                 $this = $(this);
71                 var coords = $this.data("coords");
72                 this._picture_mark = self.createMark({
73                     label: $this.text(),
74                     coords: coords,
75                 });
76             }, function() {
77                 $(this._picture_mark).remove();
78                 this._picture_mark = undefined;
79             });
80             return self;
81         },
82
83         natural_size: function() { 
84             var img = this.element.find('img').get(0);
85             return [ img.naturalWidth, img.naturalHeight ] 
86         },
87
88         currentZoom: function() { return this._zoom; },
89
90         initOriginal: function() {
91             var self = this;
92             function subst_original() {
93                 self.element.find("img.initial").remove();
94                 self.element.find("img.loading").removeClass("loading");
95                 self._original = true;
96             }
97             if (!this._original) {
98                 if (this._original_loaded) {
99                     return subst_original();
100                 } else {
101                     self.original_loaded = subst_original;
102                     self.spinner.start();
103                 }
104             }
105
106         },
107
108         zoom: function(steps) {
109             this.initOriginal();
110             var t = this._zoom + steps;
111             return this.zoomTo(t);
112         },
113
114         zoomForStep: function(step) {
115             // 0 => initial
116             // max_step-1 => max %
117             return 100 + (this.options.max - 100) / this.options.steps * step
118         },
119
120         zoomTo: function(level) {
121             if (level < 0 || level > this.options.steps)
122                 return;
123             var ratio = this.zoomForStep(level) / 100;
124             var new_width  = ratio * this.initial_size[0];
125             var new_height = ratio * this.initial_size[1];
126             var target = {
127 //              'width': new_width,
128                 'left': Math.max(0, 
129                                  this.initial_position.left 
130                                  - (new_width - this.initial_size[0])/2),
131                 'top': Math.max(0, 
132                                 this.initial_position.top 
133                                 - (new_height - this.initial_size[1])/2),
134             };
135
136             this._zoom = level;
137
138             this.element.css(target);
139             this.element.find(".original").width(new_width);
140
141 //          this.element.animate(target, 1200); // default duration=400
142         },
143
144         allowedPosition: function(off) {
145             var x = undefined, fix_x = undefined;
146             var y = undefined, fix_y = undefined;
147             var w = this.element.width();
148             var h = this.element.height();
149             var cw = $(window).width();
150             var ch = $(window).height();
151             var off = off || this.element.offset();
152
153             if (w <= cw) {
154                 var x = off.left;
155                 if (x < 0) 
156                     fix_x = 0;
157                 if (x + w > cw)
158                     fix_x = cw - w;
159             } else {
160                 if (x > 0)
161                     fix_x = 0;
162                 if (x + w < cw)
163                     fix_x = cw - w;
164             }
165
166             if (h <= ch) {
167                 var y = off.top;
168                 if (y < 0)
169                     fix_y = 0;
170                 if (y + h > ch)
171                     fix_y = ch - h;
172             } else {
173                 if (y > 0)
174                     fix_y = 0;
175                 if (y + h < ch)
176                     fix_y = ch - h;
177             }
178             if (fix_x !== undefined || fix_y !== undefined)
179                 return { top: fix_y, left: fix_x };
180             return undefined;
181
182         },
183
184         // mark
185         // {
186         //  label: "...",
187         //  coords: [x, y, w, h]
188         // }
189         createMark: function(mark) {
190             var $mark = $('<div class="mark"><div class="label">' + 
191                           mark.label + '</div></div>');
192             var ratio = this.zoomForStep(this.currentZoom()) *
193                 this.initial_size[0] / (100 * this.natural_size()[0]);
194             var scale = function (v) { 
195                 return v * ratio; 
196             }
197             if (mark.coords[1][0] < 0 || mark.coords[1][1] < 0) { // whole
198                 var s = self.natural_size();
199                 if (mark.coords[1][0] < 0) mark.coords[1][0] = s[0];
200                 if (mark.coords[1][1] < 0) mark.coords[1][1] = s[1];
201             }
202
203             var coords = [[scale(mark.coords[0][0]), scale(mark.coords[0][1])],
204                           [scale(mark.coords[1][0]), scale(mark.coords[1][1])]];
205             this.element.append($mark);
206             $mark.width(coords[1][0] - coords[0][0]);
207             $mark.height(coords[1][1] - coords[0][1]);
208             $mark.css({left: coords[0][0], top: coords[0][1]});
209             return $mark.get(0);
210         },
211     });
212 }(jQuery));
213
214
215 $(document).ready(function(){
216     $(".picture-wrap").pictureviewer({
217         plus_button: $(".toolbar .button.plus"),
218         minus_button: $(".toolbar .button.minus"),
219         areas_links: $("#picture-objects a, #picture-themes a"),
220     });
221
222     $.highlightFade.defaults.speed = 3000;
223
224     $('.toolbar a.dropdown').each(function() {
225         $t = $(this);
226         $($t.attr('href')).hide().insertAfter(this);
227     });
228
229     function closeDD() {
230         $(this).removeClass('selected');
231         $($(this).attr('href')).slideUp('fast');
232         
233     }
234     $('.toolbar a.dropdown').click(function() {
235         if ($(this).hasClass('selected')) {
236             closeDD.call(this);
237         } else {
238             $(this).addClass('selected');
239             $($(this).attr('href')).slideDown('fast');
240             $(this).parent().siblings(".button:has(.dropdown)").children(".dropdown").each(closeDD);
241         }
242     });
243
244
245 });
246