/public/jscolor/jscolor.js

http://github.com/mtravers/wuwei · JavaScript · 830 lines · 668 code · 128 blank · 34 comment · 185 complexity · 48cfbe492f6d59b0b21e634d25f189cd MD5 · raw file

  1. /**
  2. * jscolor, JavaScript Color Picker
  3. *
  4. * @version 1.2.3
  5. * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  6. * @author Honza Odvarko <honza@odvarko.cz>
  7. * @created 2008-06-15
  8. * @updated 2009-02-25
  9. * @link http://jscolor.com
  10. */
  11. var jscolor = {
  12. dir : '', // location of jscolor directory (leave empty to autodetect)
  13. bindClass : 'color', // class name
  14. binding : true, // automatic binding via <input class="...">
  15. preloading : true, // use image preloading?
  16. install : function() {
  17. jscolor.addEvent(window, 'load', jscolor.init)
  18. },
  19. init : function() {
  20. if(jscolor.binding) {
  21. jscolor.bind()
  22. }
  23. if(jscolor.preloading) {
  24. jscolor.preload()
  25. }
  26. },
  27. getDir : function() {
  28. if(!jscolor.dir) {
  29. var detected = jscolor.detectDir()
  30. jscolor.dir = detected!=false ? detected : 'jscolor/'
  31. }
  32. return jscolor.dir
  33. },
  34. detectDir : function() {
  35. var base = location.href
  36. var e = document.getElementsByTagName('base')
  37. for(var i=0; i<e.length; i++) {
  38. if(e[i].href) base = e[i].href
  39. }
  40. var e = document.getElementsByTagName('script')
  41. for(var i=0; i<e.length; i++) {
  42. if(e[i].src && /(^|\/)jscolor\.js([?#].*)?$/i.test(e[i].src)) {
  43. var src = new jscolor.URI(e[i].src)
  44. var srcAbs = src.toAbsolute(base)
  45. srcAbs.path = srcAbs.path.replace(/[^\/]+$/, '') // remove filename
  46. delete srcAbs.query
  47. delete srcAbs.fragment
  48. return srcAbs.toString()
  49. }
  50. }
  51. return false
  52. },
  53. bind : function() {
  54. var matchClass = new RegExp('(^|\\s)('+jscolor.bindClass+')\\s*(\\{[^}]*\\})?', 'i')
  55. var e = document.getElementsByTagName('input')
  56. for(var i=0; i<e.length; i++) {
  57. var m
  58. if(!e[i].color && e[i].className && (m = e[i].className.match(matchClass))) {
  59. var prop = {}
  60. if(m[3]) {
  61. try {
  62. eval('prop='+m[3])
  63. } catch(eInvalidProp) {}
  64. }
  65. e[i].color = new jscolor.color(e[i], prop)
  66. }
  67. }
  68. },
  69. preload : function() {
  70. for(var fn in jscolor.imgRequire) {
  71. jscolor.loadImage(fn)
  72. }
  73. },
  74. images : {
  75. pad : [ 181, 101 ],
  76. sld : [ 16, 101 ],
  77. cross : [ 15, 15 ],
  78. arrow : [ 7, 11 ]
  79. },
  80. imgRequire : {},
  81. imgLoaded : {},
  82. requireImage : function(filename) {
  83. jscolor.imgRequire[filename] = true
  84. },
  85. loadImage : function(filename) {
  86. if(!jscolor.imgLoaded[filename]) {
  87. jscolor.imgLoaded[filename] = new Image()
  88. jscolor.imgLoaded[filename].src = jscolor.getDir()+filename
  89. }
  90. },
  91. fetchElement : function(mixed) {
  92. return typeof(mixed) == 'string' ? document.getElementById(mixed) : mixed
  93. },
  94. addEvent : function(el, evnt, func) {
  95. if(el.addEventListener) {
  96. return el.addEventListener(evnt, func, false)
  97. } else if(el.attachEvent) {
  98. return el.attachEvent('on'+evnt, func)
  99. } else {
  100. return false
  101. }
  102. },
  103. fireEvent : function(el, evnt) {
  104. if(!el) {
  105. return false
  106. } else if(document.createEventObject) {
  107. var ev = document.createEventObject()
  108. return el.fireEvent('on'+evnt, ev)
  109. } else if(document.createEvent) {
  110. var ev = document.createEvent('HTMLEvents')
  111. ev.initEvent(evnt, true, true)
  112. return el.dispatchEvent(ev)
  113. } else if(el['on'+evnt]) { // alternatively use the traditional event model (IE5)
  114. return el['on'+evnt]()
  115. } else {
  116. return false
  117. }
  118. },
  119. getElementPos : function(e) {
  120. var e1=e, e2=e
  121. var x=0, y=0
  122. if(e1.offsetParent) {
  123. do {
  124. x += e1.offsetLeft
  125. y += e1.offsetTop
  126. } while(e1 = e1.offsetParent)
  127. }
  128. while((e2 = e2.parentNode) && e2.nodeName != 'BODY') {
  129. x -= e2.scrollLeft
  130. y -= e2.scrollTop
  131. }
  132. return [x, y]
  133. },
  134. getElementSize : function(e) {
  135. return [e.offsetWidth, e.offsetHeight]
  136. },
  137. getMousePos : function(e) {
  138. if(!e) e = window.event
  139. if(typeof e.pageX == 'number') {
  140. return [e.pageX, e.pageY]
  141. } else if(typeof e.clientX == 'number') {
  142. return [
  143. e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft,
  144. e.clientY + document.body.scrollTop + document.documentElement.scrollTop
  145. ]
  146. }
  147. },
  148. getViewPos : function() {
  149. if(typeof window.pageYOffset == 'number') {
  150. return [window.pageXOffset, window.pageYOffset]
  151. } else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) {
  152. return [document.body.scrollLeft, document.body.scrollTop]
  153. } else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
  154. return [document.documentElement.scrollLeft, document.documentElement.scrollTop]
  155. } else {
  156. return [0, 0]
  157. }
  158. },
  159. getViewSize : function() {
  160. if(typeof window.innerWidth == 'number') {
  161. return [window.innerWidth, window.innerHeight]
  162. } else if(document.body && (document.body.clientWidth || document.body.clientHeight)) {
  163. return [document.body.clientWidth, document.body.clientHeight]
  164. } else if(document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
  165. return [document.documentElement.clientWidth, document.documentElement.clientHeight]
  166. } else {
  167. return [0, 0]
  168. }
  169. },
  170. URI : function(uri) { // See RFC3986
  171. this.scheme = null
  172. this.authority = null
  173. this.path = ''
  174. this.query = null
  175. this.fragment = null
  176. this.parse = function(uri) {
  177. var m = uri.match(/^(([A-Za-z][0-9A-Za-z+.-]*)(:))?((\/\/)([^\/?#]*))?([^?#]*)((\?)([^#]*))?((#)(.*))?/)
  178. this.scheme = m[3] ? m[2] : null
  179. this.authority = m[5] ? m[6] : null
  180. this.path = m[7]
  181. this.query = m[9] ? m[10] : null
  182. this.fragment = m[12] ? m[13] : null
  183. return this
  184. }
  185. this.toString = function() {
  186. var result = ''
  187. if(this.scheme != null) result = result + this.scheme + ':'
  188. if(this.authority != null) result = result + '//' + this.authority
  189. if(this.path != null) result = result + this.path
  190. if(this.query != null) result = result + '?' + this.query
  191. if(this.fragment != null) result = result + '#' + this.fragment
  192. return result
  193. }
  194. this.toAbsolute = function(base) {
  195. var base = new jscolor.URI(base)
  196. var r = this
  197. var t = new jscolor.URI
  198. if(base.scheme == null) return false
  199. if(r.scheme != null && r.scheme.toLowerCase() == base.scheme.toLowerCase()) {
  200. r.scheme = null
  201. }
  202. if(r.scheme != null) {
  203. t.scheme = r.scheme
  204. t.authority = r.authority
  205. t.path = removeDotSegments(r.path)
  206. t.query = r.query
  207. } else {
  208. if(r.authority != null) {
  209. t.authority = r.authority
  210. t.path = removeDotSegments(r.path)
  211. t.query = r.query
  212. } else {
  213. if(r.path == '') {
  214. t.path = base.path
  215. if(r.query != null) {
  216. t.query = r.query
  217. } else {
  218. t.query = base.query
  219. }
  220. } else {
  221. if(r.path.substr(0,1) == '/') {
  222. t.path = removeDotSegments(r.path)
  223. } else {
  224. if(base.authority != null && base.path == '') {
  225. t.path = '/'+r.path
  226. } else {
  227. t.path = base.path.replace(/[^\/]+$/,'')+r.path
  228. }
  229. t.path = removeDotSegments(t.path)
  230. }
  231. t.query = r.query
  232. }
  233. t.authority = base.authority
  234. }
  235. t.scheme = base.scheme
  236. }
  237. t.fragment = r.fragment
  238. return t
  239. }
  240. function removeDotSegments(path) {
  241. var out = ''
  242. while(path) {
  243. if(path.substr(0,3)=='../' || path.substr(0,2)=='./') {
  244. path = path.replace(/^\.+/,'').substr(1)
  245. } else if(path.substr(0,3)=='/./' || path=='/.') {
  246. path = '/'+path.substr(3)
  247. } else if(path.substr(0,4)=='/../' || path=='/..') {
  248. path = '/'+path.substr(4)
  249. out = out.replace(/\/?[^\/]*$/, '')
  250. } else if(path=='.' || path=='..') {
  251. path = ''
  252. } else {
  253. var rm = path.match(/^\/?[^\/]*/)[0]
  254. path = path.substr(rm.length)
  255. out = out + rm
  256. }
  257. }
  258. return out
  259. }
  260. if(uri) {
  261. this.parse(uri)
  262. }
  263. },
  264. /*
  265. * Usage example:
  266. * var myColor = new jscolor.color(myInputElement)
  267. */
  268. color : function(target, prop) {
  269. this.required = true // refuse empty values?
  270. this.adjust = true // adjust value to uniform notation?
  271. this.hash = false // prefix color with # symbol?
  272. this.caps = true // uppercase?
  273. this.valueElement = target // value holder
  274. this.styleElement = target // where to reflect current color
  275. this.hsv = [0, 0, 1] // read-only 0-6, 0-1, 0-1
  276. this.rgb = [1, 1, 1] // read-only 0-1, 0-1, 0-1
  277. this.pickerOnfocus = true // display picker on focus?
  278. this.pickerMode = 'HSV' // HSV | HVS
  279. this.pickerPosition = 'bottom' // left | right | top | bottom
  280. this.pickerFace = 10 // px
  281. this.pickerFaceColor = 'ThreeDFace' // CSS color
  282. this.pickerBorder = 1 // px
  283. this.pickerBorderColor = 'ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight' // CSS color
  284. this.pickerInset = 1 // px
  285. this.pickerInsetColor = 'ThreeDShadow ThreeDHighlight ThreeDHighlight ThreeDShadow' // CSS color
  286. this.pickerZIndex = 10000
  287. for(var p in prop) this[p] = prop[p]
  288. this.hidePicker = function() {
  289. if(isPickerOwner()) {
  290. removePicker()
  291. }
  292. }
  293. this.showPicker = function() {
  294. if(!isPickerOwner()) {
  295. var tp = jscolor.getElementPos(target) // target pos
  296. var ts = jscolor.getElementSize(target) // target size
  297. var vp = jscolor.getViewPos() // view pos
  298. var vs = jscolor.getViewSize() // view size
  299. var ps = [ // picker size
  300. 2*this.pickerBorder + 4*this.pickerInset + 2*this.pickerFace + jscolor.images.pad[0] + 2*jscolor.images.arrow[0] + jscolor.images.sld[0],
  301. 2*this.pickerBorder + 2*this.pickerInset + 2*this.pickerFace + jscolor.images.pad[1]
  302. ]
  303. var a, b, c
  304. switch(this.pickerPosition.toLowerCase()) {
  305. case 'left': a=1; b=0; c=-1; break
  306. case 'right':a=1; b=0; c=1; break
  307. case 'top': a=0; b=1; c=-1; break
  308. default: a=0; b=1; c=1; break
  309. }
  310. var l = (ts[b]+ps[b])/2
  311. var pp = [ // picker pos
  312. -vp[a]+tp[a]+ps[a] > vs[a] ?
  313. (-vp[a]+tp[a]+ts[a]/2 > vs[a]/2 && tp[a]+ts[a]-ps[a] >= 0 ? tp[a]+ts[a]-ps[a] : tp[a]) :
  314. tp[a],
  315. -vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ?
  316. (-vp[b]+tp[b]+ts[b]/2 > vs[b]/2 && tp[b]+ts[b]-l-l*c >= 0 ? tp[b]+ts[b]-l-l*c : tp[b]+ts[b]-l+l*c) :
  317. (tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c)
  318. ]
  319. drawPicker(pp[a], pp[b])
  320. }
  321. }
  322. this.importColor = function() {
  323. if(!valueElement) {
  324. this.exportColor()
  325. } else {
  326. if(!this.adjust) {
  327. if(!this.fromString(valueElement.value, leaveValue)) {
  328. styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor
  329. styleElement.style.color = styleElement.jscStyle.color
  330. this.exportColor(leaveValue | leaveStyle)
  331. }
  332. } else if(!this.required && /^\s*$/.test(valueElement.value)) {
  333. valueElement.value = ''
  334. styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor
  335. styleElement.style.color = styleElement.jscStyle.color
  336. this.exportColor(leaveValue | leaveStyle)
  337. } else if(this.fromString(valueElement.value)) {
  338. // OK
  339. } else {
  340. this.exportColor()
  341. }
  342. }
  343. }
  344. this.exportColor = function(flags) {
  345. if(!(flags & leaveValue) && valueElement) {
  346. var value = this.toString()
  347. if(this.caps) value = value.toUpperCase()
  348. if(this.hash) value = '#'+value
  349. valueElement.value = value
  350. }
  351. if(!(flags & leaveStyle) && styleElement) {
  352. styleElement.style.backgroundColor = '#'+this.toString()
  353. styleElement.style.color =
  354. 0.213 * this.rgb[0] +
  355. 0.715 * this.rgb[1] +
  356. 0.072 * this.rgb[2]
  357. < 0.5 ? '#FFF' : '#000'
  358. }
  359. if(!(flags & leavePad) && isPickerOwner()) {
  360. redrawPad()
  361. }
  362. if(!(flags & leaveSld) && isPickerOwner()) {
  363. redrawSld()
  364. }
  365. }
  366. this.fromHSV = function(h, s, v, flags) { // null = don't change
  367. h<0 && (h=0) || h>6 && (h=6)
  368. s<0 && (s=0) || s>1 && (s=1)
  369. v<0 && (v=0) || v>1 && (v=1)
  370. this.rgb = HSV_RGB(
  371. h==null ? this.hsv[0] : (this.hsv[0]=h),
  372. s==null ? this.hsv[1] : (this.hsv[1]=s),
  373. v==null ? this.hsv[2] : (this.hsv[2]=v)
  374. )
  375. this.exportColor(flags)
  376. }
  377. this.fromRGB = function(r, g, b, flags) { // null = don't change
  378. r<0 && (r=0) || r>1 && (r=1)
  379. g<0 && (g=0) || g>1 && (g=1)
  380. b<0 && (b=0) || b>1 && (b=1)
  381. var hsv = RGB_HSV(
  382. r==null ? this.rgb[0] : (this.rgb[0]=r),
  383. g==null ? this.rgb[1] : (this.rgb[1]=g),
  384. b==null ? this.rgb[2] : (this.rgb[2]=b)
  385. )
  386. if(hsv[0] != null) {
  387. this.hsv[0] = hsv[0]
  388. }
  389. if(hsv[2] != 0) {
  390. this.hsv[1] = hsv[1]
  391. }
  392. this.hsv[2] = hsv[2]
  393. this.exportColor(flags)
  394. }
  395. this.fromString = function(hex, flags) {
  396. var m = hex.match(/^\W*([0-9A-F]{3}([0-9A-F]{3})?)\W*$/i)
  397. if(!m) {
  398. return false
  399. } else {
  400. if(m[1].length == 6) { // 6-char notation
  401. this.fromRGB(
  402. parseInt(m[1].substr(0,2),16) / 255,
  403. parseInt(m[1].substr(2,2),16) / 255,
  404. parseInt(m[1].substr(4,2),16) / 255,
  405. flags
  406. )
  407. } else { // 3-char notation
  408. this.fromRGB(
  409. parseInt(m[1].charAt(0)+m[1].charAt(0),16) / 255,
  410. parseInt(m[1].charAt(1)+m[1].charAt(1),16) / 255,
  411. parseInt(m[1].charAt(2)+m[1].charAt(2),16) / 255,
  412. flags
  413. )
  414. }
  415. return true
  416. }
  417. }
  418. this.toString = function() {
  419. return (
  420. (0x100 | Math.round(255*this.rgb[0])).toString(16).substr(1) +
  421. (0x100 | Math.round(255*this.rgb[1])).toString(16).substr(1) +
  422. (0x100 | Math.round(255*this.rgb[2])).toString(16).substr(1)
  423. )
  424. }
  425. function RGB_HSV(r, g, b) {
  426. var n = Math.min(Math.min(r,g),b)
  427. var v = Math.max(Math.max(r,g),b)
  428. var m = v - n
  429. if(m == 0) return [ null, 0, v ]
  430. var h = r==n ? 3+(b-g)/m : (g==n ? 5+(r-b)/m : 1+(g-r)/m)
  431. return [ h==6?0:h, m/v, v ]
  432. }
  433. function HSV_RGB(h, s, v) {
  434. if(h == null) return [ v, v, v ]
  435. var i = Math.floor(h)
  436. var f = i%2 ? h-i : 1-(h-i)
  437. var m = v * (1 - s)
  438. var n = v * (1 - s*f)
  439. switch(i) {
  440. case 6:
  441. case 0: return [v,n,m]
  442. case 1: return [n,v,m]
  443. case 2: return [m,v,n]
  444. case 3: return [m,n,v]
  445. case 4: return [n,m,v]
  446. case 5: return [v,m,n]
  447. }
  448. }
  449. function removePicker() {
  450. delete jscolor.picker.owner
  451. document.getElementsByTagName('body')[0].removeChild(jscolor.picker.boxB)
  452. }
  453. function drawPicker(x, y) {
  454. if(!jscolor.picker) {
  455. jscolor.picker = {
  456. box : document.createElement('div'),
  457. boxB : document.createElement('div'),
  458. pad : document.createElement('div'),
  459. padB : document.createElement('div'),
  460. padM : document.createElement('div'),
  461. sld : document.createElement('div'),
  462. sldB : document.createElement('div'),
  463. sldM : document.createElement('div')
  464. }
  465. for(var i=0,segSize=4; i<jscolor.images.sld[1]; i+=segSize) {
  466. var seg = document.createElement('div')
  467. seg.style.height = segSize+'px'
  468. seg.style.fontSize = '1px'
  469. seg.style.lineHeight = '0'
  470. jscolor.picker.sld.appendChild(seg)
  471. }
  472. jscolor.picker.sldB.appendChild(jscolor.picker.sld)
  473. jscolor.picker.box.appendChild(jscolor.picker.sldB)
  474. jscolor.picker.box.appendChild(jscolor.picker.sldM)
  475. jscolor.picker.padB.appendChild(jscolor.picker.pad)
  476. jscolor.picker.box.appendChild(jscolor.picker.padB)
  477. jscolor.picker.box.appendChild(jscolor.picker.padM)
  478. jscolor.picker.boxB.appendChild(jscolor.picker.box)
  479. }
  480. var p = jscolor.picker
  481. // recompute controls positions
  482. posPad = [
  483. x+THIS.pickerBorder+THIS.pickerFace+THIS.pickerInset,
  484. y+THIS.pickerBorder+THIS.pickerFace+THIS.pickerInset ]
  485. posSld = [
  486. null,
  487. y+THIS.pickerBorder+THIS.pickerFace+THIS.pickerInset ]
  488. // controls interaction
  489. p.box.onmouseup =
  490. p.box.onmouseout = function() { target.focus() }
  491. p.box.onmousedown = function() { abortBlur=true }
  492. p.box.onmousemove = function(e) { holdPad && setPad(e); holdSld && setSld(e) }
  493. p.padM.onmouseup =
  494. p.padM.onmouseout = function() { if(holdPad) { holdPad=false; jscolor.fireEvent(valueElement,'change') } }
  495. p.padM.onmousedown = function(e) { holdPad=true; setPad(e) }
  496. p.sldM.onmouseup =
  497. p.sldM.onmouseout = function() { if(holdSld) { holdSld=false; jscolor.fireEvent(valueElement,'change') } }
  498. p.sldM.onmousedown = function(e) { holdSld=true; setSld(e) }
  499. // picker
  500. p.box.style.width = 4*THIS.pickerInset + 2*THIS.pickerFace + jscolor.images.pad[0] + 2*jscolor.images.arrow[0] + jscolor.images.sld[0] + 'px'
  501. p.box.style.height = 2*THIS.pickerInset + 2*THIS.pickerFace + jscolor.images.pad[1] + 'px'
  502. // picker border
  503. p.boxB.style.position = 'absolute'
  504. p.boxB.style.clear = 'both'
  505. p.boxB.style.left = x+'px'
  506. p.boxB.style.top = y+'px'
  507. p.boxB.style.zIndex = THIS.pickerZIndex
  508. p.boxB.style.border = THIS.pickerBorder+'px solid'
  509. p.boxB.style.borderColor = THIS.pickerBorderColor
  510. p.boxB.style.background = THIS.pickerFaceColor
  511. // pad image
  512. p.pad.style.width = jscolor.images.pad[0]+'px'
  513. p.pad.style.height = jscolor.images.pad[1]+'px'
  514. // pad border
  515. p.padB.style.position = 'absolute'
  516. p.padB.style.left = THIS.pickerFace+'px'
  517. p.padB.style.top = THIS.pickerFace+'px'
  518. p.padB.style.border = THIS.pickerInset+'px solid'
  519. p.padB.style.borderColor = THIS.pickerInsetColor
  520. // pad mouse area
  521. p.padM.style.position = 'absolute'
  522. p.padM.style.left = '0'
  523. p.padM.style.top = '0'
  524. p.padM.style.width = THIS.pickerFace + 2*THIS.pickerInset + jscolor.images.pad[0] + jscolor.images.arrow[0] + 'px'
  525. p.padM.style.height = p.box.style.height
  526. p.padM.style.cursor = 'crosshair'
  527. // slider image
  528. p.sld.style.overflow = 'hidden'
  529. p.sld.style.width = jscolor.images.sld[0]+'px'
  530. p.sld.style.height = jscolor.images.sld[1]+'px'
  531. // slider border
  532. p.sldB.style.position = 'absolute'
  533. p.sldB.style.right = THIS.pickerFace+'px'
  534. p.sldB.style.top = THIS.pickerFace+'px'
  535. p.sldB.style.border = THIS.pickerInset+'px solid'
  536. p.sldB.style.borderColor = THIS.pickerInsetColor
  537. // slider mouse area
  538. p.sldM.style.position = 'absolute'
  539. p.sldM.style.right = '0'
  540. p.sldM.style.top = '0'
  541. p.sldM.style.width = jscolor.images.sld[0] + jscolor.images.arrow[0] + THIS.pickerFace + 2*THIS.pickerInset + 'px'
  542. p.sldM.style.height = p.box.style.height
  543. try {
  544. p.sldM.style.cursor = 'pointer'
  545. } catch(eOldIE) {
  546. p.sldM.style.cursor = 'hand'
  547. }
  548. // load images in optimal order
  549. switch(modeID) {
  550. case 0: var padImg = 'hs.png'; break
  551. case 1: var padImg = 'hv.png'; break
  552. }
  553. p.padM.style.background = "url('"+jscolor.getDir()+"cross.gif') no-repeat"
  554. p.sldM.style.background = "url('"+jscolor.getDir()+"arrow.gif') no-repeat"
  555. p.pad.style.background = "url('"+jscolor.getDir()+padImg+"') 0 0 no-repeat"
  556. // place pointers
  557. redrawPad()
  558. redrawSld()
  559. jscolor.picker.owner = THIS
  560. document.getElementsByTagName('body')[0].appendChild(p.boxB)
  561. }
  562. function redrawPad() {
  563. // redraw the pad pointer
  564. switch(modeID) {
  565. case 0: var yComponent = 1; break
  566. case 1: var yComponent = 2; break
  567. }
  568. var x = Math.round((THIS.hsv[0]/6) * (jscolor.images.pad[0]-1))
  569. var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.pad[1]-1))
  570. jscolor.picker.padM.style.backgroundPosition =
  571. (THIS.pickerFace+THIS.pickerInset+x - Math.floor(jscolor.images.cross[0]/2)) + 'px ' +
  572. (THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.cross[1]/2)) + 'px'
  573. // redraw the slider image
  574. var seg = jscolor.picker.sld.childNodes
  575. switch(modeID) {
  576. case 0:
  577. var rgb = HSV_RGB(THIS.hsv[0], THIS.hsv[1], 1)
  578. for(var i=0; i<seg.length; i++) {
  579. seg[i].style.backgroundColor = 'rgb('+
  580. (rgb[0]*(1-i/seg.length)*100)+'%,'+
  581. (rgb[1]*(1-i/seg.length)*100)+'%,'+
  582. (rgb[2]*(1-i/seg.length)*100)+'%)'
  583. }
  584. break
  585. case 1:
  586. var rgb, s, c = [ THIS.hsv[2], 0, 0 ]
  587. var i = Math.floor(THIS.hsv[0])
  588. var f = i%2 ? THIS.hsv[0]-i : 1-(THIS.hsv[0]-i)
  589. switch(i) {
  590. case 6:
  591. case 0: rgb=[0,1,2]; break
  592. case 1: rgb=[1,0,2]; break
  593. case 2: rgb=[2,0,1]; break
  594. case 3: rgb=[2,1,0]; break
  595. case 4: rgb=[1,2,0]; break
  596. case 5: rgb=[0,2,1]; break
  597. }
  598. for(var i=0; i<seg.length; i++) {
  599. s = 1 - 1/(seg.length-1)*i
  600. c[1] = c[0] * (1 - s*f)
  601. c[2] = c[0] * (1 - s)
  602. seg[i].style.backgroundColor = 'rgb('+
  603. (c[rgb[0]]*100)+'%,'+
  604. (c[rgb[1]]*100)+'%,'+
  605. (c[rgb[2]]*100)+'%)'
  606. }
  607. break
  608. }
  609. }
  610. function redrawSld() {
  611. // redraw the slider pointer
  612. switch(modeID) {
  613. case 0: var yComponent = 2; break
  614. case 1: var yComponent = 1; break
  615. }
  616. var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.sld[1]-1))
  617. jscolor.picker.sldM.style.backgroundPosition =
  618. '0 ' + (THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.arrow[1]/2)) + 'px'
  619. }
  620. function isPickerOwner() {
  621. return jscolor.picker && jscolor.picker.owner == THIS
  622. }
  623. function blurTarget() {
  624. if(valueElement == target) THIS.importColor()
  625. if(THIS.pickerOnfocus) THIS.hidePicker()
  626. }
  627. function blurValue() {
  628. if(valueElement != target) THIS.importColor()
  629. }
  630. function setPad(e) {
  631. var posM = jscolor.getMousePos(e)
  632. var x = posM[0]-posPad[0]
  633. var y = posM[1]-posPad[1]
  634. switch(modeID) {
  635. case 0: THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), 1 - y/(jscolor.images.pad[1]-1), null, leaveSld); break
  636. case 1: THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), null, 1 - y/(jscolor.images.pad[1]-1), leaveSld); break
  637. }
  638. }
  639. function setSld(e) {
  640. var posM = jscolor.getMousePos(e)
  641. var y = posM[1]-posPad[1]
  642. switch(modeID) {
  643. case 0: THIS.fromHSV(null, null, 1 - y/(jscolor.images.sld[1]-1), leavePad); break
  644. case 1: THIS.fromHSV(null, 1 - y/(jscolor.images.sld[1]-1), null, leavePad); break
  645. }
  646. }
  647. var THIS = this
  648. var modeID = this.pickerMode.toLowerCase()=='hvs' ? 1 : 0
  649. var abortBlur = false
  650. var
  651. valueElement = jscolor.fetchElement(this.valueElement),
  652. styleElement = jscolor.fetchElement(this.styleElement)
  653. var
  654. holdPad = false,
  655. holdSld = false
  656. var
  657. posPad,
  658. posSld
  659. var
  660. leaveValue = 1<<0,
  661. leaveStyle = 1<<1,
  662. leavePad = 1<<2,
  663. leaveSld = 1<<3
  664. // target
  665. jscolor.addEvent(target, 'focus', function() {
  666. if(THIS.pickerOnfocus) THIS.showPicker()
  667. })
  668. jscolor.addEvent(target, 'blur', function() {
  669. if(!abortBlur) {
  670. setTimeout(function(){ abortBlur || blurTarget(); abortBlur=false }, 0)
  671. } else {
  672. abortBlur = false
  673. }
  674. })
  675. // valueElement
  676. if(valueElement) {
  677. var updateField = function() {
  678. THIS.fromString(valueElement.value, leaveValue)
  679. }
  680. jscolor.addEvent(valueElement, 'keyup', updateField)
  681. jscolor.addEvent(valueElement, 'input', updateField)
  682. jscolor.addEvent(valueElement, 'blur', blurValue)
  683. valueElement.setAttribute('autocomplete', 'off')
  684. }
  685. // styleElement
  686. if(styleElement) {
  687. styleElement.jscStyle = {
  688. backgroundColor : styleElement.style.backgroundColor,
  689. color : styleElement.style.color
  690. }
  691. }
  692. // require images
  693. switch(modeID) {
  694. case 0: jscolor.requireImage('hs.png'); break
  695. case 1: jscolor.requireImage('hv.png'); break
  696. }
  697. jscolor.requireImage('cross.gif');
  698. jscolor.requireImage('arrow.gif');
  699. this.importColor()
  700. }
  701. }
  702. jscolor.install()