/* * jGraduate 0.4 * * 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, newstop: String of value "same", "inverse", "black" or "white" OR object with one or both values {color: #Hex color, opac: number 0-1} } - 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 = isNaN(options.alpha) ? 100 : options.alpha; // 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/" }, newstop: 'inverse' // same, inverse, black, white }; var isGecko = navigator.userAgent.indexOf('Gecko/') >= 0; function setAttrs(elem, attrs) { if(isGecko) { for (var aname in attrs) elem.setAttribute(aname, attrs[aname]); } else { for (var aname in attrs) { var val = attrs[aname], prop = elem[aname]; if(prop && prop.constructor === 'SVGLength') { prop.baseVal.value = val; } else { elem.setAttribute(aname, val); } } } } function mkElem(name, attrs, newparent) { var elem = document.createElementNS(ns.svg, name); setAttrs(elem, attrs); if(newparent) newparent.appendChild(elem); return elem; } 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() { switch ( $this.paint.type ) { case "radialGradient": $this.paint.linearGradient = null; break; case "linearGradient": $this.paint.radialGradient = null; break; case "solidColor": $this.paint.radialGradient = $this.paint.linearGradient = null; break; } $.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; var $win = $(window); if ($this.paint.type == "none") { $this.paint = $.jGraduate.Paint({solidColor: 'ffffff'}); } $this.addClass('jGraduate_Picker'); $this.html('' + '
' + '
' + '
' + '
' ); var colPicker = $(idref + '> .jGraduate_colPick'); var gradPicker = $(idref + '> .jGraduate_gradPick'); gradPicker.html( '
' + '

' + $settings.window.pickerTitle + '

' + '
' + '
' + '
' + '
' + '
' + '' + '
' + '' + '' + '' + '' + '
' + '
' + '
' + '' + '
' + '' + '' + '' + '' + '
' + '
' + '
' + '
' + '
' + '' + '
' + '' + '' + '' + '' + '
' + '
' + '
' + '' + '
' + '
' + '' + '' + '' + '' + '
' + '
' + '
' + '
' + '' + '
' + '' + '
' + '
' + '
' + '
' + '' + '
' + '' + '
' + '' + '
' + '
' + '' + '
' + '' + '
' + '' + '
' + '
' + '' + '
' + '' + '
' + '' + '
' + '
' + '' + '
' + '' + '
' + '' + '
' + '
' + '
' + '' + '' + '
'); // -------------- // 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; var curType, curGradient, previewRect; var attr_input = {}; var SLIDERW = 145; $('.jGraduate_SliderBar').width(SLIDERW); var container = $('#' + id+'_jGraduate_GradContainer')[0]; var svg = mkElem('svg', { id: id + '_jgraduate_svg', width: MAX, height: MAX, xmlns: ns.svg }, container); // if we are sent a gradient, import it curType = curType || $this.paint.type; var grad = curGradient = $this.paint[curType]; var gradalpha = $this.paint.alpha; var isSolid = curType === 'solidColor'; // Make any missing gradients switch ( curType ) { case "solidColor": // fall through case "linearGradient": if(!isSolid) { curGradient.id = id+'_lg_jgraduate_grad'; grad = curGradient = svg.appendChild(curGradient);//.cloneNode(true)); } mkElem('radialGradient', { id: id + '_rg_jgraduate_grad' }, svg); if(curType === "linearGradient") break; case "radialGradient": if(!isSolid) { curGradient.id = id+'_rg_jgraduate_grad'; grad = curGradient = svg.appendChild(curGradient);//.cloneNode(true)); } mkElem('linearGradient', { id: id + '_lg_jgraduate_grad' }, svg); } if(isSolid) { grad = curGradient = $('#' + id + '_lg_jgraduate_grad')[0]; var color = $this.paint[curType]; mkStop(0, '#' + color, 1); var type = typeof $settings.newstop; if(type === 'string') { switch ( $settings.newstop ) { case 'same': mkStop(1, '#' + color, 1); break; case 'inverse': // Invert current color for second stop var inverted = ''; for(var i = 0; i < 6; i += 2) { var ch = color.substr(i, 2); var inv = (255 - parseInt(color.substr(i, 2), 16)).toString(16); if(inv.length < 2) inv = 0 + inv; inverted += inv; } mkStop(1, '#' + inverted, 1); break; case 'white': mkStop(1, '#ffffff', 1); break; case 'black': mkStop(1, '#000000', 1); break; } } else if(type === 'object'){ var opac = ('opac' in $settings.newstop) ? $settings.newstop.opac : 1; mkStop(1, ($settings.newstop.color || '#' + color), opac); } } var x1 = parseFloat(grad.getAttribute('x1')||0.0), y1 = parseFloat(grad.getAttribute('y1')||0.0), x2 = parseFloat(grad.getAttribute('x2')||1.0), y2 = parseFloat(grad.getAttribute('y2')||0.0); var cx = parseFloat(grad.getAttribute('cx')||0.5), cy = parseFloat(grad.getAttribute('cy')||0.5), fx = parseFloat(grad.getAttribute('fx')|| cx), fy = parseFloat(grad.getAttribute('fy')|| cy); var previewRect = mkElem('rect', { id: id + '_jgraduate_rect', x: MARGINX, y: MARGINY, width: SIZEX, height: SIZEY, fill: 'url(#'+id+'_jgraduate_grad)', 'fill-opacity': gradalpha/100 }, svg); // stop visuals created here var beginCoord = $('
').attr({ 'class': 'grad_coord jGraduate_lg_field', title: 'Begin Stop' }).text(1).css({ top: y1 * MAX, left: x1 * MAX }).data('coord', 'start').appendTo(container); var endCoord = beginCoord.clone().text(2).css({ top: y2 * MAX, left: x2 * MAX }).attr('title', 'End stop').data('coord', 'end').appendTo(container); var centerCoord = $('
').attr({ 'class': 'grad_coord jGraduate_rg_field', title: 'Center stop' }).text('C').css({ top: cy * MAX, left: cx * MAX }).data('coord', 'center').appendTo(container); var focusCoord = centerCoord.clone().text('F').css({ top: fy * MAX, left: fx * MAX, display: 'none' }).attr('title', 'Focus point').data('coord', 'focus').appendTo(container); focusCoord[0].id = id + '_jGraduate_focusCoord'; var coords = $(idref + ' .grad_coord'); // $(container).hover(function() { // coords.animate({ // opacity: 1 // }, 500); // }, function() { // coords.animate({ // opacity: .2 // }, 500); // }); $.each(['x1', 'y1', 'x2', 'y2', 'cx', 'cy', 'fx', 'fy'], function(i, attr) { var attrval = curGradient.getAttribute(attr); var isRadial = isNaN(attr[1]); if(!attrval) { // Set defaults if(isRadial) { // For radial points attrval = "0.5"; } else { // Only x2 is 1 attrval = attr === 'x2' ? "1.0" : "0.0"; } } attr_input[attr] = $('#'+id+'_jGraduate_' + attr) .val(attrval) .change(function() { // TODO: Support values < 0 and > 1 (zoomable preview?) if (isNaN(parseFloat(this.value)) || this.value < 0) { this.value = 0.0; } else if(this.value > 1) { this.value = 1.0; } if(!(attr[0] === 'f' && !showFocus)) { if(isRadial && curType === 'radialGradient' || !isRadial && curType === 'linearGradient') { curGradient.setAttribute(attr, this.value); } } if(isRadial) { var $elem = attr[0] === "c" ? centerCoord : focusCoord; } else { var $elem = attr[1] === "1" ? beginCoord : endCoord; } var cssName = attr.indexOf('x') >= 0 ? 'left' : 'top'; $elem.css(cssName, this.value * MAX); }).change(); }); function mkStop(n, color, opac, sel, stop_elem) { var stop = stop_elem || mkElem('stop',{'stop-color':color,'stop-opacity':opac,offset:n}, curGradient); if(stop_elem) { color = stop_elem.getAttribute('stop-color'); opac = stop_elem.getAttribute('stop-opacity'); n = stop_elem.getAttribute('offset'); } else { curGradient.appendChild(stop); } if(opac === null) opac = 1; var picker_d = 'M-6.2,0.9c3.6-4,6.7-4.3,6.7-12.4c-0.2,7.9,3.1,8.8,6.5,12.4c3.5,3.8,2.9,9.6,0,12.3c-3.1,2.8-10.4,2.7-13.2,0C-9.6,9.9-9.4,4.4-6.2,0.9z'; var pathbg = mkElem('path',{ d: picker_d, fill: 'url(#jGraduate_trans)', transform: 'translate(' + (10 + n * MAX) + ', 26)' }, stopGroup); var path = mkElem('path',{ d: picker_d, fill: color, 'fill-opacity': opac, transform: 'translate(' + (10 + n * MAX) + ', 26)', stroke: '#000', 'stroke-width': 1.5 }, stopGroup); $(path).mousedown(function(e) { selectStop(this); drag = cur_stop; $win.mousemove(dragColor).mouseup(remDrags); stop_offset = stopMakerDiv.offset(); e.preventDefault(); return false; }).data('stop', stop).data('bg', pathbg).dblclick(function() { $('div.jGraduate_LightBox').show(); var colorhandle = this; var stopOpacity = +stop.getAttribute('stop-opacity') || 1; var stopColor = stop.getAttribute('stop-color') || 1; var thisAlpha = (parseFloat(stopOpacity)*255).toString(16); while (thisAlpha.length < 2) { thisAlpha = "0" + thisAlpha; } color = stopColor.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, arg2){ stopColor = color.val('hex') ? ('#'+color.val('hex')) : "none"; stopOpacity = color.val('a') !== null ? color.val('a')/256 : 1; colorhandle.setAttribute('fill', stopColor); colorhandle.setAttribute('fill-opacity', stopOpacity); stop.setAttribute('stop-color', stopColor); stop.setAttribute('stop-opacity', stopOpacity); $('div.jGraduate_LightBox').hide(); $('#'+id+'_jGraduate_stopPicker').hide(); }, null, function() { $('div.jGraduate_LightBox').hide(); $('#'+id+'_jGraduate_stopPicker').hide(); }); }); $(curGradient).find('stop').each(function() { var cur_s = $(this); if(+this.getAttribute('offset') > n) { if(!color) { var newcolor = this.getAttribute('stop-color'); var newopac = this.getAttribute('stop-opacity'); stop.setAttribute('stop-color', newcolor); path.setAttribute('fill', newcolor); stop.setAttribute('stop-opacity', newopac === null ? 1 : newopac); path.setAttribute('fill-opacity', newopac === null ? 1 : newopac); } cur_s.before(stop); return false; } }); if(sel) selectStop(path); return stop; } function remStop() { delStop.setAttribute('display', 'none'); var path = $(cur_stop); var stop = path.data('stop'); var bg = path.data('bg'); $([cur_stop, stop, bg]).remove(); } var stops, stopGroup; var stopMakerDiv = $('#' + id + '_jGraduate_StopSlider'); var cur_stop, stopGroup, stopMakerSVG, drag; var delStop = mkElem('path',{ d:'m9.75,-6l-19.5,19.5m0,-19.5l19.5,19.5', fill:'none', stroke:'#D00', 'stroke-width':5, display:'none' }, stopMakerSVG); function selectStop(item) { if(cur_stop) cur_stop.setAttribute('stroke', '#000'); item.setAttribute('stroke', 'blue'); cur_stop = item; cur_stop.parentNode.appendChild(cur_stop); // stops = $('stop'); // opac_select.val(cur_stop.attr('fill-opacity') || 1); // root.append(delStop); } var stop_offset; function remDrags() { $win.unbind('mousemove', dragColor); if(delStop.getAttribute('display') !== 'none') { remStop(); } drag = null; } var scale_x = 1, scale_y = 1, angle = 0; var c_x = cx; var c_y = cy; function xform() { var rot = angle?'rotate(' + angle + ',' + c_x + ',' + c_y + ') ':''; if(scale_x === 1 && scale_y === 1) { curGradient.removeAttribute('gradientTransform'); // $('#ang').addClass('dis'); } else { var x = -c_x * (scale_x-1); var y = -c_y * (scale_y-1); curGradient.setAttribute('gradientTransform', rot + 'translate(' + x + ',' + y + ') scale(' + scale_x + ',' + scale_y + ')'); // $('#ang').removeClass('dis'); } } function dragColor(evt) { var x = evt.pageX - stop_offset.left; var y = evt.pageY - stop_offset.top; x = x < 10 ? 10 : x > MAX + 10 ? MAX + 10: x; var xf_str = 'translate(' + x + ', 26)'; if(y < -60 || y > 130) { delStop.setAttribute('display', 'block'); delStop.setAttribute('transform', xf_str); } else { delStop.setAttribute('display', 'none'); } drag.setAttribute('transform', xf_str); $.data(drag, 'bg').setAttribute('transform', xf_str); var stop = $.data(drag, 'stop'); var s_x = (x - 10) / MAX; stop.setAttribute('offset', s_x); var last = 0; $(curGradient).find('stop').each(function(i) { var cur = this.getAttribute('offset'); var t = $(this); if(cur < last) { t.prev().before(t); stops = $(curGradient).find('stop'); } last = cur; }); } stopMakerSVG = mkElem('svg', { width: '100%', height: 45 }, stopMakerDiv[0]); var trans_pattern = mkElem('pattern', { width: 16, height: 16, patternUnits: 'userSpaceOnUse', id: 'jGraduate_trans' }, stopMakerSVG); var trans_img = mkElem('image', { width: 16, height: 16 }, trans_pattern); var bg_image = $settings.images.clientPath + 'map-opacity.png'; trans_img.setAttributeNS(ns.xlink, 'xlink:href', bg_image); $(stopMakerSVG).on("click touchstart", function(evt) { stop_offset = stopMakerDiv.offset(); var target = evt.target; if(target.tagName === 'path') return; var x = evt.pageX - stop_offset.left - 8; x = x < 10 ? 10 : x > MAX + 10 ? MAX + 10: x; mkStop(x / MAX, 0, 0, true); evt.stopPropagation(); }); $(stopMakerSVG).mouseover(function() { stopMakerSVG.appendChild(delStop); }); stopGroup = mkElem('g', {}, stopMakerSVG); mkElem('line', { x1: 10, y1: 15, x2: MAX + 10, y2: 15, 'stroke-width': 2, stroke: '#000' }, stopMakerSVG); var spreadMethodOpt = gradPicker.find('.jGraduate_spreadMethod').change(function() { curGradient.setAttribute('spreadMethod', $(this).val()); }); // handle dragging the stop around the swatch var draggingCoord = null; var onCoordDrag = function(evt) { var x = evt.pageX - offset.left; var y = evt.pageY - offset.top; // clamp stop to the swatch x = x < 0 ? 0 : x > MAX ? MAX : x; y = y < 0 ? 0 : y > MAX ? MAX : y; draggingCoord.css('left', x).css('top', y); // calculate stop offset var fracx = x / SIZEX; var fracy = y / SIZEY; var type = draggingCoord.data('coord'); var grad = curGradient; switch ( type ) { case 'start': attr_input.x1.val(fracx); attr_input.y1.val(fracy); grad.setAttribute('x1', fracx); grad.setAttribute('y1', fracy); break; case 'end': attr_input.x2.val(fracx); attr_input.y2.val(fracy); grad.setAttribute('x2', fracx); grad.setAttribute('y2', fracy); break; case 'center': attr_input.cx.val(fracx); attr_input.cy.val(fracy); grad.setAttribute('cx', fracx); grad.setAttribute('cy', fracy); c_x = fracx; c_y = fracy; xform(); break; case 'focus': attr_input.fx.val(fracx); attr_input.fy.val(fracy); grad.setAttribute('fx', fracx); grad.setAttribute('fy', fracy); xform(); } evt.preventDefault(); } var onCoordUp = function() { draggingCoord = null; $win.unbind('mousemove', onCoordDrag).unbind('mouseup', onCoordUp); } // Linear gradient // (function() { stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); // if there are not at least two stops, then if (numstops < 2) { while (numstops < 2) { curGradient.appendChild( document.createElementNS(ns.svg, 'stop') ); ++numstops; } stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); } var numstops = stops.length; for(var i = 0; i < numstops; i++) { mkStop(0, 0, 0, 0, stops[i]); } spreadMethodOpt.val(curGradient.getAttribute('spreadMethod') || 'pad'); var offset; // No match, so show focus point var showFocus = false; previewRect.setAttribute('fill-opacity', gradalpha/100); $('#' + id + ' div.grad_coord').mousedown(function(evt) { evt.preventDefault(); draggingCoord = $(this); var s_pos = draggingCoord.offset(); offset = draggingCoord.parent().offset(); $win.mousemove(onCoordDrag).mouseup(onCoordUp); }); // bind GUI elements $('#'+id+'_jGraduate_Ok').bind('click touchstart', function() { $this.paint.type = curType; $this.paint[curType] = curGradient.cloneNode(true);; $this.paint.solidColor = null; okClicked(); }); $('#'+id+'_jGraduate_Cancel').bind('click touchstart', function(paint) { cancelClicked(); }); if(curType === 'radialGradient') { if(showFocus) { focusCoord.show(); } else { focusCoord.hide(); attr_input.fx.val(""); attr_input.fy.val(""); } } $("#" + id + "_jGraduate_match_ctr")[0].checked = !showFocus; var lastfx, lastfy; $("#" + id + "_jGraduate_match_ctr").change(function() { showFocus = !this.checked; focusCoord.toggle(showFocus); attr_input.fx.val(''); attr_input.fy.val(''); var grad = curGradient; 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); attr_input.fx.val(fx); attr_input.fy.val(fy); } }); var stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); var numstops = stops.length; // if there are not at least two stops, then if (numstops < 2) { while (numstops < 2) { curGradient.appendChild( document.createElementNS(ns.svg, 'stop') ); ++numstops; } stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); } var slider; var setSlider = function(e) { var offset = slider.offset; var div = slider.parent; var x = (e.pageX - offset.left - parseInt(div.css('border-left-width'))); if (x > SLIDERW) x = SLIDERW; if (x <= 0) x = 0; var posx = x - 5; x /= SLIDERW; switch ( slider.type ) { case 'radius': x = Math.pow(x * 2, 2.5); if(x > .98 && x < 1.02) x = 1; if (x <= .01) x = .01; curGradient.setAttribute('r', x); break; case 'opacity': $this.paint.alpha = parseInt(x*100); previewRect.setAttribute('fill-opacity', x); break; case 'ellip': scale_x = 1, scale_y = 1; if(x < .5) { x /= .5; // 0.001 scale_x = x <= 0 ? .01 : x; } else if(x > .5) { x /= .5; // 2 x = 2 - x; scale_y = x <= 0 ? .01 : x; } xform(); x -= 1; if(scale_y === x + 1) { x = Math.abs(x); } break; case 'angle': x = x - .5; angle = x *= 180; xform(); x /= 100; break; } slider.elem.css({'margin-left':posx}); x = Math.round(x*100); slider.input.val(x); }; var ellip_val = 0, angle_val = 0; if(curType === 'radialGradient') { var tlist = curGradient.gradientTransform.baseVal; if(tlist.numberOfItems === 2) { var t = tlist.getItem(0); var s = tlist.getItem(1); if(t.type === 2 && s.type === 3) { var m = s.matrix; if(m.a !== 1) { ellip_val = Math.round(-(1 - m.a) * 100); } else if(m.d !== 1) { ellip_val = Math.round((1 - m.d) * 100); } } } else if(tlist.numberOfItems === 3) { // Assume [R][T][S] var r = tlist.getItem(0); var t = tlist.getItem(1); var s = tlist.getItem(2); if(r.type === 4 && t.type === 2 && s.type === 3) { angle_val = Math.round(r.angle); var m = s.matrix; if(m.a !== 1) { ellip_val = Math.round(-(1 - m.a) * 100); } else if(m.d !== 1) { ellip_val = Math.round((1 - m.d) * 100); } } } } var sliders = { radius: { handle: '#' + id + '_jGraduate_RadiusArrows', input: '#' + id + '_jGraduate_RadiusInput', val: (curGradient.getAttribute('r') || .5) * 100 }, opacity: { handle: '#' + id + '_jGraduate_OpacArrows', input: '#' + id + '_jGraduate_OpacInput', val: $this.paint.alpha || 100 }, ellip: { handle: '#' + id + '_jGraduate_EllipArrows', input: '#' + id + '_jGraduate_EllipInput', val: ellip_val }, angle: { handle: '#' + id + '_jGraduate_AngleArrows', input: '#' + id + '_jGraduate_AngleInput', val: angle_val } } $.each(sliders, function(type, data) { var handle = $(data.handle); handle.mousedown(function(evt) { var parent = handle.parent(); slider = { type: type, elem: handle, input: $(data.input), parent: parent, offset: parent.offset() }; $win.mousemove(dragSlider).mouseup(stopSlider); evt.preventDefault(); }); $(data.input).val(data.val).change(function() { var val = +this.value; var xpos = 0; var isRad = curType === 'radialGradient'; switch ( type ) { case 'radius': if(isRad) curGradient.setAttribute('r', val / 100); xpos = (Math.pow(val / 100, 1 / 2.5) / 2) * SLIDERW; break; case 'opacity': $this.paint.alpha = val; previewRect.setAttribute('fill-opacity', val / 100); xpos = val * (SLIDERW / 100); break; case 'ellip': scale_x = scale_y = 1; if(val === 0) { xpos = SLIDERW * .5; break; } if(val > 99.5) val = 99.5; if(val > 0) { scale_y = 1 - (val / 100); } else { scale_x = - (val / 100) - 1; } xpos = SLIDERW * ((val + 100) / 2) / 100; if(isRad) xform(); break; case 'angle': angle = val; xpos = angle / 180; xpos += .5; xpos *= SLIDERW; if(isRad) xform(); } if(xpos > SLIDERW) { xpos = SLIDERW; } else if(xpos < 0) { xpos = 0; } handle.css({'margin-left': xpos - 5}); }).change(); }); var dragSlider = function(evt) { setSlider(evt); evt.preventDefault(); }; var stopSlider = function(evt) { $win.unbind('mousemove', dragSlider).unbind('mouseup', stopSlider); slider = null; }; // -------------- var thisAlpha = ($this.paint.alpha*255/100).toString(16); while (thisAlpha.length < 2) { thisAlpha = "0" + thisAlpha; } thisAlpha = thisAlpha.split(".")[0]; color = $this.paint.solidColor == "none" ? "" : $this.paint.solidColor + thisAlpha; if(!isSolid) { color = stops[0].getAttribute('stop-color'); } // This should be done somewhere else, probably $.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.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.on("click touchstart", function() { tabs.removeClass('jGraduate_tab_current'); $(this).addClass('jGraduate_tab_current'); $(idref + " > div").hide(); var type = $(this).attr('data-type'); var container = $(idref + ' .jGraduate_gradPick').show(); if(type === 'rg' || type === 'lg') { // Show/hide appropriate fields $('.jGraduate_' + type + '_field').show(); $('.jGraduate_' + (type === 'lg' ? 'rg' : 'lg') + '_field').hide(); $('#' + id + '_jgraduate_rect')[0].setAttribute('fill', 'url(#' + id + '_' + type + '_jgraduate_grad)'); // Copy stops curType = type === 'lg' ? 'linearGradient' : 'radialGradient'; $('#' + id + '_jGraduate_OpacInput').val($this.paint.alpha).change(); var newGrad = $('#' + id + '_' + type + '_jgraduate_grad')[0]; if(curGradient !== newGrad) { var cur_stops = $(curGradient).find('stop'); $(newGrad).empty().append(cur_stops); curGradient = newGrad; var sm = spreadMethodOpt.val(); curGradient.setAttribute('spreadMethod', sm); } showFocus = type === 'rg' && curGradient.getAttribute('fx') != null && !(cx == fx && cy == fy); $('#' + id + '_jGraduate_focusCoord').toggle(showFocus); if(showFocus) { $('#' + id + '_jGraduate_match_ctr')[0].checked = false; } } else { $(idref + ' .jGraduate_gradPick').hide(); $(idref + ' .jGraduate_colPick').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); }); }; })();