/* * jGraduate 0.3.x * * jQuery Plugin for a gradient picker * * Copyright (c) 2010 Jeff Schiller * http://blog.codedread.com/ * Copyright (c) 2010 Alexis Deveria * http://a.deveria.com/ * * Apache 2 License jGraduate( options, okCallback, cancelCallback ) where options is an object literal: { window: { title: "Pick the start color and opacity for the gradient" }, images: { clientPath: "images/" }, paint: a Paint object } - the Paint object is: Paint { type: String, // one of "none", "solidColor", "linearGradient", "radialGradient" alpha: Number representing opacity (0-100), solidColor: String representing #RRGGBB hex of color, linearGradient: object of interface SVGLinearGradientElement, radialGradient: object of interface SVGRadialGradientElement, } $.jGraduate.Paint() -> constructs a 'none' color $.jGraduate.Paint({copy: o}) -> creates a copy of the paint o $.jGraduate.Paint({hex: "#rrggbb"}) -> creates a solid color paint with hex = "#rrggbb" $.jGraduate.Paint({linearGradient: o, a: 50}) -> creates a linear gradient paint with opacity=0.5 $.jGraduate.Paint({radialGradient: o, a: 7}) -> creates a radial gradient paint with opacity=0.07 $.jGraduate.Paint({hex: "#rrggbb", linearGradient: o}) -> throws an exception? - picker accepts the following object as input: { okCallback: function to call when Ok is pressed cancelCallback: function to call when Cancel is pressed paint: object describing the paint to display initially, if not set, then default to opaque white } - okCallback receives a Paint object * */ (function() { var ns = { svg: 'http://www.w3.org/2000/svg', xlink: 'http://www.w3.org/1999/xlink' }; if(!window.console) { window.console = new function() { this.log = function(str) {}; this.dir = function(str) {}; }; } $.jGraduate = { Paint: function(opt) { var options = opt || {}; this.alpha = options.alpha || 100; // copy paint object if (options.copy) { this.type = options.copy.type; this.alpha = options.copy.alpha; this.solidColor = null; this.linearGradient = null; this.radialGradient = null; switch(this.type) { case "none": break; case "solidColor": this.solidColor = options.copy.solidColor; break; case "linearGradient": this.linearGradient = options.copy.linearGradient.cloneNode(true); break; case "radialGradient": this.radialGradient = options.copy.radialGradient.cloneNode(true); break; } } // create linear gradient paint else if (options.linearGradient) { this.type = "linearGradient"; this.solidColor = null; this.radialGradient = null; this.linearGradient = options.linearGradient.cloneNode(true); } // create linear gradient paint else if (options.radialGradient) { this.type = "radialGradient"; this.solidColor = null; this.linearGradient = null; this.radialGradient = options.radialGradient.cloneNode(true); } // create solid color paint else if (options.solidColor) { this.type = "solidColor"; this.solidColor = options.solidColor; } // create empty paint else { this.type = "none"; this.solidColor = null; this.linearGradient = null; this.radialGradient = null; } } }; jQuery.fn.jGraduateDefaults = { paint: new $.jGraduate.Paint(), window: { pickerTitle: "Drag markers to pick a paint", }, images: { clientPath: "images/", }, }; jQuery.fn.jGraduate = function(options) { var $arguments = arguments; return this.each( function() { var $this = $(this), $settings = $.extend(true, {}, jQuery.fn.jGraduateDefaults, options), id = $this.attr('id'), idref = '#'+$this.attr('id')+' '; if (!idref) { alert('Container element must have an id attribute to maintain unique id strings for sub-elements.'); return; } var okClicked = function() { // TODO: Fix this ugly hack if($this.paint.type == "radialGradient") { $this.paint.linearGradient = null; } else if($this.paint.type == "linearGradient") { $this.paint.radialGradient = null; } else if($this.paint.type == "solidColor") { $this.paint.linearGradient = null; $this.paint.radialGradient = null; } $.isFunction($this.okCallback) && $this.okCallback($this.paint); $this.hide(); }, cancelClicked = function() { $.isFunction($this.cancelCallback) && $this.cancelCallback(); $this.hide(); }; $.extend(true, $this, // public properties, methods, and callbacks { // make a copy of the incoming paint paint: new $.jGraduate.Paint({copy: $settings.paint}), okCallback: $.isFunction($arguments[1]) && $arguments[1] || null, cancelCallback: $.isFunction($arguments[2]) && $arguments[2] || null, }); var pos = $this.position(), color = null; if ($this.paint.type == "none") { $this.paint = $.jGraduate.Paint({solidColor: 'ffffff'}); } $this.addClass('jGraduate_Picker'); $this.html('' + '
' + '
' + '
'); var colPicker = $(idref + '> .jGraduate_colPick'); var lgPicker = $(idref + '> .jGraduate_lgPick'); var rgPicker = $(idref + '> .jGraduate_rgPick'); lgPicker.html( '
' + '

' + $settings.window.pickerTitle + '

' + '
' + '
' + '' + '
' + '
' + '
' + '
' + '' + '
' + '' + '' + '' + '' + '
' + '' + '
' + '
' + '
' + '' + '
' + '' + '' + '' + '' + '
' + '' + '
' + '
' + '
' + '' + '%' + '
' + '
' + '
' + '' + '' + '
' + '
' + '
'); rgPicker.html( '
' + '

' + $settings.window.pickerTitle + '

' + '
' + '
' + '' + '
' + '
' + '
' + '' + '
' + '
Center:' + '
' + '
' + '
Outer:' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '' + '
' + '' + '' + '' + '' + '
' + '
' + '
' + '' + '
' + '
' + '' + '' + '' + '' + '
' + '
' + '
' + '' + '
' + '
' + '%' + '
' + '' + '
' + '
' + '
' + '
' + '
' + '' + '%' + '
' + '
' + '' + '' + '
' + '
' + '
'); // -------------- // Set up all the SVG elements (the gradient, stops and rectangle) var MAX = 256, MARGINX = 0, MARGINY = 0, STOP_RADIUS = 15/2, SIZEX = MAX - 2*MARGINX, SIZEY = MAX - 2*MARGINY; $.each(['lg', 'rg'], function(i) { var grad_id = id + '_' + this; var container = document.getElementById(grad_id+'_jGraduate_GradContainer'); var svg = container.appendChild(document.createElementNS(ns.svg, 'svg')); svg.id = grad_id + '_jgraduate_svg'; svg.setAttribute('width', MAX); svg.setAttribute('height', MAX); svg.setAttribute("xmlns", ns.svg); }); // Linear gradient (function() { var svg = document.getElementById(id + '_lg_jgraduate_svg'); // if we are sent a gradient, import it if ($this.paint.type == "linearGradient") { $this.paint.linearGradient.id = id+'_jgraduate_grad'; $this.paint.linearGradient = svg.appendChild($this.paint.linearGradient.cloneNode(true)); } else { // we create a gradient var grad = svg.appendChild(document.createElementNS(ns.svg, 'linearGradient')); grad.id = id+'_jgraduate_grad'; grad.setAttribute('x1','0.0'); grad.setAttribute('y1','0.0'); grad.setAttribute('x2','1.0'); grad.setAttribute('y2','1.0'); var begin = grad.appendChild(document.createElementNS(ns.svg, 'stop')); begin.setAttribute('offset', '0.0'); begin.setAttribute('stop-color', '#ff0000'); var end = grad.appendChild(document.createElementNS(ns.svg, 'stop')); end.setAttribute('offset', '1.0'); end.setAttribute('stop-color', '#ffff00'); $this.paint.linearGradient = grad; } var gradalpha = $this.paint.alpha; $('#' + id + '_lg_jGraduate_OpacityInput').val(gradalpha); var posx = parseInt(255*(gradalpha/100)) - 4.5; $('#' + id + '_lg_jGraduate_AlphaArrows').css({'margin-left':posx}); var x1 = parseFloat($this.paint.linearGradient.getAttribute('x1')||0.0), y1 = parseFloat($this.paint.linearGradient.getAttribute('y1')||0.0), x2 = parseFloat($this.paint.linearGradient.getAttribute('x2')||1.0), y2 = parseFloat($this.paint.linearGradient.getAttribute('y2')||0.0); var rect = document.createElementNS(ns.svg, 'rect'); rect.id = id + '_lg_jgraduate_rect'; rect.setAttribute('x', MARGINX); rect.setAttribute('y', MARGINY); rect.setAttribute('width', SIZEY); rect.setAttribute('height', SIZEY); rect.setAttribute('fill', 'url(#'+id+'_jgraduate_grad)'); rect.setAttribute('fill-opacity', '1.0'); rect = svg.appendChild(rect); $('#' + id + '_lg_jgraduate_rect').attr('fill-opacity', gradalpha/100); // stop visuals created here var beginStop = document.createElementNS(ns.svg, 'image'); beginStop.id = id + "_stop1"; beginStop.setAttribute('class', 'stop'); beginStop.setAttributeNS(ns.xlink, 'href', $settings.images.clientPath + 'mappoint.gif'); beginStop.setAttributeNS(ns.xlink, "title", "Begin Stop"); beginStop.appendChild(document.createElementNS(ns.svg, 'title')).appendChild( document.createTextNode("Begin Stop")); beginStop.setAttribute('width', 18); beginStop.setAttribute('height', 18); beginStop.setAttribute('x', MARGINX + SIZEX*x1 - STOP_RADIUS); beginStop.setAttribute('y', MARGINY + SIZEY*y1 - STOP_RADIUS); beginStop.setAttribute('cursor', 'move'); // must append only after setting all attributes due to Webkit Bug 27952 // https://bugs.webkit.org/show_bug.cgi?id=27592 beginStop = svg.appendChild(beginStop); var endStop = document.createElementNS(ns.svg, 'image'); endStop.id = id + "_stop2"; endStop.setAttribute('class', 'stop'); endStop.setAttributeNS(ns.xlink, 'href', $settings.images.clientPath + 'mappoint.gif'); endStop.setAttributeNS(ns.xlink, "title", "End Stop"); endStop.appendChild(document.createElementNS(ns.svg, 'title')).appendChild( document.createTextNode("End Stop")); endStop.setAttribute('width', 18); endStop.setAttribute('height', 18); endStop.setAttribute('x', MARGINX + SIZEX*x2 - STOP_RADIUS); endStop.setAttribute('y', MARGINY + SIZEY*y2 - STOP_RADIUS); endStop.setAttribute('cursor', 'move'); endStop = svg.appendChild(endStop); // bind GUI elements $('#'+id+'_lg_jGraduate_Ok').bind('click', function() { $this.paint.type = "linearGradient"; $this.paint.solidColor = null; okClicked(); }); $('#'+id+'_lg_jGraduate_Cancel').bind('click', function(paint) { cancelClicked(); }); var x1 = $this.paint.linearGradient.getAttribute('x1'); if(!x1) x1 = "0.0"; var x1Input = $('#'+id+'_jGraduate_x1'); x1Input.val(x1); x1Input.change( function() { if (isNaN(parseFloat(this.value)) || this.value < 0.0 || this.value > 1.0) { this.value = 0.0; } $this.paint.linearGradient.setAttribute('x1', this.value); beginStop.setAttribute('x', MARGINX + SIZEX*this.value - STOP_RADIUS); }); var y1 = $this.paint.linearGradient.getAttribute('y1'); if(!y1) y1 = "0.0"; var y1Input = $('#'+id+'_jGraduate_y1'); y1Input.val(y1); y1Input.change( function() { if (isNaN(parseFloat(this.value)) || this.value < 0.0 || this.value > 1.0) { this.value = 0.0; } $this.paint.linearGradient.setAttribute('y1', this.value); beginStop.setAttribute('y', MARGINY + SIZEY*this.value - STOP_RADIUS); }); var x2 = $this.paint.linearGradient.getAttribute('x2'); if(!x2) x2 = "1.0"; var x2Input = $('#'+id+'_jGraduate_x2'); x2Input.val(x2); x2Input.change( function() { if (isNaN(parseFloat(this.value)) || this.value < 0.0 || this.value > 1.0) { this.value = 1.0; } $this.paint.linearGradient.setAttribute('x2', this.value); endStop.setAttribute('x', MARGINX + SIZEX*this.value - STOP_RADIUS); }); var y2 = $this.paint.linearGradient.getAttribute('y2'); if(!y2) y2 = "0.0"; y2Input = $('#'+id+'_jGraduate_y2'); y2Input.val(y2); y2Input.change( function() { if (isNaN(parseFloat(this.value)) || this.value < 0.0 || this.value > 1.0) { this.value = 0.0; } $this.paint.linearGradient.setAttribute('y2', this.value); endStop.setAttribute('y', MARGINY + SIZEY*this.value - STOP_RADIUS); }); var stops = $this.paint.linearGradient.getElementsByTagNameNS(ns.svg, 'stop'); var numstops = stops.length; // if there are not at least two stops, then if (numstops < 2) { while (numstops < 2) { $this.paint.linearGradient.appendChild( document.createElementNS(ns.svg, 'stop') ); ++numstops; } stops = $this.paint.linearGradient.getElementsByTagNameNS(ns.svg, 'stop'); } var setLgOpacitySlider = function(e, div) { var offset = div.offset(); var x = (e.pageX - offset.left - parseInt(div.css('border-left-width'))); if (x > 255) x = 255; if (x < 0) x = 0; var posx = x - 4.5; x /= 255; $('#' + id + '_lg_jGraduate_AlphaArrows').css({'margin-left':posx}); $('#' + id + '_lg_jgraduate_rect').attr('fill-opacity', x); x = parseInt(x*100); $('#' + id + '_lg_jGraduate_OpacityInput').val(x); $this.paint.alpha = x; }; // handle dragging on the opacity slider var bSlidingOpacity = false; $('#' + id + '_lg_jGraduate_Opacity').mousedown(function(evt) { setLgOpacitySlider(evt, $(this)); bSlidingOpacity = true; evt.preventDefault(); }).mousemove(function(evt) { if (bSlidingOpacity) { setLgOpacitySlider(evt, $(this)); evt.preventDefault(); } }).mouseup(function(evt) { setLgOpacitySlider(evt, $(this)); bSlidingOpacity = false; evt.preventDefault(); }); // handle dragging the stop around the swatch var draggingStop = null; var startx = -1, starty = -1; // for whatever reason, Opera does not allow $('image.stop') here, // and Firefox 1.5 does not allow $('.stop') $('.stop, #color_picker_lg_jGraduate_GradContainer image').mousedown(function(evt) { draggingStop = this; startx = evt.clientX; starty = evt.clientY; evt.preventDefault(); }); $('#'+id+'_lg_jgraduate_svg').mousemove(function(evt) { if (null != draggingStop) { var dx = evt.clientX - startx; var dy = evt.clientY - starty; startx += dx; starty += dy; var x = parseFloat(draggingStop.getAttribute('x')) + dx; var y = parseFloat(draggingStop.getAttribute('y')) + dy; // clamp stop to the swatch if (x < MARGINX - STOP_RADIUS) x = MARGINX - STOP_RADIUS; if (y < MARGINY - STOP_RADIUS) y = MARGINY - STOP_RADIUS; if (x > MARGINX + SIZEX - STOP_RADIUS) x = MARGINX + SIZEX - STOP_RADIUS; if (y > MARGINY + SIZEY - STOP_RADIUS) y = MARGINY + SIZEY - STOP_RADIUS; draggingStop.setAttribute('x', x); draggingStop.setAttribute('y', y); // calculate stop offset var fracx = (x - MARGINX + STOP_RADIUS)/SIZEX; var fracy = (y - MARGINY + STOP_RADIUS)/SIZEY; if (draggingStop.id == (id+'_stop1')) { x1Input.val(fracx); y1Input.val(fracy); $this.paint.linearGradient.setAttribute('x1', fracx); $this.paint.linearGradient.setAttribute('y1', fracy); } else { x2Input.val(fracx); y2Input.val(fracy); $this.paint.linearGradient.setAttribute('x2', fracx); $this.paint.linearGradient.setAttribute('y2', fracy); } evt.preventDefault(); } }); $('#'+id+'_lg_jgraduate_svg').mouseup(function(evt) { draggingStop = null; }); var beginColor = stops[0].getAttribute('stop-color'); if(!beginColor) beginColor = '#000'; beginColorBox = $('#'+id+'_jGraduate_colorBoxBegin'); beginColorBox.css({'background-color':beginColor}); var beginOpacity = stops[0].getAttribute('stop-opacity'); if(!beginOpacity) beginOpacity = '1.0'; $('#'+id+'lg_jGraduate_beginOpacity').html( (beginOpacity*100)+'%' ); var endColor = stops[stops.length-1].getAttribute('stop-color'); if(!endColor) endColor = '#000'; endColorBox = $('#'+id+'_jGraduate_colorBoxEnd'); endColorBox.css({'background-color':endColor}); var endOpacity = stops[stops.length-1].getAttribute('stop-opacity'); if(!endOpacity) endOpacity = '1.0'; $('#'+id+'jGraduate_endOpacity').html( (endOpacity*100)+'%' ); $('#'+id+'_jGraduate_colorBoxBegin').click(function() { $('div.jGraduate_LightBox').show(); var colorbox = $(this); var thisAlpha = (parseFloat(beginOpacity)*255).toString(16); while (thisAlpha.length < 2) { thisAlpha = "0" + thisAlpha; } color = beginColor.substr(1) + thisAlpha; $('#'+id+'_jGraduate_stopPicker').css({'left': 100, 'bottom': 15}).jPicker({ window: { title: "Pick the start color and opacity for the gradient" }, images: { clientPath: $settings.images.clientPath }, color: { active: color, alphaSupport: true } }, function(color){ beginColor = color.val('hex') ? ('#'+color.val('hex')) : "none"; beginOpacity = color.val('ahex') ? color.val('ahex')/100 : 1; colorbox.css('background', beginColor); $('#'+id+'_jGraduate_beginOpacity').html(parseInt(beginOpacity*100)+'%'); stops[0].setAttribute('stop-color', beginColor); stops[0].setAttribute('stop-opacity', beginOpacity); $('div.jGraduate_LightBox').hide(); $('#'+id+'_jGraduate_stopPicker').hide(); }, null, function() { $('div.jGraduate_LightBox').hide(); $('#'+id+'_jGraduate_stopPicker').hide(); }); }); $('#'+id+'_jGraduate_colorBoxEnd').click(function() { $('div.jGraduate_LightBox').show(); var colorbox = $(this); var thisAlpha = (parseFloat(endOpacity)*255).toString(16); while (thisAlpha.length < 2) { thisAlpha = "0" + thisAlpha; } color = endColor.substr(1) + thisAlpha; $('#'+id+'_jGraduate_stopPicker').css({'left': 100, 'top': 15}).jPicker({ window: { title: "Pick the end color and opacity for the gradient" }, images: { clientPath: $settings.images.clientPath }, color: { active: color, alphaSupport: true } }, function(color){ endColor = color.val('hex') ? ('#'+color.val('hex')) : "none"; endOpacity = color.val('ahex') ? color.val('ahex')/100 : 1; colorbox.css('background', endColor); $('#'+id+'_jGraduate_endOpacity').html(parseInt(endOpacity*100)+'%'); stops[1].setAttribute('stop-color', endColor); stops[1].setAttribute('stop-opacity', endOpacity); $('div.jGraduate_LightBox').hide(); $('#'+id+'_jGraduate_stopPicker').hide(); }, null, function() { $('div.jGraduate_LightBox').hide(); $('#'+id+'_jGraduate_stopPicker').hide(); }); }); // -------------- var thisAlpha = ($this.paint.alpha*255/100).toString(16); while (thisAlpha.length < 2) { thisAlpha = "0" + thisAlpha; } color = $this.paint.solidColor == "none" ? "" : $this.paint.solidColor + thisAlpha; $.extend($.fn.jPicker.defaults.window, { alphaSupport: true, effects: {type: 'show',speed: 0} }); colPicker.jPicker( { window: { title: $settings.window.pickerTitle}, images: { clientPath: $settings.images.clientPath }, color: { active: color, alphaSupport: true } }, function(color) { $this.paint.alpha = color.val('ahex') ? Math.round((color.val('a') / 255) * 100) : 100; $this.paint.solidColor = color.val('hex') ? color.val('hex') : "none"; $this.paint.linearGradient = null; okClicked(); }, null, function(){ cancelClicked(); } ); }()); // Radial gradient (function() { var svg = document.getElementById(id + '_rg_jgraduate_svg'); // if we are sent a gradient, import it if ($this.paint.type == "radialGradient") { $this.paint.radialGradient.id = id+'_rg_jgraduate_grad'; $this.paint.radialGradient = svg.appendChild($this.paint.radialGradient.cloneNode(true)); } else { // we create a gradient var grad = svg.appendChild(document.createElementNS(ns.svg, 'radialGradient')); grad.id = id+'_rg_jgraduate_grad'; grad.setAttribute('cx','0.5'); grad.setAttribute('cy','0.5'); grad.setAttribute('r','0.5'); var begin = grad.appendChild(document.createElementNS(ns.svg, 'stop')); begin.setAttribute('offset', '0.0'); begin.setAttribute('stop-color', '#ff0000'); var end = grad.appendChild(document.createElementNS(ns.svg, 'stop')); end.setAttribute('offset', '1.0'); end.setAttribute('stop-color', '#ffff00'); $this.paint.radialGradient = grad; } var gradalpha = $this.paint.alpha; $('#' + id + '_rg_jGraduate_OpacityInput').val(gradalpha); var posx = parseInt(255*(gradalpha/100)) - 4.5; $('#' + id + '_rg_jGraduate_AlphaArrows').css({'margin-left':posx}); var grad = $this.paint.radialGradient; var cx = parseFloat(grad.getAttribute('cx')||0.5), cy = parseFloat(grad.getAttribute('cy')||0.5), fx = parseFloat(grad.getAttribute('fx')||0.5), fy = parseFloat(grad.getAttribute('fy')||0.5); // No match, so show focus point var showFocus = grad.getAttribute('fx') != null && !(cx == fx && cy == fy); var rect = document.createElementNS(ns.svg, 'rect'); rect.id = id + '_rg_jgraduate_rect'; rect.setAttribute('x', MARGINX); rect.setAttribute('y', MARGINY); rect.setAttribute('width', SIZEY); rect.setAttribute('height', SIZEY); rect.setAttribute('fill', 'url(#'+id+'_rg_jgraduate_grad)'); rect.setAttribute('fill-opacity', '1.0'); rect = svg.appendChild(rect); $('#' + id + '_rg_jgraduate_rect').attr('fill-opacity', gradalpha/100); // stop visuals created here var centerPoint = document.createElementNS(ns.svg, 'image'); centerPoint.id = id + "_center_pt"; centerPoint.setAttribute('class', 'stop'); centerPoint.setAttributeNS(ns.xlink, 'href', $settings.images.clientPath + 'mappoint_c.png'); centerPoint.setAttributeNS(ns.xlink, "title", "Center Point"); centerPoint.appendChild(document.createElementNS(ns.svg, 'title')).appendChild( document.createTextNode("Center Point")); centerPoint.setAttribute('width', 18); centerPoint.setAttribute('height', 18); centerPoint.setAttribute('x', MARGINX + SIZEX*cx - STOP_RADIUS); centerPoint.setAttribute('y', MARGINY + SIZEY*cy - STOP_RADIUS); centerPoint.setAttribute('cursor', 'move'); var focusPoint = document.createElementNS(ns.svg, 'image'); focusPoint.id = id + "_focus_pt"; focusPoint.setAttribute('class', 'stop'); focusPoint.setAttributeNS(ns.xlink, 'href', $settings.images.clientPath + 'mappoint_f.png'); focusPoint.setAttributeNS(ns.xlink, "title", "Focus Point"); focusPoint.appendChild(document.createElementNS(ns.svg, 'title')).appendChild( document.createTextNode("Focus Point")); focusPoint.setAttribute('width', 18); focusPoint.setAttribute('height', 18); focusPoint.setAttribute('x', MARGINX + SIZEX*fx - STOP_RADIUS); focusPoint.setAttribute('y', MARGINY + SIZEY*fy - STOP_RADIUS); focusPoint.setAttribute('cursor', 'move'); // must append only after setting all attributes due to Webkit Bug 27952 // https://bugs.webkit.org/show_bug.cgi?id=27592 // centerPoint is added last so it is moved first focusPoint = svg.appendChild(focusPoint); centerPoint = svg.appendChild(centerPoint); // bind GUI elements $('#'+id+'_rg_jGraduate_Ok').bind('click', function() { $this.paint.type = "radialGradient"; $this.paint.solidColor = null; okClicked(); }); $('#'+id+'_rg_jGraduate_Cancel').bind('click', function(paint) { cancelClicked(); }); var cx = $this.paint.radialGradient.getAttribute('cx'); if(!cx) cx = "0.0"; var cxInput = $('#'+id+'_jGraduate_cx'); cxInput.val(cx); cxInput.change( function() { if (isNaN(parseFloat(this.value)) || this.value < 0.0 || this.value > 1.0) { this.value = 0.0; } $this.paint.radialGradient.setAttribute('cx', this.value); centerPoint.setAttribute('x', MARGINX + SIZEX*this.value - STOP_RADIUS); }); var cy = $this.paint.radialGradient.getAttribute('cy'); if(!cy) cy = "0.0"; var cyInput = $('#'+id+'_jGraduate_cy'); cyInput.val(cy); cyInput.change( function() { if (isNaN(parseFloat(this.value)) || this.value < 0.0 || this.value > 1.0) { this.value = 0.0; } $this.paint.radialGradient.setAttribute('cy', this.value); centerPoint.setAttribute('y', MARGINY + SIZEY*this.value - STOP_RADIUS); }); var fx = $this.paint.radialGradient.getAttribute('fx'); if(!fx) fx = "1.0"; var fxInput = $('#'+id+'_jGraduate_fx'); fxInput.val(fx); fxInput.change( function() { if (isNaN(parseFloat(this.value)) || this.value < 0.0 || this.value > 1.0) { this.value = 1.0; } $this.paint.radialGradient.setAttribute('fx', this.value); focusPoint.setAttribute('x', MARGINX + SIZEX*this.value - STOP_RADIUS); }); var fy = $this.paint.radialGradient.getAttribute('fy'); if(!fy) fy = "0.0"; var fyInput = $('#'+id+'_jGraduate_fy'); fyInput.val(fy); fyInput.change( function() { if (isNaN(parseFloat(this.value)) || this.value < 0.0 || this.value > 1.0) { this.value = 0.0; } $this.paint.radialGradient.setAttribute('fy', this.value); focusPoint.setAttribute('y', MARGINY + SIZEY*this.value - STOP_RADIUS); }); if(!showFocus) { focusPoint.setAttribute('display', 'none'); fxInput.val(""); fyInput.val(""); } $("#" + id + "_jGraduate_match_ctr")[0].checked = !showFocus; var lastfx, lastfy; $("#" + id + "_jGraduate_match_ctr").change(function() { showFocus = !this.checked; focusPoint.setAttribute('display', showFocus?'inline':'none'); fxInput.val(""); fyInput.val(""); var grad = $this.paint.radialGradient; if(!showFocus) { lastfx = grad.getAttribute('fx'); lastfy = grad.getAttribute('fy'); grad.removeAttribute('fx'); grad.removeAttribute('fy'); } else { var fx = lastfx || .5; var fy = lastfy || .5; grad.setAttribute('fx', fx); grad.setAttribute('fy', fy); fxInput.val(fx); fyInput.val(fy); } }); var stops = $this.paint.radialGradient.getElementsByTagNameNS(ns.svg, 'stop'); var numstops = stops.length; // if there are not at least two stops, then if (numstops < 2) { while (numstops < 2) { $this.paint.radialGradient.appendChild( document.createElementNS(ns.svg, 'stop') ); ++numstops; } stops = $this.paint.radialGradient.getElementsByTagNameNS(ns.svg, 'stop'); } var radius = $this.paint.radialGradient.getAttribute('r')-0; var radiusx = parseInt((245/2)*(radius)) - 4.5; $('#' + id + '_jGraduate_RadiusArrows').css({'margin-left':radiusx}); $('#' + id + '_jGraduate_RadiusInput').val(parseInt(radius*100)).change(function(e) { var x = this.value / 100; if(x < 0.01) { x = 0.01; } $this.paint.radialGradient.setAttribute('r', x); // Allow higher value, but pretend it's the max for the slider if(x > 2) x = 2; var posx = parseInt((245/2) * x) - 4.5; $('#' + id + '_jGraduate_RadiusArrows').css({'margin-left':posx}); }); var setRgOpacitySlider = function(e, div) { var offset = div.offset(); var x = (e.pageX - offset.left - parseInt(div.css('border-left-width'))); if (x > 255) x = 255; if (x < 0) x = 0; var posx = x - 4.5; x /= 255; $('#' + id + '_rg_jGraduate_AlphaArrows').css({'margin-left':posx}); $('#' + id + '_rg_jgraduate_rect').attr('fill-opacity', x); x = parseInt(x*100); $('#' + id + '_rg_jGraduate_OpacityInput').val(x); $this.paint.alpha = x; }; // handle dragging on the opacity slider var bSlidingOpacity = false; $('#' + id + '_rg_jGraduate_Opacity').mousedown(function(evt) { setRgOpacitySlider(evt, $(this)); bSlidingOpacity = true; evt.preventDefault(); }).mousemove(function(evt) { if (bSlidingOpacity) { setRgOpacitySlider(evt, $(this)); evt.preventDefault(); } }).mouseup(function(evt) { setRgOpacitySlider(evt, $(this)); bSlidingOpacity = false; evt.preventDefault(); }); var setRadiusSlider = function(e, div) { var offset = div.offset(); var x = (e.pageX - offset.left - parseInt(div.css('border-left-width'))); if (x > 245) x = 245; if (x <= 1) x = 1; var posx = x - 5; x /= (245/2); $('#' + id + '_jGraduate_RadiusArrows').css({'margin-left':posx}); $this.paint.radialGradient.setAttribute('r', x); x = parseInt(x*100); $('#' + id + '_jGraduate_RadiusInput').val(x); }; // handle dragging on the radius slider var bSlidingRadius = false; $('#' + id + '_jGraduate_Radius').mousedown(function(evt) { setRadiusSlider(evt, $(this)); bSlidingRadius = true; evt.preventDefault(); }).mousemove(function(evt) { if (bSlidingRadius) { setRadiusSlider(evt, $(this)); evt.preventDefault(); } }).mouseup(function(evt) { setRadiusSlider(evt, $(this)); bSlidingRadius = false; evt.preventDefault(); }); // handle dragging the stop around the swatch var draggingStop = null; var startx = -1, starty = -1; // for whatever reason, Opera does not allow $('image.stop') here, // and Firefox 1.5 does not allow $('.stop') $('.stop, #color_picker_rg_jGraduate_GradContainer image').mousedown(function(evt) { draggingStop = this; startx = evt.clientX; starty = evt.clientY; evt.preventDefault(); }); $('#'+id+'_rg_jgraduate_svg').mousemove(function(evt) { if (null != draggingStop) { var dx = evt.clientX - startx; var dy = evt.clientY - starty; startx += dx; starty += dy; var x = parseFloat(draggingStop.getAttribute('x')) + dx; var y = parseFloat(draggingStop.getAttribute('y')) + dy; // clamp stop to the swatch if (x < MARGINX - STOP_RADIUS) x = MARGINX - STOP_RADIUS; if (y < MARGINY - STOP_RADIUS) y = MARGINY - STOP_RADIUS; if (x > MARGINX + SIZEX - STOP_RADIUS) x = MARGINX + SIZEX - STOP_RADIUS; if (y > MARGINY + SIZEY - STOP_RADIUS) y = MARGINY + SIZEY - STOP_RADIUS; draggingStop.setAttribute('x', x); draggingStop.setAttribute('y', y); // calculate stop offset var fracx = (x - MARGINX + STOP_RADIUS)/SIZEX; var fracy = (y - MARGINY + STOP_RADIUS)/SIZEY; if (draggingStop.id == (id+'_center_pt')) { cxInput.val(fracx); cyInput.val(fracy); $this.paint.radialGradient.setAttribute('cx', fracx); $this.paint.radialGradient.setAttribute('cy', fracy); if(!showFocus) { $this.paint.radialGradient.setAttribute('fx', fracx); $this.paint.radialGradient.setAttribute('fy', fracy); } } else { fxInput.val(fracx); fyInput.val(fracy); $this.paint.radialGradient.setAttribute('fx', fracx); $this.paint.radialGradient.setAttribute('fy', fracy); } evt.preventDefault(); } }); $('#'+id+'_rg_jgraduate_svg').mouseup(function(evt) { draggingStop = null; }); var centerColor = stops[0].getAttribute('stop-color'); if(!centerColor) centerColor = '#000'; centerColorBox = $('#'+id+'_jGraduate_colorBoxCenter'); centerColorBox.css({'background-color':centerColor}); var centerOpacity = stops[0].getAttribute('stop-opacity'); if(!centerOpacity) centerOpacity = '1.0'; $('#'+id+'jGraduate_centerOpacity').html( (centerOpacity*100)+'%' ); var outerColor = stops[stops.length-1].getAttribute('stop-color'); if(!outerColor) outerColor = '#000'; outerColorBox = $('#'+id+'_jGraduate_colorBoxOuter'); outerColorBox.css({'background-color':outerColor}); var outerOpacity = stops[stops.length-1].getAttribute('stop-opacity'); if(!outerOpacity) outerOpacity = '1.0'; $('#'+id+'rg_jGraduate_outerOpacity').html( (outerOpacity*100)+'%' ); $('#'+id+'_jGraduate_colorBoxCenter').click(function() { $('div.jGraduate_LightBox').show(); var colorbox = $(this); var thisAlpha = (parseFloat(centerOpacity)*255).toString(16); while (thisAlpha.length < 2) { thisAlpha = "0" + thisAlpha; } color = centerColor.substr(1) + thisAlpha; $('#'+id+'_rg_jGraduate_stopPicker').css({'left': 100, 'bottom': 15}).jPicker({ window: { title: "Pick the center color and opacity for the gradient" }, images: { clientPath: $settings.images.clientPath }, color: { active: color, alphaSupport: true } }, function(color){ centerColor = color.val('hex') ? ('#'+color.val('hex')) : "none"; centerOpacity = color.val('ahex') ? color.val('ahex')/100 : 1; colorbox.css('background', centerColor); $('#'+id+'_rg_jGraduate_centerOpacity').html(parseInt(centerOpacity*100)+'%'); stops[0].setAttribute('stop-color', centerColor); stops[0].setAttribute('stop-opacity', centerOpacity); $('div.jGraduate_LightBox').hide(); $('#'+id+'_rg_jGraduate_stopPicker').hide(); }, null, function() { $('div.jGraduate_LightBox').hide(); $('#'+id+'_rg_jGraduate_stopPicker').hide(); }); }); $('#'+id+'_jGraduate_colorBoxOuter').click(function() { $('div.jGraduate_LightBox').show(); var colorbox = $(this); var thisAlpha = (parseFloat(outerOpacity)*255).toString(16); while (thisAlpha.length < 2) { thisAlpha = "0" + thisAlpha; } color = outerColor.substr(1) + thisAlpha; $('#'+id+'_rg_jGraduate_stopPicker').css({'left': 100, 'top': 15}).jPicker({ window: { title: "Pick the outer color and opacity for the gradient" }, images: { clientPath: $settings.images.clientPath }, color: { active: color, alphaSupport: true } }, function(color){ outerColor = color.val('hex') ? ('#'+color.val('hex')) : "none"; outerOpacity = color.val('ahex') ? color.val('ahex')/100 : 1; colorbox.css('background', outerColor); $('#'+id+'_jGraduate_outerOpacity').html(parseInt(outerOpacity*100)+'%'); stops[1].setAttribute('stop-color', outerColor); stops[1].setAttribute('stop-opacity', outerOpacity); $('div.jGraduate_LightBox').hide(); $('#'+id+'_rg_jGraduate_stopPicker').hide(); }, null, function() { $('div.jGraduate_LightBox').hide(); $('#'+id+'_rg_jGraduate_stopPicker').hide(); }); }); // -------------- var thisAlpha = ($this.paint.alpha*255/100).toString(16); while (thisAlpha.length < 2) { thisAlpha = "0" + thisAlpha; } color = $this.paint.solidColor == "none" ? "" : $this.paint.solidColor + thisAlpha; colPicker.jPicker( { window: { title: $settings.window.pickerTitle }, images: { clientPath: $settings.images.clientPath }, color: { active: color, alphaSupport: true } }, function(color) { $this.paint.type = "solidColor"; $this.paint.alpha = color.val('ahex') ? Math.round((color.val('a') / 255) * 100) : 100; $this.paint.solidColor = color.val('hex') ? color.val('hex') : "none"; $this.paint.radialGradient = null; okClicked(); }, null, function(){ cancelClicked(); } ); }()); var tabs = $(idref + ' .jGraduate_tabs li'); tabs.click(function() { tabs.removeClass('jGraduate_tab_current'); $(this).addClass('jGraduate_tab_current'); $(idref + " > div").hide(); $(idref + ' .jGraduate_' + $(this).attr('data-type') + 'Pick').show(); }); $(idref + " > div").hide(); tabs.removeClass('jGraduate_tab_current'); var tab; switch ( $this.paint.type ) { case 'linearGradient': tab = $(idref + ' .jGraduate_tab_lingrad'); break; case 'radialGradient': tab = $(idref + ' .jGraduate_tab_radgrad'); break; default: tab = $(idref + ' .jGraduate_tab_color'); break; } $this.show(); // jPicker will try to show after a 0ms timeout, so need to fire this after that setTimeout(function() { tab.addClass('jGraduate_tab_current').click(); }, 10); }); }; })();