/[colormatch]/trunk/slider.js
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/slider.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Sat Oct 2 23:24:01 2004 UTC (19 years, 5 months ago) by dpavlin
File MIME type: application/javascript
File size: 15965 byte(s)
imported original ColorMatch

1 /*----------------------------------------------------------------------------\
2 | Slider 1.0 |
3 |-----------------------------------------------------------------------------|
4 | Created by Erik Arvidsson |
5 | (http://webfx.eae.net/contact.html#erik) |
6 | For WebFX (http://webfx.eae.net/) |
7 |-----------------------------------------------------------------------------|
8 | A slider control that degrades to an input control for non supported |
9 | browsers. |
10 |-----------------------------------------------------------------------------|
11 | Copyright (c) 1999 - 2002 Erik Arvidsson |
12 |-----------------------------------------------------------------------------|
13 | This software is provided "as is", without warranty of any kind, express or |
14 | implied, including but not limited to the warranties of merchantability, |
15 | fitness for a particular purpose and noninfringement. In no event shall the |
16 | authors or copyright holders be liable for any claim, damages or other |
17 | liability, whether in an action of contract, tort or otherwise, arising |
18 | from, out of or in connection with the software or the use or other |
19 | dealings in the software. |
20 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
21 | This software is available under the three different licenses mentioned |
22 | below. To use this software you must chose, and qualify, for one of those. |
23 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
24 | The WebFX Non-Commercial License http://webfx.eae.net/license.html |
25 | Permits anyone the right to use the software in a non-commercial context |
26 | free of charge. |
27 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
28 | The WebFX Commercial license http://webfx.eae.net/commercial.html |
29 | Permits the license holder the right to use the software in a commercial |
30 | context. Such license must be specifically obtained, however it's valid for |
31 | any number of implementations of the licensed software. |
32 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
33 | GPL - The GNU General Public License http://www.gnu.org/licenses/gpl.txt |
34 | Permits anyone the right to use and modify the software without limitations |
35 | as long as proper credits are given and the original and modified source |
36 | code are included. Requires that the final product, software derivate from |
37 | the original source or any software utilizing a GPL component, such as |
38 | this, is also licensed under the GPL license. |
39 |-----------------------------------------------------------------------------|
40 | 2002-10-14 | Original version released |
41 |-----------------------------------------------------------------------------|
42 | Dependencies: timer.js - an OO abstraction of timers |
43 | range.js - provides the data model for the slider |
44 | winclassic.css or any other css file describing the look |
45 |-----------------------------------------------------------------------------|
46 | Created 2002-10-14 | All changes are in the log above. | Updated 2002-10-14 |
47 \----------------------------------------------------------------------------*/
48
49
50 Slider.isSupported = typeof document.createElement != "undefined" &&
51 typeof document.documentElement != "undefined" &&
52 typeof document.documentElement.offsetWidth == "number";
53
54
55 function Slider(oElement, oInput, sOrientation) {
56
57 this._orientation = sOrientation || "horizontal";
58 this._range = new Range();
59 this._range.setExtent(0);
60 this._blockIncrement = 10;
61 this._unitIncrement = 1;
62 this._timer = new Timer(100);
63
64
65 if (Slider.isSupported && oElement) {
66
67 this.document = oElement.ownerDocument || oElement.document;
68
69 this.element = oElement;
70 this.element.slider = this;
71 this.element.unselectable = "on";
72
73 // add class name tag to class name
74 this.element.className = this._orientation + " " + this.classNameTag + " " + this.element.className;
75
76 // create line
77 this.line = this.document.createElement("DIV");
78 this.line.className = "line";
79 this.line.unselectable = "on";
80 this.line.appendChild(this.document.createElement("DIV"));
81 this.element.appendChild(this.line);
82
83 // create handle
84 this.handle = this.document.createElement("DIV");
85 this.handle.className = "handle";
86 this.handle.unselectable = "on";
87 this.handle.appendChild(this.document.createElement("DIV"));
88 this.handle.firstChild.appendChild(
89 this.document.createTextNode(String.fromCharCode(160)));
90 this.element.appendChild(this.handle);
91 }
92
93 this.input = oInput;
94
95 // events
96 var oThis = this;
97 this._range.onchange = function () {
98 oThis.recalculate();
99 if (typeof oThis.onchange == "function")
100 oThis.onchange();
101 };
102
103 if (Slider.isSupported && oElement) {
104 this.element.onfocus = Slider.eventHandlers.onfocus;
105 this.element.onblur = Slider.eventHandlers.onblur;
106 this.element.onmousedown = Slider.eventHandlers.onmousedown;
107 this.element.onmouseover = Slider.eventHandlers.onmouseover;
108 this.element.onmouseout = Slider.eventHandlers.onmouseout;
109 this.element.onkeydown = Slider.eventHandlers.onkeydown;
110 this.element.onkeypress = Slider.eventHandlers.onkeypress;
111 this.element.onmousewheel = Slider.eventHandlers.onmousewheel;
112 this.handle.onselectstart =
113 this.element.onselectstart = function () { return false; };
114
115 this._timer.ontimer = function () {
116 oThis.ontimer();
117 };
118
119 // extra recalculate for ie
120 window.setTimeout(function() {
121 oThis.recalculate();
122 }, 1);
123 }
124 else {
125 this.input.onchange = function (e) {
126 oThis.setValue(oThis.input.value);
127 };
128 }
129 }
130
131 Slider.eventHandlers = {
132
133 // helpers to make events a bit easier
134 getEvent: function (e, el) {
135 if (!e) {
136 if (el)
137 e = el.document.parentWindow.event;
138 else
139 e = window.event;
140 }
141 if (!e.srcElement) {
142 var el = e.target;
143 while (el != null && el.nodeType != 1)
144 el = el.parentNode;
145 e.srcElement = el;
146 }
147 if (typeof e.offsetX == "undefined") {
148 e.offsetX = e.layerX;
149 e.offsetY = e.layerY;
150 }
151
152 return e;
153 },
154
155 getDocument: function (e) {
156 if (e.target)
157 return e.target.ownerDocument;
158 return e.srcElement.document;
159 },
160
161 getSlider: function (e) {
162 var el = e.target || e.srcElement;
163 while (el != null && el.slider == null) {
164 el = el.parentNode;
165 }
166 if (el)
167 return el.slider;
168 return null;
169 },
170
171 getLine: function (e) {
172 var el = e.target || e.srcElement;
173 while (el != null && el.className != "line") {
174 el = el.parentNode;
175 }
176 return el;
177 },
178
179 getHandle: function (e) {
180 var el = e.target || e.srcElement;
181 var re = /handle/;
182 while (el != null && !re.test(el.className)) {
183 el = el.parentNode;
184 }
185 return el;
186 },
187 // end helpers
188
189 onfocus: function (e) {
190 var s = this.slider;
191 s._focused = true;
192 s.handle.className = "handle hover";
193 },
194
195 onblur: function (e) {
196 var s = this.slider
197 s._focused = false;
198 s.handle.className = "handle";
199 },
200
201 onmouseover: function (e) {
202 e = Slider.eventHandlers.getEvent(e, this);
203 var s = this.slider;
204 if (e.srcElement == s.handle)
205 s.handle.className = "handle hover";
206 },
207
208 onmouseout: function (e) {
209 e = Slider.eventHandlers.getEvent(e, this);
210 var s = this.slider;
211 if (e.srcElement == s.handle && !s._focused)
212 s.handle.className = "handle";
213 },
214
215 onmousedown: function (e) {
216 e = Slider.eventHandlers.getEvent(e, this);
217 var s = this.slider;
218 if (s.element.focus)
219 s.element.focus();
220
221 Slider._currentInstance = s;
222 var doc = s.document;
223
224 if (doc.addEventListener) {
225 doc.addEventListener("mousemove", Slider.eventHandlers.onmousemove, true);
226 doc.addEventListener("mouseup", Slider.eventHandlers.onmouseup, true);
227 }
228 else if (doc.attachEvent) {
229 doc.attachEvent("onmousemove", Slider.eventHandlers.onmousemove);
230 doc.attachEvent("onmouseup", Slider.eventHandlers.onmouseup);
231 doc.attachEvent("onlosecapture", Slider.eventHandlers.onmouseup);
232 s.element.setCapture();
233 }
234
235 if (Slider.eventHandlers.getHandle(e)) { // start drag
236 Slider._sliderDragData = {
237 screenX: e.screenX,
238 screenY: e.screenY,
239 dx: e.screenX - s.handle.offsetLeft,
240 dy: e.screenY - s.handle.offsetTop,
241 startValue: s.getValue(),
242 slider: s
243 };
244 }
245 else {
246 var lineEl = Slider.eventHandlers.getLine(e);
247 s._mouseX = e.offsetX + (lineEl ? s.line.offsetLeft : 0);
248 s._mouseY = e.offsetY + (lineEl ? s.line.offsetTop : 0);
249 s._increasing = null;
250 s.ontimer();
251 }
252 },
253
254 onmousemove: function (e) {
255 e = Slider.eventHandlers.getEvent(e, this);
256
257 if (Slider._sliderDragData) { // drag
258 var s = Slider._sliderDragData.slider;
259
260 var boundSize = s.getMaximum() - s.getMinimum();
261 var size, pos, reset;
262
263 if (s._orientation == "horizontal") {
264 size = s.element.offsetWidth - s.handle.offsetWidth;
265 pos = e.screenX - Slider._sliderDragData.dx;
266 reset = Math.abs(e.screenY - Slider._sliderDragData.screenY) > 100;
267 }
268 else {
269 size = s.element.offsetHeight - s.handle.offsetHeight;
270 pos = s.element.offsetHeight - s.handle.offsetHeight -
271 (e.screenY - Slider._sliderDragData.dy);
272 reset = Math.abs(e.screenX - Slider._sliderDragData.screenX) > 100;
273 }
274 s.setValue(reset ? Slider._sliderDragData.startValue :
275 s.getMinimum() + boundSize * pos / size);
276 return false;
277 }
278 else {
279 var s = Slider._currentInstance;
280 if (s != null) {
281 var lineEl = Slider.eventHandlers.getLine(e);
282 s._mouseX = e.offsetX + (lineEl ? s.line.offsetLeft : 0);
283 s._mouseY = e.offsetY + (lineEl ? s.line.offsetTop : 0);
284 }
285 }
286
287 },
288
289 onmouseup: function (e) {
290 e = Slider.eventHandlers.getEvent(e, this);
291 var s = Slider._currentInstance;
292 var doc = s.document;
293 if (doc.removeEventListener) {
294 doc.removeEventListener("mousemove", Slider.eventHandlers.onmousemove, true);
295 doc.removeEventListener("mouseup", Slider.eventHandlers.onmouseup, true);
296 }
297 else if (doc.detachEvent) {
298 doc.detachEvent("onmousemove", Slider.eventHandlers.onmousemove);
299 doc.detachEvent("onmouseup", Slider.eventHandlers.onmouseup);
300 doc.detachEvent("onlosecapture", Slider.eventHandlers.onmouseup);
301 s.element.releaseCapture();
302 }
303
304 if (Slider._sliderDragData) { // end drag
305 Slider._sliderDragData = null;
306 }
307 else {
308 s._timer.stop();
309 s._increasing = null;
310 }
311 Slider._currentInstance = null;
312 },
313
314 onkeydown: function (e) {
315 e = Slider.eventHandlers.getEvent(e, this);
316 //var s = Slider.eventHandlers.getSlider(e);
317 var s = this.slider;
318 var kc = e.keyCode;
319 switch (kc) {
320 case 33: // page up
321 s.setValue(s.getValue() + s.getBlockIncrement());
322 break;
323 case 34: // page down
324 s.setValue(s.getValue() - s.getBlockIncrement());
325 break;
326 case 35: // end
327 s.setValue(s.getOrientation() == "horizontal" ?
328 s.getMaximum() :
329 s.getMinimum());
330 break;
331 case 36: // home
332 s.setValue(s.getOrientation() == "horizontal" ?
333 s.getMinimum() :
334 s.getMaximum());
335 break;
336 case 38: // up
337 case 39: // right
338 s.setValue(s.getValue() + s.getUnitIncrement());
339 break;
340
341 case 37: // left
342 case 40: // down
343 s.setValue(s.getValue() - s.getUnitIncrement());
344 break;
345 }
346
347 if (kc >= 33 && kc <= 40) {
348 return false;
349 }
350 },
351
352 onkeypress: function (e) {
353 e = Slider.eventHandlers.getEvent(e, this);
354 var kc = e.keyCode;
355 if (kc >= 33 && kc <= 40) {
356 return false;
357 }
358 },
359
360 onmousewheel: function (e) {
361 e = Slider.eventHandlers.getEvent(e, this);
362 var s = this.slider;
363 s.setValue(s.getValue() + e.wheelDelta / 120 * s.getUnitIncrement());
364 // windows inverts this on horizontal sliders. That does not
365 // make sense to me
366 return false;
367 }
368 };
369
370
371
372 Slider.prototype.classNameTag = "dynamic-slider-control",
373
374 Slider.prototype.setValue = function (v) {
375 this._range.setValue(v);
376 this.input.value = this.getValue();
377 };
378
379 Slider.prototype.getValue = function () {
380 return this._range.getValue();
381 };
382
383 Slider.prototype.setMinimum = function (v) {
384 this._range.setMinimum(v);
385 this.input.value = this.getValue();
386 };
387
388 Slider.prototype.getMinimum = function () {
389 return this._range.getMinimum();
390 };
391
392 Slider.prototype.setMaximum = function (v) {
393 this._range.setMaximum(v);
394 this.input.value = this.getValue();
395 };
396
397 Slider.prototype.getMaximum = function () {
398 return this._range.getMaximum();
399 };
400
401 Slider.prototype.setUnitIncrement = function (v) {
402 this._unitIncrement = v;
403 };
404
405 Slider.prototype.getUnitIncrement = function () {
406 return this._unitIncrement;
407 };
408
409 Slider.prototype.setBlockIncrement = function (v) {
410 this._blockIncrement = v;
411 };
412
413 Slider.prototype.getBlockIncrement = function () {
414 return this._blockIncrement;
415 };
416
417 Slider.prototype.getOrientation = function () {
418 return this._orientation;
419 };
420
421 Slider.prototype.setOrientation = function (sOrientation) {
422 if (sOrientation != this._orientation) {
423 if (Slider.isSupported && this.element) {
424 // add class name tag to class name
425 this.element.className = this.element.className.replace(this._orientation,
426 sOrientation);
427 }
428 this._orientation = sOrientation;
429 this.recalculate();
430
431 }
432 };
433
434 Slider.prototype.recalculate = function() {
435 if (!Slider.isSupported || !this.element) return;
436
437 var w = this.element.offsetWidth;
438 var h = this.element.offsetHeight;
439 var hw = this.handle.offsetWidth;
440 var hh = this.handle.offsetHeight;
441 var lw = this.line.offsetWidth;
442 var lh = this.line.offsetHeight;
443
444 // this assumes a border-box layout
445
446 if (this._orientation == "horizontal") {
447 this.handle.style.left = (w - hw) * (this.getValue() - this.getMinimum()) /
448 (this.getMaximum() - this.getMinimum()) + "px";
449 this.handle.style.top = (h - hh) / 2 + "px";
450
451 this.line.style.top = (h - lh) / 2 + "px";
452 this.line.style.left = hw / 2 + "px";
453 //this.line.style.right = hw / 2 + "px";
454 this.line.style.width = Math.max(0, w - hw - 2)+ "px";
455 this.line.firstChild.style.width = Math.max(0, w - hw - 4)+ "px";
456 }
457 else {
458 this.handle.style.left = (w - hw) / 2 + "px";
459 this.handle.style.top = h - hh - (h - hh) * (this.getValue() - this.getMinimum()) /
460 (this.getMaximum() - this.getMinimum()) + "px";
461
462 this.line.style.left = (w - lw) / 2 + "px";
463 this.line.style.top = hh / 2 + "px";
464 this.line.style.height = Math.max(0, h - hh - 2) + "px"; //hard coded border width
465 //this.line.style.bottom = hh / 2 + "px";
466 this.line.firstChild.style.height = Math.max(0, h - hh - 4) + "px"; //hard coded border width
467 }
468 };
469
470 Slider.prototype.ontimer = function () {
471 var hw = this.handle.offsetWidth;
472 var hh = this.handle.offsetHeight;
473 var hl = this.handle.offsetLeft;
474 var ht = this.handle.offsetTop;
475
476 if (this._orientation == "horizontal") {
477 if (this._mouseX > hl + hw &&
478 (this._increasing == null || this._increasing)) {
479 this.setValue(this.getValue() + this.getBlockIncrement());
480 this._increasing = true;
481 }
482 else if (this._mouseX < hl &&
483 (this._increasing == null || !this._increasing)) {
484 this.setValue(this.getValue() - this.getBlockIncrement());
485 this._increasing = false;
486 }
487 }
488 else {
489 if (this._mouseY > ht + hh &&
490 (this._increasing == null || !this._increasing)) {
491 this.setValue(this.getValue() - this.getBlockIncrement());
492 this._increasing = false;
493 }
494 else if (this._mouseY < ht &&
495 (this._increasing == null || this._increasing)) {
496 this.setValue(this.getValue() + this.getBlockIncrement());
497 this._increasing = true;
498 }
499 }
500
501 this._timer.start();
502 };

  ViewVC Help
Powered by ViewVC 1.1.26