bcbdbc1773676362b4fd11989e5bc98cffc6e31b
[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             
37             if (self.options.max <= 0) {
38                 self.options.max = original.naturalWidth
39                     * 100 / self.initial_size[0];
40             }
41
42             self.element.css({
43                 'margin': 0,
44             });
45
46             self.element.offset(self.initial_position);
47             self.element.draggable({containment:"parent"});
48
49             if (self.options.plus_button)
50                 self.options.plus_button.click(
51                     function(ev) { self.zoom(1); });
52             if (self.options.minus_button)
53                 self.options.minus_button.click(
54                     function(ev) { self.zoom(-1); });
55
56             self.options.areas_links.hover(function() {
57                 $this = $(this);
58                 var coords = $this.data("coords");
59                 this._picture_mark = self.createMark({
60                     label: $this.text(),
61                     coords: coords,
62                 });
63             }, function() {
64                 $(this._picture_mark).remove();
65                 this._picture_mark = undefined;
66             });
67             return self;
68         },
69
70         natural_size: function() { 
71             var img = this.element.find('img').get(0);
72             return [ img.naturalWidth, img.naturalHeight ] 
73         },
74
75         currentZoom: function() { return this._zoom; },
76
77         initOriginal: function() {
78             if (!this._original) {
79                 this.element.find("img.initial").remove();
80                 this.element.find("img.loading").removeClass("loading");
81                 this._original = true;
82             }
83
84         },
85
86         zoom: function(steps) {
87             this.initOriginal();
88             var t = this._zoom + steps;
89             return this.zoomTo(t);
90         },
91
92         zoomForStep: function(step) {
93             // 0 => initial
94             // max_step-1 => max %
95             return 100 + (this.options.max - 100) / this.options.steps * step
96         },
97
98         zoomTo: function(level) {
99             if (level < 0 || level > this.options.steps)
100                 return;
101             var ratio = this.zoomForStep(level) / 100;
102             var new_width  = ratio * this.initial_size[0];
103             var new_height = ratio * this.initial_size[1];
104             var target = {
105                 'width': new_width,
106                 'left': Math.max(0, 
107                                  this.initial_position.left 
108                                  - (new_width - this.initial_size[0])/2),
109                 'top': Math.max(0, 
110                                 this.initial_position.top 
111                                 - (new_height - this.initial_size[1])/2),
112             };
113
114             this._zoom = level;
115             this.element.animate(target, 200); // default duration=400
116         },
117
118         allowedPosition: function(off) {
119             var x = undefined, fix_x = undefined;
120             var y = undefined, fix_y = undefined;
121             var w = this.element.width();
122             var h = this.element.height();
123             var cw = $(window).width();
124             var ch = $(window).height();
125             var off = off || this.element.offset();
126
127             if (w <= cw) {
128                 var x = off.left;
129                 if (x < 0) 
130                     fix_x = 0;
131                 if (x + w > cw)
132                     fix_x = cw - w;
133             } else {
134                 if (x > 0)
135                     fix_x = 0;
136                 if (x + w < cw)
137                     fix_x = cw - w;
138             }
139
140             if (h <= ch) {
141                 var y = off.top;
142                 if (y < 0)
143                     fix_y = 0;
144                 if (y + h > ch)
145                     fix_y = ch - h;
146             } else {
147                 if (y > 0)
148                     fix_y = 0;
149                 if (y + h < ch)
150                     fix_y = ch - h;
151             }
152             if (fix_x !== undefined || fix_y !== undefined)
153                 return { top: fix_y, left: fix_x };
154             return undefined;
155
156         },
157
158         // mark
159         // {
160         //  label: "...",
161         //  coords: [x, y, w, h]
162         // }
163         createMark: function(mark) {
164             var $mark = $('<div class="mark"><div class="label">' + 
165                           mark.label + '</div></div>');
166             var ratio = this.zoomForStep(this.currentZoom()) *
167                 this.initial_size[0] / (100 * this.natural_size()[0]);
168             var scale = function (v) { 
169                 return v * ratio; 
170             }
171             if (mark.coords[1][0] < 0 || mark.coords[1][1] < 0) { // whole
172                 var s = self.natural_size();
173                 if (mark.coords[1][0] < 0) mark.coords[1][0] = s[0];
174                 if (mark.coords[1][1] < 0) mark.coords[1][1] = s[1];
175             }
176
177             var coords = [[scale(mark.coords[0][0]), scale(mark.coords[0][1])],
178                           [scale(mark.coords[1][0]), scale(mark.coords[1][1])]];
179             this.element.append($mark);
180             $mark.width(coords[1][0] - coords[0][0]);
181             $mark.height(coords[1][1] - coords[0][1]);
182             $mark.css({left: coords[0][0], top: coords[0][1]});
183             return $mark.get(0);
184         },
185     });
186 }(jQuery));
187
188
189 $(document).ready(function(){
190     $(".picture-wrap").pictureviewer({
191         plus_button: $(".toolbar .button.plus"),
192         minus_button: $(".toolbar .button.minus"),
193         areas_links: $("#picture-objects a, #picture-themes a"),
194     });
195
196     $.highlightFade.defaults.speed = 3000;
197
198     $('.toolbar a.dropdown').each(function() {
199         $t = $(this);
200         $($t.attr('href')).hide().insertAfter(this);
201     });
202
203     $('.toolbar a.dropdown').toggle(function() {
204         $(this).addClass('selected');
205         $($(this).attr('href')).slideDown('fast');
206     }, function() {
207         $(this).removeClass('selected');
208         $($(this).attr('href')).slideUp('fast');
209     });
210
211
212 });
213