comparison webapp/src/main/webapp/jquery/jquery.digilib.sliders.js @ 1057:d139f59a5f80

rgb slider functional, get/set values not yet
author hertzhaft
date Sat, 31 Mar 2012 00:41:28 +0200
parents 4f17420392a9
children 95d28c6ad018
comparison
equal deleted inserted replaced
1056:89c5b56933af 1057:d139f59a5f80
11 // the functions made available by digilib 11 // the functions made available by digilib
12 var fn = null; 12 var fn = null;
13 // affine geometry plugin 13 // affine geometry plugin
14 var geom = null; 14 var geom = null;
15 15
16 var defaults = { 16 var defaults = {};
17 'label' : 'Slider',
18 'direction' : 'x',
19 'handlesize' : 16,
20 'min' : 0,
21 'max' : 100,
22 'start' : 33,
23 'numberoffset' : -24,
24 'labeloffset' : 16,
25 'rect' : null,
26 'factor' : null,
27 'onmove' : null // callback function
28 };
29 17
30 var sliderOptions = { 18 var sliderOptions = {
31 rot : { 19 rot : {
32 label : "Rotation angle", 20 label : "Rotation angle",
33 tooltip : "rotate image", 21 tooltip : "rotate image",
52 icon : "contrast.png", 40 icon : "contrast.png",
53 'min' : -4, 41 'min' : -4,
54 'max' : 4, 42 'max' : 4,
55 'step' : 0.01, 43 'step' : 0.01,
56 'start' : 0 44 'start' : 0
57 }, 45 }
58 red : { 46 };
59 label : "Red value", 47
60 tooltip : "set red value", 48 var rgb = {
61 icon : "rgb.png", 49 r : {
62 'min' : 0, 50 label : "red",
63 'max' : 255, 51 color : "#800000"
64 'start' : 127 52 },
65 }, 53 g : {
66 54 label : "green",
67 green : { 55 color : "#008000"
68 label : "Green value", 56 },
69 tooltip : "set green value", 57 b : {
70 icon : "rgb.png", 58 label : "blue",
71 'min' : 0, 59 color : "#000080"
72 'max' : 255, 60 }
73 'start' : 127 61 }
74 },
75
76 blue : {
77 label : "Blue value",
78 tooltip : "set blue value",
79 icon : "rgb.png",
80 'min' : 0,
81 'max' : 255,
82 'start' : 127
83 },
84 };
85
86 var actions = { 62 var actions = {
87 // slider to set a rotation angle
88 sliderRotate : function (data) {
89 var $elem = data.$elem;
90 var $panel = fn.setupPanel(data);
91 var opts = { 'start' : parseFloat(data.settings.rot) };
92 var $slider = fn.setupSlider(data, 'rot', opts);
93 var ok = function(d) {
94 var angle = $slider.slider('getval');
95 digilib.actions.rotate(d, angle);
96 };
97 $panel.data['ok'] = ok;
98 $panel.fadeIn();
99 $panel.prepend($slider);
100 fn.centerOnScreen(data, $panel);
101 $slider.slider('show');
102 },
103
104 // slider to set a brightness value
105 sliderBrightness : function (data) {
106 var $elem = data.$elem;
107 var $panel = fn.setupPanel(data);
108 var opts = { 'start' : parseFloat(data.settings.brgt) };
109 var $slider = fn.setupSlider(data, 'brgt', opts);
110 var ok = function(d) {
111 var brgt = $slider.slider('getval');
112 digilib.actions.brightness(d, brgt);
113 };
114 $panel.data['ok'] = ok;
115 $panel.prepend($slider);
116 fn.centerOnScreen(data, $panel);
117 $slider.slider('show');
118 },
119
120 // slider to set a contrast value
121 sliderContrast : function (data) {
122 var $elem = data.$elem;
123 var $panel = fn.setupPanel(data);
124 var opts = { 'start' : parseFloat(data.settings.cont) };
125 var $slider = fn.setupSlider(data, 'cont', opts);
126 var ok = function(d) {
127 var cont = $slider.slider('getval');
128 digilib.actions.contrast(d, cont, true);
129 };
130 $panel.data['ok'] = ok;
131 $panel.fadeIn();
132 $panel.prepend($slider);
133 fn.centerOnScreen(data, $panel);
134 $slider.slider('show');
135 },
136
137 // shows brightness slider 63 // shows brightness slider
138 tinySliderBrgt : function (data) { 64 tinySliderBrgt : function (data) {
139 var callback = function(val) { 65 var callback = function(val) {
140 digilib.actions.brightness(data, val); 66 digilib.actions.brightness(data, val);
141 }; 67 };
142 setupTinyRangeSlider(data, 'brgt', callback); 68 singleSlider(data, 'brgt', callback);
143 }, 69 },
144 70
145 // shows contrast slider 71 // shows contrast slider
146 tinySliderCont : function (data) { 72 tinySliderCont : function (data) {
147 var callback = function(val) { 73 var callback = function(val) {
148 digilib.actions.contrast(data, val, true); 74 digilib.actions.contrast(data, val, true);
149 }; 75 };
150 setupTinyRangeSlider(data, 'cont', callback); 76 singleSlider(data, 'cont', callback);
151 }, 77 },
152 78
153 // shows rotate slider 79 // shows rotate slider
154 tinySliderRot : function (data) { 80 tinySliderRot : function (data) {
155 var callback = function(val) { 81 var callback = function(val) {
156 digilib.actions.rotate(data, val); 82 digilib.actions.rotate(data, val);
157 }; 83 };
158 setupTinyRangeSlider(data, 'rot', callback); 84 singleSlider(data, 'rot', callback);
159 } 85 },
160 }; 86
161 87 // shows RGB sliders
162 var getval = function (data) { 88 tinySliderRGB : function (data) {
163 // returns the slider value 89 var callback = function(m, a) {
164 var $this = this; 90 digilib.actions.setRGB(data, m, a);
165 var settings = $this.data('settings'); 91 };
166 return settings.val; 92 rgbSlider(data, callback);
167 }; 93 }
168
169 var setval = function (data, val) {
170 // sets the slider value and moves the handle acordingly
171 var $this = this;
172 var settings = $this.data('settings');
173 if (val != null) settings.val = val;
174 var ratio = (settings.val - settings.min) / settings.diff;
175 var r = settings.rect;
176 var newpos = settings.vertical
177 ? geom.position(r.x + r.width / 2, r.y + ratio * r.height)
178 : geom.position(r.x + ratio * r.width, r.y + r.height / 2);
179 $this.slider('moveto', newpos);
180 };
181
182 var moveto = function (data, pos, calc) {
183 // move the handle in response to a mouse position
184 var $this = this;
185 var settings = $this.data('settings');
186 var r = settings.rect;
187 var h = settings.handlerect;
188 var handlepos = r.getCenter();
189 if (settings.vertical) {
190 handlepos.y = Math.min(Math.max(r.y, pos.y), r.y + r.height)
191 } else {
192 handlepos.x = Math.min(Math.max(r.x, pos.x), r.x + r.width)
193 }
194 h.setCenter(handlepos);
195 h.adjustDiv(settings.$handle);
196 if (calc) {
197 // calculate new slider value
198 var temp = settings.vertical
199 ? (handlepos.y - r.y)
200 : (handlepos.x - r.x);
201 settings.val = fn.cropFloat(temp * settings.factor + settings.min);
202 }
203 if (settings.onmove) {
204 settings.onmove($this);
205 }
206 };
207
208 var show = function (data) {
209 var $this = this;
210 $this.fadeIn();
211 var settings = $this.data('settings');
212 // the jquery elements we need
213 var $body = $('body');
214 // some variables for easier calculation
215 var label = settings.label + ': ';
216 // calculate positions for the slider elements
217 var r = geom.rectangle($this);
218 settings.rect = r;
219 var v = settings.vertical;
220 settings.factor = v
221 ? settings.diff / r.height
222 : settings.diff / r.width;
223 var labelpos = geom.position(r.x, r.y + settings.labeloffset);
224 var minpos = v
225 ? geom.position(r.x + settings.numberoffset, r.y)
226 : geom.position(r.x, r.y + settings.numberoffset);
227 var maxpos = v
228 ? geom.position(r.x + settings.numberoffset, r.y + r.width)
229 : geom.position(r.x + r.width - settings.$max.width(), r.y + settings.numberoffset);
230 // adjust elements
231 labelpos.adjustDiv(settings.$label);
232 minpos.adjustDiv(settings.$min);
233 maxpos.adjustDiv(settings.$max);
234 // set the handle
235 $this.slider('setval');
236
237 // mousedown handler: start sliding
238 var sliderStart = function (event) {
239 $body.on("mousemove.slider", sliderMove);
240 $body.on("mouseup.slider", sliderEnd);
241 return false;
242 };
243
244 // mousemove handler: move slider
245 var sliderMove = function (event) {
246 var pos = geom.position(event);
247 $this.slider('moveto', pos, true);
248 settings.$label.text(label + settings.val);
249 return false;
250 };
251
252 // mouseup handler: end sliding
253 var sliderEnd = function (event) {
254 $body.off("mousemove.slider");
255 $body.off("mouseup.slider");
256 return false;
257 };
258
259 // bind mousedown handler to sliderhandle
260 settings.$handle.on('mousedown.slider', sliderStart);
261 console.debug('show slider: ', $this, ' settings:', settings);
262 };
263
264 var destroy = function() {
265 var $this = this;
266 var settings = $this.data('settings');
267 var $handle = settings.$handle;
268 $handle.off('mousedown.slider');
269 fn.withdraw($this);
270 }; 94 };
271 95
272 // assign button actions to sliders (rotate, brightness, contrast) 96 // assign button actions to sliders (rotate, brightness, contrast)
273 var setButtonActions = function () { 97 var setButtonActions = function () {
274 if (fn.setButtonAction == null) { 98 if (fn.setButtonAction == null) {
277 } 101 }
278 console.debug('sliders: assign new button actions. digilib:', digilib); 102 console.debug('sliders: assign new button actions. digilib:', digilib);
279 fn.setButtonAction('brgt', 'tinySliderBrgt'); 103 fn.setButtonAction('brgt', 'tinySliderBrgt');
280 fn.setButtonAction('cont', 'tinySliderCont'); 104 fn.setButtonAction('cont', 'tinySliderCont');
281 fn.setButtonAction('rot', 'tinySliderRot'); 105 fn.setButtonAction('rot', 'tinySliderRot');
106 // fn.setButtonAction('rgb', 'tinySliderRGB');
282 }; 107 };
283 108
284 // plugin installation called by digilib on plugin object. 109 // plugin installation called by digilib on plugin object.
285 var install = function (plugin) { 110 var install = function (plugin) {
286 digilib = plugin; 111 digilib = plugin;
291 // add defaults, actions, buttons 116 // add defaults, actions, buttons
292 $.extend(true, digilib.defaults, defaults); // make deep copy 117 $.extend(true, digilib.defaults, defaults); // make deep copy
293 $.extend(digilib.actions, actions); 118 $.extend(digilib.actions, actions);
294 setButtonActions(digilib.buttons); 119 setButtonActions(digilib.buttons);
295 // export functions 120 // export functions
296 fn.setupSlider = setupSlider;
297 fn.setupPanel = setupPanel;
298 }; 121 };
299 122
300 // plugin initialization 123 // plugin initialization
301 var init = function (data) { 124 var init = function (data) {
302 console.debug('initialising sliders plugin. data:', data); 125 console.debug('initialising sliders plugin. data:', data);
303 var settings = data.settings; 126 // var settings = data.settings;
304 var $data = $(data); 127 // var $data = $(data);
305 // we do setup at runtime 128 // we do setup at runtime
306 // $data.bind('setup', handleSetup); 129 // $data.bind('setup', handleSetup);
307 }; 130 };
308 131
309 /** creates the HTML structure for a panel div 132 /** creates a div with a form, setup events and callback
310 */ 133 */
311 var setupPanel = function (data) { 134 var setupFormDiv = function (data, $content, cssSuffix, callback) {
312 var $elem = data.$elem; 135 var cssPrefix = data.settings.cssPrefix;
313 var panelClass = data.settings.cssPrefix + 'panel'; 136 var cls = cssPrefix + cssSuffix;
314 var $panel = $elem.find('.' + panelClass);
315 if ($panel.length == 0) {
316 // new panel
317 $panel = $('<div/>');
318 $panel.addClass(panelClass);
319 $elem.append($panel);
320 $panel.fadeIn();
321 } else {
322 // panel exists, so empty it
323 $panel.empty();
324 }
325 var $okcancel = setupOkCancel(data);
326 $panel.append($okcancel);
327 return $panel;
328 };
329
330 /** creates the HTML structure for a slider div
331 */
332 var setupSlider = function (data, paramname, opts) {
333 var id = "slider-" + paramname;
334 var $div = $('#' + id);
335 if ($div.length > 0) {
336 return $div;
337 }
338 // slider not yet created
339 var cssClass = data.cssPrefix+'slider';
340 var html = '\ 137 var html = '\
341 <div id="'+id+' class="'+cssClass+'">\ 138 <div class="'+cls+'">\
342 <div class="'+cssClass+'handle"/>\ 139 <form class="'+cls+'">\
343 <div class="'+cssClass+'number">'+options.min+'</div>\ 140 <input class="'+cls+'cancel" type="button" value="Cancel"/>\
344 <div class="'+cssClass+'number">'+options.max+'</div>\ 141 <input type="submit" name="sub" value="Ok"/>\
345 <div class="'+cssClass+'label">\
346 <span>'+options.label+'</span>\
347 <input class="'+cssClass+'input">'+options.start+'</input>\
348 </div>\
349 </div>';
350 var $div = $(html);
351 var $handle = $div.find('div.'+cssClass+'handle');
352 var $label = $div.find('div.'+cssClass+'label');
353 var $input = $div.find('div.'+cssClass+'input');
354 var $numbers = $div.find('div.'+cssClass+'number');
355 var $min = $numbers[0];
356 var $max = $numbers[1];
357 var options = defaults;
358 $.extend(options, sliderOptions[paramname], opts);
359 $.extend(options, {
360 '$handle' : $handle,
361 '$label' : $label,
362 '$input' : $input,
363 '$min' : $min,
364 '$max' : $max,
365 'diff' : options.max - options.min,
366 'vertical' : options.direction == 'y',
367 'val' : options.start,
368 'handlerect' : geom.rectangle(0, 0, options.handlesize, options.handlesize)
369 });
370 $div.data(options);
371 console.debug('new slider: ', $div, ', options: ', options);
372 return $div;
373 };
374
375 /** creates the HTML structure for a ok and cancel div
376 */
377 var setupOkCancel = function (data) {
378 var settings = data.settings;
379 var cssPrefix = settings.cssPrefix;
380 var html = '\
381 <div>\
382 <button class="'+cssPrefix+'button" id="'+cssPrefix+'Ok">OK</button>\
383 <button class="'+cssPrefix+'button" id="'+cssPrefix+'Cancel">Cancel</button>\
384 </div>';
385 var $div = $(html);
386 var handler = function(event) {
387 var $panel = $(this).parents('.'+cssPrefix+'panel');
388 if (event.keyCode == 27 || event.target.id == cssPrefix+'Cancel') {
389 var callback = $panel.data['cancel'];
390 if (callback) {
391 callback(data);
392 }
393 }
394 if (event.keyCode == 13 || event.target.id == cssPrefix+'Ok') {
395 var callback = $panel.data['ok'];
396 if (callback) {
397 callback(data);
398 }
399 }
400 fn.withdraw($panel);
401 return false;
402 };
403 $div.children().on('click', handler);
404 return $div;
405 };
406
407 /** creates a TinyRangeSlider
408 */
409 var setupTinyRangeSlider = function (data, paramname, callback) {
410 var $elem = data.$elem;
411 var opts = sliderOptions[paramname];
412 var param = data.settings[paramname] || opts.start;
413 var cssPrefix = data.settings.cssPrefix;
414 var cssClass = cssPrefix + 'tinyslider';
415 var sliderHtml = '\
416 <div class="'+cssClass+'" title="'+opts.tooltip+'">\
417 <form class="'+cssClass+'">\
418 <span>'+opts.label+'</span>\
419 <input type="range" class="'+cssClass+'range" name="'+paramname+'" step="'+opts.step+'" min="'+opts.min+'" max="'+opts.max+'" value="'+param+'"/>\
420 <input type="text" class="'+cssClass+'text" name="'+paramname+'" size="4" value="'+param+'"/>\
421 <br/>\
422 <input class="'+cssClass+'cancel" type="button" value="Cancel"/><input type="submit" name="sub" value="Ok"/>\
423 </form>\ 142 </form>\
424 </div>'; 143 </div>';
425 var $slider = $(sliderHtml); 144 var $elem = data.$elem;
426 $elem.append($slider); 145 var $div = $(html).appendTo($elem);
427 $slider.fadeIn(); 146 var $form = $div.find('form');
428 var $range = $slider.find('input.'+cssClass+'range'); 147 $form.prepend($content);
429 var $text = $slider.find('input.'+cssClass+'text'); 148 // handle submit
149 $form.on('submit', function () {
150 callback();
151 fn.withdraw($div);
152 return false;
153 });
154 // handle cancel
155 $form.find('.'+cls+'cancel').on('click', function () {
156 fn.withdraw($div);
157 });
158 // show div
159 $div.fadeIn();
430 // fix non-HTML5 slider 160 // fix non-HTML5 slider
161 var tiny = cssPrefix + 'tinyslider';
162 var $range = $form.find('input.'+tiny+'range');
431 var HTML5 = $range.prop('type') === 'range'; 163 var HTML5 = $range.prop('type') === 'range';
432 if (!HTML5) { 164 if (!HTML5) {
433 console.debug('fix input type=range'); 165 console.debug('fix input type=range');
434 $range.range({change: function (val) { 166 $range.range({change: function (val) {
435 $range.trigger('change'); 167 $range.trigger('change');
436 }}); 168 }});
437 } 169 }
170 fn.centerOnScreen(data, $div);
171 return $div;
172 };
173
174 /** creates a TinyRangeSlider
175 */
176 var tinySlider = function (data, paramname, startval) {
177 var $elem = data.$elem;
178 var opts = sliderOptions[paramname];
179 var param = startval || data.settings[paramname] || opts.start;
180 var cssPrefix = data.settings.cssPrefix;
181 var cls = cssPrefix + 'tinyslider';
182 var html = '\
183 <div class="'+cls+'frame">\
184 <span>'+opts.label+'</span>\
185 <input type="range" class="'+cls+'range" name="'+paramname+'" step="'+opts.step+'" min="'+opts.min+'" max="'+opts.max+'" value="'+param+'"/>\
186 <input type="text" class="'+cls+'text" name="'+paramname+'" size="4" value="'+param+'"/>\
187 </div>';
188 var $slider = $(html);
189 var $range = $slider.find('input.'+cls+'range');
190 var $text = $slider.find('input.'+cls+'text');
191 $slider.data({'$text' : $text, '$range' : $range});
438 // connect slider and input 192 // connect slider and input
439 $range.on('change', function () { 193 $range.on('change', function () {
440 // TinyRange rounds to integer values, not always desired
441 var val = $range.val(); 194 var val = $range.val();
442 $text.val(val); 195 $text.val(val);
443 }); 196 });
444 $text.on('change', function () { 197 $text.on('change', function () {
445 var val = $text.val(); 198 var val = $text.val();
446 $range.val(val); 199 $range.val(val);
200 // val doesn't change the slider handle position in Tinyrange
201 // can't use a jQuery "valHook" here because input type is reported as "text" (???)
202 var HTML5 = $range.prop('type') === 'range';
447 if (!HTML5) { 203 if (!HTML5) {
448 $range.range('set', val); 204 $range.range('set', val);
449 } 205 }
450 }); 206 });
451 // handle submit 207 return $slider;
452 $slider.find('form').on('submit', function () { 208 };
453 // console.debug("brgt-form:", this, " sub=", this.sub); 209
454 callback($text.val()); 210 /** creates a single TinyRangeSlider for param "paramname",
455 fn.withdraw($slider); 211 the new value is passed to the "callback" function.
456 return false; 212 */
457 }); 213 var singleSlider = function (data, paramname, callback) {
458 // handle cancel 214 var $slider = tinySlider(data, paramname);
459 $slider.find('.'+cssClass+'cancel').on('click', function () { 215 var getValue = function () {
460 fn.withdraw($slider); 216 var val = $slider.data('$text').val();
461 }); 217 callback(val);
462 fn.centerOnScreen(data, $slider); 218 };
219 setupFormDiv(data, $slider, 'singleslider', getValue);
220 };
221
222 /** creates a compound RGB slider
223 the new values are passed to the "callback" function.
224 */
225 var rgbSlider = function (data, callback) {
226 var cls = data.settings.cssPrefix + 'rgbslider';
227 var $table = $('<table class="'+cls+'" />');
228 var makeSliders = function(index, value) {
229 // TODO: set start values
230 var $tr = $('<tr/>').appendTo($table);
231 var $td = $('<td class="color">'+rgb[value].label+'</td>').appendTo($tr);
232 var $td = $('<td class="rgb"/>').append(tinySlider(data, 'brgt')).appendTo($tr);
233 var $td = $('<td class="rgb"/>').append(tinySlider(data, 'cont')).appendTo($tr);
234 }
235 $.each(['r','g','b'], makeSliders);
236 var getValue = function () {
237 // TODO: get values from sliders
238 callback(null, null);
239 };
240 setupFormDiv(data, $table, 'rgbslider', getValue);
463 }; 241 };
464 242
465 // plugin object with name and init 243 // plugin object with name and init
466 // shared objects filled by digilib on registration 244 // shared objects filled by digilib on registration
467 var plugin = { 245 var plugin = {