/*
* 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) {};
};
}
$.cloneNode = function(el) {
if(!window.opera) return el.cloneNode(true);
// manually create a copy of the element
opera.postError(ns.svg, el.nodeName);
var new_el = document.createElementNS(ns.svg, el.nodeName);
$.each(el.attributes, function(i, attr) {
new_el.setAttributeNS(ns.svg, attr.nodeName, attr.nodeValue);
});
$.each(el.childNodes, function(i, child) {
if(child.nodeType == 1) {
new_el.appendChild($.cloneNode(child));
}
});
return new_el;
}
$.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 = $.cloneNode(options.copy.linearGradient);
break;
case "radialGradient":
this.radialGradient = $.cloneNode(options.copy.radialGradient);
break;
}
}
// create linear gradient paint
else if (options.linearGradient) {
this.type = "linearGradient";
this.solidColor = null;
this.radialGradient = null;
this.linearGradient = $.cloneNode(options.linearGradient);
}
// create linear gradient paint
else if (options.radialGradient) {
this.type = "radialGradient";
this.solidColor = null;
this.linearGradient = null;
this.radialGradient = $.cloneNode(options.radialGradient);
}
// 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('
' +
'- Solid Color
' +
'- Linear Gradient
' +
'- Radial Gradient
' +
'
' +
'' +
'' +
'');
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 + '
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'' +
'' +
'
' +
'' +
'' +
'' +
'%' +
'
' +
'' +
'' +
'' +
'
' +
'' +
'');
// --------------
// 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($.cloneNode($this.paint.linearGradient));
} 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.get_Hex() ? ('#'+color.get_Hex()) : "none";
beginOpacity = color.get_A() ? color.get_A()/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.get_Hex() ? ('#'+color.get_Hex()) : "none";
endOpacity = color.get_A() ? color.get_A()/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;
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.get_A() ? color.get_A() : 100;
$this.paint.solidColor = color.get_Hex() ? color.get_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($.cloneNode($this.paint.radialGradient));
} 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.get_Hex() ? ('#'+color.get_Hex()) : "none";
centerOpacity = color.get_A() ? color.get_A()/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.get_Hex() ? ('#'+color.get_Hex()) : "none";
outerOpacity = color.get_A() ? color.get_A()/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.get_A() ? color.get_A() : 100;
$this.paint.solidColor = color.get_Hex() ? color.get_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;
}
tab.addClass('jGraduate_tab_current').click();
$this.show();
});
};
})();