source: trunk/www.guidonia.net/wp/wp-content/themes/atahualpa/options/jscolor/jscolor.js@ 44

Last change on this file since 44 was 44, checked in by luciano, 14 years ago
File size: 15.8 KB
Line 
1/**
2 * JavaScript Color Picker
3 *
4 * @author Honza Odvarko, http://odvarko.cz
5 * @copyright Honza Odvarko
6 * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
7 * @version 1.0.8
8 * @link http://jscolor.com
9 */
10
11
12jscolor_register() // register jscolor_init() at page load
13
14
15function jscolor_register() {
16 if(typeof window.onload == 'function') {
17 var f = window.onload
18 window.onload = function() {
19 if(f)/* IE7 */ f()
20 jscolor_init()
21 }
22 } else {
23 window.onload = jscolor_init
24 }
25}
26
27
28function jscolor_init() {
29
30 // bind <input class="..."> elements
31 var bindClass = 'color'
32
33 // set field's background according selected color?
34 var reflectOnBackground = true
35
36 // prepend field's color code with #
37 var leadingHash = false
38
39 // allow an empty value in the field instead of setting it to #000000
40 var allowEmpty = false
41
42 // spectrum's width and height
43 var HVSize = [ 180, 101 ] // normal
44 //var HVSize = [ 120, 69 ] // small
45 //var HVSize = [ 102, 61 ] // tiny
46
47 var padding = 10
48 var borderWidth = 1
49 var HVCrossSize = [ 15, 15 ]
50 var SSize = 22
51 var SArrowSize = [ 7, 11 ]
52 var SSampleSize = 4
53 var ClientSliderSize = 18
54
55 var instanceId = 0
56 var instance
57 var elements = {}
58
59 var dir = function() {
60 var base = location.href
61
62 var e = document.getElementsByTagName('base')
63 for(var i=0; i<e.length; i++) {
64 if(e[i].href) base = e[i].href
65 }
66
67 var e = document.getElementsByTagName('script')
68 for(var i=0; i<e.length; i++) {
69 if(e[i].src) {
70 var src = new URI(e[i].src)
71 if(/\/jscolor\.js$/.test(src.path)) {
72 var srcAbs = src.toAbsolute(base).toString()
73 delete srcAbs.query
74 delete srcAbs.fragment
75 return srcAbs.replace(/[^\/]+$/, '') // remove filename from path
76 }
77 }
78 }
79 return false
80 }()
81
82
83 function createDialog() {
84
85 // dialog
86 elements.dialog = document.createElement('div')
87 setStyle(elements.dialog, {
88 'zIndex' : '100',
89 'clear' : 'both',
90 'position' : 'absolute',
91 'width' : HVSize[0]+SSize+3*padding+'px',
92 'height' : HVSize[1]+2*padding+'px',
93 'border' : borderWidth+'px solid ThreeDHighlight',
94 'borderRightColor' : 'ThreeDShadow', 'borderBottomColor' : 'ThreeDShadow',
95 'background' : "url('"+dir+"hv"+HVSize[0]+'x'+HVSize[1]+".png') "+padding+"px "+padding+"px no-repeat ThreeDFace"
96 })
97 elements.dialog.onmousedown = function() {
98 instance.preserve = true
99 }
100 elements.dialog.onmousemove = function(e) {
101 if(instance.holdHV) setHV(e)
102 if(instance.holdS) setS(e)
103 }
104 elements.dialog.onmouseup = elements.dialog.onmouseout = function() {
105 if(instance.holdHV || instance.holdS) {
106 instance.holdHV = instance.holdS = false
107 if(typeof instance.input.onchange == 'function') instance.input.onchange()
108 }
109 instance.input.focus()
110 }
111
112 // hue/value spectrum
113 elements.hv = document.createElement('div')
114 setStyle(elements.hv, {
115 'position' : 'absolute',
116 'left' : '0',
117 'top' : '0',
118 'width' : HVSize[0]+2*padding+'px',
119 'height' : HVSize[1]+2*padding+'px',
120 'background' : "url('"+dir+"cross.gif') no-repeat",
121 'cursor' : 'crosshair'
122 })
123 var setHV = function(e) {
124 var p = getMousePos(e)
125 var relX = p[0]<instance.posHV[0] ? 0 : (p[0]-instance.posHV[0]>HVSize[0]-1 ? HVSize[0]-1 : p[0]-instance.posHV[0])
126 var relY = p[1]<instance.posHV[1] ? 0 : (p[1]-instance.posHV[1]>HVSize[1]-1 ? HVSize[1]-1 : p[1]-instance.posHV[1])
127 instance.color.setHSV(6/HVSize[0]*relX, null, 1-1/(HVSize[1]-1)*relY)
128 updateDialogPointers()
129 updateDialogSaturation()
130 updateInput(instance.input, instance.color, null)
131 }
132 elements.hv.onmousedown = function(e) { instance.holdHV = true; setHV(e) }
133 elements.dialog.appendChild(elements.hv)
134
135 // saturation gradient
136 elements.grad = document.createElement('div')
137 setStyle(elements.grad, {
138 'position' : 'absolute',
139 'left' : HVSize[0]+SArrowSize[0]+2*padding+'px',
140 'top' : padding+'px',
141 'width' : SSize-SArrowSize[0]+'px'
142 })
143 // saturation gradient's samples
144 for(var i=0; i+SSampleSize<=HVSize[1]; i+=SSampleSize) {
145 var g = document.createElement('div')
146 g.style.height = SSampleSize+'px'
147 g.style.fontSize = '1px'
148 g.style.lineHeight = '0'
149 elements.grad.appendChild(g)
150 }
151 elements.dialog.appendChild(elements.grad)
152
153 // saturation slider
154 elements.s = document.createElement('div')
155 setStyle(elements.s, {
156 'position' : 'absolute',
157 'left' : HVSize[0]+2*padding+'px',
158 'top' : '0',
159 'width' : SSize+padding+'px',
160 'height' : HVSize[1]+2*padding+'px',
161 'background' : "url('"+dir+"s.gif') no-repeat"
162 })
163 // IE 5 fix
164 try {
165 elements.s.style.cursor = 'pointer'
166 } catch(eOldIE) {
167 elements.s.style.cursor = 'hand'
168 }
169 var setS = function(e) {
170 var p = getMousePos(e)
171 var relY = p[1]<instance.posS[1] ? 0 : (p[1]-instance.posS[1]>HVSize[1]-1 ? HVSize[1]-1 : p[1]-instance.posS[1])
172 instance.color.setHSV(null, 1-1/(HVSize[1]-1)*relY, null)
173 updateDialogPointers()
174 updateInput(instance.input, instance.color, null)
175 }
176 elements.s.onmousedown = function(e) { instance.holdS = true; setS(e) }
177 elements.dialog.appendChild(elements.s)
178 }
179
180
181 function showDialog(input) {
182 var is = [ input.offsetWidth, input.offsetHeight ]
183 var ip = getElementPos(input)
184 var sp = getScrollPos()
185 var ws = getWindowSize()
186 var ds = [
187 HVSize[0]+SSize+3*padding+2*borderWidth,
188 HVSize[1]+2*padding+2*borderWidth
189 ]
190 var dp = [
191 -sp[0]+ip[0]+ds[0] > ws[0]-ClientSliderSize ? (-sp[0]+ip[0]+is[0]/2 > ws[0]/2 ? ip[0]+is[0]-ds[0] : ip[0]) : ip[0],
192 -sp[1]+ip[1]+is[1]+ds[1] > ws[1]-ClientSliderSize ? (-sp[1]+ip[1]+is[1]/2 > ws[1]/2 ? ip[1]-ds[1] : ip[1]+is[1]) : ip[1]+is[1]
193 ]
194
195 instanceId++
196 instance = {
197 input : input,
198 color : new color(input.value),
199 preserve : false,
200 holdHV : false,
201 holdS : false,
202 posHV : [ dp[0]+borderWidth+padding, dp[1]+borderWidth+padding ],
203 posS : [ dp[0]+borderWidth+HVSize[0]+2*padding, dp[1]+borderWidth+padding ]
204 }
205
206 updateDialogPointers()
207 updateDialogSaturation()
208
209 elements.dialog.style.left = dp[0]+'px'
210 elements.dialog.style.top = dp[1]+'px'
211 document.getElementsByTagName('body')[0].appendChild(elements.dialog)
212 }
213
214
215 function hideDialog() {
216 var b = document.getElementsByTagName('body')[0]
217 b.removeChild(elements.dialog)
218
219 instance = null
220 }
221
222
223 function updateDialogPointers() {
224 // update hue/value cross
225 var x = Math.round(instance.color.hue/6*HVSize[0])
226 var y = Math.round((1-instance.color.value)*(HVSize[1]-1))
227 elements.hv.style.backgroundPosition =
228 (padding-Math.floor(HVCrossSize[0]/2)+x)+'px '+
229 (padding-Math.floor(HVCrossSize[1]/2)+y)+'px'
230
231 // update saturation arrow
232 var y = Math.round((1-instance.color.saturation)*HVSize[1])
233 elements.s.style.backgroundPosition = '0 '+(padding-Math.floor(SArrowSize[1]/2)+y)+'px'
234 }
235
236
237 function updateDialogSaturation() {
238 // update saturation gradient
239 var r, g, b, s, c = [ instance.color.value, 0, 0 ]
240 var i = Math.floor(instance.color.hue)
241 var f = i%2 ? instance.color.hue-i : 1-(instance.color.hue-i)
242 switch(i) {
243 case 6:
244 case 0: r=0;g=1;b=2; break
245 case 1: r=1;g=0;b=2; break
246 case 2: r=2;g=0;b=1; break
247 case 3: r=2;g=1;b=0; break
248 case 4: r=1;g=2;b=0; break
249 case 5: r=0;g=2;b=1; break
250 }
251 var gr = elements.grad.childNodes
252 for(var i=0; i<gr.length; i++) {
253 s = 1 - 1/(gr.length-1)*i
254 c[1] = c[0] * (1 - s*f)
255 c[2] = c[0] * (1 - s)
256 gr[i].style.backgroundColor = 'rgb('+(c[r]*100)+'%,'+(c[g]*100)+'%,'+(c[b]*100)+'%)'
257 }
258 }
259
260
261 function bindInputs() {
262 var onfocus = function() {
263 if(instance && instance.preserve) {
264 instance.preserve = false
265 } else {
266 showDialog(this)
267 }
268 }
269 var onblur = function() {
270 if(instance && instance.preserve) return
271
272 var This = this
273 var Id = instanceId
274 setTimeout(function() {
275 if(instance && instance.preserve) return
276
277 if(instance && instanceId == Id) hideDialog() // if dialog hasn't been already shown by another instance
278 updateInput(This, new color(This.value), This.value)
279 }, 0)
280 }
281 var setcolor = function(str) {
282 var c = new color(str)
283 updateInput(this, c, str)
284 if(instance && instance.input == this) {
285 instance.color = c
286 updateDialogPointers()
287 updateDialogSaturation()
288 }
289 }
290
291 var e = document.getElementsByTagName('input')
292 var matchClass = new RegExp('\\s'+bindClass+'\\s')
293
294 for(var i=0; i<e.length; i++) {
295 if(e[i].type == 'text' && matchClass.test(' '+e[i].className+' ')) {
296
297 e[i].originalStyle = {
298 'color' : e[i].style.color,
299 'backgroundColor' : e[i].style.backgroundColor
300 }
301 e[i].setAttribute('autocomplete', 'off')
302 e[i].onfocus = onfocus
303 e[i].onblur = onblur
304 e[i].setcolor = setcolor
305
306 updateInput(e[i], new color(e[i].value), e[i].value)
307 }
308 }
309 }
310
311
312 function updateInput(e, color, realValue) {
313 if(allowEmpty && realValue != null && !/^\s*#?([0-9A-F]{3}([0-9A-F]{3})?)\s*$/i.test(realValue)) {
314 e.value = ''
315 if(reflectOnBackground) {
316 e.style.backgroundColor = e.originalStyle.backgroundColor
317 e.style.color = e.originalStyle.color
318 }
319 } else {
320 e.value = (leadingHash?'#':'')+color
321 if(reflectOnBackground) {
322 e.style.backgroundColor = '#'+color
323 e.style.color =
324 0.212671 * color.red +
325 0.715160 * color.green +
326 0.072169 * color.blue
327 < 0.5 ? '#FFF' : '#000'
328 }
329 }
330 }
331
332
333 function setStyle(e, properties) {
334 for(var p in properties) eval('e.style.'+p+' = properties[p]')
335 }
336
337
338 function getElementPos(e) {
339 var x=0, y=0
340 if(e.offsetParent) {
341 do {
342 x += e.offsetLeft
343 y += e.offsetTop
344 } while(e = e.offsetParent)
345 }
346 return [ x, y ]
347 }
348
349
350 function getMousePos(e) {
351 if(!e) var e = window.event
352 var x=0, y=0
353 if(typeof e.pageX == 'number') {
354 x = e.pageX
355 y = e.pageY
356 } else if(typeof e.clientX == 'number') {
357 x = e.clientX+document.documentElement.scrollLeft+document.body.scrollLeft
358 y = e.clientY+document.documentElement.scrollTop+document.body.scrollTop
359 }
360 return [ x, y ]
361 }
362
363
364 function getScrollPos() {
365 var x=0, y=0
366 if(typeof window.pageYOffset == 'number') {
367 x = window.pageXOffset
368 y = window.pageYOffset
369 } else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) {
370 x = document.body.scrollLeft
371 y = document.body.scrollTop
372 } else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
373 x = document.documentElement.scrollLeft
374 y = document.documentElement.scrollTop
375 }
376 return [ x, y ]
377 }
378
379
380 function getWindowSize() {
381 var w=0, h=0
382 if(typeof window.innerWidth == 'number') {
383 w = window.innerWidth
384 h = window.innerHeight
385 } else if(document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
386 w = document.documentElement.clientWidth
387 h = document.documentElement.clientHeight
388 } else if(document.body && (document.body.clientWidth || document.body.clientHeight)) {
389 w = document.body.clientWidth
390 h = document.body.clientHeight
391 }
392 return [ w, h ]
393 }
394
395
396 function color(hex) {
397
398 this.hue = 0 // 0-6
399 this.saturation = 0 // 0-1
400 this.value = 0 // 0-1
401
402 this.red = 0 // 0-1
403 this.green = 0 // 0-1
404 this.blue = 0 // 0-1
405
406 this.setRGB = function(r, g, b) { // null = don't change
407 var hsv = RGB_HSV(
408 r==null ? this.red : (this.red=r),
409 g==null ? this.green : (this.green=g),
410 b==null ? this.blue : (this.blue=b)
411 )
412 if(hsv[0] != null) {
413 this.hue = hsv[0]
414 }
415 this.saturation = hsv[1]
416 this.value = hsv[2]
417 }
418
419 this.setHSV = function(h, s, v) { // null = don't change
420 var rgb = HSV_RGB(
421 h==null ? this.hue : (this.hue=h),
422 s==null ? this.saturation : (this.saturation=s),
423 v==null ? this.value : (this.value=v)
424 )
425 this.red = rgb[0]
426 this.green = rgb[1]
427 this.blue = rgb[2]
428 }
429
430 function RGB_HSV(r, g, b) {
431 var n = Math.min(Math.min(r,g),b)
432 var v = Math.max(Math.max(r,g),b)
433 var m = v - n
434 if(m == 0) return [ null, 0, v ]
435 var h = r==n ? 3+(b-g)/m : (g==n ? 5+(r-b)/m : 1+(g-r)/m)
436 return [ h==6?0:h, m/v, v ]
437 }
438
439 function HSV_RGB(h, s, v) {
440 if(h == null) return [ v, v, v ]
441 var i = Math.floor(h)
442 var f = i%2 ? h-i : 1-(h-i)
443 var m = v * (1 - s)
444 var n = v * (1 - s*f)
445 switch(i) {
446 case 6:
447 case 0: return [ v, n, m ]
448 case 1: return [ n, v, m ]
449 case 2: return [ m, v, n ]
450 case 3: return [ m, n, v ]
451 case 4: return [ n, m, v ]
452 case 5: return [ v, m, n ]
453 }
454 }
455
456 this.setString = function(hex) {
457 var m = hex.match(/^\s*#?([0-9A-F]{3}([0-9A-F]{3})?)\s*$/i)
458 if(m) {
459 if(m[1].length==6) { // 6x hex
460 this.setRGB(
461 parseInt(m[1].substr(0,2),16)/255,
462 parseInt(m[1].substr(2,2),16)/255,
463 parseInt(m[1].substr(4,2),16)/255
464 )
465 } else { // 3x hex
466 this.setRGB(
467 parseInt(m[1].charAt(0)+m[1].charAt(0),16)/255,
468 parseInt(m[1].charAt(1)+m[1].charAt(1),16)/255,
469 parseInt(m[1].charAt(2)+m[1].charAt(2),16)/255
470 )
471 }
472 } else {
473 this.setRGB(0,0,0)
474 return false
475 }
476 }
477
478 this.toString = function() {
479 var r = Math.round(this.red * 255).toString(16)
480 var g = Math.round(this.green * 255).toString(16)
481 var b = Math.round(this.blue * 255).toString(16)
482 return (
483 (r.length==1 ? '0'+r : r)+
484 (g.length==1 ? '0'+g : g)+
485 (b.length==1 ? '0'+b : b)
486 ).toUpperCase()
487 }
488
489 if(hex) {
490 this.setString(hex)
491 }
492
493 }
494
495
496 function URI(uri) { // See RFC3986
497
498 this.scheme = null
499 this.authority = null
500 this.path = ''
501 this.query = null
502 this.fragment = null
503
504 this.parse = function(uri) {
505 var m = uri.match(/^(([A-Za-z][0-9A-Za-z+.-]*)(:))?((\/\/)([^\/?#]*))?([^?#]*)((\?)([^#]*))?((#)(.*))?/)
506 this.scheme = m[3] ? m[2] : null
507 this.authority = m[5] ? m[6] : null
508 this.path = m[7]
509 this.query = m[9] ? m[10] : null
510 this.fragment = m[12] ? m[13] : null
511 return this
512 }
513
514 this.toString = function() {
515 var result = ''
516 if(this.scheme != null) result = result + this.scheme + ':'
517 if(this.authority != null) result = result +'//'+ this.authority
518 if(this.path != null) result = result + this.path
519 if(this.query != null) result = result + '?'+ this.query
520 if(this.fragment != null) result = result + '#'+ this.fragment
521 return result
522 }
523
524 this.toAbsolute = function(base) {
525 var base = new URI(base)
526 var r = this
527 var t = new URI
528
529 if(base.scheme == null) return false
530
531 if(r.scheme != null && r.scheme.toLowerCase() == base.scheme.toLowerCase()) {
532 r.scheme = null
533 }
534
535 if(r.scheme != null) {
536 t.scheme = r.scheme
537 t.authority = r.authority
538 t.path = removeDotSegments(r.path)
539 t.query = r.query
540 } else {
541 if(r.authority != null) {
542 t.authority = r.authority
543 t.path = removeDotSegments(r.path)
544 t.query = r.query
545 } else {
546 if(r.path == '') {
547 t.path = base.path
548 if(r.query != null) {
549 t.query = r.query
550 } else {
551 t.query = base.query
552 }
553 } else {
554 if(r.path.substr(0,1) == '/') {
555 t.path = removeDotSegments(r.path)
556 } else {
557 if(base.authority != null && base.path == '') {
558 t.path = '/'+r.path
559 } else {
560 t.path = base.path.replace(/[^\/]+$/,'')+r.path
561 }
562 t.path = removeDotSegments(t.path)
563 }
564 t.query = r.query
565 }
566 t.authority = base.authority
567 }
568 t.scheme = base.scheme
569 }
570 t.fragment = r.fragment
571
572 return t
573 }
574
575 function removeDotSegments(path) {
576 var out = ''
577 while(path) {
578 if(path.substr(0,3)=='../' || path.substr(0,2)=='./') {
579 path = path.replace(/^\.+/,'').substr(1)
580 } else if(path.substr(0,3)=='/./' || path=='/.') {
581 path = '/'+path.substr(3)
582 } else if(path.substr(0,4)=='/../' || path=='/..') {
583 path = '/'+path.substr(4)
584 out = out.replace(/\/?[^\/]*$/, '')
585 } else if(path=='.' || path=='..') {
586 path = ''
587 } else {
588 var rm = path.match(/^\/?[^\/]*/)[0]
589 path = path.substr(rm.length)
590 out = out + rm
591 }
592 }
593 return out
594 }
595
596 if(uri) {
597 this.parse(uri)
598 }
599
600 }
601
602 // init
603 createDialog()
604 bindInputs()
605
606}
Note: See TracBrowser for help on using the repository browser.