diff --git a/CHANGELOG b/CHANGELOG index 83f28c18..0f216c00 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,6 +5,23 @@ N.B.: You *must* run after installing the new software, to enjoy the benefits of this new version. +------------------------------------------------------------------------------ +* 0.19.1 + +New Features: +* From the "All" or Category listings, you can export selected pages (in any + desired order) to a single LaTeX file. +* LaTeX export supports \array{} (with no options) and a LaTeX-style optional + argument for \sqrt[]{}. The latter requires itextomml 1.4.5 or later. +* Updated to itextomml 1.4.5 (a bunch of new itex language features). +* Updated to Rails 2.3.10. (There were security issues in 2.3.9 which, happily, + did NOT affect Instiki 0.19. But 2.3.10 has other improvements, as well.) + +Bugs Fixed: +* Several SVG-Edit bugs fixed. +* Removed some superfluous junk, to slim down the distribution (cuts the size of + the compressed .tar.gz nearly in half). + ------------------------------------------------------------------------------ * 0.19 diff --git a/Gemfile b/Gemfile index dc5ae079..73232e95 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,6 @@ source "http://rubygems.org" gem "sqlite3-ruby", :require => "sqlite3" -gem "itextomml", ">=1.4.2" +gem "itextomml", ">=1.4.5" gem "mongrel", ">=1.2.0.pre2" gem "rubyzip" gem "erubis" diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 28576d9d..2313a696 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -282,7 +282,7 @@ module Instiki module VERSION #:nodoc: MAJOR = 0 MINOR = 19 - TINY = 0 + TINY = 1 SUFFIX = '(MML+)' PRERELEASE = false if PRERELEASE diff --git a/public/stylesheets/instiki.css b/public/stylesheets/instiki.css index fe723e42..709fd3ce 100644 --- a/public/stylesheets/instiki.css +++ b/public/stylesheets/instiki.css @@ -427,7 +427,7 @@ padding-left:0; ul#sortable_pages li { border: 1px solid #FFF; } -ul#sortable_pages li:hover { +ul#sortable_pages li:hover, ul#sortable_pages li:focus { border: 1px solid blue; } diff --git a/public/svg-edit/editor/contextmenu/jquery.contextMenu.js b/public/svg-edit/editor/contextmenu/jquery.contextMenu.js index 75b79491..3892cc3b 100755 --- a/public/svg-edit/editor/contextmenu/jquery.contextMenu.js +++ b/public/svg-edit/editor/contextmenu/jquery.contextMenu.js @@ -14,6 +14,9 @@ // and the MIT License and is copyright A Beautiful Site, LLC. // if(jQuery)( function() { + var win = $(window); + var doc = $(document); + $.extend($.fn, { contextMenu: function(o, callback) { @@ -28,75 +31,78 @@ if(jQuery)( function() { $(this).each( function() { var el = $(this); var offset = $(el).offset(); + + var menu = $('#' + o.menu); + // Add contextMenu class - $('#' + o.menu).addClass('contextMenu'); + menu.addClass('contextMenu'); + // Simulate a true right click $(this).mousedown( function(e) { var evt = e; $(this).mouseup( function(e) { var srcElement = $(this); - $(this).unbind('mouseup'); - if( evt.button == 2 || o.allowLeft) { + srcElement.unbind('mouseup'); + if( evt.button === 2 || o.allowLeft) { e.stopPropagation(); // Hide context menus that may be showing $(".contextMenu").hide(); // Get this context menu - var menu = $('#' + o.menu); - - if( $(el).hasClass('disabled') ) return false; + + if( el.hasClass('disabled') ) return false; // Detect mouse position var d = {}, x = e.pageX, y = e.pageY; - var x_off = $(window).width() - menu.width(), - y_off = $(window).height() - menu.height(); - - if(x > x_off) x = x_off-15; - if(y > y_off) y = y_off-15; + var x_off = win.width() - menu.width(), + y_off = win.height() - menu.height(); + + if(x > x_off - 15) x = x_off-15; + if(y > y_off - 30) y = y_off-30; // 30 is needed to prevent scrollbars in FF // Show the menu - $(document).unbind('click'); - $(menu).css({ top: y, left: x }).fadeIn(o.inSpeed); + doc.unbind('click'); + menu.css({ top: y, left: x }).fadeIn(o.inSpeed); // Hover events - $(menu).find('A').mouseover( function() { - $(menu).find('LI.hover').removeClass('hover'); + menu.find('A').mouseover( function() { + menu.find('LI.hover').removeClass('hover'); $(this).parent().addClass('hover'); }).mouseout( function() { - $(menu).find('LI.hover').removeClass('hover'); + menu.find('LI.hover').removeClass('hover'); }); // Keyboard - $(document).keypress( function(e) { + doc.keypress( function(e) { switch( e.keyCode ) { case 38: // up - if( $(menu).find('LI.hover').size() == 0 ) { - $(menu).find('LI:last').addClass('hover'); + if( !menu.find('LI.hover').length ) { + menu.find('LI:last').addClass('hover'); } else { - $(menu).find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover'); - if( $(menu).find('LI.hover').size() == 0 ) $(menu).find('LI:last').addClass('hover'); + menu.find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover'); + if( !menu.find('LI.hover').length ) menu.find('LI:last').addClass('hover'); } break; case 40: // down - if( $(menu).find('LI.hover').size() == 0 ) { - $(menu).find('LI:first').addClass('hover'); + if( menu.find('LI.hover').length == 0 ) { + menu.find('LI:first').addClass('hover'); } else { - $(menu).find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover'); - if( $(menu).find('LI.hover').size() == 0 ) $(menu).find('LI:first').addClass('hover'); + menu.find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover'); + if( !menu.find('LI.hover').length ) menu.find('LI:first').addClass('hover'); } break; case 13: // enter - $(menu).find('LI.hover A').trigger('click'); + menu.find('LI.hover A').trigger('click'); break; case 27: // esc - $(document).trigger('click'); + doc.trigger('click'); break } }); // When items are selected - $('#' + o.menu).find('A').unbind('mouseup'); - $('#' + o.menu).find('LI:not(.disabled) A').mouseup( function() { - $(document).unbind('click').unbind('keypress'); + menu.find('A').unbind('mouseup'); + menu.find('LI:not(.disabled) A').mouseup( function() { + doc.unbind('click').unbind('keypress'); $(".contextMenu").hide(); // Callback if( callback ) callback( $(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y} ); @@ -105,9 +111,9 @@ if(jQuery)( function() { // Hide bindings setTimeout( function() { // Delay for Mozilla - $(document).click( function() { - $(document).unbind('click').unbind('keypress'); - $(menu).fadeOut(o.outSpeed); + doc.click( function() { + doc.unbind('click').unbind('keypress'); + menu.fadeOut(o.outSpeed); return false; }); }, 0); diff --git a/public/svg-edit/editor/extensions/ext-imagelib.js b/public/svg-edit/editor/extensions/ext-imagelib.js index cb874694..5f8d7997 100644 --- a/public/svg-edit/editor/extensions/ext-imagelib.js +++ b/public/svg-edit/editor/extensions/ext-imagelib.js @@ -289,10 +289,11 @@ svgEditor.addExtension("imagelib", function() { var leftBlock = $('').css({position:'absolute',top:5,left:10}).appendTo(browser); - var back = $('Show libraries').appendTo(leftBlock).click(function() { + var back = $('Show library list').appendTo(leftBlock).click(function() { frame.attr('src', 'about:blank').hide(); lib_opts.show(); header.text(all_libs); + back.hide(); }).css({ 'margin-right': 5 }); @@ -321,6 +322,7 @@ svgEditor.addExtension("imagelib", function() { frame.attr('src', opts.url).show(); header.text(opts.name); lib_opts.hide(); + back.show(); }).append('' + opts.description + ''); }); diff --git a/public/svg-edit/editor/jgraduate/css/jPicker-1.0.12.css b/public/svg-edit/editor/jgraduate/css/jPicker-1.0.12.css deleted file mode 100644 index c943ae16..00000000 --- a/public/svg-edit/editor/jgraduate/css/jPicker-1.0.12.css +++ /dev/null @@ -1,191 +0,0 @@ -.jPicker_Picker { - display: inline-block; - height: 24px; /* change this value if using a different sized color picker icon */ - position: relative; /* make this element an absolute positioning container */ - text-align: left; /* make the zero width children position to the left of container */ - width: 25px; /* change this value if using a different sized color picker icon */ -} -.jPicker_Color, .jPicker_Alpha { - background-position: 2px 2px; - display: block; - height: 100%; - left: 0px; - position: absolute; - top: 0px; - width: 100%; -} -.jPicker_Icon { - background-repeat: no-repeat; - cursor: pointer; - display: block; - height: 100%; - left: 0px; - position: absolute; - top: 0px; - width: 100%; -} -.jPicker_Container { - display: none; - z-index: 10; /* make sure container draws above color picker icon in Firefox/Safari/Chrome/Opera/etc. - - IE calculates z-index so this won't work - we will hide all color picker icons placed after the selected one in code when shown in IE */ -} -.jPicker_table { - background-color: #efefef; - border: 1px outset #666; - font-family: Arial, Helvetica, Sans-Serif; - font-size: 12px; - margin: 0px; - padding: 5px; - width: 550px; -} -.jPicker_table td { - margin: 0px; - padding: 0px; - vertical-align: top; -} -.jPicker_MoveBar { - background-color: #dddddd; - border: 1px outset #aaa; - cursor: move; - height: 12px; -} -.jPicker_Title { - font-size: 11px !important; - font-weight: bold; - margin: -2px 0px 0px 0px; - padding: 0px; - text-align: center; - width: 100%; -} -.jPicker_ColorMap { - border: 2px inset #eee; - cursor: crosshair; - height: 260px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 256px later */ - margin: 0px 5px 0px 5px; - overflow: hidden; /* hide the overdraw of the Color Map icon when at edge of viewing box */ - padding: 0px; - position: relative; /* make this element an absolute positioning container */ - width: 260px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 256px later */ -} -div[class="jPicker_ColorMap"] { - height: 256px; /* correct to 256px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */ - width: 256px; /* correct to 256px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */ -} -.jPicker_ColorBar { - border: 2px inset #eee; - cursor: n-resize; - height: 260px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 256px later */ - margin: 12px 10px 0px 5px; - padding: 0px; - position: relative; - width: 24px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 20px later */ -} -div[class="jPicker_ColorBar"] { - height: 256px; /* correct to 256px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */ - width: 20px; /* correct to 20px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */ -} -.jPicker_ColorMap_l1, .jPicker_ColorMap_l2, .jPicker_ColorMap_l3, .jPicker_ColorBar_l1, .jPicker_ColorBar_l2, .jPicker_ColorBar_l3, .jPicker_ColorBar_l4, .jPicker_ColorBar_l5, .jPicker_ColorBar_l6 { - background-color: transparent; - background-image: none; - display: block; - height: 256px; /* must specific pixel height. IE7/8 Quirks mode ignores opacity for an absolutely positioned item in a relative container with "overflow: visible". The marker in the colorBar - would not be drawn if its overflow is set to hidden. */ - left: 0px; - position: absolute; - top: 0px; -} -.jPicker_ColorMap_l1, .jPicker_ColorMap_l2, .jPicker_ColorMap_l3 { - width: 256px; /* must specific pixel width. IE7/8 Quirks mode ignores opacity for an absolutely positioned item in a relative container with "overflow: visible". The marker in the colorBar - would not be drawn if its overflow is set to hidden. */ -} -.jPicker_ColorBar_l1, .jPicker_ColorBar_l2, .jPicker_ColorBar_l3, .jPicker_ColorBar_l4, .jPicker_ColorBar_l5, .jPicker_ColorBar_l6 { - width: 20px; /* must specific pixel width. IE7/8 Quirks mode ignores opacity for an absolutely positioned item in a relative container with "overflow: visible". The marker in the colorBar - would not be drawn if its overflow is set to hidden. */ -} -.jPicker_ColorMap_l1, .jPicker_ColorMap_l2, .jPicker_ColorBar_l6 { - background-repeat: no-repeat; -} -.jPicker_ColorMap_l3, .jPicker_ColorBar_l5 { - background-repeat: repeat; -} -.jPicker_ColorBar_l1, .jPicker_ColorBar_l2, .jPicker_ColorBar_l3, .jPicker_ColorBar_l4 { - background-repeat: repeat-x; -} -.jPicker_ColorMap_Arrow { - display: block; - position: absolute; -} -.jPicker_ColorBar_Arrow { - display: block; - left: -10px; /* (arrow width / 2) - (element width / 2) - position arrows' center in elements' center */ - position: absolute; -} -.jPicker_Preview { - font-size: x-small; - text-align: center; -} -.jPicker_Preview div { - border: 2px inset #eee; - height: 62px; - margin: 0px auto; - padding: 0px; - width: 62px; -} -.jPicker_Preview div span { - border: 1px solid #000; - display: block; - height: 30px; - margin: 0px auto; - padding: 0px; - width: 60px; -} -.jPicker_Preview div span.jPicker_Active { - border-bottom-width: 0px; -} -.jPicker_Preview div span.jPicker_Current { - border-top-width: 0px; - cursor: pointer; -} -.jPicker_OkCancel { - text-align: center; - width: 120px; -} -.jPicker_OkCancel input { - width: 100px; -} -.jPicker_OkCancel input.jPicker_Ok { - margin: 12px 0px 5px 0px; -} -.jPicker_Text { - text-align: left; -} -.jPicker_HueText, .jPicker_SaturationText, .jPicker_BrightnessText, .jPicker_RedText, .jPicker_GreenText, .jPicker_BlueText, .jPicker_AlphaText { - background-color: #fff; - border: 1px inset #aaa; - margin: 0px 0px 0px 5px; - text-align: left; - width: 30px; -} -.jPicker_HexText { - background-color: #fff; - border: 1px inset #aaa; - margin: 0px 0px 0px 5px; - width: 65px; -} -.jPicker_Grid { - text-align: center; -} -span.jPicker_QuickColor { - border: 1px inset #aaa; - cursor: pointer; - display: block; - float: left; - height: 13px; - line-height: 13px; - margin: 2px 2px 1px 2px; - padding: 0px; - width: 15px; -} -span[class="jPicker_QuickColor"] { - width: 13px; -} \ No newline at end of file diff --git a/public/svg-edit/editor/jgraduate/css/jPicker.css b/public/svg-edit/editor/jgraduate/css/jPicker.css new file mode 100644 index 00000000..d186af7b --- /dev/null +++ b/public/svg-edit/editor/jgraduate/css/jPicker.css @@ -0,0 +1 @@ +.jPicker .Icon{display:inline-block;height:24px;position:relative;text-align:left;width:25px}.jPicker .Icon span.Color,.jPicker .Icon span.Alpha{background-position:2px 2px;display:block;height:100%;left:0;position:absolute;top:0;width:100%}.jPicker .Icon span.Image{background-repeat:no-repeat;cursor:pointer;display:block;height:100%;left:0;position:absolute;top:0;width:100%}.jPicker.Container{z-index:10}table.jPicker{background-color:#efefef;border:1px outset #666;font-family:Arial,Helvetica,Sans-Serif;font-size:12px!important;margin:0;padding:5px;width:545px;z-index:20}.jPicker .Move{background-color:#ddd;border-color:#fff #666 #666 #fff;border-style:solid;border-width:1px;cursor:move;height:12px;padding:0}.jPicker .Title{font-size:11px!important;font-weight:bold;margin:-2px 0 0 0;padding:0;text-align:center;width:100%}.jPicker div.Map{border-bottom:2px solid #fff;border-left:2px solid #9a9a9a;border-right:2px solid #fff;border-top:2px solid #9a9a9a;cursor:crosshair;height:260px;margin:0 5px 0 5px;overflow:hidden;padding:0;position:relative;width:260px}.jPicker div[class="Map"]{height:256px;width:256px}.jPicker div.Bar{border-bottom:2px solid #fff;border-left:2px solid #9a9a9a;border-right:2px solid #fff;border-top:2px solid #9a9a9a;cursor:n-resize;height:260px;margin:12px 10px 0 5px;overflow:hidden;padding:0;position:relative;width:24px}.jPicker div[class="Bar"]{height:256px;width:20px}.jPicker .Map .Map1,.jPicker .Map .Map2,.jPicker .Map .Map3,.jPicker .Bar .Map1,.jPicker .Bar .Map2,.jPicker .Bar .Map3,.jPicker .Bar .Map4,.jPicker .Bar .Map5,.jPicker .Bar .Map6{background-color:transparent;background-image:none;display:block;left:0;position:absolute;top:0}.jPicker .Map .Map1,.jPicker .Map .Map2,.jPicker .Map .Map3{height:2596px;width:256px}.jPicker .Bar .Map1,.jPicker .Bar .Map2,.jPicker .Bar .Map3,.jPicker .Bar .Map4{height:3896px;width:20px}.jPicker .Bar .Map5,.jPicker .Bar .Map6{height:256px;width:20px}.jPicker .Map .Map1,.jPicker .Map .Map2,.jPicker .Bar .Map6{background-repeat:no-repeat}.jPicker .Map .Map3,.jPicker .Bar .Map5{background-repeat:repeat}.jPicker .Bar .Map1,.jPicker .Bar .Map2,.jPicker .Bar .Map3,.jPicker .Bar .Map4{background-repeat:repeat-x}.jPicker .Map .Arrow{display:block;position:absolute}.jPicker .Bar .Arrow{display:block;left:0;position:absolute}.jPicker .Preview{font-size:9px;text-align:center}.jPicker .Preview div{border:2px inset #eee;height:62px;margin:0 auto;padding:0;width:62px}.jPicker .Preview div span{border:1px solid #000;display:block;height:30px;margin:0 auto;padding:0;width:60px}.jPicker .Preview .Active{border-bottom-width:0}.jPicker .Preview .Current{border-top-width:0;cursor:pointer}.jPicker .Button{text-align:center;width:115px}.jPicker .Button input{width:100px}.jPicker .Button .Ok{margin:12px 0 5px 0}.jPicker td.Radio{margin:0;padding:0;width:31px}.jPicker td.Radio input{margin:0 5px 0 0;padding:0}.jPicker td.Text{font-size:12px!important;height:22px;margin:0;padding:0;text-align:left;width:70px}.jPicker tr.Hex td.Text{width:100px}.jPicker td.Text input{background-color:#fff;border:1px inset #aaa;height:19px;margin:0 0 0 5px;text-align:left;width:30px}.jPicker td[class="Text"] input{height:15px}.jPicker tr.Hex td.Text input.Hex{width:50px}.jPicker tr.Hex td.Text input.AHex{width:20px}.jPicker .Grid{text-align:center;width:114px}.jPicker .Grid span.QuickColor{border:1px inset #aaa;cursor:pointer;display:inline-block;height:15px;line-height:15px;margin:0;padding:0;width:19px}.jPicker .Grid span[class="QuickColor"]{width:17px} \ No newline at end of file diff --git a/public/svg-edit/editor/jgraduate/images/Bars.png b/public/svg-edit/editor/jgraduate/images/Bars.png index a9801ec1..80eb2bbe 100644 Binary files a/public/svg-edit/editor/jgraduate/images/Bars.png and b/public/svg-edit/editor/jgraduate/images/Bars.png differ diff --git a/public/svg-edit/editor/jgraduate/images/Maps.png b/public/svg-edit/editor/jgraduate/images/Maps.png index de33e3de..853d38c6 100644 Binary files a/public/svg-edit/editor/jgraduate/images/Maps.png and b/public/svg-edit/editor/jgraduate/images/Maps.png differ diff --git a/public/svg-edit/editor/jgraduate/images/NoColor.png b/public/svg-edit/editor/jgraduate/images/NoColor.png index ae361455..5dc47670 100644 Binary files a/public/svg-edit/editor/jgraduate/images/NoColor.png and b/public/svg-edit/editor/jgraduate/images/NoColor.png differ diff --git a/public/svg-edit/editor/jgraduate/images/rangearrows.gif b/public/svg-edit/editor/jgraduate/images/rangearrows.gif index 218872cc..9fe89f47 100644 Binary files a/public/svg-edit/editor/jgraduate/images/rangearrows.gif and b/public/svg-edit/editor/jgraduate/images/rangearrows.gif differ diff --git a/public/svg-edit/editor/jgraduate/jpicker-1.0.12.min.js b/public/svg-edit/editor/jgraduate/jpicker-1.0.12.min.js deleted file mode 100644 index 9b408ad9..00000000 --- a/public/svg-edit/editor/jgraduate/jpicker-1.0.12.min.js +++ /dev/null @@ -1 +0,0 @@ -(function(e,a){var d=function(t,k){var o=this,j=t.find("img"),B=0,A=100,s=100,z=0,w=100,r=100,q=0,p=0,m,n=function(x){var y=t.offset();m={left:y.left+parseInt(t.css("border-left-width")),top:y.top+parseInt(t.css("border-top-width"))};u(x);o.draw();e(document).bind("mousemove",l).bind("mouseup",h);x.stopPropagation();x.preventDefault();return false;},l=function(x){u(x);o.draw();x.stopPropagation();x.preventDefault();return false;},h=function(x){e(document).unbind("mouseup",h).unbind("mousemove",l);x.stopPropagation();x.preventDefault();return false;},u=function(E){var C=E.pageX-m.left,x=E.pageY-m.top,D=t.w,y=t.h;if(C<0){C=0;}else{if(C>D){C=D;}}if(x<0){x=0;}else{if(x>y){x=y;}}o.set_X(((C/D)*s)+B);o.set_Y(((x/y)*r)+z);e.isFunction(o.valuesChanged)&&o.valuesChanged(o);};e.extend(true,o,{settings:k,valuesChanged:e.isFunction(arguments[2])&&arguments[2]||null,get_X:function(){return q;},set_X:function(x){x=Math.floor(x);if(q==x){return;}if(xA){x=A;}}q=x;},get_Y:function(){return p;},set_Y:function(x){x=Math.floor(x);if(p==x){return;}if(xw){x=w;}}p=x;},set_RangeX:function(y,x){if(B==y&&A==x){return;}if(y>x){return;}B=y;A=x;s=A-B;},set_RangeY:function(y,x){if(z==y&&w==x){return;}if(y>x){return;}z=y;w=x;r=w-z;},draw:function(){var D=0,x=0,F=t.w,C=t.h,E=j.w,y=j.h;if(s>0){if(q==A){D=F;}else{D=Math.floor((q/s)*F);}}if(r>0){if(p==w){x=C;}else{x=Math.floor((p/r)*C);}}if(E>F){D=(F>>1)-(E>>1);}else{D-=E>>1;}if(y>C){x=(C>>1)-(y>>1);}else{x-=y>>1;}j.css({left:D+"px",top:x+"px"});},destroy:function(){e(document).unbind("mouseup",h).unbind("mousemove",l);t.unbind("mousedown",n);t=null;j=null;o.valuesChanged=null;}});var v=o.settings;j.src=v.arrow&&v.arrow.image;j.w=v.arrow&&v.arrow.width||j.width();j.h=v.arrow&&v.arrow.height||j.height();t.w=v.map&&v.map.width||t.width();t.h=v.map&&v.map.height||t.height();t.bind("mousedown",n);o.draw();e.isFunction(o.valuesChanged)&&o.valuesChanged(o);},b=function(m){var l=this,w=function(A){if(A.target.value==""){return;}if(!u.get_R()){s.red.val(0);}if(!u.get_G()){s.green.val(0);}if(!u.get_B()){s.blue.val(0);}if(!u.get_A()){s.alpha.val(100);}q(A);l.setValuesFromHsva();e.isFunction(l.valuesChanged)&&l.valuesChanged(l);},p=function(A){if(A.target.value==""){return;}if(!u.get_H()){s.hue.val(0);}if(!u.get_S()){s.saturation.val(0);}if(!u.get_V()){s.value.val(0);}if(!u.get_A()){s.alpha.val(100);}o(A);l.setValuesFromRgba();e.isFunction(l.valuesChanged)&&l.valuesChanged(l);},r=function(A){if(A.target.value==""){return;}if(!u.get_R()){s.red.val(0);}if(!u.get_G()){s.green.val(0);}if(!u.get_B()){s.blue.val(0);}if(!u.get_H()){s.hue.val(0);}if(!u.get_S()){s.saturation.val(0);}if(!u.get_V()){s.value.val(0);}y(A);l.setValuesFromRgba();e.isFunction(l.valuesChanged)&&l.valuesChanged(l);},t=function(A){if(A.target.value==""){l.setValuesFromRgba();}e.isFunction(l.valuesChanged)&&l.valuesChanged(l);},k=function(A){if(A.target.value==""){l.setValuesFromHsva();}e.isFunction(l.valuesChanged)&&l.valuesChanged(l);},x=function(A){if(A.target.value==""){s.alpha.val(100);}e.isFunction(l.valuesChanged)&&l.valuesChanged(l);},z=function(A){v(A);l.setValuesFromHex();e.isFunction(l.valuesChanged)&&l.valuesChanged(l);},j=function(A){if(A.target.value==""){l.setValuesFromHex();}},o=function(D){if(!n(D)){return D;}var C=h(s.red.val(),0,255),B=h(s.green.val(),0,255),A=h(s.blue.val(),0,255);s.red.val(C!=null?C:"");s.green.val(B!=null?B:"");s.blue.val(A!=null?A:"");},y=function(B){if(!n(B)){return B;}var A=h(s.alpha.val(),0,100);s.alpha.val(A!=null?A:"");},q=function(D){if(!n(D)){return D;}var A=h(s.hue.val(),0,360),B=h(s.saturation.val(),0,100),C=h(s.value.val(),0,100);s.hue.val(A!=null?A:"");s.saturation.val(B!=null?B:"");s.value.val(C!=null?C:"");},v=function(A){if(!n(A)){return A;}s.hex.val(s.hex.val().replace(/[^a-fA-F0-9]/g,"").toLowerCase().substring(0,8));},n=function(A){switch(A.keyCode){case 9:case 16:case 29:case 37:case 38:case 40:return false;case"c".charCodeAt():case"v".charCodeAt():if(A.ctrlKey){return false;}}return true;},h=function(C,B,A){if(C==""||isNaN(C)){return B;}if(C>A){return A;}if(C6){l=m.substring(0,2);k=m.substring(2,4);h=m.substring(4,6);j=m.substring(6,m.length);}else{if(m.length>4){l=m.substring(4,m.length);m=m.substring(0,4);}if(m.length>2){k=m.substring(2,m.length);m=m.substring(0,2);}if(m.length>0){h=m.substring(0,m.length);}}return{r:this.hexToInt(l),g:this.hexToInt(k),b:this.hexToInt(h),a:Math.floor((this.hexToInt(j)*100)/255)};},validateHex:function(h){h=h.toLowerCase().replace(/[^a-f0-9]/g,"");if(h.length>8){h=h.substring(0,8);}return h;},rgbaToHex:function(h){return this.intToHex(h.r)+this.intToHex(h.g)+this.intToHex(h.b)+this.intToHex(Math.floor((h.a*255)/100));},intToHex:function(j){var h=Math.floor(j).toString(16);if(h.length==1){h=("0"+h);}return h.toLowerCase();},hexToInt:function(h){return parseInt(h,16);},rgbToHsv:function(l){var o=l.r/255,n=l.g/255,j=l.b/255,k={h:0,s:0,v:0},m=0,h=0,p;if(o>=n&&o>=j){h=o;m=n>j?j:n;}else{if(n>=j&&n>=o){h=n;m=o>j?j:o;}else{h=j;m=n>o?o:n;}}k.v=h;k.s=h?(h-m)/h:0;if(!k.s){k.h=0;}else{p=h-m;if(o==h){k.h=(n-j)/p;}else{if(n==h){k.h=2+(j-o)/p;}else{k.h=4+(o-n)/p;}}k.h=parseInt(k.h*60);if(k.h<0){k.h+=360;}}k.s=Math.floor(k.s*100);k.v=Math.floor(k.v*100);return k;},hsvToRgb:function(n){var r={r:0,g:0,b:0,a:100},m=n.h,x=n.s,u=n.v;if(x==0){if(u==0){r.r=r.g=r.b=0;}else{r.r=r.g=r.b=Math.floor(u*255/100);}}else{if(m==360){m=0;}m/=60;x=x/100;u=u/100;var l=Math.floor(m),o=m-l,k=u*(1-x),j=u*(1-(x*o)),w=u*(1-(x*(1-o)));switch(l){case 0:r.r=u;r.g=w;r.b=k;break;case 1:r.r=j;r.g=u;r.b=k;break;case 2:r.r=k;r.g=u;r.b=w;break;case 3:r.r=k;r.g=j;r.b=u;break;case 4:r.r=w;r.g=k;r.b=u;break;case 5:r.r=u;r.g=k;r.b=j;break;}r.r=Math.floor(r.r*255);r.g=Math.floor(r.g*255);r.b=Math.floor(r.b*255);}return r;}}};var f=e.jPicker.Color,c=e.jPicker.List,g=e.jPicker.ColorMethods;e.fn.jPicker=function(j){var h=arguments;return this.each(function(){var w=e(this),y=e.extend(true,{},e.fn.jPicker.defaults,j);if(w.get(0).nodeName.toLowerCase()=="input"){e.extend(true,y,{window:{bindToInput:true,expandable:true,input:w}});if(g.validateHex(w.val())){y.color.active=new f({hex:w.val(),a:y.color.active.get_A()});y.color.current=new f({hex:w.val(),a:y.color.active.get_A()});}}if(y.window.expandable){w.after(' ');}else{y.window.liveUpdate=false;}var U=parseFloat(navigator.appVersion.split("MSIE")[1])<7&&document.body.filters,ay=null,av=null,au=null,T=null,S=null,R=null,Q=null,P=null,O=null,V=null,aa=null,aA=null,ak=null,am=null,ao=null,I=null,aw=null,G=null,Y=null,az=null,M=null,L=null,at=null,aq=null,A=null,l=null,J=null,ap=null,ab=null,ai=null,o=null,m=null,C=null,u=null,an=function(aE){K.active=az.color;var aF=K.active,aG=q.clientPath,aD=aF.get_Hex(),aC=function(aH){ad(aH,100);aH.css({backgroundColor:"transparent",backgroundPosition:"0px 0px",filter:""});};aC(ay);aC(av);aC(au);aC(T);aC(S);aC(R);aC(Q);aC(P);aC(O);aa.add(aA).add(ak).add(am).add(ao).add(I).removeAttr("checked");switch(aE){case"h":aa.attr({checked:true});ay.css({backgroundColor:aD&&aD.length==6?"#"+aD:"transparent"});av.css({backgroundColor:"transparent"});x(av,-256);ad(av,100);x(Q,-256);ad(O,0);break;case"s":aA.attr({checked:true});x(ay,-512);x(av,-768);z(R,aF.get_Hex());x(Q,-512);ad(O,0);break;case"v":ak.attr({checked:true});z(ay,"000000");x(av,-1024);R.css({backgroundColor:aD&&aD.length==6?"#"+aD:"transparent"});x(Q,-768);ad(O,0);break;case"r":am.attr({checked:true});x(av,-1536);x(ay,-1280);x(Q,-1024);x(R,-1280);x(S,-1536);x(T,-1792);ad(O,0);break;case"g":ao.attr({checked:true});x(av,-2048);x(ay,-1792);x(Q,-2048);x(R,-2304);x(S,-2560);x(T,-2816);ad(O,0);break;case"b":I.attr({checked:true});x(av,-2560);x(ay,-2304);x(Q,-3072);x(R,-3328);x(S,-3584);x(T,-3840);ad(O,0);break;case"a":aw.attr({checked:true});x(ay,-512);x(av,-768);ad(av,0);z(R,aF.get_Hex());ad(Q,0);ad(P,0);ad(O,100);break;default:throw ("Invalid Mode");break;}switch(aE){case"h":G.set_RangeX(0,100);G.set_RangeY(0,100);Y.set_RangeY(0,360);break;case"s":case"v":case"a":G.set_RangeX(0,360);G.set_RangeY(0,100);Y.set_RangeY(0,100);break;case"r":case"g":case"b":G.set_RangeX(0,255);G.set_RangeY(0,255);Y.set_RangeY(0,255);break;}K.mode=aE;v();G.draw();Y.draw();ah();if(aj.expandable&&aj.liveUpdate){o.css({backgroundColor:aD&&aD.length==6?"#"+aD:"transparent"});ad(m,100-aF.get_A());if(aj.bindToInput){aj.input.val(aF.get_Rgba()||"").css({backgroundColor:aD&&aD.length==6?"#"+aD:"transparent",color:aF.get_V()>75?"#000000":"#ffffff"});}}e.isFunction(w.liveCallback)&&w.liveCallback(aF);},n=function(){v();G.draw();Y.draw();ah();K.active=az.color;var aD=K.active;if(aj.expandable&&aj.liveUpdate){var aC=aD.get_Hex();o.css({backgroundColor:aC&&aC.length==6?"#"+aC:"transparent"});ad(m,100-aD.get_A());if(aj.bindToInput){aj.input.val(az.fields.hex.val()||"").css({backgroundColor:aC&&aC.length==6?"#"+aC:"transparent",color:aD.get_V()>75?"#000000":"#ffffff"});}}e.isFunction(w.liveCallback)&&w.liveCallback(aD);},B=function(){if(!az||!G||!Y){return;}K.active=az.color;var aC=az.fields,aE=K.active;switch(K.mode){case"h":aC.saturation.val(G.get_X());aC.value.val(100-G.get_Y());if(aE.get_H()==null){aC.hue.val(0);}break;case"s":case"a":aC.hue.val(G.get_X());aC.value.val(100-G.get_Y());if(aE.get_S()==null){aC.saturation.val(0);}break;case"v":aC.hue.val(G.get_X());aC.saturation.val(100-G.get_Y());if(aE.get_V()==null){aC.value.val(0);}break;case"r":aC.green.val(255-G.get_Y());aC.blue.val(G.get_X());if(aE.get_R()==null){aC.red.val(0);}break;case"g":aC.red.val(255-G.get_Y());aC.blue.val(G.get_X());if(aE.get_G()==null){aC.green.val(0);}break;case"b":aC.red.val(G.get_X());aC.green.val(255-G.get_Y());if(aE.get_B()==null){aC.blue.val(0);}break;}if(aE.get_A()==null){aC.alpha.val(100);az.setValuesFromHsva();v();Y.draw();}switch(K.mode){case"h":case"s":case"v":case"a":az.setValuesFromHsva();break;case"r":case"g":case"b":az.setValuesFromRgba();break;}ah();if(aj.expandable&&aj.liveUpdate){var aD=aE.get_Hex();o.css({backgroundColor:aD&&aD.length==6?"#"+aD:"transparent"});ad(m,100-aE.get_A());if(aj.bindToInput){aj.input.val(aE.get_Rgba()||"").css({backgroundColor:aD&&aD.length==6?"#"+aD:"transparent",color:aE.get_V()>75?"#000000":"#ffffff"});}}e.isFunction(w.liveCallback)&&w.liveCallback(aE);},al=function(){if(!az||!G||!Y){return;}K.active=az.color;var aC=az.fields,aE=K.active;switch(K.mode){case"h":aC.hue.val(360-Y.get_Y());if(aE.get_S()==null){aC.saturation.val(0);}if(aE.get_V()==null){aC.value.val(0);}break;case"s":aC.saturation.val(100-Y.get_Y());if(aE.get_H()==null){aC.hue.val(0);}if(aE.get_V()==null){aC.value.val(0);}break;case"v":aC.value.val(100-Y.get_Y());if(aE.get_H()==null){aC.hue.val(0);}if(aE.get_S()==null){aC.saturation.val(0);}break;case"r":aC.red.val(255-Y.get_Y());if(aE.get_G()==null){aC.green.val(0);}if(aE.get_B()==null){aC.blue.val(0);}break;case"g":aC.green.val(255-Y.get_Y());if(aE.get_R()==null){aC.red.val(0);}if(aE.get_B()==null){aC.blue.val(0);}break;case"b":aC.blue.val(255-Y.get_Y());if(aE.get_R()==null){aC.red.val(0);}if(aE.get_G()==null){aC.green.val(0);}break;case"a":aC.alpha.val(100-Y.get_Y());if(aE.get_R()==null){aC.red.val(0);}if(aE.get_G()==null){aC.green.val(0);}if(aE.get_B()==null){aC.blue.val(0);}break;}if(aE.get_A()==null){aC.alpha.val(100);}switch(K.mode){case"h":case"s":case"v":az.setValuesFromHsva();break;case"r":case"g":case"b":case"a":az.setValuesFromRgba();break;}ah();if(aj.expandable&&aj.liveUpdate){var aD=aE.get_Hex();o.css({backgroundColor:aD&&aD.length==6?"#"+aD:"transparent"});ad(m,100-aE.get_A());if(aj.bindToInput){aj.input.val(aE.get_Rgba()||"").css({backgroundColor:aD&&aD.length==6?"#"+aD:"transparent",color:aE.get_V()>75?"#000000":"#ffffff"});}}e.isFunction(w.liveCallback)&&w.liveCallback(aE);},v=function(){K.active=az.color;var aF=0,aE=K.active;switch(w.settings.color.mode){case"h":aF=360-aE.get_H();break;case"s":aF=100-aE.get_S();break;case"v":aF=100-aE.get_V();break;case"r":aF=255-aE.get_R();break;case"g":aF=255-aE.get_G();break;case"b":aF=255-aE.get_B();break;case"a":aF=100-aE.get_A();break;}Y.set_Y(aF);var aD=0,aC=0;switch(w.settings.color.mode){case"h":aD=aE.get_S();aC=100-aE.get_V();break;case"s":case"a":aD=aE.get_H();aC=100-aE.get_V();break;case"v":aD=aE.get_H();aC=100-aE.get_S();break;case"r":aD=aE.get_B();aC=255-aE.get_G();break;case"g":aD=aE.get_B();aC=255-aE.get_R();break;case"b":aD=aE.get_R();aC=255-aE.get_G();break;}G.set_X(aD);G.set_Y(aC);},ah=function(){aB();ar();Z();},aB=function(){try{var aC=az.color.get_Hex();A.css({backgroundColor:aC&&aC.length==6?"#"+aC:"transparent"});ad(A,az.color.get_A());}catch(aD){}},ar=function(){if(!K||!az){return;}K.active=az.color;var aC=K.active;switch(K.mode){case"h":z(ay,new f({h:aC.get_H(),s:100,v:100}).get_Hex());break;case"s":case"a":ad(av,100-aC.get_S());break;case"v":ad(av,aC.get_V());break;case"r":ad(av,aC.get_R()/255*100);break;case"g":ad(av,aC.get_G()/255*100);break;case"b":ad(av,aC.get_B()/255*100);break;}ad(au,100-aC.get_A());},Z=function(){if(!K||!az){return;}K.active=az.color;var aG=K.active;switch(K.mode){case"h":ad(P,100-aG.get_A());break;case"s":var aH=new f({h:aG.get_H(),s:100,v:aG.get_V()});z(R,aH.get_Hex());ad(P,100-aG.get_A());break;case"v":var aJ=new f({h:aG.get_H(),s:aG.get_S(),v:100});z(R,aJ.get_Hex());ad(P,100-aG.get_A());break;case"r":case"g":case"b":var aI=0,aK=0;if(K.mode=="r"){aI=aG.get_B();aK=aG.get_G();}else{if(K.mode=="g"){aI=aG.get_B();aK=aG.get_R();}else{if(K.mode=="b"){aI=aG.get_R();aK=aG.get_G();}}}var aC=aI/255*100,aF=aK/255*100,aE=(255-aI)/255*100,aD=(255-aK)/255*100;ad(T,aD>aE?aE:aD);ad(S,aD>aC?aC:aD);ad(R,aF>aC?aC:aF);ad(Q,aF>aE?aE:aF);ad(P,100-aG.get_A());break;case"a":z(R,aG.get_Hex());break;}},z=function(aC,aD){aC.css({backgroundColor:aD&&aD.length==6?"#"+aD:"transparent"});},t=function(aC,aD){aC.css({backgroundImage:"url("+aD+")"});},x=function(aC,aD){aC.css({backgroundPosition:"0px "+aD+"px"});},ad=function(aD,aC){aD.css({visibility:aC>0?"visible":"hidden"});if(aC>0&&aC<100){aD.css({opacity:aC/100});}else{if(aC==0||aC==100){aD.css({opacity:""});}}},E=function(){az.fields.hex.val(K.current.get_Rgba()||"");az.setValuesFromHex();e.isFunction(az.valuesChanged)&&az.valuesChanged(az);},D=function(aC){an(aC.target.value);},ae=function(){E();},s=function(){E();aj.expandable&&w.hide();e.isFunction(w.cancelCallback)&&w.cancelCallback(K.active);},X=function(){var aD=K.active;K.current=new f({hex:aD.get_Rgba()});var aC=aD.get_Hex();l.css({backgroundColor:aC&&aC.length==6?"#"+aC:"transparent"});ad(l,az.color.get_A());if(aj.expandable){o.css({backgroundColor:aC&&aC.length==6?"#"+aC:"transparent"});ad(m,100-aD.get_A());if(aj.bindToInput){aj.input.val(aD.get_Rgba()||"").css({backgroundColor:aC&&aC.length==6?"#"+aC:"transparent",color:aD.get_V()>75?"#000000":"#ffffff"});}}e.isFunction(w.commitCallback)&&w.commitCallback(aD);},p=function(){X();aj.expandable&&w.hide();},ag=function(){w.show();},W=function(aE){var aC=aj.element,aD=aj.page;M=parseInt(V.css("left"));L=parseInt(V.css("top"));at=aE.pageX;aq=aE.pageY;e(document).bind("mousemove",k).bind("mouseup",r);aE.stopPropagation();aE.preventDefault();return false;},k=function(aC){V.css({left:M-(at-aC.pageX)+"px",top:L-(aq-aC.pageY)+"px"});aC.stopPropagation();aC.preventDefault();return false;},r=function(aC){e(document).unbind("mousemove",k).unbind("mouseup",r);aC.stopPropagation();aC.preventDefault();return false;},F=function(aC){az.fields.hex.val(w.settings.window.input.val());az.bindedHexKeyUp(aC);},H=function(aC){az.fields.hex.val(new f({hex:e(this).attr("title")}).get_Rgba()||"");az.setValuesFromHex();e.isFunction(az.valuesChanged)&&az.valuesChanged(az);};e.extend(true,w,{id:w.attr("id"),settings:y,color:null,icon:null,commitCallback:e.isFunction(h[1])&&h[1]||null,liveCallback:e.isFunction(h[2])&&h[2]||null,cancelCallback:e.isFunction(h[3])&&h[3]||null,show:function(){if(document.all){var aD=false;for(i=0;i>1)-259)-w.next().offset().left+"px":aj.position.x,position:"absolute",top:aj.position.y=="top"?"-350px":aj.position.y=="center"?"-158px":aj.position.y=="bottom"?"25px":aj.position.y});}if((typeof(K.active)).toString().toLowerCase()=="string"){K.active=new f({hex:K.active});}V.html(''+(aj.expandable?' ':"")+''+(aj.title||af.text.title)+' '+af.text.newColor+' '+af.text.currentColor+' H: °S: %B: %R:G:B:A: %#:');aa=V.find(".jPicker_HueRadio");aA=V.find(".jPicker_SaturationRadio");ak=V.find(".jPicker_BrightnessRadio");am=V.find(".jPicker_RedRadio");ao=V.find(".jPicker_GreenRadio");I=V.find(".jPicker_BlueRadio");aw=V.find(".jPicker_AlphaRadio");ay=V.find(".jPicker_ColorMap_l1");av=V.find(".jPicker_ColorMap_l2");au=V.find(".jPicker_ColorMap_l3");T=V.find(".jPicker_ColorBar_l1");S=V.find(".jPicker_ColorBar_l2");R=V.find(".jPicker_ColorBar_l3");Q=V.find(".jPicker_ColorBar_l4");P=V.find(".jPicker_ColorBar_l5");O=V.find(".jPicker_ColorBar_l6");J=V.find(".jPicker_NewCurrent");var ac=K.active.get_Hex();A=V.find(".jPicker_Active").css({backgroundColor:ac&&ac.length==6?"#"+ac:"transparent"});l=V.find(".jPicker_Current").css({backgroundColor:ac&&ac.length==6?"#"+ac:"transparent"});ap=V.find(".jPicker_Ok");ab=V.find(".jPicker_Cancel");ai=V.find(".jPicker_Grid");w.color=e(".Picker_Color");w.icon=e(".jPicker_Icon");az=new b(V,n);G=new d(V.find(".jPicker_ColorMap"),{map:{width:q.colorMap.width,height:q.colorMap.height},arrow:{image:q.clientPath+q.colorMap.arrow.file,width:q.colorMap.arrow.width,height:q.colorMap.arrow.height}},B);Y=new d(V.find(".jPicker_ColorBar"),{map:{width:q.colorBar.width,height:q.colorBar.height},arrow:{image:q.clientPath+q.colorBar.arrow.file,width:q.colorBar.arrow.width,height:q.colorBar.arrow.height}},al);t(ay,q.clientPath+"Maps.png");t(av,q.clientPath+"Maps.png");t(au,q.clientPath+"map-opacity.png");t(T,q.clientPath+"Bars.png");t(S,q.clientPath+"Bars.png");t(R,q.clientPath+"Bars.png");t(Q,q.clientPath+"Bars.png");t(P,q.clientPath+"bar-opacity.png");t(O,q.clientPath+"AlphaBar.png");t(J,q.clientPath+"preview-opacity.png");if(aj.expandable){o=w.next().find(".jPicker_Color").css({backgroundColor:ac&&ac.length==6?"#"+ac:"transparent"});m=w.next().find(".jPicker_Alpha");t(m,q.clientPath+"bar-opacity.png");ad(m,100-K.active.get_A());C=w.next().find(".jPicker_Icon").css({backgroundImage:"url("+q.clientPath+q.picker.file+")"}).bind("click",ag);if(aj.bindToInput){aj.input.bind("keyup",F).bind("change",F);}}aa.add(aA).add(ak).add(am).add(ao).add(I).add(aw).bind("click",D);l.bind("click",ae);ab.bind("click",s);ap.bind("click",p);if(aj.expandable){u=V.find(".jPicker_MoveBar").bind("mousedown",W);}if(K.quickList&&K.quickList.length>0){ai.html("");for(i=0;i ');var N=K.quickList[i].get_Hex();V.find(".jPicker_QuickColor").eq(i).css({backgroundColor:N&&N.length==6?"#"+N:"transparent",backgroundImage:N?"none":"url("+q.clientPath+"NoColor.png)"}).click(H);}}an(K.mode);az.fields.hex.val(K.active.get_Rgba()||"");az.setValuesFromHex();v();ah();if(!aj.expandable){w.show();}c.push(w);});};e.fn.jPicker.defaults={window:{title:null,position:{x:"screenCenter",y:"top"},expandable:false,liveUpdate:true},color:{mode:"h",active:new f({hex:"#ffcc00ff"}),quickList:[new f({h:360,s:33,v:100}),new f({h:360,s:66,v:100}),new f({h:360,s:100,v:100}),new f({h:360,s:100,v:75}),new f({h:360,s:100,v:50}),new f({h:180,s:0,v:100}),new f({h:30,s:33,v:100}),new f({h:30,s:66,v:100}),new f({h:30,s:100,v:100}),new f({h:30,s:100,v:75}),new f({h:30,s:100,v:50}),new f({h:180,s:0,v:90}),new f({h:60,s:33,v:100}),new f({h:60,s:66,v:100}),new f({h:60,s:100,v:100}),new f({h:60,s:100,v:75}),new f({h:60,s:100,v:50}),new f({h:180,s:0,v:80}),new f({h:90,s:33,v:100}),new f({h:90,s:66,v:100}),new f({h:90,s:100,v:100}),new f({h:90,s:100,v:75}),new f({h:90,s:100,v:50}),new f({h:180,s:0,v:70}),new f({h:120,s:33,v:100}),new f({h:120,s:66,v:100}),new f({h:120,s:100,v:100}),new f({h:120,s:100,v:75}),new f({h:120,s:100,v:50}),new f({h:180,s:0,v:60}),new f({h:150,s:33,v:100}),new f({h:150,s:66,v:100}),new f({h:150,s:100,v:100}),new f({h:150,s:100,v:75}),new f({h:150,s:100,v:50}),new f({h:180,s:0,v:50}),new f({h:180,s:33,v:100}),new f({h:180,s:66,v:100}),new f({h:180,s:100,v:100}),new f({h:180,s:100,v:75}),new f({h:180,s:100,v:50}),new f({h:180,s:0,v:40}),new f({h:210,s:33,v:100}),new f({h:210,s:66,v:100}),new f({h:210,s:100,v:100}),new f({h:210,s:100,v:75}),new f({h:210,s:100,v:50}),new f({h:180,s:0,v:30}),new f({h:240,s:33,v:100}),new f({h:240,s:66,v:100}),new f({h:240,s:100,v:100}),new f({h:240,s:100,v:75}),new f({h:240,s:100,v:50}),new f({h:180,s:0,v:20}),new f({h:270,s:33,v:100}),new f({h:270,s:66,v:100}),new f({h:270,s:100,v:100}),new f({h:270,s:100,v:75}),new f({h:270,s:100,v:50}),new f({h:180,s:0,v:10}),new f({h:300,s:33,v:100}),new f({h:300,s:66,v:100}),new f({h:300,s:100,v:100}),new f({h:300,s:100,v:75}),new f({h:300,s:100,v:50}),new f({h:180,s:0,v:0}),new f({h:330,s:33,v:100}),new f({h:330,s:66,v:100}),new f({h:330,s:100,v:100}),new f({h:330,s:100,v:75}),new f({h:330,s:100,v:50}),new f()]},images:{clientPath:"/jPicker/images/",colorMap:{width:256,height:256,arrow:{file:"mappoint.gif",width:15,height:15}},colorBar:{width:20,height:256,arrow:{file:"rangearrows.gif",width:40,height:9}},picker:{file:"picker.gif",width:25,height:24}},localization:{text:{title:"Drag Markers To Pick A Color",newColor:"new",currentColor:"current",ok:"OK",cancel:"Cancel"},tooltips:{colors:{newColor:"New Color - Press “OK” To Commit",currentColor:"Click To Revert To Original Color"},buttons:{ok:"Commit To This Color Selection",cancel:"Cancel And Revert To Original Color"},hue:{radio:"Set To “Hue” Color Mode",textbox:"Enter A “Hue” Value (0-360°)"},saturation:{radio:"Set To “Saturation” Color Mode",textbox:"Enter A “Saturation” Value (0-100%)"},brightness:{radio:"Set To “Brightness” Color Mode",textbox:"Enter A “Brightness” Value (0-100%)"},red:{radio:"Set To “Red” Color Mode",textbox:"Enter A “Red” Value (0-255)"},green:{radio:"Set To “Green” Color Mode",textbox:"Enter A “Green” Value (0-255)"},blue:{radio:"Set To “Blue” Color Mode",textbox:"Enter A “Blue” Value (0-255)"},alpha:{radio:"Set To “Alpha” Color Mode",textbox:"Enter A “Alpha” Value (0-100)"},hex:{textbox:"Enter A “Hex” Color Value (#000000-#ffffff)"}}}};})(jQuery,"1.0.12"); \ No newline at end of file diff --git a/public/svg-edit/editor/jgraduate/jpicker.min.js b/public/svg-edit/editor/jgraduate/jpicker.min.js new file mode 100644 index 00000000..36c4836b --- /dev/null +++ b/public/svg-edit/editor/jgraduate/jpicker.min.js @@ -0,0 +1 @@ +(function(e,a){Math.precision=function(j,h){if(h===undefined){h=0}return Math.round(j*Math.pow(10,h))/Math.pow(10,h)};var d=function(z,k){var o=this,j=z.find("img:first"),F=0,E=100,w=100,D=0,C=100,v=100,s=0,p=0,n,q,u=new Array(),l=function(y){for(var x=0;xL){K=L}}if(x<0){x=0}else{if(x>y){x=y}}J.call(o,"xy",{x:((K/L)*w)+F,y:((x/y)*v)+D})},r=function(){var L=0,x=0,N=z.w,K=z.h,M=j.w,y=j.h;setTimeout(function(){if(w>0){if(s==E){L=N}else{L=((s/w)*N)|0}}if(v>0){if(p==C){x=K}else{x=((p/v)*K)|0}}if(M>=N){L=(N>>1)-(M>>1)}else{L-=M>>1}if(y>=K){x=(K>>1)-(y>>1)}else{x-=y>>1}j.css({left:L+"px",top:x+"px"})},0)},J=function(x,K,y){var O=K!==undefined;if(!O){if(x===undefined||x==null){x="xy"}switch(x.toLowerCase()){case"x":return s;case"y":return p;case"xy":default:return{x:s,y:p}}}if(y!=null&&y==o){return}var N=false,M,L;if(x==null){x="xy"}switch(x.toLowerCase()){case"x":M=K&&(K.x&&K.x|0||K|0)||0;break;case"y":L=K&&(K.y&&K.y|0||K|0)||0;break;case"xy":default:M=K&&K.x&&K.x|0||0;L=K&&K.y&&K.y|0||0;break}if(M!=null){if(ME){M=E}}if(s!=M){s=M;N=true}}if(L!=null){if(LC){L=C}}if(p!=L){p=L;N=true}}N&&l.call(o,y||o)},t=function(x,L){var P=L!==undefined;if(!P){if(x===undefined||x==null){x="all"}switch(x.toLowerCase()){case"minx":return F;case"maxx":return E;case"rangex":return{minX:F,maxX:E,rangeX:w};case"miny":return D;case"maxy":return C;case"rangey":return{minY:D,maxY:C,rangeY:v};case"all":default:return{minX:F,maxX:E,rangeX:w,minY:D,maxY:C,rangeY:v}}}var O=false,N,K,M,y;if(x==null){x="all"}switch(x.toLowerCase()){case"minx":N=L&&(L.minX&&L.minX|0||L|0)||0;break;case"maxx":K=L&&(L.maxX&&L.maxX|0||L|0)||0;break;case"rangex":N=L&&L.minX&&L.minX|0||0;K=L&&L.maxX&&L.maxX|0||0;break;case"miny":M=L&&(L.minY&&L.minY|0||L|0)||0;break;case"maxy":y=L&&(L.maxY&&L.maxY|0||L|0)||0;break;case"rangey":M=L&&L.minY&&L.minY|0||0;y=L&&L.maxY&&L.maxY|0||0;break;case"all":default:N=L&&L.minX&&L.minX|0||0;K=L&&L.maxX&&L.maxX|0||0;M=L&&L.minY&&L.minY|0||0;y=L&&L.maxY&&L.maxY|0||0;break}if(N!=null&&F!=N){F=N;w=E-F}if(K!=null&&E!=K){E=K;w=E-F}if(M!=null&&D!=M){D=M;v=C-D}if(y!=null&&C!=y){C=y;v=C-D}},I=function(x){if(e.isFunction(x)){u.push(x)}},m=function(y){if(!e.isFunction(y)){return}var x;while((x=e.inArray(y,u))!=-1){u.splice(x,1)}},G=function(){e(document).unbind("mouseup",B).unbind("mousemove",h);z.unbind("mousedown",H);z=null;j=null;u=null};e.extend(true,o,{val:J,range:t,bind:I,unbind:m,destroy:G});j.src=k.arrow&&k.arrow.image;j.w=k.arrow&&k.arrow.width||j.width();j.h=k.arrow&&k.arrow.height||j.height();z.w=k.map&&k.map.width||z.width();z.h=k.map&&k.map.height||z.height();z.bind("mousedown",H);I.call(o,r)},b=function(u,z,k,y){var q=this,l=u.find("td.Text input"),r=l.eq(3),v=l.eq(4),h=l.eq(5),o=l.length>7?l.eq(6):null,n=l.eq(0),p=l.eq(1),x=l.eq(2),s=l.eq(l.length>7?7:6),B=l.length>7?l.eq(8):null,w=function(D){if(D.target.value==""&&D.target!=s.get(0)&&(k!=null&&D.target!=k.get(0)||k==null)){return}if(!t(D)){return D}switch(D.target){case r.get(0):r.val(j.call(q,r.val(),0,255));z.val("r",r.val(),D.target);break;case v.get(0):v.val(j.call(q,v.val(),0,255));z.val("g",v.val(),D.target);break;case h.get(0):h.val(j.call(q,h.val(),0,255));z.val("b",h.val(),D.target);break;case o&&o.get(0):o.val(j.call(q,o.val(),0,100));z.val("a",Math.precision((o.val()*255)/100,y),D.target);break;case n.get(0):n.val(j.call(q,n.val(),0,360));z.val("h",n.val(),D.target);break;case p.get(0):p.val(j.call(q,p.val(),0,100));z.val("s",p.val(),D.target);break;case x.get(0):x.val(j.call(q,x.val(),0,100));z.val("v",x.val(),D.target);break;case s.get(0):s.val(s.val().replace(/[^a-fA-F0-9]/g,"").toLowerCase().substring(0,6));k&&k.val(s.val());z.val("hex",s.val()!=""?s.val():null,D.target);break;case k&&k.get(0):k.val(k.val().replace(/[^a-fA-F0-9]/g,"").toLowerCase().substring(0,6));s.val(k.val());z.val("hex",k.val()!=""?k.val():null,D.target);break;case B&&B.get(0):B.val(B.val().replace(/[^a-fA-F0-9]/g,"").toLowerCase().substring(0,2));z.val("a",B.val()!=null?parseInt(B.val(),16):null,D.target);break}},A=function(D){if(z.val()!=null){switch(D.target){case r.get(0):r.val(z.val("r"));break;case v.get(0):v.val(z.val("g"));break;case h.get(0):h.val(z.val("b"));break;case o&&o.get(0):o.val(Math.precision((z.val("a")*100)/255,y));break;case n.get(0):n.val(z.val("h"));break;case p.get(0):p.val(z.val("s"));break;case x.get(0):x.val(z.val("v"));break;case s.get(0):case k&&k.get(0):s.val(z.val("hex"));k&&k.val(z.val("hex"));break;case B&&B.get(0):B.val(z.val("ahex").substring(6));break}}},t=function(D){switch(D.keyCode){case 9:case 16:case 29:case 37:case 38:case 40:return false;case"c".charCodeAt():case"v".charCodeAt():if(D.ctrlKey){return false}}return true},j=function(F,E,D){if(F==""||isNaN(F)){return E}if(F>D){return D}if(F255){s.r=255}}if(j!=s.r){j=s.r;v=true}break;case"g":if(C){continue}E=true;s.g=G&&G.g&&G.g|0||G&&G|0||0;if(s.g<0){s.g=0}else{if(s.g>255){s.g=255}}if(o!=s.g){o=s.g;v=true}break;case"b":if(C){continue}E=true;s.b=G&&G.b&&G.b|0||G&&G|0||0;if(s.b<0){s.b=0}else{if(s.b>255){s.b=255}}if(t!=s.b){t=s.b;v=true}break;case"a":s.a=G&&G.a!=null?G.a|0:G!=null?G|0:255;if(s.a<0){s.a=0}else{if(s.a>255){s.a=255}}if(u!=s.a){u=s.a;v=true}break;case"h":if(E){continue}C=true;s.h=G&&G.h&&G.h|0||G&&G|0||0;if(s.h<0){s.h=0}else{if(s.h>360){s.h=360}}if(n!=s.h){n=s.h;v=true}break;case"s":if(E){continue}C=true;s.s=G&&G.s!=null?G.s|0:G!=null?G|0:100;if(s.s<0){s.s=0}else{if(s.s>100){s.s=100}}if(A!=s.s){A=s.s;v=true}break;case"v":if(E){continue}C=true;s.v=G&&G.v!=null?G.v|0:G!=null?G|0:100;if(s.v<0){s.v=0}else{if(s.v>100){s.v=100}}if(x!=s.v){x=s.v;v=true}break}}if(v){if(E){j=j||0;o=o||0;t=t||0;var D=g.rgbToHsv({r:j,g:o,b:t});n=D.h;A=D.s;x=D.v}else{if(C){n=n||0;A=A!=null?A:100;x=x!=null?x:100;var D=g.hsvToRgb({h:n,s:A,v:x});j=D.r;o=D.g;t=D.b}}u=u!=null?u:255;m.call(q,r||q)}break}},p=function(h){if(e.isFunction(h)){k.push(h)}},y=function(r){if(!e.isFunction(r)){return}var h;while((h=e.inArray(r,k))!=-1){k.splice(h,1)}},w=function(){k=null};e.extend(true,q,{val:l,bind:p,unbind:y,destroy:w});if(z){if(z.ahex!=null){l("ahex",z)}else{if(z.hex!=null){l((z.a!=null?"a":"")+"hex",z.a!=null?{ahex:z.hex+g.intToHex(z.a)}:z)}else{if(z.r!=null&&z.g!=null&&z.b!=null){l("rgb"+(z.a!=null?"a":""),z)}else{if(z.h!=null&&z.s!=null&&z.v!=null){l("hsv"+(z.a!=null?"a":""),z)}}}}}},ColorMethods:{hexToRgba:function(m){m=this.validateHex(m);if(m==""){return{r:null,g:null,b:null,a:null}}var l="00",k="00",h="00",j="255";if(m.length==6){m+="ff"}if(m.length>6){l=m.substring(0,2);k=m.substring(2,4);h=m.substring(4,6);j=m.substring(6,m.length)}else{if(m.length>4){l=m.substring(4,m.length);m=m.substring(0,4)}if(m.length>2){k=m.substring(2,m.length);m=m.substring(0,2)}if(m.length>0){h=m.substring(0,m.length)}}return{r:this.hexToInt(l),g:this.hexToInt(k),b:this.hexToInt(h),a:this.hexToInt(j)}},validateHex:function(h){h=h.toLowerCase().replace(/[^a-f0-9]/g,"");if(h.length>8){h=h.substring(0,8)}return h},rgbaToHex:function(h){return this.intToHex(h.r)+this.intToHex(h.g)+this.intToHex(h.b)+this.intToHex(h.a)},intToHex:function(j){var h=(j|0).toString(16);if(h.length==1){h=("0"+h)}return h.toLowerCase()},hexToInt:function(h){return parseInt(h,16)},rgbToHsv:function(l){var o=l.r/255,n=l.g/255,j=l.b/255,k={h:0,s:0,v:0},m=0,h=0,p;if(o>=n&&o>=j){h=o;m=n>j?j:n}else{if(n>=j&&n>=o){h=n;m=o>j?j:o}else{h=j;m=n>o?o:n}}k.v=h;k.s=h?(h-m)/h:0;if(!k.s){k.h=0}else{p=h-m;if(o==h){k.h=(n-j)/p}else{if(n==h){k.h=2+(j-o)/p}else{k.h=4+(o-n)/p}}k.h=parseInt(k.h*60);if(k.h<0){k.h+=360}}k.s=(k.s*100)|0;k.v=(k.v*100)|0;return k},hsvToRgb:function(n){var r={r:0,g:0,b:0,a:100},m=n.h,x=n.s,u=n.v;if(x==0){if(u==0){r.r=r.g=r.b=0}else{r.r=r.g=r.b=(u*255/100)|0}}else{if(m==360){m=0}m/=60;x=x/100;u=u/100;var l=m|0,o=m-l,k=u*(1-x),j=u*(1-(x*o)),w=u*(1-(x*(1-o)));switch(l){case 0:r.r=u;r.g=w;r.b=k;break;case 1:r.r=j;r.g=u;r.b=k;break;case 2:r.r=k;r.g=u;r.b=w;break;case 3:r.r=k;r.g=j;r.b=u;break;case 4:r.r=w;r.g=k;r.b=u;break;case 5:r.r=u;r.g=k;r.b=j;break}r.r=(r.r*255)|0;r.g=(r.g*255)|0;r.b=(r.b*255)|0}return r}}};var f=e.jPicker.Color,c=e.jPicker.List,g=e.jPicker.ColorMethods;e.fn.jPicker=function(j){var h=arguments;return this.each(function(){var w=this,av=e.extend(true,{},e.fn.jPicker.defaults,j);if(e(w).get(0).nodeName.toLowerCase()=="input"){e.extend(true,av,{window:{bindToInput:true,expandable:true,input:e(w)}});if(e(w).val()==""){av.color.active=new f({hex:null});av.color.current=new f({hex:null})}else{if(g.validateHex(e(w).val())){av.color.active=new f({hex:e(w).val(),a:av.color.active.val("a")});av.color.current=new f({hex:e(w).val(),a:av.color.active.val("a")})}}}if(av.window.expandable){e(w).after(' ')}else{av.window.liveUpdate=false}var Q=parseFloat(navigator.appVersion.split("MSIE")[1])<7&&document.body.filters,R=null,l=null,s=null,au=null,at=null,ar=null,P=null,O=null,N=null,M=null,L=null,K=null,D=null,U=null,aw=null,J=null,I=null,am=null,ai=null,E=null,an=null,ah=null,X=null,ab=null,aq=null,r=null,C=null,u=null,ag=function(aB){var aD=G.active,aE=n.clientPath,aA=aD.val("hex"),aC,az;av.color.mode=aB;switch(aB){case"h":setTimeout(function(){y.call(w,l,"transparent");x.call(w,au,0);Y.call(w,au,100);x.call(w,at,260);Y.call(w,at,100);y.call(w,s,"transparent");x.call(w,P,0);Y.call(w,P,100);x.call(w,O,260);Y.call(w,O,100);x.call(w,N,260);Y.call(w,N,100);x.call(w,M,260);Y.call(w,M,100);x.call(w,K,260);Y.call(w,K,100)},0);D.range("all",{minX:0,maxX:100,minY:0,maxY:100});U.range("rangeY",{minY:0,maxY:360});if(aD.val("ahex")==null){break}D.val("xy",{x:aD.val("s"),y:100-aD.val("v")},D);U.val("y",360-aD.val("h"),U);break;case"s":setTimeout(function(){y.call(w,l,"transparent");x.call(w,au,-260);x.call(w,at,-520);x.call(w,P,-260);x.call(w,O,-520);x.call(w,K,260);Y.call(w,K,100)},0);D.range("all",{minX:0,maxX:360,minY:0,maxY:100});U.range("rangeY",{minY:0,maxY:100});if(aD.val("ahex")==null){break}D.val("xy",{x:aD.val("h"),y:100-aD.val("v")},D);U.val("y",100-aD.val("s"),U);break;case"v":setTimeout(function(){y.call(w,l,"000000");x.call(w,au,-780);x.call(w,at,260);y.call(w,s,aA);x.call(w,P,-520);x.call(w,O,260);Y.call(w,O,100);x.call(w,K,260);Y.call(w,K,100)},0);D.range("all",{minX:0,maxX:360,minY:0,maxY:100});U.range("rangeY",{minY:0,maxY:100});if(aD.val("ahex")==null){break}D.val("xy",{x:aD.val("h"),y:100-aD.val("s")},D);U.val("y",100-aD.val("v"),U);break;case"r":aC=-1040;az=-780;D.range("all",{minX:0,maxX:255,minY:0,maxY:255});U.range("rangeY",{minY:0,maxY:255});if(aD.val("ahex")==null){break}D.val("xy",{x:aD.val("b"),y:255-aD.val("g")},D);U.val("y",255-aD.val("r"),U);break;case"g":aC=-1560;az=-1820;D.range("all",{minX:0,maxX:255,minY:0,maxY:255});U.range("rangeY",{minY:0,maxY:255});if(aD.val("ahex")==null){break}D.val("xy",{x:aD.val("b"),y:255-aD.val("r")},D);U.val("y",255-aD.val("g"),U);break;case"b":aC=-2080;az=-2860;D.range("all",{minX:0,maxX:255,minY:0,maxY:255});U.range("rangeY",{minY:0,maxY:255});if(aD.val("ahex")==null){break}D.val("xy",{x:aD.val("r"),y:255-aD.val("g")},D);U.val("y",255-aD.val("b"),U);break;case"a":setTimeout(function(){y.call(w,l,"transparent");x.call(w,au,-260);x.call(w,at,-520);x.call(w,P,260);x.call(w,O,260);Y.call(w,O,100);x.call(w,K,0);Y.call(w,K,100)},0);D.range("all",{minX:0,maxX:360,minY:0,maxY:100});U.range("rangeY",{minY:0,maxY:255});if(aD.val("ahex")==null){break}D.val("xy",{x:aD.val("h"),y:100-aD.val("v")},D);U.val("y",255-aD.val("a"),U);break;default:throw ("Invalid Mode");break}switch(aB){case"h":break;case"s":case"v":case"a":setTimeout(function(){Y.call(w,au,100);Y.call(w,P,100);x.call(w,N,260);Y.call(w,N,100);x.call(w,M,260);Y.call(w,M,100)},0);break;case"r":case"g":case"b":setTimeout(function(){y.call(w,l,"transparent");y.call(w,s,"transparent");Y.call(w,P,100);Y.call(w,au,100);x.call(w,au,aC);x.call(w,at,aC-260);x.call(w,P,az-780);x.call(w,O,az-520);x.call(w,N,az);x.call(w,M,az-260);x.call(w,K,260);Y.call(w,K,100)},0);break}if(aD.val("ahex")==null){return}aj.call(w,aD)},aj=function(aA,az){if(az==null||(az!=U&&az!=D)){v.call(w,aA,az)}setTimeout(function(){ay.call(w,aA);al.call(w,aA);W.call(w,aA)},0)},z=function(aA,az){var aC=G.active;if(az!=D&&aC.val()==null){return}var aB=aA.val("all");switch(av.color.mode){case"h":aC.val("sv",{s:aB.x,v:100-aB.y},az);break;case"s":case"a":aC.val("hv",{h:aB.x,v:100-aB.y},az);break;case"v":aC.val("hs",{h:aB.x,s:100-aB.y},az);break;case"r":aC.val("gb",{g:255-aB.y,b:aB.x},az);break;case"g":aC.val("rb",{r:255-aB.y,b:aB.x},az);break;case"b":aC.val("rg",{r:aB.x,g:255-aB.y},az);break}},ac=function(aA,az){var aB=G.active;if(az!=U&&aB.val()==null){return}switch(av.color.mode){case"h":aB.val("h",{h:360-aA.val("y")},az);break;case"s":aB.val("s",{s:100-aA.val("y")},az);break;case"v":aB.val("v",{v:100-aA.val("y")},az);break;case"r":aB.val("r",{r:255-aA.val("y")},az);break;case"g":aB.val("g",{g:255-aA.val("y")},az);break;case"b":aB.val("b",{b:255-aA.val("y")},az);break;case"a":aB.val("a",255-aA.val("y"),az);break}},v=function(aC,az){if(az!=D){switch(av.color.mode){case"h":var aH=aC.val("sv");D.val("xy",{x:aH!=null?aH.s:100,y:100-(aH!=null?aH.v:100)},az);break;case"s":case"a":var aB=aC.val("hv");D.val("xy",{x:aB&&aB.h||0,y:100-(aB!=null?aB.v:100)},az);break;case"v":var aE=aC.val("hs");D.val("xy",{x:aE&&aE.h||0,y:100-(aE!=null?aE.s:100)},az);break;case"r":var aA=aC.val("bg");D.val("xy",{x:aA&&aA.b||0,y:255-(aA&&aA.g||0)},az);break;case"g":var aI=aC.val("br");D.val("xy",{x:aI&&aI.b||0,y:255-(aI&&aI.r||0)},az);break;case"b":var aG=aC.val("rg");D.val("xy",{x:aG&&aG.r||0,y:255-(aG&&aG.g||0)},az);break}}if(az!=U){switch(av.color.mode){case"h":U.val("y",360-(aC.val("h")||0),az);break;case"s":var aJ=aC.val("s");U.val("y",100-(aJ!=null?aJ:100),az);break;case"v":var aF=aC.val("v");U.val("y",100-(aF!=null?aF:100),az);break;case"r":U.val("y",255-(aC.val("r")||0),az);break;case"g":U.val("y",255-(aC.val("g")||0),az);break;case"b":U.val("y",255-(aC.val("b")||0),az);break;case"a":var aD=aC.val("a");U.val("y",255-(aD!=null?aD:255),az);break}}},ay=function(aA){try{var az=aA.val("all");E.css({backgroundColor:az&&"#"+az.hex||"transparent"});Y.call(w,E,az&&Math.precision((az.a*100)/255,4)||0)}catch(aB){}},al=function(aC){switch(av.color.mode){case"h":y.call(w,l,new f({h:aC.val("h")||0,s:100,v:100}).val("hex"));break;case"s":case"a":var aB=aC.val("s");Y.call(w,at,100-(aB!=null?aB:100));break;case"v":var aA=aC.val("v");Y.call(w,au,aA!=null?aA:100);break;case"r":Y.call(w,at,Math.precision((aC.val("r")||0)/255*100,4));break;case"g":Y.call(w,at,Math.precision((aC.val("g")||0)/255*100,4));break;case"b":Y.call(w,at,Math.precision((aC.val("b")||0)/255*100));break}var az=aC.val("a");Y.call(w,ar,Math.precision(((255-(az||0))*100)/255,4))},W=function(aF){switch(av.color.mode){case"h":var aH=aF.val("a");Y.call(w,L,Math.precision(((255-(aH||0))*100)/255,4));break;case"s":var aA=aF.val("hva"),aB=new f({h:aA&&aA.h||0,s:100,v:aA!=null?aA.v:100});y.call(w,s,aB.val("hex"));Y.call(w,O,100-(aA!=null?aA.v:100));Y.call(w,L,Math.precision(((255-(aA&&aA.a||0))*100)/255,4));break;case"v":var aC=aF.val("hsa"),aE=new f({h:aC&&aC.h||0,s:aC!=null?aC.s:100,v:100});y.call(w,s,aE.val("hex"));Y.call(w,L,Math.precision(((255-(aC&&aC.a||0))*100)/255,4));break;case"r":case"g":case"b":var aD=0,aG=0,az=aF.val("rgba");if(av.color.mode=="r"){aD=az&&az.b||0;aG=az&&az.g||0}else{if(av.color.mode=="g"){aD=az&&az.b||0;aG=az&&az.r||0}else{if(av.color.mode=="b"){aD=az&&az.r||0;aG=az&&az.g||0}}}var aI=aG>aD?aD:aG;Y.call(w,O,aD>aG?Math.precision(((aD-aG)/(255-aG))*100,4):0);Y.call(w,N,aG>aD?Math.precision(((aG-aD)/(255-aD))*100,4):0);Y.call(w,M,Math.precision((aI/255)*100,4));Y.call(w,L,Math.precision(((255-(az&&az.a||0))*100)/255,4));break;case"a":var aH=aF.val("a");y.call(w,s,aF.val("hex")||"000000");Y.call(w,L,aH!=null?0:100);Y.call(w,K,aH!=null?100:0);break}},y=function(az,aA){az.css({backgroundColor:aA&&aA.length==6&&"#"+aA||"transparent"})},t=function(az,aA){if(Q&&(aA.indexOf("AlphaBar.png")!=-1||aA.indexOf("Bars.png")!=-1||aA.indexOf("Maps.png")!=-1)){az.attr("pngSrc",aA);az.css({backgroundImage:"none",filter:"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+aA+"', sizingMethod='scale')"})}else{az.css({backgroundImage:"url("+aA+")"})}},x=function(az,aA){az.css({top:aA+"px"})},Y=function(aA,az){aA.css({visibility:az>0?"visible":"hidden"});if(az>0&&az<100){if(Q){var aB=aA.attr("pngSrc");if(aB!=null&&(aB.indexOf("AlphaBar.png")!=-1||aB.indexOf("Bars.png")!=-1||aB.indexOf("Maps.png")!=-1)){aA.css({filter:"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+aB+"', sizingMethod='scale') progid:DXImageTransform.Microsoft.Alpha(opacity="+az+")"})}else{aA.css({opacity:Math.precision(az/100,4)})}}else{aA.css({opacity:Math.precision(az/100,4)})}}else{if(az==0||az==100){if(Q){var aB=aA.attr("pngSrc");if(aB!=null&&(aB.indexOf("AlphaBar.png")!=-1||aB.indexOf("Bars.png")!=-1||aB.indexOf("Maps.png")!=-1)){aA.css({filter:"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+aB+"', sizingMethod='scale')"})}else{aA.css({opacity:""})}}else{aA.css({opacity:""})}}}},B=function(){G.active.val("ahex",G.current.val("ahex"))},T=function(){G.current.val("ahex",G.active.val("ahex"))},A=function(az){e(this).parents("tbody:first").find('input:radio[value!="'+az.target.value+'"]').removeAttr("checked");ag.call(w,az.target.value)},Z=function(){B.call(w)},q=function(){B.call(w);av.window.expandable&&ao.call(w);e.isFunction(ax)&&ax.call(w,G.active,X)},m=function(){T.call(w);av.window.expandable&&ao.call(w);e.isFunction(ae)&&ae.call(w,G.active,ah)},af=function(){V.call(w)},ap=function(aB,az){var aA=aB.val("hex");an.css({backgroundColor:aA&&"#"+aA||"transparent"});Y.call(w,an,Math.precision(((aB.val("a")||0)*100)/255,4))},H=function(aC,az){var aB=aC.val("hex");var aA=aC.val("va");aq.css({backgroundColor:aB&&"#"+aB||"transparent"});Y.call(w,r,Math.precision(((255-(aA&&aA.a||0))*100)/255,4));if(av.window.bindToInput&&av.window.updateInputColor){av.window.input.css({backgroundColor:aB&&"#"+aB||"transparent",color:aA==null||aA.v>75?"#000000":"#ffffff"})}},S=function(aB){var az=av.window.element,aA=av.window.page;J=parseInt(R.css("left"));I=parseInt(R.css("top"));am=aB.pageX;ai=aB.pageY;e(document).bind("mousemove",k).bind("mouseup",p);aB.preventDefault()},k=function(az){R.css({left:J-(am-az.pageX)+"px",top:I-(ai-az.pageY)+"px"});if(av.window.expandable&&!e.support.boxModel){R.prev().css({left:R.css("left"),top:R.css("top")})}az.stopPropagation();az.preventDefault();return false},p=function(az){e(document).unbind("mousemove",k).unbind("mouseup",p);az.stopPropagation();az.preventDefault();return false},F=function(az){az.preventDefault();az.stopPropagation();G.active.val("ahex",e(this).attr("title")||null,az.target);return false},ae=e.isFunction(h[1])&&h[1]||null,ad=e.isFunction(h[2])&&h[2]||null,ax=e.isFunction(h[3])&&h[3]||null,V=function(){G.current.val("ahex",G.active.val("ahex"));var az=function(){if(!av.window.expandable||e.support.boxModel){return}var aA=R.find("table:first");R.before("");R.prev().css({width:aA.width(),height:R.height(),opacity:0,position:"absolute",left:R.css("left"),top:R.css("top")})};if(av.window.expandable){e(document.body).children("div.jPicker.Container").css({zIndex:10});R.css({zIndex:20})}switch(av.window.effects.type){case"fade":R.fadeIn(av.window.effects.speed.show,az);break;case"slide":R.slideDown(av.window.effects.speed.show,az);break;case"show":default:R.show(av.window.effects.speed.show,az);break}},ao=function(){var az=function(){if(av.window.expandable){R.css({zIndex:10})}if(!av.window.expandable||e.support.boxModel){return}R.prev().remove()};switch(av.window.effects.type){case"fade":R.fadeOut(av.window.effects.speed.hide,az);break;case"slide":R.slideUp(av.window.effects.speed.hide,az);break;case"show":default:R.hide(av.window.effects.speed.hide,az);break}},o=function(){var aG=av.window,az=aG.expandable?e(w).next().find(".Container:first"):null;R=aG.expandable?e(""):e(w);R.addClass("jPicker Container");if(aG.expandable){R.hide()}R.get(0).onselectstart=function(){return false};var aJ=G.active.val("all");if(aG.alphaPrecision<0){aG.alphaPrecision=0}else{if(aG.alphaPrecision>2){aG.alphaPrecision=2}}var aK=''+(aG.expandable?' ':"")+''+(aG.title||aa.text.title)+' '+aa.text.newColor+' '+aa.text.currentColor+' H: °S: %V: %R:G:B:'+(aG.alphaSupport?'A:":" ")+''+(aG.alphaSupport?' %':" ")+'#:'+(aG.alphaSupport?'':" ")+"";if(aG.expandable){R.html(aK);if(e(document.body).children("div.jPicker.Container").length==0){e(document.body).prepend(R)}else{e(document.body).children("div.jPicker.Container:last").after(R)}R.mousedown(function(){e(document.body).children("div.jPicker.Container").css({zIndex:10});R.css({zIndex:20})});R.css({left:aG.position.x=="left"?(az.offset().left-530-(aG.position.y=="center"?25:0))+"px":aG.position.x=="center"?(az.offset().left-260)+"px":aG.position.x=="right"?(az.offset().left-10+(aG.position.y=="center"?25:0))+"px":aG.position.x=="screenCenter"?((e(document).width()>>1)-260)+"px":(az.offset().left+parseInt(aG.position.x))+"px",position:"absolute",top:aG.position.y=="top"?(az.offset().top-312)+"px":aG.position.y=="center"?(az.offset().top-156)+"px":aG.position.y=="bottom"?(az.offset().top+25)+"px":(az.offset().top+parseInt(aG.position.y))+"px"})}else{R=e(w);R.html(aK)}var aD=R.find("tbody:first");l=aD.find("div.Map:first");s=aD.find("div.Bar:first");var aL=l.find("span"),aI=s.find("span");au=aL.filter(".Map1:first");at=aL.filter(".Map2:first");ar=aL.filter(".Map3:first");P=aI.filter(".Map1:first");O=aI.filter(".Map2:first");N=aI.filter(".Map3:first");M=aI.filter(".Map4:first");L=aI.filter(".Map5:first");K=aI.filter(".Map6:first");D=new d(l,{map:{width:n.colorMap.width,height:n.colorMap.height},arrow:{image:n.clientPath+n.colorMap.arrow.file,width:n.colorMap.arrow.width,height:n.colorMap.arrow.height}});D.bind(z);U=new d(s,{map:{width:n.colorBar.width,height:n.colorBar.height},arrow:{image:n.clientPath+n.colorBar.arrow.file,width:n.colorBar.arrow.width,height:n.colorBar.arrow.height}});U.bind(ac);aw=new b(aD,G.active,aG.expandable&&aG.bindToInput?aG.input:null,aG.alphaPrecision);var aB=aJ!=null?aJ.hex:null,aH=aD.find(".Preview"),aF=aD.find(".Button");E=aH.find(".Active:first").css({backgroundColor:aB&&"#"+aB||"transparent"});an=aH.find(".Current:first").css({backgroundColor:aB&&"#"+aB||"transparent"}).bind("click",Z);Y.call(w,an,Math.precision(G.current.val("a")*100)/255,4);ah=aF.find(".Ok:first").bind("click",m);X=aF.find(".Cancel:first").bind("click",q);ab=aF.find(".Grid:first");setTimeout(function(){t.call(w,au,n.clientPath+"Maps.png");t.call(w,at,n.clientPath+"Maps.png");t.call(w,ar,n.clientPath+"map-opacity.png");t.call(w,P,n.clientPath+"Bars.png");t.call(w,O,n.clientPath+"Bars.png");t.call(w,N,n.clientPath+"Bars.png");t.call(w,M,n.clientPath+"Bars.png");t.call(w,L,n.clientPath+"bar-opacity.png");t.call(w,K,n.clientPath+"AlphaBar.png");t.call(w,aH.find("div:first"),n.clientPath+"preview-opacity.png")},0);aD.find("td.Radio input").bind("click",A);if(G.quickList&&G.quickList.length>0){var aE="";for(i=0;i '}t.call(w,ab,n.clientPath+"bar-opacity.png");ab.html(aE);ab.find(".QuickColor").click(F)}ag.call(w,av.color.mode);G.active.bind(aj);e.isFunction(ad)&&G.active.bind(ad);G.current.bind(ap);if(aG.expandable){w.icon=az.parents(".Icon:first");aq=w.icon.find(".Color:first").css({backgroundColor:aB&&"#"+aB||"transparent"});r=w.icon.find(".Alpha:first");t.call(w,r,n.clientPath+"bar-opacity.png");Y.call(w,r,Math.precision(((255-(aJ!=null?aJ.a:0))*100)/255,4));C=w.icon.find(".Image:first").css({backgroundImage:"url("+n.clientPath+n.picker.file+")"}).bind("click",af);if(aG.bindToInput&&aG.updateInputColor){aG.input.css({backgroundColor:aB&&"#"+aB||"transparent",color:aJ==null||aJ.v>75?"#000000":"#ffffff"})}u=aD.find(".Move:first").bind("mousedown",S);G.active.bind(H)}else{V.call(w)}},ak=function(){R.find("td.Radio input").unbind("click",A);an.unbind("click",Z);X.unbind("click",q);ah.unbind("click",m);if(av.window.expandable){C.unbind("click",af);u.unbind("mousedown",S);w.icon=null}R.find(".QuickColor").unbind("click",F);l=null;s=null;au=null;at=null;ar=null;P=null;O=null;N=null;M=null;L=null;K=null;D.destroy();D=null;U.destroy();U=null;aw.destroy();aw=null;E=null;an=null;ah=null;X=null;ab=null;ae=null;ax=null;ad=null;R.html("");for(i=0;i div").hide(); $(idref + ' .jGraduate_' + $(this).attr('data-type') + 'Pick').show(); }); - $(idref + " > div").hide(); tabs.removeClass('jGraduate_tab_current'); var tab; @@ -1066,9 +1051,12 @@ jQuery.fn.jGraduate = tab = $(idref + ' .jGraduate_tab_color'); break; } - tab.addClass('jGraduate_tab_current').click(); - $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); }); }; })(); \ No newline at end of file diff --git a/public/svg-edit/editor/locale/lang.it.js b/public/svg-edit/editor/locale/lang.it.js index e5a7759e..c19606ea 100644 --- a/public/svg-edit/editor/locale/lang.it.js +++ b/public/svg-edit/editor/locale/lang.it.js @@ -1,173 +1,176 @@ [ -{"id": "align_relative_to", "title": "Allineati alla ..."}, -{"id": "bkgnd_color", "title": "Cambia il colore di sfondo / opacità"}, -{"id": "circle_cx", "title": "Cx cerchio Modifica di coordinate"}, -{"id": "circle_cy", "title": "Cambia's circle CY coordinare"}, +{"id": "align_relative_to", "title": "Allineati a ..."}, +{"id": "bkgnd_color", "title": "Cambia colore/opacità dello sfondo"}, +{"id": "circle_cx", "title": "Cambia la coordinata Cx del cerchio"}, +{"id": "circle_cy", "title": "Cambia la coordinata Cy del cerchio"}, {"id": "circle_r", "title": "Cambia il raggio del cerchio"}, -{"id": "connector_no_arrow", "textContent": "No arrow"}, +{"id": "connector_no_arrow", "textContent": "No freccia"}, {"id": "copyrightLabel", "textContent": "Powered by"}, -{"id": "cornerRadiusLabel", "title": "Cambia Rectangle Corner Radius"}, -{"id": "curve_segments", "textContent": "Curve"}, -{"id": "ellipse_cx", "title": "Cambia dell'ellisse cx coordinare"}, -{"id": "ellipse_cy", "title": "Ellisse Cambia's CY coordinare"}, -{"id": "ellipse_rx", "title": "Raggio x ellisse Cambia's"}, -{"id": "ellipse_ry", "title": "Raggio y ellisse Cambia's"}, +{"id": "cornerRadiusLabel", "title": "Cambia il raggio dell'angolo"}, +{"id": "curve_segments", "textContent": "Curva"}, +{"id": "ellipse_cx", "title": "Cambia la coordinata Cx dell'ellisse"}, +{"id": "ellipse_cy", "title": "Cambia la coordinata Cy dell'ellisse"}, +{"id": "ellipse_rx", "title": "Cambia l'asse x dell'ellisse"}, +{"id": "ellipse_ry", "title": "Cambia l'asse y dell'ellisse"}, {"id": "fill_color", "title": "Cambia il colore di riempimento"}, {"id": "fitToContent", "textContent": "Adatta al contenuto"}, {"id": "fit_to_all", "textContent": "Adatta a tutti i contenuti"}, -{"id": "fit_to_canvas", "textContent": "Adatta alla tela"}, -{"id": "fit_to_layer_content", "textContent": "Adatta a livello di contenuti"}, +{"id": "fit_to_canvas", "textContent": "Adatta all'area di disegno"}, +{"id": "fit_to_layer_content", "textContent": "Adatta al contenuto del livello"}, {"id": "fit_to_sel", "textContent": "Adatta alla selezione"}, -{"id": "font_family", "title": "Change Font Family"}, -{"id": "icon_large", "textContent": "Large"}, -{"id": "icon_medium", "textContent": "Medium"}, -{"id": "icon_small", "textContent": "Small"}, -{"id": "icon_xlarge", "textContent": "Extra Large"}, -{"id": "image_height", "title": "Cambia l'altezza dell'immagine"}, -{"id": "image_opt_embed", "textContent": "Embed data (local files)"}, -{"id": "image_opt_ref", "textContent": "Use file reference"}, +{"id": "font_family", "title": "Cambia il tipo di Font"}, +{"id": "icon_large", "textContent": "Grande"}, +{"id": "icon_medium", "textContent": "Medio"}, +{"id": "icon_small", "textContent": "Piccolo"}, +{"id": "icon_xlarge", "textContent": "Molto grande"}, +{"id": "idLabel", "title": "Identifica l'elemento"}, +{"id": "image_height", "title": "Cambia l'altezza dell'immagine"}, +{"id": "image_opt_embed", "textContent": "Incorpora dati (file locali)"}, +{"id": "image_opt_ref", "textContent": "Usa l'identificativo di riferimento"}, {"id": "image_url", "title": "Cambia URL"}, -{"id": "image_width", "title": "Cambia la larghezza dell'immagine"}, -{"id": "includedImages", "textContent": "Included Images"}, -{"id": "largest_object", "textContent": "il più grande oggetto"}, -{"id": "layer_delete", "title": "Elimina livello"}, -{"id": "layer_down", "title": "Move Layer Down"}, +{"id": "image_width", "title": "Cambia la larghezza dell'immagine"}, +{"id": "includedImages", "textContent": "Immagini incluse"}, +{"id": "largest_object", "textContent": "Oggetto più grande"}, +{"id": "layer_delete", "title": "Elimina il livello"}, +{"id": "layer_down", "title": "Sposta indietro il livello"}, {"id": "layer_new", "title": "Nuovo livello"}, -{"id": "layer_rename", "title": "Rinominare il livello"}, -{"id": "layer_up", "title": "Move Layer Up"}, -{"id": "layersLabel", "textContent": "Livelli:"}, -{"id": "line_x1", "title": "Modifica la linea di partenza coordinata x"}, -{"id": "line_x2", "title": "Modifica la linea di fine coordinata x"}, -{"id": "line_y1", "title": "Modifica la linea di partenza coordinata y"}, -{"id": "line_y2", "title": "Modifica la linea di fine coordinata y"}, -{"id": "linecap_butt", "title": "Linecap: Butt"}, -{"id": "linecap_round", "title": "Linecap: Round"}, -{"id": "linecap_square", "title": "Linecap: Square"}, -{"id": "linejoin_bevel", "title": "Linejoin: Bevel"}, -{"id": "linejoin_miter", "title": "Linejoin: Miter"}, -{"id": "linejoin_round", "title": "Linejoin: Round"}, -{"id": "main_icon", "title": "Main Menu"}, -{"id": "mode_connect", "title": "Connect two objects"}, +{"id": "layer_rename", "title": "Rinomina il livello"}, +{"id": "layer_up", "title": "Sposta avanti il livello"}, +{"id": "layersLabel", "textContent": "Livello:"}, +{"id": "line_x1", "title": "Modifica la coordinata iniziale x della linea"}, +{"id": "line_x2", "title": "Modifica la coordinata finale x della linea"}, +{"id": "line_y1", "title": "Modifica la coordinata iniziale y della linea"}, +{"id": "line_y2", "title": "Modifica la coordinata finale y della linea"}, +{"id": "linecap_butt", "title": "Inizio linea: Punto"}, +{"id": "linecap_round", "title": "Inizio linea: Tondo"}, +{"id": "linecap_square", "title": "Inizio linea: Quadrato"}, +{"id": "linejoin_bevel", "title": "Giunzione: smussata"}, +{"id": "linejoin_miter", "title": "Giunzione: spezzata"}, +{"id": "linejoin_round", "title": "Giunzione: arrotondata"}, +{"id": "main_icon", "title": "Menù principale"}, +{"id": "mode_connect", "title": "Collega due oggetti"}, {"id": "page", "textContent": "Pagina"}, {"id": "palette", "title": "Fare clic per cambiare il colore di riempimento, shift-click per cambiare colore del tratto"}, -{"id": "path_node_x", "title": "Change node's x coordinate"}, -{"id": "path_node_y", "title": "Change node's y coordinate"}, -{"id": "rect_height_tool", "title": "Cambia l'altezza rettangolo"}, +{"id": "path_node_x", "title": "Modifica la coordinata x del nodo"}, +{"id": "path_node_y", "title": "Modifica la coordinata y del nodo"}, +{"id": "rect_height_tool", "title": "Cambia l'altezza rettangolo"}, {"id": "rect_width_tool", "title": "Cambia la larghezza rettangolo"}, -{"id": "relativeToLabel", "textContent": "rispetto al:"}, -{"id": "seg_type", "title": "Change Segment type"}, -{"id": "selLayerLabel", "textContent": "Move elements to:"}, -{"id": "selLayerNames", "title": "Move selected elements to a different layer"}, -{"id": "selectedPredefined", "textContent": "Seleziona predefinite:"}, -{"id": "selected_objects", "textContent": "eletto oggetti"}, -{"id": "selected_x", "title": "Change X coordinate"}, -{"id": "selected_y", "title": "Change Y coordinate"}, -{"id": "smallest_object", "textContent": "più piccolo oggetto"}, -{"id": "straight_segments", "textContent": "Straight"}, -{"id": "stroke_color", "title": "Cambia colore ictus"}, -{"id": "stroke_style", "title": "Cambia lo stile dash ictus"}, -{"id": "stroke_width", "title": "Cambia la larghezza ictus"}, -{"id": "svginfo_bg_note", "textContent": "Note: Background will not be saved with image."}, -{"id": "svginfo_change_background", "textContent": "Editor Background"}, -{"id": "svginfo_dim", "textContent": "Canvas Dimensions"}, -{"id": "svginfo_editor_prefs", "textContent": "Editor Preferences"}, +{"id": "relativeToLabel", "textContent": "Rispetto a:"}, +{"id": "seg_type", "title": "Cambia il tipo di segmento"}, +{"id": "selLayerLabel", "textContent": "Sposta verso:"}, +{"id": "selLayerNames", "title": "Sposta gli elementi in un diverso livello"}, +{"id": "selectedPredefined", "textContent": "Selezioni predefinite:"}, +{"id": "selected_objects", "textContent": "Oggetti selezionati"}, +{"id": "selected_x", "title": "Modifica la coordinata x"}, +{"id": "selected_y", "title": "Modifica la coordinata y"}, +{"id": "smallest_object", "textContent": "Oggetto più piccolo"}, +{"id": "straight_segments", "textContent": "Linea retta"}, +{"id": "stroke_color", "title": "Cambia il colore del tratto"}, +{"id": "stroke_style", "title": "Cambia lo stile del tratto"}, +{"id": "stroke_width", "title": "Cambia la larghezza del tratto"}, +{"id": "svginfo_bg_note", "textContent": "Nota: Lo sfondo non verrà salvato con l'immagine."}, +{"id": "svginfo_change_background", "textContent": "Sfondo dell'editor"}, +{"id": "svginfo_dim", "textContent": "Dimensioni dell'area di disegno"}, +{"id": "svginfo_editor_prefs", "textContent": "Preferenze"}, {"id": "svginfo_height", "textContent": "Altezza:"}, -{"id": "svginfo_icons", "textContent": "Icon size"}, -{"id": "svginfo_image_props", "textContent": "Image Properties"}, -{"id": "svginfo_lang", "textContent": "Language"}, -{"id": "svginfo_title", "textContent": "Title"}, +{"id": "svginfo_icons", "textContent": "Dimensione Icona"}, +{"id": "svginfo_image_props", "textContent": "Proprietà Immagine"}, +{"id": "svginfo_lang", "textContent": "Lingua"}, +{"id": "svginfo_title", "textContent": "Titolo"}, {"id": "svginfo_width", "textContent": "Ampiezza:"}, {"id": "text", "title": "Cambia il contenuto del testo"}, -{"id": "toggle_stroke_tools", "title": "Show/hide more stroke tools"}, -{"id": "tool_add_subpath", "title": "Add sub-path"}, +{"id": "toggle_stroke_tools", "title": "Mostra/nascondi strumenti per il tratto"}, +{"id": "tool_add_subpath", "title": "Aggiungi sotto-percorso"}, {"id": "tool_alignbottom", "title": "Allinea in basso"}, {"id": "tool_aligncenter", "title": "Allinea al centro"}, {"id": "tool_alignleft", "title": "Allinea a sinistra"}, {"id": "tool_alignmiddle", "title": "Allinea al centro"}, {"id": "tool_alignright", "title": "Allinea a destra"}, {"id": "tool_aligntop", "title": "Allinea in alto"}, -{"id": "tool_angle", "title": "Cambia l'angolo di rotazione"}, -{"id": "tool_blur", "title": "Change gaussian blur value"}, +{"id": "tool_angle", "title": "Cambia l'angolo di rotazione"}, +{"id": "tool_blur", "title": "Cambia l'intensità della sfocatura"}, {"id": "tool_bold", "title": "Grassetto"}, -{"id": "tool_circle", "title": "Circle"}, -{"id": "tool_clear", "textContent": "New Image"}, -{"id": "tool_clone", "title": "Clone Element"}, -{"id": "tool_clone_multi", "title": "Clone Elements"}, -{"id": "tool_delete", "title": "Cancellare l'elemento"}, -{"id": "tool_delete_multi", "title": "Elimina elementi selezionati"}, +{"id": "tool_circle", "title": "Cerchio"}, +{"id": "tool_clear", "textContent": "Nuova immagine"}, +{"id": "tool_clone", "title": "Clona l'elemento"}, +{"id": "tool_clone_multi", "title": "Clona più elementi"}, +{"id": "tool_delete", "title": "Cancella l'elemento"}, +{"id": "tool_delete_multi", "title": "Elimina gli elementi selezionati"}, {"id": "tool_docprops", "textContent": "Proprietà del documento"}, {"id": "tool_docprops_cancel", "textContent": "Annulla"}, -{"id": "tool_docprops_save", "textContent": "Salvare"}, -{"id": "tool_ellipse", "title": "Ellipse"}, -{"id": "tool_export", "textContent": "Export as PNG"}, -{"id": "tool_eyedropper", "title": "Eye Dropper Tool"}, -{"id": "tool_fhellipse", "title": "Free-Hand Ellipse"}, -{"id": "tool_fhpath", "title": "Lo strumento matita"}, -{"id": "tool_fhrect", "title": "Free-Hand Rectangle"}, +{"id": "tool_docprops_save", "textContent": "Salva"}, +{"id": "tool_ellipse", "title": "Ellisse"}, +{"id": "tool_export", "textContent": "Esporta come PNG"}, +{"id": "tool_eyedropper", "title": "Seleziona colore"}, +{"id": "tool_fhellipse", "title": "Ellisse a mano libera"}, +{"id": "tool_fhpath", "title": "Matita"}, +{"id": "tool_fhrect", "title": "Rettangolo a mano libera"}, {"id": "tool_font_size", "title": "Modifica dimensione carattere"}, -{"id": "tool_group", "title": "Group Elements"}, -{"id": "tool_image", "title": "Image Tool"}, -{"id": "tool_import", "textContent": "Import SVG"}, +{"id": "tool_group", "title": "Raggruppa elementi"}, +{"id": "tool_image", "title": "Immagine"}, +{"id": "tool_import", "textContent": "Importa SVG"}, {"id": "tool_italic", "title": "Corsivo"}, -{"id": "tool_line", "title": "Line Tool"}, -{"id": "tool_move_bottom", "title": "Move to Bottom"}, -{"id": "tool_move_top", "title": "Move to Top"}, -{"id": "tool_node_clone", "title": "Clone Node"}, -{"id": "tool_node_delete", "title": "Delete Node"}, -{"id": "tool_node_link", "title": "Link Control Points"}, -{"id": "tool_opacity", "title": "Cambia l'opacità dell'oggetto selezionato"}, +{"id": "tool_line", "title": "Linea"}, +{"id": "tool_move_bottom", "title": "Sposta in fondo"}, +{"id": "tool_move_top", "title": "Sposta in cima"}, +{"id": "tool_node_clone", "title": "Clona nodo"}, +{"id": "tool_node_delete", "title": "Elimina nodo"}, +{"id": "tool_node_link", "title": "Collegamento tra punti di controllo"}, +{"id": "tool_opacity", "title": "Cambia l'opacità dell'oggetto selezionato"}, {"id": "tool_open", "textContent": "Apri immagine"}, -{"id": "tool_path", "title": "Path Tool"}, +{"id": "tool_openclose_path", "title": "Apri/chiudi spezzata"}, +{"id": "tool_path", "title": "Spezzata"}, +{"id": "tool_position", "title": "Allinea elementi alla pagina"}, {"id": "tool_rect", "title": "Rettangolo"}, -{"id": "tool_redo", "title": "Redo"}, -{"id": "tool_reorient", "title": "Reorient path"}, -{"id": "tool_save", "textContent": "Salvare l'immagine"}, -{"id": "tool_select", "title": "Selezionare Tool"}, -{"id": "tool_source", "title": "Edit Source"}, +{"id": "tool_redo", "title": "Rifai"}, +{"id": "tool_reorient", "title": "Riallinea"}, +{"id": "tool_save", "textContent": "Salva"}, +{"id": "tool_select", "title": "Seleziona"}, +{"id": "tool_source", "title": "Modifica sorgente"}, {"id": "tool_source_cancel", "textContent": "Annulla"}, -{"id": "tool_source_save", "textContent": "Salvare"}, -{"id": "tool_square", "title": "Piazza"}, -{"id": "tool_text", "title": "Strumento Testo"}, -{"id": "tool_topath", "title": "Convert to Path"}, +{"id": "tool_source_save", "textContent": "Salva"}, +{"id": "tool_square", "title": "Quadrato"}, +{"id": "tool_text", "title": "Testo"}, +{"id": "tool_topath", "title": "Converti in tracciato"}, {"id": "tool_undo", "title": "Annulla"}, -{"id": "tool_ungroup", "title": "Separa Elements"}, -{"id": "tool_wireframe", "title": "Wireframe Mode"}, -{"id": "tool_zoom", "title": "Zoom Tool"}, -{"id": "url_notice", "title": "NOTE: This image cannot be embedded. It will depend on this path to be displayed"}, +{"id": "tool_ungroup", "title": "Separa gli elementi"}, +{"id": "tool_wireframe", "title": "Contorno"}, +{"id": "tool_zoom", "title": "Zoom"}, +{"id": "url_notice", "title": "NOTA: L'immagine non può essere incorporata: dipenderà dal percorso assoluto per essere vista"}, {"id": "zoom_panel", "title": "Cambia il livello di zoom"}, -{"id": "sidepanel_handle", "textContent": "L a y e r s", "title": "Drag left/right to resize side panel"}, +{"id": "sidepanel_handle", "textContent": "L a y e r s", "titolo": "Trascina a sinistra/destra per ridimensionare il pannello"}, { "js_strings": { - "QerrorsRevertToSource": "There were parsing errors in your SVG source.\nRevert back to original SVG source?", - "QignoreSourceChanges": "Ignore changes made to SVG source?", - "QmoveElemsToLayer": "Move selected elements to layer '%s'?", - "QwantToClear": "Do you want to clear the drawing?\nThis will also erase your undo history!", - "cancel": "Cancel", - "defsFailOnSave": "NOTE: Due to a bug in your browser, this image may appear wrong (missing gradients or elements). It will however appear correct once actually saved.", - "dupeLayerName": "There is already a layer named that!", - "enterNewImgURL": "Enter the new image URL", - "enterNewLayerName": "Please enter the new layer name", - "enterUniqueLayerName": "Please enter a unique layer name", - "exportNoBlur": "Blurred elements will appear as un-blurred", - "exportNoDashArray": "Strokes will appear filled", - "exportNoImage": "Image elements will not appear", - "exportNoText": "Text may not appear as expected", - "exportNoforeignObject": "foreignObject elements will not appear", - "featNotSupported": "Feature not supported", - "invalidAttrValGiven": "Invalid value given", + "QerrorsRevertToSource": "Ci sono errori nel codice sorgente SVG.\nRitorno al codice originale?", + "QignoreSourceChanges": "Ignoro i cambiamenti nel sorgente SVG?", + "QmoveElemsToLayer": "Sposta gli elementi selezionali al livello '%s'?", + "QwantToClear": "Vuoi cancellare il disegno?\nVerrà eliminato anche lo storico delle modifiche!", + "cancel": "Annulla", + "defsFailOnSave": "NOTA: A causa dlle caratteristiche del tuo browser, l'immagine potrà apparire errata (senza elementi o gradazioni) finché non sarà salvata.", + "dupeLayerName": "C'è già un livello con questo nome!", + "enterNewImgURL": "Scrivi un nuovo URL per l'immagine", + "enterNewLayerName": "Assegna un nome al livello", + "enterUniqueLayerName": "Assegna un diverso nome a ciascun livello, grazie!", + "exportNoBlur": "Gli elementi sfocati appariranno non sfocati", + "exportNoDashArray": "I tratti appariranno pieni", + "exportNoImage": "Elementi dell'immagine non compariranno", + "exportNoText": "Il testo non apparirà come indicato", + "exportNoforeignObject": "Gli elementi dell'oggetto esterno non potranno essere visti", + "featNotSupported": "Caratteristica non supportata", + "invalidAttrValGiven": "Valore assegnato non valido", "key_backspace": "backspace", - "key_del": "delete", - "key_down": "down", - "key_up": "up", - "layer": "Layer", - "layerHasThatName": "Layer already has that name", - "loadingImage": "Loading image, please wait...", - "noContentToFitTo": "No content to fit to", - "noteTheseIssues": "Also note the following issues: ", + "key_del": "Canc", + "key_down": "giù", + "key_up": "su", + "layer": "Livello", + "layerHasThatName": "Un livello ha già questo nome", + "loadingImage": "Sto caricando l'immagine. attendere prego...", + "noContentToFitTo": "Non c'è contenuto cui adeguarsi", + "noteTheseIssues": "Nota le seguenti particolarità: ", "ok": "OK", - "pathCtrlPtTooltip": "Drag control point to adjust curve properties", - "pathNodeTooltip": "Drag node to move it. Double-click node to change segment type", - "saveFromBrowser": "Select \"Save As...\" in your browser to save this image as a %s file." + "pathCtrlPtTooltip": "Trascina il punto di controllo per assestare le proprietà della curva", + "pathNodeTooltip": "Trascina il nodo per spostarlo. Doppo click per cambiare i tipo di segmento", + "saveFromBrowser": "Seleziona \"Salva con nome...\" nel browser per salvare l'immagine con nome %s ." } } ] \ No newline at end of file diff --git a/public/svg-edit/editor/svg-editor.html b/public/svg-edit/editor/svg-editor.html index d193edeb..97f90c41 100644 --- a/public/svg-edit/editor/svg-editor.html +++ b/public/svg-edit/editor/svg-editor.html @@ -5,7 +5,7 @@ - + @@ -37,7 +37,7 @@ script type="text/javascript" src="locale/locale.min.js"> - + @@ -664,6 +664,7 @@ script type="text/javascript" src="locale/locale.min.js"> Français Frysk हिन्दी, हिंदी + Italiano 日本語 Nederlands Português (BR) diff --git a/public/svg-edit/editor/svg-editor.js b/public/svg-edit/editor/svg-editor.js index c0575f14..326ab5b6 100644 --- a/public/svg-edit/editor/svg-editor.js +++ b/public/svg-edit/editor/svg-editor.js @@ -207,10 +207,15 @@ svgEditor.setConfig(urldata); - // FIXME: This is null if Data URL ends with '='. var src = urldata.source; var qstr = $.param.querystring(); - + + if(!src) { // urldata.source may have been null if it ended with '=' + if(qstr.indexOf('source=data:') >= 0) { + src = qstr.match(/source=(data:[^&]*)/)[1]; + } + } + if(src) { if(src.indexOf("data:") === 0) { // plusses get replaced by spaces, so re-insert @@ -474,7 +479,9 @@ tool_scale = 1, zoomInIcon = 'crosshair', zoomOutIcon = 'crosshair', - ui_context = 'toolbars'; + ui_context = 'toolbars', + orig_source = '', + paintBox = {fill: null, stroke:null}; // This sets up alternative dialog boxes. They mostly work the same way as // their UI counterparts, expect instead of returning the result, a callback @@ -564,9 +571,6 @@ var cur_context = ''; var orig_title = $('title:first').text(); - var fillPaint = new $.jGraduate.Paint({solidColor: curConfig.initFill.color}); - var strokePaint = new $.jGraduate.Paint({solidColor: curConfig.initStroke.color}); - var saveHandler = function(window,svg) { show_save_warning = false; @@ -584,7 +588,6 @@ showSourceEditor(0,true); return; } - var win = window.open("data:image/svg+xml;base64," + Utils.encode64(svg)); // Alert will only appear the first time saved OR the first time the bug is encountered @@ -656,8 +659,7 @@ // upon creation of a text element the editor is switched into // select mode and this event fires - we need our UI to be in sync - if (mode !== "multiselect" && !is_node) { - // FIXME: This also needs to fire if only one element is selected via multiselect + if (!is_node) { updateToolbar(); } @@ -675,7 +677,8 @@ // called when any element has changed var elementChanged = function(window,elems) { - if(svgCanvas.getMode() == "select") { + var mode = svgCanvas.getMode(); + if(mode === "select") { setSelectMode(); } @@ -683,7 +686,7 @@ var elem = elems[i]; // if the element changed was the svg, then it could be a resolution change - if (elem && elem.tagName == "svg") { + if (elem && elem.tagName === "svg") { populateLayers(); updateCanvas(); } @@ -706,6 +709,12 @@ // text element was previously in focus updateContextPanel(); + // In the event a gradient was flipped: + if(selectedElement && mode === "select") { + paintBox.fill.update(); + paintBox.stroke.update(); + } + svgCanvas.runExtensions("elementChanged", { elems: elems }); @@ -782,6 +791,12 @@ updateTitle(); } + // Makes sure the current selected paint is available to work with + var prepPaints = function() { + paintBox.fill.prep(); + paintBox.stroke.prep(); + } + var flyout_funcs = {}; var setupFlyouts = function(holders) { @@ -1266,15 +1281,21 @@ runCallback(); }; - var getPaint = function(color, opac) { + var getPaint = function(color, opac, type) { // update the editor's fill paint var opts = null; - if (color.substr(0,5) == "url(#") { - var grad = document.getElementById(color.substr(5,color.length-6)); + if (color.indexOf("url(#") === 0) { + var refElem = svgCanvas.getRefElem(color); + if(refElem) { + refElem = refElem.cloneNode(true); + } else { + refElem = $("#" + type + "_color defs *")[0]; + } + opts = { alpha: opac }; - opts[grad.tagName] = grad; + opts[refElem.tagName] = refElem; } - else if (color.substr(0,1) == "#") { + else if (color.indexOf("#") === 0) { opts = { alpha: opac, solidColor: color.substr(1) @@ -1294,61 +1315,11 @@ var updateToolbar = function() { if (selectedElement != null && ['use', 'image', 'foreignObject', 'g', 'a'].indexOf(selectedElement.tagName) === -1) { - // get opacity values - var fillOpacity = parseFloat(selectedElement.getAttribute("fill-opacity")); - if (isNaN(fillOpacity)) { - fillOpacity = 1.0; - } + paintBox.fill.update(true); + paintBox.stroke.update(true); - var strokeOpacity = parseFloat(selectedElement.getAttribute("stroke-opacity")); - if (isNaN(strokeOpacity)) { - strokeOpacity = 1.0; - } - - // update fill color and opacity - var fillColor = selectedElement.getAttribute("fill")||"black"; - // prevent undo on these canvas changes - svgCanvas.setColor('fill', fillColor, true); - svgCanvas.setPaintOpacity('fill', fillOpacity, true); - - // update stroke color and opacity - var strokeColor = selectedElement.getAttribute("stroke")||"none"; - // prevent undo on these canvas changes - svgCanvas.setColor('stroke', strokeColor, true); - svgCanvas.setPaintOpacity('stroke', strokeOpacity, true); - - // update the rect inside #fill_color - $("#stroke_color rect").attr({ - fill: strokeColor, - opacity: strokeOpacity - }); - - // update the rect inside #fill_color - $("#fill_color rect").attr({ - fill: fillColor, - opacity: fillOpacity - }); - - fillOpacity *= 100; - strokeOpacity *= 100; - - fillPaint = getPaint(fillColor, fillOpacity); - strokePaint = getPaint(strokeColor, strokeOpacity); - - fillOpacity = fillOpacity + " %"; - strokeOpacity = strokeOpacity + " %"; - - // update fill color - if (fillColor == "none") { - fillOpacity = "N/A"; - } - if (strokeColor == null || strokeColor == "" || strokeColor == "none") { - strokeColor = "none"; - strokeOpacity = "N/A"; - } - - $('#stroke_width').val(selectedElement.getAttribute("stroke-width")||1).change(); - $('#stroke_style').val(selectedElement.getAttribute("stroke-dasharray")||"none").change(); + $('#stroke_width').val(selectedElement.getAttribute("stroke-width")||1); + $('#stroke_style').val(selectedElement.getAttribute("stroke-dasharray")||"none"); var attr = selectedElement.getAttribute("stroke-linejoin") || 'miter'; @@ -1359,7 +1330,6 @@ if ($('#linecap_' + attr).length != 0) setStrokeOpt($('#linecap_' + attr)[0]); - } // All elements including image and group have opacity @@ -1820,26 +1790,23 @@ $('.palette_item').mousedown(function(evt){ var right_click = evt.button === 2; - var picker = ((evt.shiftKey || right_click) ? "stroke" : "fill"); - var id = ((evt.shiftKey || right_click) ? '#stroke_' : '#fill_'); + var isStroke = evt.shiftKey || right_click; + var picker = isStroke ? "stroke" : "fill"; var color = $(this).attr('data-rgb'); - var rectbox = document.getElementById("gradbox_"+picker).parentNode.firstChild; var paint = null; // Webkit-based browsers returned 'initial' here for no stroke - if (color == 'transparent' || color == 'initial') { + if (color === 'transparent' || color === 'initial') { color = 'none'; - $(id + "opacity").html("N/A"); paint = new $.jGraduate.Paint(); } else { paint = new $.jGraduate.Paint({alpha: 100, solidColor: color.substr(1)}); } - rectbox.setAttribute("fill", color); - rectbox.setAttribute("opacity", 1); - if (evt.shiftKey) { - strokePaint = paint; + paintBox[picker].setPaint(paint); + + if (isStroke) { if (svgCanvas.getColor('stroke') != color) { svgCanvas.setColor('stroke', color); } @@ -1847,7 +1814,6 @@ svgCanvas.setPaintOpacity('stroke', 1.0); } } else { - fillPaint = paint; if (svgCanvas.getColor('fill') != color) { svgCanvas.setColor('fill', color); } @@ -2445,6 +2411,7 @@ zoomImage(); populateLayers(); updateContextPanel(); + prepPaints(); }); }; @@ -2580,7 +2547,7 @@ $('#save_output_btns').toggle(!!forSaving); $('#tool_source_back').toggle(!forSaving); - var str = svgCanvas.getSvgString(); + var str = orig_source = svgCanvas.getSvgString(); $('#svg_source_textarea').val(str); $('#svg_source_editor').fadeIn(); properlySourceSizeTextArea(); @@ -2652,6 +2619,7 @@ zoomImage(); populateLayers(); updateTitle(); + prepPaints(); } if (!svgCanvas.setSvgString($('#svg_source_textarea').val())) { @@ -2668,9 +2636,11 @@ var updateTitle = function(title) { title = title || svgCanvas.getDocumentTitle(); var new_title = orig_title + (title?': ' + title:''); - if(cur_context) { - new_title = new_title + cur_context; - } + + // Remove title update with current context info, isn't really necessary +// if(cur_context) { +// new_title = new_title + cur_context; +// } $('title:first').text(new_title); } @@ -3039,8 +3009,7 @@ }; if (editingsource) { - var oldString = svgCanvas.getSvgString(); - if (oldString != $('#svg_source_textarea').val()) { + if (orig_source !== $('#svg_source_textarea').val()) { $.confirm(uiStrings.QignoreSourceChanges, function(ok) { if(ok) hideSourceEditor(); }); @@ -3156,12 +3125,12 @@ var colorPicker = function(elem) { var picker = elem.attr('id') == 'stroke_color' ? 'stroke' : 'fill'; // var opacity = (picker == 'stroke' ? $('#stroke_opacity') : $('#fill_opacity')); - var paint = (picker == 'stroke' ? strokePaint : fillPaint); + var paint = paintBox[picker].paint; var title = (picker == 'stroke' ? 'Pick a Stroke Paint and Opacity' : 'Pick a Fill Paint and Opacity'); var was_none = false; var pos = elem.position(); $("#color_picker") - .draggable({cancel:'.jPicker_table,.jGraduate_lgPick,.jGraduate_rgPick'}) + .draggable({cancel:'.jGraduate_tabs,.jGraduate_colPick,.jGraduate_lgPick,.jGraduate_rgPick'}) .css(curConfig.colorPickerCSS || {'left': pos.left, 'bottom': 50 - pos.top}) .jGraduate( { @@ -3172,30 +3141,9 @@ function(p) { paint = new $.jGraduate.Paint(p); - var oldgrad = document.getElementById("gradbox_"+picker); - var svgbox = oldgrad.parentNode; - var rectbox = svgbox.firstChild; - if (paint.type == "linearGradient" || paint.type == "radialGradient") { - svgbox.removeChild(oldgrad); - var newgrad = svgbox.appendChild(document.importNode(paint[paint.type], true)); - newgrad.id = "gradbox_"+picker; - rectbox.setAttribute("fill", "url(#gradbox_" + picker + ")"); - rectbox.setAttribute("opacity", paint.alpha/100); - } - else { - rectbox.setAttribute("fill", paint.solidColor != "none" ? "#" + paint.solidColor : "none"); - rectbox.setAttribute("opacity", paint.alpha/100); - } - - if (picker == 'stroke') { - svgCanvas.setPaint('stroke', paint); - strokePaint = paint; - } - else { - svgCanvas.setPaint('fill', paint); - fillPaint = paint; - } - updateToolbar(); + paintBox[picker].setPaint(paint); + svgCanvas.setPaint(picker, paint); + $('#color_picker').hide(); }, function(p) { @@ -3260,39 +3208,103 @@ operaRepaint(); }; - // set up gradients to be used for the buttons - var svgdocbox = new DOMParser().parseFromString( - '\ - \ - \ - \ - ', 'text/xml'); - var docElem = svgdocbox.documentElement; - var boxgrad = svgdocbox.getElementById('gradbox_'); - boxgrad.id = 'gradbox_fill'; - docElem.setAttribute('width',16.5); - $('#fill_color').append( document.importNode(docElem,true) ); - - boxgrad.id = 'gradbox_stroke'; - docElem.setAttribute('width',16.5); - $('#stroke_color').append( document.importNode(docElem,true) ); - $('#stroke_color rect').attr({ - 'fill': '#' + curConfig.initStroke.color, - 'opacity': curConfig.initStroke.opacity - }); + var PaintBox = function(container, type) { + var cur = curConfig[type === 'fill' ? 'initFill' : 'initStroke']; + + // set up gradients to be used for the buttons + var svgdocbox = new DOMParser().parseFromString( + '\ + ', 'text/xml'); + var docElem = svgdocbox.documentElement; + + docElem = $(container)[0].appendChild(document.importNode(docElem, true)); + + docElem.setAttribute('width',16.5); + + this.rect = docElem.firstChild; + this.defs = docElem.getElementsByTagName('defs')[0]; + this.grad = this.defs.firstChild; + this.paint = new $.jGraduate.Paint({solidColor: cur.color}); + this.type = type; + + this.setPaint = function(paint, apply) { + this.paint = paint; + + var fillAttr = "none"; + var ptype = paint.type; + var opac = paint.alpha / 100; + + switch ( ptype ) { + case 'solidColor': + fillAttr = "#" + paint[ptype]; + break; + case 'linearGradient': + case 'radialGradient': + this.defs.removeChild(this.grad); + this.grad = this.defs.appendChild(paint[ptype]); + var id = this.grad.id = 'gradbox_' + this.type; + fillAttr = "url(#" + id + ')'; + } + + this.rect.setAttribute('fill', fillAttr); + this.rect.setAttribute('opacity', opac); + + if(apply) { + svgCanvas.setColor(this.type, paintColor, true); + svgCanvas.setPaintOpacity(this.type, paintOpacity, true); + } + } + + this.update = function(apply) { + if(!selectedElement) return; + var type = this.type; + var paintOpacity = parseFloat(selectedElement.getAttribute(type + "-opacity")); + if (isNaN(paintOpacity)) { + paintOpacity = 1.0; + } + + var defColor = type === "fill" ? "black" : "none"; + var paintColor = selectedElement.getAttribute(type) || defColor; + + if(apply) { + svgCanvas.setColor(type, paintColor, true); + svgCanvas.setPaintOpacity(type, paintOpacity, true); + } + + paintOpacity *= 100; + + var paint = getPaint(paintColor, paintOpacity, type); + // update the rect inside #fill_color/#stroke_color + this.setPaint(paint); + } + + this.prep = function() { + var ptype = this.paint.type; + + switch ( ptype ) { + case 'linearGradient': + case 'radialGradient': + var paint = new $.jGraduate.Paint({copy: this.paint}); + svgCanvas.setPaint(type, paint); + } + } + }; + paintBox.fill = new PaintBox('#fill_color', 'fill'); + paintBox.stroke = new PaintBox('#stroke_color', 'stroke'); + $('#stroke_width').val(curConfig.initStroke.width); $('#group_opacity').val(curConfig.initOpacity * 100); // Use this SVG elem to test vectorEffect support - var test_el = docElem.firstChild; + var test_el = paintBox.fill.rect.cloneNode(false); test_el.setAttribute('style','vector-effect:non-scaling-stroke'); var supportsNonSS = (test_el.style.vectorEffect === 'non-scaling-stroke'); test_el.removeAttribute('style'); - + var svgdocbox = paintBox.fill.rect.ownerDocument; // Use this to test support for blur element. Seems to work to test support in Webkit var blur_test = svgdocbox.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur'); if(typeof blur_test.stdDeviationX === "undefined") { @@ -4084,7 +4096,7 @@ if(f.files.length==1) { var reader = new FileReader(); reader.onloadend = function(e) { - svgCanvas.setSvgString(e.target.result); + loadSvgString(e.target.result); updateCanvas(); }; reader.readAsText(f.files[0]); @@ -4107,6 +4119,7 @@ } var updateCanvas = Editor.updateCanvas = function(center, new_ctr) { + var w = workarea.width(), h = workarea.height(); var w_orig = w, h_orig = h; var zoom = svgCanvas.getZoom(); @@ -4290,7 +4303,7 @@ updateCanvas(true); // }); - // var revnums = "svg-editor.js ($Rev: 1778 $) "; + // var revnums = "svg-editor.js ($Rev: 1802 $) "; // revnums += svgCanvas.getVersion(); // $('#copyright')[0].setAttribute("title", revnums); @@ -4399,6 +4412,18 @@ var callbacks = []; + function loadSvgString(str, callback) { + var success = svgCanvas.setSvgString(str) !== false; + callback = callback || $.noop; + if(success) { + callback(true); + } else { + $.alert('Error: Unable to load SVG data', function() { + callback(false); + }); + } + } + Editor.ready = function(cb) { if(!is_ready) { callbacks.push(cb); @@ -4416,22 +4441,29 @@ Editor.loadFromString = function(str) { Editor.ready(function() { - svgCanvas.setSvgString(str); + loadSvgString(str); }); }; - Editor.loadFromURL = function(url, cache) { + Editor.loadFromURL = function(url, opts) { + if(!opts) opts = {}; + + var cache = opts.cache; + var cb = opts.callback; + Editor.ready(function() { $.ajax({ 'url': url, 'dataType': 'text', cache: !!cache, - success: svgCanvas.setSvgString, + success: function(str) { + loadSvgString(str, cb); + }, error: function(xhr, stat, err) { - if(xhr.responseText) { - svgCanvas.setSvgString(xhr.responseText); + if(xhr.status != 404 && xhr.responseText) { + loadSvgString(xhr.responseText, cb); } else { - $.alert("Unable to load from URL. Error: \n"+err+''); + $.alert("Unable to load from URL. Error: \n"+err+'', cb); } } }); @@ -4440,10 +4472,9 @@ Editor.loadFromDataURI = function(str) { Editor.ready(function() { - svgCanvas.setSvgString(str); var pre = 'data:image/svg+xml;base64,'; var src = str.substring(pre.length); - svgCanvas.setSvgString(Utils.decode64(src)); + loadSvgString(svgCanvas.Utils.decode64(src)); }); }; diff --git a/public/svg-edit/editor/svgcanvas.js b/public/svg-edit/editor/svgcanvas.js index 46880a58..cbed8968 100644 --- a/public/svg-edit/editor/svgcanvas.js +++ b/public/svg-edit/editor/svgcanvas.js @@ -1,4 +1,4 @@ -/* +/* * svgcanvas.js * * Licensed under the Apache License, Version 2 @@ -118,7 +118,7 @@ var userAgent = navigator.userAgent, "mask": ["class", "height", "id", "maskContentUnits", "maskUnits", "width", "x", "y"], "metadata": ["class", "id"], "path": ["class", "clip-path", "clip-rule", "d", "fill", "fill-opacity", "fill-rule", "filter", "id", "marker-end", "marker-mid", "marker-start", "mask", "opacity", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform"], - "pattern": ["class", "height", "id", "patternContentUnits", "patternTransform", "patternUnits", "requiredFeatures", "style", "systemLanguage", "width", "x", "xlink:href", "y"], + "pattern": ["class", "height", "id", "patternContentUnits", "patternTransform", "patternUnits", "requiredFeatures", "style", "systemLanguage", "viewBox", "width", "x", "xlink:href", "y"], "polygon": ["class", "clip-path", "clip-rule", "id", "fill", "fill-opacity", "fill-rule", "filter", "id", "class", "marker-end", "marker-mid", "marker-start", "mask", "opacity", "points", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform"], "polyline": ["class", "clip-path", "clip-rule", "id", "fill", "fill-opacity", "fill-rule", "filter", "marker-end", "marker-mid", "marker-start", "mask", "opacity", "points", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform"], "radialGradient": ["class", "cx", "cy", "fx", "fy", "gradientTransform", "gradientUnits", "id", "r", "requiredFeatures", "spreadMethod", "systemLanguage", "xlink:href"], @@ -190,6 +190,7 @@ var userAgent = navigator.userAgent, var visElems_arr = visElems.split(','); // var hidElems = 'clipPath,defs,desc,feGaussianBlur,filter,linearGradient,marker,mask,metadata,pattern,radialGradient,stop,switch,symbol,title,textPath'; + var ref_attrs = ["clip-path", "fill", "filter", "marker-end", "marker-mid", "marker-start", "mask", "stroke"]; // Update config with new one if given @@ -712,6 +713,22 @@ var convertToNum, convertToUnit, setUnitAttr, unitConvertAttrs; })(); +var restoreRefElems = function(elem) { + // Look for missing reference elements, restore any found + var attrs = $(elem).attr(ref_attrs); + for(var o in attrs) { + var val = attrs[o]; + if (val && val.indexOf('url(') === 0) { + var id = getUrlFromAttr(val).substr(1); + var ref = getElem(id); + if(!ref) { + findDefs().appendChild(removedElements[id]); + delete removedElements[id]; + } + } + } +} + // Group: Undo/Redo history management this.undoCmd = {}; @@ -841,6 +858,9 @@ var InsertElementCommand = this.undoCmd.insertElement = function(elem, text) { // Re-Inserts the new element this.apply = function() { this.elem = this.parent.insertBefore(this.elem, this.elem.nextSibling); + + restoreRefElems(this.elem); + if (this.parent == svgcontent) { identifyLayers(); } @@ -894,8 +914,11 @@ var RemoveElementCommand = this.undoCmd.removeElement = function(elem, parent, t delete svgTransformLists[this.elem.id]; } - this.elem = this.parent.insertBefore(this.elem, this.elem.nextSibling); - if (this.parent == svgcontent) { + this.parent.insertBefore(this.elem, this.elem.nextSibling); + + restoreRefElems(this.elem); + + if (this.parent === svgcontent) { identifyLayers(); } }; @@ -1272,6 +1295,7 @@ var SelectorManager; if (selected.getAttribute("stroke") != "none" && !isNaN(sw)) { offset += (sw/2); } + if (selected.tagName == "text") { offset += 2/current_zoom; } @@ -1298,18 +1322,19 @@ var SelectorManager; m.f *= current_zoom; // apply the transforms - var l=bbox.x-offset, t=bbox.y-offset, w=bbox.width+(offset*2), h=bbox.height+(offset*2), + var l=bbox.x, t=bbox.y, w=bbox.width, h=bbox.height, bbox = {x:l, y:t, width:w, height:h}; + // we need to handle temporary transforms too // if skewed, get its transformed box, then find its axis-aligned bbox //* var nbox = transformBox(l*current_zoom, t*current_zoom, w*current_zoom, h*current_zoom, m), - nbax = nbox.aabox.x, - nbay = nbox.aabox.y, - nbaw = nbox.aabox.width, - nbah = nbox.aabox.height; + nbax = nbox.aabox.x - offset, + nbay = nbox.aabox.y - offset, + nbaw = nbox.aabox.width + (offset * 2), + nbah = nbox.aabox.height + (offset * 2); // now if the shape is rotated, un-rotate it var cx = nbax + nbaw/2, @@ -1332,10 +1357,10 @@ var SelectorManager; maxx = nbox.tl.x, maxy = nbox.tl.y; - minx = Math.min(minx, Math.min(nbox.tr.x, Math.min(nbox.bl.x, nbox.br.x) ) ); - miny = Math.min(miny, Math.min(nbox.tr.y, Math.min(nbox.bl.y, nbox.br.y) ) ); - maxx = Math.max(maxx, Math.max(nbox.tr.x, Math.max(nbox.bl.x, nbox.br.x) ) ); - maxy = Math.max(maxy, Math.max(nbox.tr.y, Math.max(nbox.bl.y, nbox.br.y) ) ); + minx = Math.min(minx, Math.min(nbox.tr.x, Math.min(nbox.bl.x, nbox.br.x) ) ) - offset; + miny = Math.min(miny, Math.min(nbox.tr.y, Math.min(nbox.bl.y, nbox.br.y) ) ) - offset; + maxx = Math.max(maxx, Math.max(nbox.tr.x, Math.max(nbox.bl.x, nbox.br.x) ) ) + offset; + maxy = Math.max(maxy, Math.max(nbox.tr.y, Math.max(nbox.bl.y, nbox.br.y) ) ) + offset; nbax = minx; nbay = miny; @@ -1683,6 +1708,7 @@ var SVGEditTransformList = function(elem) { var bits = x.split(/\s*\(/); var name = bits[0]; var val_bits = bits[1].match(/\s*(.*?)\s*\)/); + val_bits[1] = val_bits[1].replace(/(\d)-/g, "$1 -"); var val_arr = val_bits[1].split(/[, ]+/); var letters = 'abcdef'.split(''); var mtx = svgroot.createSVGMatrix(); @@ -1833,11 +1859,11 @@ var assignAttributes = this.assignAttributes = function(node, attrs, suspendLeng if(!suspendLength) suspendLength = 0; // Opera has a problem with suspendRedraw() apparently var handle = null; - if (!window.opera) svgroot.suspendRedraw(suspendLength); + if (!isOpera) svgroot.suspendRedraw(suspendLength); for (var i in attrs) { - var ns = (i.substr(0,4) == "xml:" ? xmlns : - i.substr(0,6) == "xlink:" ? xlinkns : null); + var ns = (i.substr(0,4) === "xml:" ? xmlns : + i.substr(0,6) === "xlink:" ? xlinkns : null); if(ns || !unitCheck) { node.setAttributeNS(ns, i, attrs[i]); @@ -2036,7 +2062,10 @@ var cur_shape = all_properties.shape, extensions = {}, // Canvas point for the most recent right click - lastClickPoint = null; + lastClickPoint = null, + + // Map of deleted reference elements + removedElements = {} // Clipboard for cut, copy&pasted elements canvas.clipBoard = []; @@ -2204,12 +2233,13 @@ var getStrokedBBox = this.getStrokedBBox = function(elems) { } if(!good_bb) { + // Must use clone else FF freaks out + var clone = elem.cloneNode(true); var g = document.createElementNS(svgns, "g"); var parent = elem.parentNode; - parent.replaceChild(g, elem); - g.appendChild(elem); + parent.appendChild(g); + g.appendChild(clone); bb = g.getBBox(); - parent.insertBefore(elem,g); parent.removeChild(g); } @@ -2418,11 +2448,6 @@ var copyElem = function(el) { // Parameters: // id - String with the element's new ID function getElem(id) { -// if(svgroot.getElementById) { -// // getElementById lookup -// return svgroot.getElementById(id); -// } else - if(svgroot.querySelector) { // querySelector lookup return svgroot.querySelector('#'+id); @@ -2566,6 +2591,18 @@ var sanitizeSvg = this.sanitizeSvg = function(node) { node.setAttribute('d',pathActions.convertPath(node)); pathActions.fixEnd(node); } + + // Add spaces before negative signs where necessary + if(isGecko) { + switch ( attrName ) { + case "transform": + case "gradientTransform": + case "patternTransform": + var val = attr.nodeValue.replace(/(\d)-/g, "$1 -"); + node.setAttribute(attrName, val); + } + } + // for the style attribute, rewrite it in terms of XML presentational attributes if (attrName == "style") { var props = attr.nodeValue.split(";"), @@ -2612,7 +2649,7 @@ var sanitizeSvg = this.sanitizeSvg = function(node) { if (val) { val = getUrlFromAttr(val); // simply check for first character being a '#' - if (val && val[0] != "#") { + if (val && val[0] !== "#") { node.setAttribute(attr, ""); node.removeAttribute(attr); } @@ -2657,20 +2694,29 @@ var sanitizeSvg = this.sanitizeSvg = function(node) { var getUrlFromAttr = this.getUrlFromAttr = function(attrVal) { if (attrVal) { // url("#somegrad") - if (attrVal.indexOf('url("') == 0) { + if (attrVal.indexOf('url("') === 0) { return attrVal.substring(5,attrVal.indexOf('"',6)); } // url('#somegrad') - else if (attrVal.indexOf("url('") == 0) { + else if (attrVal.indexOf("url('") === 0) { return attrVal.substring(5,attrVal.indexOf("'",6)); } - else if (attrVal.indexOf("url(") == 0) { + else if (attrVal.indexOf("url(") === 0) { return attrVal.substring(4,attrVal.indexOf(')')); } } return null; }; +// Function getRefElem +// Get the reference element associated with the given attribute value +// +// Parameters: +// attrVal - The attribute value as a string +var getRefElem = this.getRefElem = function(attrVal) { + return getElem(getUrlFromAttr(attrVal).substr(1)); +} + // Function: getBBox // Get the given/selected element's bounding box object, convert it to be more // usable when necessary @@ -2934,6 +2980,10 @@ var getTransformList = this.getTransformList = function(elem) { else if (elem.gradientTransform) { return elem.gradientTransform.baseVal; } + else if (elem.patternTransform) { + return elem.patternTransform.baseVal; + } + return null; }; @@ -2977,82 +3027,159 @@ var logMatrix = function(m) { // changes - Object with changes to be remapped // m - Matrix object to use for remapping coordinates var remapElement = this.remapElement = function(selected,changes,m) { + var remap = function(x,y) { return transformPoint(x,y,m); }, scalew = function(w) { return m.a*w; }, scaleh = function(h) { return m.d*h; }, + doSnapping = curConfig.gridSnapping && selected.parentNode.parentNode.localName === "svg", + finishUp = function() { + if(doSnapping) for(var o in changes) changes[o] = snapToGrid(changes[o]); + assignAttributes(selected, changes, 1000, true); + } box = getBBox(selected); + + for(var i = 0; i < 2; i++) { + var type = i === 0 ? 'fill' : 'stroke'; + var attrVal = selected.getAttribute(type); + if(attrVal && attrVal.indexOf('url(') === 0) { + if(m.a < 0 || m.d < 0) { + var grad = getRefElem(attrVal); + var newgrad = grad.cloneNode(true); + + if(m.a < 0) { + //flip x + var x1 = newgrad.getAttribute('x1'); + var x2 = newgrad.getAttribute('x2'); + newgrad.setAttribute('x1', -(x1 - 1)); + newgrad.setAttribute('x2', -(x2 - 1)); + } + + if(m.d < 0) { + //flip y + var y1 = newgrad.getAttribute('y1'); + var y2 = newgrad.getAttribute('y2'); + newgrad.setAttribute('y1', -(y1 - 1)); + newgrad.setAttribute('y2', -(y2 - 1)); + } + newgrad.id = getNextId(); + findDefs().appendChild(newgrad); + selected.setAttribute(type, 'url(#' + newgrad.id + ')'); + } + } + + } - switch (selected.tagName) + + var elName = selected.tagName; + if(elName === "g" || elName === "text" || elName === "use") { + // if it was a translate, then just update x,y + if (m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 && + (m.e != 0 || m.f != 0) ) + { + // [T][M] = [M][T'] + // therefore [T'] = [M_inv][T][M] + var existing = transformListToTransform(selected).matrix, + t_new = matrixMultiply(existing.inverse(), m, existing); + changes.x = parseFloat(changes.x) + t_new.e; + changes.y = parseFloat(changes.y) + t_new.f; + } + else { + // we just absorb all matrices into the element and don't do any remapping + var chlist = getTransformList(selected); + var mt = svgroot.createSVGTransform(); + mt.setMatrix(matrixMultiply(transformListToTransform(chlist).matrix,m)); + chlist.clear(); + chlist.appendItem(mt); + } + } + + // now we have a set of changes and an applied reduced transform list + // we apply the changes directly to the DOM + switch (elName) { - case "line": - var pt1 = remap(changes["x1"],changes["y1"]), - pt2 = remap(changes["x2"],changes["y2"]); - changes["x1"] = pt1.x; - changes["y1"] = pt1.y; - changes["x2"] = pt2.x; - changes["y2"] = pt2.y; - break; - case "circle": - var c = remap(changes["cx"],changes["cy"]); - changes["cx"] = c.x; - changes["cy"] = c.y; - // take the minimum of the new selected box's dimensions for the new circle radius - var tbox = transformBox(box.x, box.y, box.width, box.height, m); - var w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y; - changes["r"] = Math.min(w/2, h/2); - break; - case "ellipse": - var c = remap(changes["cx"],changes["cy"]); - changes["cx"] = c.x; - changes["cy"] = c.y; - changes["rx"] = scalew(changes["rx"]); - changes["ry"] = scaleh(changes["ry"]); - break; case "foreignObject": case "rect": case "image": - var pt1 = remap(changes["x"],changes["y"]); - changes["x"] = pt1.x; - changes["y"] = pt1.y; - changes["width"] = scalew(changes["width"]); - changes["height"] = scaleh(changes["height"]); - break; - case "use": -// var pt1 = remap(changes["x"],changes["y"]); -// changes["x"] = pt1.x; -// changes["y"] = pt1.y; -// break; - case "g": - case "text": - // if it was a translate, then just update x,y - if (m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 && - (m.e != 0 || m.f != 0) ) - { - // [T][M] = [M][T'] - // therefore [T'] = [M_inv][T][M] - var existing = transformListToTransform(selected).matrix, - t_new = matrixMultiply(existing.inverse(), m, existing); - changes["x"] = parseFloat(changes["x"]) + t_new.e; - changes["y"] = parseFloat(changes["y"]) + t_new.f; - } - else { - // we just absorb all matrices into the element and don't do any remapping + + // Allow images to be inverted (give them matrix when flipped) + if(elName === 'image' && (m.a < 0 || m.d < 0)) { + // Convert to matrix var chlist = getTransformList(selected); var mt = svgroot.createSVGTransform(); mt.setMatrix(matrixMultiply(transformListToTransform(chlist).matrix,m)); chlist.clear(); chlist.appendItem(mt); + } else { + var pt1 = remap(changes.x,changes.y); + + changes.width = scalew(changes.width); + changes.height = scaleh(changes.height); + + changes.x = pt1.x + Math.min(0,changes.width); + changes.y = pt1.y + Math.min(0,changes.height); + changes.width = Math.abs(changes.width); + changes.height = Math.abs(changes.height); + } + finishUp(); + break; + case "ellipse": + var c = remap(changes.cx,changes.cy); + changes.cx = c.x; + changes.cy = c.y; + changes.rx = scalew(changes.rx); + changes.ry = scaleh(changes.ry); + + changes.rx = Math.abs(changes.rx); + changes.ry = Math.abs(changes.ry); + finishUp(); + break; + case "circle": + var c = remap(changes.cx,changes.cy); + changes.cx = c.x; + changes.cy = c.y; + // take the minimum of the new selected box's dimensions for the new circle radius + var tbox = transformBox(box.x, box.y, box.width, box.height, m); + var w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y; + changes.r = Math.min(w/2, h/2); + + if(changes.r) changes.r = Math.abs(changes.r); + finishUp(); + break; + case "line": + var pt1 = remap(changes.x1,changes.y1), + pt2 = remap(changes.x2,changes.y2); + changes.x1 = pt1.x; + changes.y1 = pt1.y; + changes.x2 = pt2.x; + changes.y2 = pt2.y; + + case "text": + case "use": + finishUp(); + break; + case "g": + var gsvg = $(selected).data('gsvg'); + if(gsvg) { + assignAttributes(gsvg, changes, 1000, true); } break; - case "polygon": case "polyline": - var len = changes["points"].length; + case "polygon": + var len = changes.points.length; for (var i = 0; i < len; ++i) { - var pt = changes["points"][i]; + var pt = changes.points[i]; pt = remap(pt.x,pt.y); - changes["points"][i].x = pt.x; - changes["points"][i].y = pt.y; + changes.points[i].x = pt.x; + changes.points[i].y = pt.y; } + + var len = changes.points.length; + var pstr = ""; + for (var i = 0; i < len; ++i) { + var pt = changes.points[i]; + pstr += pt.x + "," + pt.y + " "; + } + selected.setAttribute("points", pstr); break; case "path": var segList = selected.pathSegList; @@ -3076,13 +3203,13 @@ var remapElement = this.remapElement = function(selected,changes,m) { }; } - var len = changes["d"].length, - firstseg = changes["d"][0], + var len = changes.d.length, + firstseg = changes.d[0], currentpt = remap(firstseg.x,firstseg.y); - changes["d"][0].x = currentpt.x; - changes["d"][0].y = currentpt.y; + changes.d[0].x = currentpt.x; + changes.d[0].y = currentpt.y; for (var i = 1; i < len; ++i) { - var seg = changes["d"][i]; + var seg = changes.d[i]; var type = seg.type; // if absolute or first segment, we want to remap x, y, x1, y1, x2, y2 // if relative, we want to scalew, scaleh @@ -3115,81 +3242,11 @@ var remapElement = this.remapElement = function(selected,changes,m) { if (seg.x) currentpt.x = seg.x; if (seg.y) currentpt.y = seg.y; } // for each segment - break; - } // switch on element type to get initial values - - // now we have a set of changes and an applied reduced transform list - // we apply the changes directly to the DOM - // TODO: merge this switch with the above one and optimize - switch (selected.tagName) - { - case "foreignObject": - case "rect": - case "image": - changes.x = changes.x-0 + Math.min(0,changes.width); - changes.y = changes.y-0 + Math.min(0,changes.height); - changes.width = Math.abs(changes.width); - changes.height = Math.abs(changes.height); - if(curConfig.gridSnapping && selected.parentNode.parentNode.localName == "svg"){ - changes.x = snapToGrid(changes.x); - changes.y = snapToGrid(changes.y); - changes.width = snapToGrid(changes.width); - changes.height = snapToGrid(changes.height); - } - assignAttributes(selected, changes, 1000, true); - break; - case "ellipse": - changes.rx = Math.abs(changes.rx); - changes.ry = Math.abs(changes.ry); - if(curConfig.gridSnapping && selected.parentNode.parentNode.localName == "svg"){ - changes.cx = snapToGrid(changes.cx); - changes.cy = snapToGrid(changes.cy); - changes.rx = snapToGrid(changes.rx); - changes.ry = snapToGrid(changes.ry); - } - case "circle": - if(changes.r) changes.r = Math.abs(changes.r); - if(curConfig.gridSnapping && selected.parentNode.parentNode.localName == "svg"){ - changes.cx = snapToGrid(changes.cx); - changes.cy = snapToGrid(changes.cy); - changes.r = snapToGrid(changes.r); - } - case "line": - if(curConfig.gridSnapping && selected.parentNode.parentNode.localName == "svg"){ - changes.x1 = snapToGrid(changes.x1); - changes.y1 = snapToGrid(changes.y1); - changes.x2 = snapToGrid(changes.x2); - changes.y2 = snapToGrid(changes.y2); - } - case "text": - if(curConfig.gridSnapping && selected.parentNode.parentNode.localName == "svg"){ - changes.x = snapToGrid(changes.x); - changes.y = snapToGrid(changes.y); - } - case "use": - assignAttributes(selected, changes, 1000, true); - break; - case "g": - var gsvg = $(selected).data('gsvg'); - if(gsvg) { - assignAttributes(gsvg, changes, 1000, true); - } - break; - case "polyline": - case "polygon": - var len = changes["points"].length; - var pstr = ""; - for (var i = 0; i < len; ++i) { - var pt = changes["points"][i]; - pstr += pt.x + "," + pt.y + " "; - } - selected.setAttribute("points", pstr); - break; - case "path": + var dstr = ""; - var len = changes["d"].length; + var len = changes.d.length; for (var i = 0; i < len; ++i) { - var seg = changes["d"][i]; + var seg = changes.d[i]; var type = seg.type; dstr += pathMap[type]; switch(type) { @@ -3242,8 +3299,7 @@ var remapElement = this.remapElement = function(selected,changes,m) { // tx - The translation's x value // ty - The translation's y value var updateClipPath = function(attr, tx, ty) { - var id = getUrlFromAttr(attr).substr(1); - var path = getElem(id).firstChild; + var path = getRefElem(attr).firstChild; var cp_xform = getTransformList(path); @@ -3324,8 +3380,8 @@ var recalculateDimensions = this.recalculateDimensions = function(selected) { if(k === 2 && tlist.getItem(0).type === 1 && tlist.getItem(1).type === 2) { var mt = svgroot.createSVGTransform(); - logMatrix(tlist.getItem(0).matrix); - logMatrix(transformListToTransform(tlist).matrix); +// logMatrix(tlist.getItem(0).matrix); +// logMatrix(transformListToTransform(tlist).matrix); mt.setMatrix(transformListToTransform(tlist).matrix); tlist.clear(); @@ -3532,8 +3588,8 @@ var recalculateDimensions = this.recalculateDimensions = function(selected) { childxforms.push(translateBack); childxforms.push(scale); childxforms.push(translateOrigin); - logMatrix(translateBack.matrix); - logMatrix(scale.matrix); +// logMatrix(translateBack.matrix); +// logMatrix(scale.matrix); } // not rotated batchCmd.addSubCommand( recalculateDimensions(child) ); // TODO: If any have this group as a parent and are @@ -3667,6 +3723,15 @@ var recalculateDimensions = this.recalculateDimensions = function(selected) { batchCmd.addSubCommand( recalculateDimensions(child) ); start_transform = old_start_transform; + + // Convert stroke + // TODO: Find out if this should actually happen somewhere else + var sw = child.getAttribute("stroke-width"); + if (child.getAttribute("stroke") !== "none" && !isNaN(sw)) { + var avg = (Math.abs(em.a) + Math.abs(em.d)) / 2; + child.setAttribute('stroke-width', sw * avg); + } + } } tlist.clear(); @@ -3806,17 +3871,18 @@ var recalculateDimensions = this.recalculateDimensions = function(selected) { if(!isWebkit) { var fill = selected.getAttribute('fill'); if(fill && fill.indexOf('url(') === 0) { - var grad = getElem(getUrlFromAttr(fill).substr(1)); - if(grad.getAttribute('gradientUnits') === 'userSpaceOnUse') { - + var paint = getRefElem(fill); + var type = 'pattern'; + if(paint.tagName !== type) type = 'gradient'; + var attrVal = paint.getAttribute(type + 'Units'); + if(attrVal === 'userSpaceOnUse') { //Update the userSpaceOnUse element - var grad = $(grad); m = transformListToTransform(tlist).matrix; - var gtlist = getTransformList(grad[0]); + var gtlist = getTransformList(paint); var gmatrix = transformListToTransform(gtlist).matrix; m = matrixMultiply(m, gmatrix); var m_str = "matrix(" + [m.a,m.b,m.c,m.d,m.e,m.f].join(",") + ")"; - grad.attr('gradientTransform', m_str); + paint.setAttribute(type + 'Transform', m_str); } } } @@ -4579,6 +4645,14 @@ var getMouseTarget = this.getMouseTarget = function(evt) { tlist.appendItem(svgroot.createSVGTransform()); tlist.appendItem(svgroot.createSVGTransform()); tlist.appendItem(svgroot.createSVGTransform()); + + if(support.nonScalingStroke) { + mouse_target.style.vectorEffect = 'non-scaling-stroke'; + var all = mouse_target.getElementsByTagName('*'), len = all.length; + for(var i = 0; i < all.length; i++) { + all[i].style.vectorEffect = 'non-scaling-stroke'; + } + } } break; case "fhellipse": @@ -4708,7 +4782,8 @@ var getMouseTarget = this.getMouseTarget = function(evt) { "font-size": cur_text.font_size, "font-family": cur_text.font_family, "text-anchor": "middle", - "xml:space": "preserve" + "xml:space": "preserve", + "opacity": cur_shape.opacity } }); // newText.textContent = "text"; @@ -5227,6 +5302,16 @@ var getMouseTarget = this.getMouseTarget = function(evt) { } } } // no change in mouse position + + // Remove non-scaling stroke + if(support.nonScalingStroke) { + var elem = selectedElements[0]; + elem.removeAttribute('style'); + walkTree(elem, function(elem) { + elem.removeAttribute('style'); + }); + } + } // we return immediately from select so that the obj_num is not incremented return; @@ -5452,8 +5537,14 @@ var getMouseTarget = this.getMouseTarget = function(evt) { } if(getRotationAngle(mouse_target)) { - // Don't do for rotated groups for now - return; + // TODO: Allow method of in-group editing without having to do + // this (similar to editing rotated paths) + + // Ungroup and regroup + canvas.ungroupSelectedElement(); + canvas.groupSelectedElements(); + mouse_target = selectedElements[0]; + clearSelection(true); } // Reset context if(current_group) { @@ -7762,19 +7853,20 @@ var removeUnusedDefElems = this.removeUnusedDefElems = function() { // gradients can refer to other gradients var href = getHref(el); - if (href && href.indexOf('#') == 0) { + if (href && href.indexOf('#') === 0) { defelem_uses.push(href.substr(1)); } }; - var defelems = $(svgcontent).find("linearGradient, radialGradient, filter, marker, svg"); + var defelems = $(svgcontent).find("linearGradient, radialGradient, filter, marker, svg, symbol"); defelem_ids = [], i = defelems.length; while (i--) { var defelem = defelems[i]; var id = defelem.id; - if(defelem_uses.indexOf(id) == -1) { - // Not found, so remove + if(defelem_uses.indexOf(id) < 0) { + // Not found, so remove (but remember) + removedElements[id] = defelem; defelem.parentNode.removeChild(defelem); numRemoved++; } @@ -8124,7 +8216,6 @@ this.randomizeIds = function() { // g - The parent element of the tree to give unique IDs var uniquifyElems = this.uniquifyElems = function(g) { var ids = {}; - var ref_attrs = ["clip-path", "fill", "filter", "marker-end", "marker-mid", "marker-start", "mask", "stroke"]; var ref_elems = ["filter", "linearGradient", "pattern", "radialGradient", "textPath", "use"]; walkTree(g, function(n) { @@ -8227,16 +8318,33 @@ var convertGradients = this.convertGradients = function(elem) { // get object's bounding box var bb = getBBox(elems[0]); + // This will occur if the element is inside a or a , + // in which we shouldn't need to convert anyway. + if(!bb) return; + if(grad.tagName === 'linearGradient') { var g_coords = $(grad).attr(['x1', 'y1', 'x2', 'y2']); + // If has transform, convert + var tlist = grad.gradientTransform.baseVal; + if(tlist && tlist.numberOfItems > 0) { + var m = transformListToTransform(tlist).matrix; + var pt1 = transformPoint(g_coords.x1, g_coords.y1, m); + var pt2 = transformPoint(g_coords.x2, g_coords.y2, m); + + g_coords.x1 = pt1.x; + g_coords.y1 = pt1.y; + g_coords.x2 = pt2.x; + g_coords.y2 = pt2.y; + grad.removeAttribute('gradientTransform'); + } + $(grad).attr({ x1: (g_coords.x1 - bb.x) / bb.width, y1: (g_coords.y1 - bb.y) / bb.height, x2: (g_coords.x2 - bb.x) / bb.width, y2: (g_coords.y2 - bb.y) / bb.height }); - grad.removeAttribute('gradientUnits'); } else { // Note: radialGradient elements cannot be easily converted @@ -8325,7 +8433,6 @@ var convertToGroup = this.convertToGroup = function(elem) { // g.appendChild(elem.firstChild.cloneNode(true)); if (ts) g.setAttribute("transform", ts); - console.log('t',g.getAttribute('transform')); var parent = elem.parentNode; @@ -8444,9 +8551,9 @@ this.setSvgString = function(xmlString) { } }); - // For Firefox: Put all gradients in defs + // For Firefox: Put all paint elems in defs if(isGecko) { - content.find('linearGradient, radialGradient').appendTo(findDefs()); + content.find('linearGradient, radialGradient, pattern').appendTo(findDefs()); } @@ -8574,6 +8681,8 @@ this.importSvgString = function(xmlString) { // import new svg document into our document var svg = svgdoc.importNode(newDoc.documentElement, true); + uniquifyElems(svg); + var innerw = convertToNum('width', svg.getAttribute("width")), innerh = convertToNum('height', svg.getAttribute("height")), innervb = svg.getAttribute("viewBox"), @@ -8597,17 +8706,17 @@ this.importSvgString = function(xmlString) { // Hack to make recalculateDimensions understand how to scale ts = "translate(0) " + ts + " translate(0)"; - // Uncomment this once Firefox has fixed their symbol bug: - // https://bugzilla.mozilla.org/show_bug.cgi?id=353575 var symbol = svgdoc.createElementNS(svgns, "symbol"); var defs = findDefs(); + if(isGecko) { + // Move all gradients into root for Firefox, workaround for this bug: + // https://bugzilla.mozilla.org/show_bug.cgi?id=353575 + $(svg).find('linearGradient, radialGradient, pattern').appendTo(defs); + } + while (svg.firstChild) { var first = svg.firstChild; - if(isGecko && first.tagName === 'defs') { - // Move all gradients into root for Firefox - $(first).find('linearGradient, radialGradient').appendTo(defs); - } symbol.appendChild(first); } var attrs = svg.attributes; @@ -8621,7 +8730,7 @@ this.importSvgString = function(xmlString) { var use_el = svgdoc.createElementNS(svgns, "use"); setHref(use_el, "#" + symbol.id); findDefs().appendChild(symbol); - + (current_group || current_layer).appendChild(use_el); use_el.id = getNextId(); clearSelection(); @@ -9253,7 +9362,7 @@ this.getZoom = function(){return current_zoom;}; // Function: getVersion // Returns a string which describes the revision number of SvgCanvas. this.getVersion = function() { - return "svgcanvas.js ($Rev: 1777 $)"; + return "svgcanvas.js ($Rev: 1804 $)"; }; // Function: setUiStrings @@ -10702,6 +10811,7 @@ this.ungroupSelectedElement = function() { var anchor = g.nextSibling; var children = new Array(g.childNodes.length); var xform = g.getAttribute("transform"); + // get consolidated matrix var glist = getTransformList(g); var m = transformListToTransform(glist).matrix; @@ -10755,14 +10865,14 @@ this.ungroupSelectedElement = function() { if(!orig_cblur) { // Set group's filter to use first child's ID if(!gfilter) { - gfilter = getElem(getUrlFromAttr(gattrs.filter).substr(1)); + gfilter = getRefElem(gattrs.filter); } else { // Clone the group's filter gfilter = copyElem(gfilter); findDefs().appendChild(gfilter); } } else { - gfilter = getElem(getUrlFromAttr(elem.getAttribute('filter')).substr(1)); + gfilter = getRefElem(elem.getAttribute('filter')); } // Change this in future for different filters @@ -11412,6 +11522,10 @@ function disableAdvancedTextEdit() { unit_types.pt = inch / 72; unit_types.pc = inch / 6; unit_types['%'] = 0; + + rect.setAttribute('style','vector-effect:non-scaling-stroke'); + support.nonScalingStroke = (rect.style.vectorEffect === 'non-scaling-stroke'); + svgcontent.removeChild(rect); }()); diff --git a/public/svg-edit/test/test1.html b/public/svg-edit/test/test1.html index bdf4b46a..751c66b6 100644 --- a/public/svg-edit/test/test1.html +++ b/public/svg-edit/test/test1.html @@ -2,6 +2,7 @@ + @@ -67,7 +68,7 @@ // "m 0,0 l 200,0 l 0,100 L 0,100" svgCanvas.setSvgString("" + - "" + + "" + "" + ""); @@ -79,19 +80,19 @@ equal(p1.nodeName, "path", "Expected 'path', got"); - equal(seglist.numberOfItems, 3, "Number of segments before conversion"); + equal(seglist.numberOfItems, 4, "Number of segments before conversion"); // verify segments before conversion curseg = seglist.getItem(0); - equal(curseg.pathSegTypeAsLetter, "M", "Before conversion, segment #1 type"); + equal(curseg.pathSegTypeAsLetter.toUpperCase(), "M", "Before conversion, segment #1 type"); curseg = seglist.getItem(1); - equal(curseg.pathSegTypeAsLetter, "L", "Before conversion, segment #2 type"); - curseg = seglist.getItem(2); - equal(curseg.pathSegTypeAsLetter, "Z", "Before conversion, segment #3 type" + d_abs); + equal(curseg.pathSegTypeAsLetter.toUpperCase(), "L", "Before conversion, segment #2 type"); + curseg = seglist.getItem(3); + equal(curseg.pathSegTypeAsLetter.toUpperCase(), "Z", "Before conversion, segment #3 type" + d_abs); // convert and verify segments var d = convert(p1, true); - equal(d, "m100,100l100,0z", "Converted path to relative string"); + equal(d, "m100,100l100,0l-100,0z", "Converted path to relative string"); // TODO: see why this isn't working in SVG-edit d = convert(p2, true); @@ -188,15 +189,19 @@ // This test makes sure import/export properly handles namespaced attributes test("Test importing/exporting namespaced attributes", function() { expect(5); - var set = svgCanvas.setSvgString(''+ + var setStr = svgCanvas.setSvgString(''+ '' + - '' + + '' + ''); var attrVal = document.getElementById('se_test_elem').getAttributeNS("http://svg-edit.googlecode.com", "foo"); equal(attrVal === "bar", true, "Preserved namespaced attribute on import"); - +// +// console.log('getSvgString' in svgCanvas) + var output = svgCanvas.getSvgString(); +// } catch(e) {console.log(e)} +// console.log('output',output); var has_xlink = output.indexOf('xmlns:xlink="http://www.w3.org/1999/xlink"') !== -1; var has_se = output.indexOf('xmlns:se=') !== -1; var has_foo = output.indexOf('xmlns:foo=') !== -1; @@ -233,9 +238,9 @@ test("Test escaping XML entities", function() { expect(3); - equal(svgCanvas.getPrivateMethods().toXml("<"), "<", "Escaped < properly"); - equal(svgCanvas.getPrivateMethods().toXml(">"), ">", "Escaped > properly"); - equal(svgCanvas.getPrivateMethods().toXml("&"), "&", "Escaped & properly"); + equal(svgCanvas.Utils.toXml("<"), "<", "Escaped < properly"); + equal(svgCanvas.Utils.toXml(">"), ">", "Escaped > properly"); + equal(svgCanvas.Utils.toXml("&"), "&", "Escaped & properly"); // TODO: what about " and ' ? }); diff --git a/vendor/plugins/rails_xss/init.rb b/vendor/plugins/rails_xss/init.rb index ae911d85..06eb5454 100644 --- a/vendor/plugins/rails_xss/init.rb +++ b/vendor/plugins/rails_xss/init.rb @@ -1,5 +1,5 @@ unless $gems_rake_task - if Rails.version <= "2.3.7" + if !(Rails::VERSION::MAJOR.to_i >= 2 && Rails::VERSION::MINOR.to_i >=3 && Rails::VERSION::TINY.to_i >=8) $stderr.puts "rails_xss requires Rails 2.3.8 or later. Please upgrade to enable automatic HTML safety." else require 'rails_xss' diff --git a/vendor/rails/actionmailer/CHANGELOG b/vendor/rails/actionmailer/CHANGELOG index e0d5525f..2b3e4ed7 100644 --- a/vendor/rails/actionmailer/CHANGELOG +++ b/vendor/rails/actionmailer/CHANGELOG @@ -1,3 +1,4 @@ +*2.3.10 (October 15, 2010)* *2.3.9 (September 4, 2010)* *2.3.8 (May 24, 2010)* *2.3.7 (May 24, 2010)* diff --git a/vendor/rails/actionmailer/Rakefile b/vendor/rails/actionmailer/Rakefile index afeab4a8..fa671826 100644 --- a/vendor/rails/actionmailer/Rakefile +++ b/vendor/rails/actionmailer/Rakefile @@ -54,7 +54,7 @@ spec = Gem::Specification.new do |s| s.rubyforge_project = "actionmailer" s.homepage = "http://www.rubyonrails.org" - s.add_dependency('actionpack', '= 2.3.9' + PKG_BUILD) + s.add_dependency('actionpack', '= 2.3.10' + PKG_BUILD) s.has_rdoc = true s.requirements << 'none' diff --git a/vendor/rails/actionmailer/lib/action_mailer/version.rb b/vendor/rails/actionmailer/lib/action_mailer/version.rb index 611a48b6..8167d903 100644 --- a/vendor/rails/actionmailer/lib/action_mailer/version.rb +++ b/vendor/rails/actionmailer/lib/action_mailer/version.rb @@ -2,7 +2,7 @@ module ActionMailer module VERSION #:nodoc: MAJOR = 2 MINOR = 3 - TINY = 9 + TINY = 10 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/vendor/rails/actionpack/CHANGELOG b/vendor/rails/actionpack/CHANGELOG index 50e67e70..87e86308 100644 --- a/vendor/rails/actionpack/CHANGELOG +++ b/vendor/rails/actionpack/CHANGELOG @@ -1,3 +1,5 @@ +*2.3.10 (October 15, 2010)* + *2.3.9 (September 4, 2010)* * Version bump. diff --git a/vendor/rails/actionpack/Rakefile b/vendor/rails/actionpack/Rakefile index 2a2ecd6f..b97eae09 100644 --- a/vendor/rails/actionpack/Rakefile +++ b/vendor/rails/actionpack/Rakefile @@ -79,7 +79,7 @@ spec = Gem::Specification.new do |s| s.has_rdoc = true s.requirements << 'none' - s.add_dependency('activesupport', '= 2.3.9' + PKG_BUILD) + s.add_dependency('activesupport', '= 2.3.10' + PKG_BUILD) s.add_dependency('rack', '~> 1.1.0') s.require_path = 'lib' diff --git a/vendor/rails/actionpack/lib/action_controller/base.rb b/vendor/rails/actionpack/lib/action_controller/base.rb index 62f43957..41a8a64a 100644 --- a/vendor/rails/actionpack/lib/action_controller/base.rb +++ b/vendor/rails/actionpack/lib/action_controller/base.rb @@ -1088,6 +1088,9 @@ module ActionController #:nodoc: # redirect_to post_url(@post), :status => 301 # redirect_to :action=>'atom', :status => 302 # + # The status code can either be a standard {HTTP Status code}[http://www.iana.org/assignments/http-status-codes] as an + # integer, or a symbol representing the downcased, underscored and symbolized description. + # # It is also possible to assign a flash message as part of the redirection. There are two special accessors for commonly used the flash names # +alert+ and +notice+ as well as a general purpose +flash+ bucket. # @@ -1097,8 +1100,7 @@ module ActionController #:nodoc: # redirect_to post_url(@post), :status => 301, :flash => { :updated_post_id => @post.id } # redirect_to { :action=>'atom' }, :alert => "Something serious happened" # - # When using redirect_to :back, if there is no referrer, - # RedirectBackError will be raised. You may specify some fallback + # When using redirect_to :back, if there is no referrer, RedirectBackError will be raised. You may specify some fallback # behavior for this case by rescuing RedirectBackError. def redirect_to(options = {}, response_status = {}) #:doc: raise ActionControllerError.new("Cannot redirect to nil!") if options.nil? diff --git a/vendor/rails/actionpack/lib/action_controller/integration.rb b/vendor/rails/actionpack/lib/action_controller/integration.rb index 1447f012..d9de6b8f 100644 --- a/vendor/rails/actionpack/lib/action_controller/integration.rb +++ b/vendor/rails/actionpack/lib/action_controller/integration.rb @@ -287,7 +287,6 @@ module ActionController "REMOTE_ADDR" => remote_addr, "CONTENT_TYPE" => "application/x-www-form-urlencoded", "CONTENT_LENGTH" => data ? data.length.to_s : nil, - "HTTP_COOKIE" => encode_cookies, "HTTP_ACCEPT" => accept, "rack.version" => [0,1], @@ -298,6 +297,8 @@ module ActionController "rack.run_once" => false ) + env['HTTP_COOKIE'] = encode_cookies if cookies.any? + (headers || {}).each do |key, value| key = key.to_s.upcase.gsub(/-/, "_") key = "HTTP_#{key}" unless env.has_key?(key) || key =~ /^HTTP_/ @@ -535,7 +536,7 @@ EOF if self.class.respond_to?(:fixture_table_names) self.class.fixture_table_names.each do |table_name| name = table_name.tr(".", "_") - next unless respond_to?(name) + next unless respond_to?(name, true) extras.__send__(:define_method, name) { |*args| delegate.send(name, *args) } diff --git a/vendor/rails/actionpack/lib/action_controller/session/abstract_store.rb b/vendor/rails/actionpack/lib/action_controller/session/abstract_store.rb index 11cb6c27..51acab24 100644 --- a/vendor/rails/actionpack/lib/action_controller/session/abstract_store.rb +++ b/vendor/rails/actionpack/lib/action_controller/session/abstract_store.rb @@ -180,6 +180,10 @@ module ActionController options = env[ENV_SESSION_OPTIONS_KEY] if !session_data.is_a?(AbstractStore::SessionHash) || session_data.loaded? || options[:expire_after] + request = ActionController::Request.new(env) + + return response if (options[:secure] && !request.ssl?) + session_data.send(:load!) if session_data.is_a?(AbstractStore::SessionHash) && !session_data.loaded? sid = options[:id] || generate_sid @@ -188,7 +192,9 @@ module ActionController return response end - if (env["rack.request.cookie_hash"] && env["rack.request.cookie_hash"][@key] != sid) || options[:expire_after] + request_cookies = env["rack.request.cookie_hash"] + + if (request_cookies.nil? || request_cookies[@key] != sid) || options[:expire_after] cookie = Rack::Utils.escape(@key) + '=' + Rack::Utils.escape(sid) cookie << "; domain=#{options[:domain]}" if options[:domain] cookie << "; path=#{options[:path]}" if options[:path] @@ -196,7 +202,7 @@ module ActionController expiry = Time.now + options[:expire_after] cookie << "; expires=#{expiry.httpdate}" end - cookie << "; Secure" if options[:secure] + cookie << "; secure" if options[:secure] cookie << "; HttpOnly" if options[:httponly] headers = response[1] diff --git a/vendor/rails/actionpack/lib/action_controller/session/cookie_store.rb b/vendor/rails/actionpack/lib/action_controller/session/cookie_store.rb index 313307c9..31b63663 100644 --- a/vendor/rails/actionpack/lib/action_controller/session/cookie_store.rb +++ b/vendor/rails/actionpack/lib/action_controller/session/cookie_store.rb @@ -101,8 +101,9 @@ module ActionController session_data = env[ENV_SESSION_KEY] options = env[ENV_SESSION_OPTIONS_KEY] - - if !session_data.is_a?(AbstractStore::SessionHash) || session_data.loaded? || options[:expire_after] + request = ActionController::Request.new(env) + + if !(options[:secure] && !request.ssl?) && (!session_data.is_a?(AbstractStore::SessionHash) || session_data.loaded? || options[:expire_after]) session_data.send(:load!) if session_data.is_a?(AbstractStore::SessionHash) && !session_data.loaded? persistent_session_id!(session_data) diff --git a/vendor/rails/actionpack/lib/action_controller/url_rewriter.rb b/vendor/rails/actionpack/lib/action_controller/url_rewriter.rb index 552c2ae9..e6d99f2e 100644 --- a/vendor/rails/actionpack/lib/action_controller/url_rewriter.rb +++ b/vendor/rails/actionpack/lib/action_controller/url_rewriter.rb @@ -1,3 +1,5 @@ +require 'uri' + module ActionController # In routes.rb one defines URL-to-controller mappings, but the reverse # is also possible: an URL can be generated from one of your routing definitions. diff --git a/vendor/rails/actionpack/lib/action_pack/version.rb b/vendor/rails/actionpack/lib/action_pack/version.rb index 3064148f..3880c00a 100644 --- a/vendor/rails/actionpack/lib/action_pack/version.rb +++ b/vendor/rails/actionpack/lib/action_pack/version.rb @@ -2,7 +2,7 @@ module ActionPack #:nodoc: module VERSION #:nodoc: MAJOR = 2 MINOR = 3 - TINY = 9 + TINY = 10 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/vendor/rails/actionpack/lib/action_view/helpers/form_helper.rb b/vendor/rails/actionpack/lib/action_view/helpers/form_helper.rb index c1b2ebe2..38c44a2d 100644 --- a/vendor/rails/actionpack/lib/action_view/helpers/form_helper.rb +++ b/vendor/rails/actionpack/lib/action_view/helpers/form_helper.rb @@ -877,9 +877,9 @@ module ActionView def value_before_type_cast(object, method_name) unless object.nil? - object.respond_to?(method_name) ? - object.send(method_name) : - object.send(method_name + "_before_type_cast") + object.respond_to?(method_name + "_before_type_cast") ? + object.send(method_name + "_before_type_cast") : + object.send(method_name) end end diff --git a/vendor/rails/actionpack/test/controller/cookie_test.rb b/vendor/rails/actionpack/test/controller/cookie_test.rb index 1062b058..a312f7f6 100644 --- a/vendor/rails/actionpack/test/controller/cookie_test.rb +++ b/vendor/rails/actionpack/test/controller/cookie_test.rb @@ -42,6 +42,10 @@ class CookieTest < ActionController::TestCase cookies["user_name"] = { :value => "david", :httponly => true } end + def authenticate_with_secure + cookies["user_name"] = { :value => "david", :secure => true } + end + def set_permanent_cookie cookies.permanent[:user_name] = "Jamie" end @@ -94,6 +98,12 @@ class CookieTest < ActionController::TestCase assert_equal ["user_name=david; path=/; HttpOnly"], @response.headers["Set-Cookie"] assert_equal({"user_name" => "david"}, @response.cookies) end + + def test_setting_cookie_with_secure + get :authenticate_with_secure + assert_equal ["user_name=david; path=/; secure"], @response.headers["Set-Cookie"] + assert_equal({"user_name" => "david"}, @response.cookies) + end def test_multiple_cookies get :set_multiple_cookies diff --git a/vendor/rails/actionpack/test/controller/integration_test.rb b/vendor/rails/actionpack/test/controller/integration_test.rb index 609fbb56..d1bb19c3 100644 --- a/vendor/rails/actionpack/test/controller/integration_test.rb +++ b/vendor/rails/actionpack/test/controller/integration_test.rb @@ -227,6 +227,24 @@ class IntegrationTestTest < Test::Unit::TestCase end end +require 'active_record_unit' +# Tests that fixtures are accessible in the integration test sessions +class IntegrationTestWithFixtures < ActiveRecordTestCase + include ActionController::Integration::Runner + + fixtures :companies + + def test_fixtures_in_new_session + sym = :thirty_seven_signals + # fixtures are accessible in main session + assert_not_nil companies(sym) + + # create a new session and the fixtures should be accessible in it as well + session1 = open_session { |sess| } + assert_not_nil session1.companies(sym) + end +end + # Tests that integration tests don't call Controller test methods for processing. # Integration tests have their own setup and teardown. class IntegrationTestUsesCorrectClass < ActionController::IntegrationTest diff --git a/vendor/rails/actionpack/test/controller/session/cookie_store_test.rb b/vendor/rails/actionpack/test/controller/session/cookie_store_test.rb index f157ae4a..d467af7e 100644 --- a/vendor/rails/actionpack/test/controller/session/cookie_store_test.rb +++ b/vendor/rails/actionpack/test/controller/session/cookie_store_test.rb @@ -6,7 +6,6 @@ class CookieStoreTest < ActionController::IntegrationTest SessionSecret = 'b3c631c314c0bbca50c1b2843150fe33' DispatcherApp = ActionController::Dispatcher.new - CookieStoreApp = ActionController::Session::CookieStore.new(DispatcherApp, :key => SessionKey, :secret => SessionSecret) Verifier = ActiveSupport::MessageVerifier.new(SessionSecret, 'SHA1') @@ -62,10 +61,6 @@ class CookieStoreTest < ActionController::IntegrationTest def rescue_action(e) raise end end - def setup - @integration_session = open_session(CookieStoreApp) - end - def test_raises_argument_error_if_missing_session_key assert_raise(ArgumentError, nil.inspect) { ActionController::Session::CookieStore.new(nil, @@ -152,6 +147,23 @@ class CookieStoreTest < ActionController::IntegrationTest end end + def test_does_not_set_secure_cookies_over_http + with_test_route_set(:secure => true) do + get '/set_session_value' + assert_response :success + assert_equal nil, headers['Set-Cookie'] + end + end + + def test_does_set_secure_cookies_over_https + with_test_route_set(:secure => true) do + get '/set_session_value', nil, 'HTTPS' => 'on' + assert_response :success + assert_equal ["_myapp_session=#{response.body}; path=/; secure; HttpOnly"], + headers['Set-Cookie'] + end + end + def test_close_raises_when_data_overflows with_test_route_set do assert_raise(ActionController::Session::CookieStore::CookieOverflow) { @@ -272,13 +284,17 @@ class CookieStoreTest < ActionController::IntegrationTest end private - def with_test_route_set + def with_test_route_set(options = {}) with_routing do |set| set.draw do |map| map.with_options :controller => "cookie_store_test/test" do |c| c.connect "/:action" end end + + options = { :key => SessionKey, :secret => SessionSecret }.merge!(options) + @integration_session = open_session(ActionController::Session::CookieStore.new(DispatcherApp, options)) + yield end end diff --git a/vendor/rails/actionpack/test/controller/session/mem_cache_store_test.rb b/vendor/rails/actionpack/test/controller/session/mem_cache_store_test.rb index cfb6a18b..2714ee52 100644 --- a/vendor/rails/actionpack/test/controller/session/mem_cache_store_test.rb +++ b/vendor/rails/actionpack/test/controller/session/mem_cache_store_test.rb @@ -37,13 +37,6 @@ class MemCacheStoreTest < ActionController::IntegrationTest begin DispatcherApp = ActionController::Dispatcher.new - MemCacheStoreApp = ActionController::Session::MemCacheStore.new( - DispatcherApp, :key => '_session_id') - - - def setup - @integration_session = open_session(MemCacheStoreApp) - end def test_setting_and_getting_session_value with_test_route_set do @@ -177,14 +170,18 @@ class MemCacheStoreTest < ActionController::IntegrationTest end private - def with_test_route_set + def with_test_route_set(options = {}) with_routing do |set| set.draw do |map| map.with_options :controller => "mem_cache_store_test/test" do |c| c.connect "/:action" end end + + options = { :key => '_session_id' }.merge!(options) + @integration_session = open_session(ActionController::Session::MemCacheStore.new(DispatcherApp, options)) + yield end end -end +end \ No newline at end of file diff --git a/vendor/rails/actionpack/test/template/form_helper_test.rb b/vendor/rails/actionpack/test/template/form_helper_test.rb index e242ddd2..5b62674f 100644 --- a/vendor/rails/actionpack/test/template/form_helper_test.rb +++ b/vendor/rails/actionpack/test/template/form_helper_test.rb @@ -91,16 +91,6 @@ end class FormHelperTest < ActionView::TestCase tests ActionView::Helpers::FormHelper - class Developer - def name_before_type_cast - "David" - end - - def name - "Santiago" - end - end - def setup super @@ -266,13 +256,6 @@ class FormHelperTest < ActionView::TestCase assert_equal object_name, "post[]" end - def test_text_field_from_a_user_defined_method - @developer = Developer.new - assert_dom_equal( - '', text_field("developer", "name") - ) - end - def test_hidden_field assert_dom_equal '', hidden_field("post", "title") diff --git a/vendor/rails/activerecord/CHANGELOG b/vendor/rails/activerecord/CHANGELOG index 8d28b2ec..9383f962 100644 --- a/vendor/rails/activerecord/CHANGELOG +++ b/vendor/rails/activerecord/CHANGELOG @@ -1,3 +1,7 @@ +*2.3.10 (October 15, 2010)* + +* Security Release to fix CVE-2010-3933 + *2.3.9 (September 4, 2010)* *2.3.8 (May 24, 2010)* *2.3.7 (May 24, 2010)* diff --git a/vendor/rails/activerecord/Rakefile b/vendor/rails/activerecord/Rakefile index 1b2c37b2..e0684466 100644 --- a/vendor/rails/activerecord/Rakefile +++ b/vendor/rails/activerecord/Rakefile @@ -192,7 +192,7 @@ spec = Gem::Specification.new do |s| s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) } end - s.add_dependency('activesupport', '= 2.3.9' + PKG_BUILD) + s.add_dependency('activesupport', '= 2.3.10' + PKG_BUILD) s.files.delete FIXTURES_ROOT + "/fixture_database.sqlite" s.files.delete FIXTURES_ROOT + "/fixture_database_2.sqlite" diff --git a/vendor/rails/activerecord/examples/performance.rb b/vendor/rails/activerecord/examples/performance.rb index facdbb5e..893d32be 100755 --- a/vendor/rails/activerecord/examples/performance.rb +++ b/vendor/rails/activerecord/examples/performance.rb @@ -27,7 +27,7 @@ conn[:socket] = Pathname.glob(%w[ /tmp/mysql.sock /var/mysql/mysql.sock /var/run/mysqld/mysqld.sock -]).find { |path| path.socket? } +]).find { |path| path.socket? }.to_s ActiveRecord::Base.establish_connection(conn) @@ -60,7 +60,7 @@ end sqlfile = "#{__DIR__}/performance.sql" if File.exists?(sqlfile) - mysql_bin = %w[mysql mysql5].select { |bin| `which #{bin}`.length > 0 } + mysql_bin = %w[mysql mysql5].detect { |bin| `which #{bin}`.length > 0 } `#{mysql_bin} -u #{conn[:username]} #{"-p#{conn[:password]}" unless conn[:password].blank?} #{conn[:database]} < #{sqlfile}` else puts 'Generating data...' @@ -90,7 +90,7 @@ else ) end - mysqldump_bin = %w[mysqldump mysqldump5].select { |bin| `which #{bin}`.length > 0 } + mysqldump_bin = %w[mysqldump mysqldump5].detect { |bin| `which #{bin}`.length > 0 } `#{mysqldump_bin} -u #{conn[:username]} #{"-p#{conn[:password]}" unless conn[:password].blank?} #{conn[:database]} exhibits users > #{sqlfile}` end @@ -157,6 +157,40 @@ RBench.run(TIMES) do ar { Exhibit.transaction { Exhibit.new } } end + report 'Model.find(id)' do + id = Exhibit.first.id + ar { Exhibit.find(id) } + end + + report 'Model.find_by_sql' do + ar { Exhibit.find_by_sql("SELECT * FROM exhibits WHERE id = #{(rand * 1000 + 1).to_i}").first } + end + + report 'Model.log', (TIMES * 10) do + ar { Exhibit.connection.send(:log, "hello", "world") {} } + end + + report 'AR.execute(query)', (TIMES / 2) do + ar { ActiveRecord::Base.connection.execute("Select * from exhibits where id = #{(rand * 1000 + 1).to_i}") } + end + + report 'Model.find(id)' do + id = Exhibit.first.id + ar { Exhibit.find(id) } + end + + report 'Model.find_by_sql' do + ar { Exhibit.find_by_sql("SELECT * FROM exhibits WHERE id = #{(rand * 1000 + 1).to_i}").first } + end + + report 'Model.log', (TIMES * 10) do + ar { Exhibit.connection.send(:log, "hello", "world") {} } + end + + report 'AR.execute(query)', (TIMES / 2) do + ar { ActiveRecord::Base.connection.execute("Select * from exhibits where id = #{(rand * 1000 + 1).to_i}") } + end + summary 'Total' end diff --git a/vendor/rails/activerecord/lib/active_record/association_preload.rb b/vendor/rails/activerecord/lib/active_record/association_preload.rb index c2206dcd..7acc4151 100644 --- a/vendor/rails/activerecord/lib/active_record/association_preload.rb +++ b/vendor/rails/activerecord/lib/active_record/association_preload.rb @@ -283,7 +283,7 @@ module ActiveRecord through_records.flatten! else options = {} - options[:include] = reflection.options[:include] || reflection.options[:source] if reflection.options[:conditions] + options[:include] = reflection.options[:include] || reflection.options[:source] if reflection.options[:conditions] || reflection.options[:order] options[:order] = reflection.options[:order] options[:conditions] = reflection.options[:conditions] records.first.class.preload_associations(records, through_association, options) diff --git a/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb b/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb index 0953fa5e..fbff07a2 100644 --- a/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb +++ b/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb @@ -332,6 +332,7 @@ module ActiveRecord def include?(record) return false unless record.is_a?(@reflection.klass) + return include_in_memory?(record) if record.new_record? load_target if @reflection.options[:finder_sql] && !loaded? return @target.include?(record) if loaded? exists?(record) @@ -491,8 +492,8 @@ module ActiveRecord def callbacks_for(callback_name) full_callback_name = "#{callback_name}_for_#{@reflection.name}" @owner.class.read_inheritable_attribute(full_callback_name.to_sym) || [] - end - + end + def ensure_owner_is_not_new if @owner.new_record? raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved" @@ -503,6 +504,18 @@ module ActiveRecord args.first.kind_of?(Hash) || !(loaded? || @owner.new_record? || @reflection.options[:finder_sql] || @target.any? { |record| record.new_record? } || args.first.kind_of?(Integer)) end + + def include_in_memory?(record) + if @reflection.is_a?(ActiveRecord::Reflection::ThroughReflection) + @owner.send(proxy_reflection.through_reflection.name.to_sym).each do |source| + source_reflection_target = source.send(proxy_reflection.source_reflection.name) + return true if source_reflection_target.respond_to?(:include?) ? source_reflection_target.include?(record) : source_reflection_target == record + end + false + else + @target.include?(record) + end + end end end end diff --git a/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index 61577915..12826b19 100644 --- a/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -274,7 +274,7 @@ module ActiveRecord if Hash === options # legacy support, since this param was a string index_type = options[:unique] ? "UNIQUE" : "" - index_name = options[:name] || index_name + index_name = options[:name].to_s if options[:name] else index_type = options end @@ -347,6 +347,7 @@ module ActiveRecord # as there's no way to determine the correct answer in that case. def index_exists?(table_name, index_name, default) return default unless respond_to?(:indexes) + index_name = index_name.to_s indexes(table_name).detect { |i| i.name == index_name } end diff --git a/vendor/rails/activerecord/lib/active_record/named_scope.rb b/vendor/rails/activerecord/lib/active_record/named_scope.rb index 901d4c2f..5e49de6a 100644 --- a/vendor/rails/activerecord/lib/active_record/named_scope.rb +++ b/vendor/rails/activerecord/lib/active_record/named_scope.rb @@ -120,7 +120,7 @@ module ActiveRecord options ||= {} [options[:extend]].flatten.each { |extension| extend extension } if options[:extend] extend Module.new(&block) if block_given? - unless Scope === proxy_scope + unless (Scope === proxy_scope || ActiveRecord::Associations::AssociationCollection === proxy_scope) @current_scoped_methods_when_defined = proxy_scope.send(:current_scoped_methods) end @proxy_scope, @proxy_options = proxy_scope, options.except(:extend) diff --git a/vendor/rails/activerecord/lib/active_record/nested_attributes.rb b/vendor/rails/activerecord/lib/active_record/nested_attributes.rb index 6290fe6c..65434fb0 100644 --- a/vendor/rails/activerecord/lib/active_record/nested_attributes.rb +++ b/vendor/rails/activerecord/lib/active_record/nested_attributes.rb @@ -286,9 +286,7 @@ module ActiveRecord assign_to_or_mark_for_destruction(record, attributes, options[:allow_destroy]) elsif attributes['id'] - existing_record = self.class.reflect_on_association(association_name).klass.find(attributes['id']) - assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy]) - self.send(association_name.to_s+'=', existing_record) + raise_nested_attributes_record_not_found(association_name, attributes['id']) elsif !reject_new_record?(association_name, attributes) method = "build_#{association_name}" @@ -358,16 +356,11 @@ module ActiveRecord unless reject_new_record?(association_name, attributes) association.build(attributes.except(*UNASSIGNABLE_KEYS)) end - - elsif existing_records.size == 0 # Existing record but not yet associated - existing_record = self.class.reflect_on_association(association_name).klass.find(attributes['id']) - association.send(:add_record_to_target_with_callbacks, existing_record) unless association.loaded? - assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy]) - elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes['id'].to_s } association.send(:add_record_to_target_with_callbacks, existing_record) unless association.loaded? assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy]) - + else + raise_nested_attributes_record_not_found(association_name, attributes['id']) end end end @@ -387,7 +380,7 @@ module ActiveRecord ConnectionAdapters::Column.value_to_boolean(hash['_destroy']) end - # Determines if a new record should be built by checking for + # Determines if a new record should be build by checking for # has_destroy_flag? or if a :reject_if proc exists for this # association and evaluates to +true+. def reject_new_record?(association_name, attributes) @@ -403,5 +396,9 @@ module ActiveRecord end end + def raise_nested_attributes_record_not_found(association_name, record_id) + reflection = self.class.reflect_on_association(association_name) + raise RecordNotFound, "Couldn't find #{reflection.klass.name} with ID=#{record_id} for #{self.class.name} with ID=#{id}" + end end end diff --git a/vendor/rails/activerecord/lib/active_record/version.rb b/vendor/rails/activerecord/lib/active_record/version.rb index 4184884b..06680c37 100644 --- a/vendor/rails/activerecord/lib/active_record/version.rb +++ b/vendor/rails/activerecord/lib/active_record/version.rb @@ -2,7 +2,7 @@ module ActiveRecord module VERSION #:nodoc: MAJOR = 2 MINOR = 3 - TINY = 9 + TINY = 10 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/vendor/rails/activerecord/test/cases/associations/eager_test.rb b/vendor/rails/activerecord/test/cases/associations/eager_test.rb index 1870f976..b7117193 100644 --- a/vendor/rails/activerecord/test/cases/associations/eager_test.rb +++ b/vendor/rails/activerecord/test/cases/associations/eager_test.rb @@ -363,7 +363,12 @@ class EagerAssociationTest < ActiveRecord::TestCase assert_equal post_tags, eager_post_tags end - + def test_eager_with_has_many_through_association_with_order + author_comments = Author.find(authors(:david).id).comments_desc + eager_author_comments = Author.find(authors(:david).id, :include => :comments_desc).comments_desc + assert_equal eager_author_comments, author_comments + end + def test_eager_with_has_many_through_join_model_with_include author_comments = Author.find(authors(:david).id, :include => :comments_with_include).comments_with_include.to_a assert_no_queries do diff --git a/vendor/rails/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/vendor/rails/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb index 5e8b2cad..b252a54a 100644 --- a/vendor/rails/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb +++ b/vendor/rails/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb @@ -819,4 +819,9 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase assert_queries(0) { david.projects.columns; david.projects.columns } end + def test_include_method_in_has_and_belongs_to_many_association_should_return_true_for_instance_added_with_build + project = Project.new + developer = project.developers.build + assert project.developers.include?(developer) + end end diff --git a/vendor/rails/activerecord/test/cases/associations/has_many_associations_test.rb b/vendor/rails/activerecord/test/cases/associations/has_many_associations_test.rb index 59f7a031..c626d457 100644 --- a/vendor/rails/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/vendor/rails/activerecord/test/cases/associations/has_many_associations_test.rb @@ -1221,5 +1221,10 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end EOF end -end + def test_include_method_in_has_many_association_should_return_true_for_instance_added_with_build + post = Post.new + comment = post.comments.build + assert post.comments.include?(comment) + end +end diff --git a/vendor/rails/activerecord/test/cases/associations/has_many_through_associations_test.rb b/vendor/rails/activerecord/test/cases/associations/has_many_through_associations_test.rb index a5afd21d..cc7e6dbe 100644 --- a/vendor/rails/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/vendor/rails/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -343,4 +343,18 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase lambda { authors(:david).very_special_comments.delete(authors(:david).very_special_comments.first) }, ].each {|block| assert_raise(ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection, &block) } end + + def test_include_method_in_association_through_should_return_true_for_instance_added_with_build + person = Person.new + reference = person.references.build + job = reference.build_job + assert person.jobs.include?(job) + end + + def test_include_method_in_association_through_should_return_true_for_instance_added_with_nested_builds + author = Author.new + post = author.posts.build + comment = post.comments.build + assert author.comments.include?(comment) + end end diff --git a/vendor/rails/activerecord/test/cases/migration_test.rb b/vendor/rails/activerecord/test/cases/migration_test.rb index aafe7482..4692f914 100644 --- a/vendor/rails/activerecord/test/cases/migration_test.rb +++ b/vendor/rails/activerecord/test/cases/migration_test.rb @@ -119,6 +119,13 @@ if ActiveRecord::Base.connection.supports_migrations? end end + def test_index_symbol_names + assert_nothing_raised { Person.connection.add_index :people, :primary_contact_id, :name => :symbol_index_name } + assert Person.connection.index_exists?(:people, :symbol_index_name, true) + assert_nothing_raised { Person.connection.remove_index :people, :name => :symbol_index_name } + assert_equal true, !Person.connection.index_exists?(:people, :symbol_index_name, false) + end + def test_add_index_length_limit good_index_name = 'x' * Person.connection.index_name_length too_long_index_name = good_index_name + 'x' diff --git a/vendor/rails/activerecord/test/cases/named_scope_test.rb b/vendor/rails/activerecord/test/cases/named_scope_test.rb index 0a04821c..755fb047 100644 --- a/vendor/rails/activerecord/test/cases/named_scope_test.rb +++ b/vendor/rails/activerecord/test/cases/named_scope_test.rb @@ -146,6 +146,12 @@ class NamedScopeTest < ActiveRecord::TestCase assert_equal authors(:david).posts & Post.containing_the_letter_a, authors(:david).posts.containing_the_letter_a end + def test_nested_named_scopes_doesnt_duplicate_conditions_on_child_scopes + comments_scope = posts(:welcome).comments.send(:construct_sql) + named_scope_sql_conditions = posts(:welcome).comments.containing_the_letter_e.send(:current_scoped_methods)[:find][:conditions] + assert_no_match /#{comments_scope}.*#{comments_scope}/i, named_scope_sql_conditions + end + def test_has_many_through_associations_have_access_to_named_scopes assert_not_equal Comment.containing_the_letter_e, authors(:david).comments assert !Comment.containing_the_letter_e.empty? diff --git a/vendor/rails/activerecord/test/cases/nested_attributes_test.rb b/vendor/rails/activerecord/test/cases/nested_attributes_test.rb index cd432e29..3adcc88d 100644 --- a/vendor/rails/activerecord/test/cases/nested_attributes_test.rb +++ b/vendor/rails/activerecord/test/cases/nested_attributes_test.rb @@ -175,6 +175,12 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name end + def test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record + assert_raise_with_message ActiveRecord::RecordNotFound, "Couldn't find Ship with ID=1234567890 for Pirate with ID=#{@pirate.id}" do + @pirate.ship_attributes = { :id => 1234567890 } + end + end + def test_should_take_a_hash_with_string_keys_and_update_the_associated_model @pirate.reload.ship_attributes = { 'id' => @ship.id, 'name' => 'Davy Jones Gold Dagger' } @@ -324,13 +330,10 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase assert_equal 'Arr', @ship.pirate.catchphrase end - def test_should_associate_with_record_if_parent_record_is_not_saved - @ship.destroy - @pirate = Pirate.create(:catchphrase => 'Arr') - @ship = Ship.new(:name => 'Nights Dirty Lightning', :pirate_attributes => { :id => @pirate.id, :catchphrase => @pirate.catchphrase}) - - assert_equal @ship.name, 'Nights Dirty Lightning' - assert_equal @pirate, @ship.pirate + def test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record + assert_raise_with_message ActiveRecord::RecordNotFound, "Couldn't find Pirate with ID=1234567890 for Ship with ID=#{@ship.id}" do + @ship.pirate_attributes = { :id => 1234567890 } + end end def test_should_take_a_hash_with_string_keys_and_update_the_associated_model @@ -434,11 +437,6 @@ module NestedAttributesOnACollectionAssociationTests assert_equal ['Grace OMalley', 'Privateers Greed'], [@child_1.reload.name, @child_2.reload.name] end - def test_should_assign_existing_children_if_parent_is_new - @pirate = Pirate.new({:catchphrase => "Don' botharr talkin' like one, savvy?"}.merge(@alternate_params)) - assert_equal ['Grace OMalley', 'Privateers Greed'], [@pirate.send(@association_name)[0].name, @pirate.send(@association_name)[1].name] - end - def test_should_take_an_array_and_assign_the_attributes_to_the_associated_models @pirate.send(association_setter, @alternate_params[association_getter].values) @pirate.save @@ -508,8 +506,8 @@ module NestedAttributesOnACollectionAssociationTests assert_equal ['Grace OMalley', 'Privateers Greed'], [@child_1.name, @child_2.name] end - def test_should_not_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record - assert_nothing_raised ActiveRecord::RecordNotFound do + def test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record + assert_raise_with_message ActiveRecord::RecordNotFound, "Couldn't find #{@child_1.class.name} with ID=1234567890 for Pirate with ID=#{@pirate.id}" do @pirate.attributes = { association_getter => [{ :id => 1234567890 }] } end end diff --git a/vendor/rails/activeresource/CHANGELOG b/vendor/rails/activeresource/CHANGELOG index cc8a5ebb..f779b6f9 100644 --- a/vendor/rails/activeresource/CHANGELOG +++ b/vendor/rails/activeresource/CHANGELOG @@ -1,3 +1,4 @@ +*2.3.10 (October 15, 2010)* *2.3.9 (September 4, 2010)* *2.3.8 (May 24, 2010)* *2.3.7 (May 24, 2010)* diff --git a/vendor/rails/activeresource/Rakefile b/vendor/rails/activeresource/Rakefile index c47fb567..ed214f74 100644 --- a/vendor/rails/activeresource/Rakefile +++ b/vendor/rails/activeresource/Rakefile @@ -66,7 +66,7 @@ spec = Gem::Specification.new do |s| s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) } end - s.add_dependency('activesupport', '= 2.3.9' + PKG_BUILD) + s.add_dependency('activesupport', '= 2.3.10' + PKG_BUILD) s.require_path = 'lib' s.autorequire = 'active_resource' diff --git a/vendor/rails/activeresource/lib/active_resource/version.rb b/vendor/rails/activeresource/lib/active_resource/version.rb index 4ea6d58e..cc4540ac 100644 --- a/vendor/rails/activeresource/lib/active_resource/version.rb +++ b/vendor/rails/activeresource/lib/active_resource/version.rb @@ -2,7 +2,7 @@ module ActiveResource module VERSION #:nodoc: MAJOR = 2 MINOR = 3 - TINY = 9 + TINY = 10 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/vendor/rails/activesupport/CHANGELOG b/vendor/rails/activesupport/CHANGELOG index fd2d5175..e6edc33a 100644 --- a/vendor/rails/activesupport/CHANGELOG +++ b/vendor/rails/activesupport/CHANGELOG @@ -1,3 +1,6 @@ +*2.3.10 (October 15, 2010)* + + *2.3.9 (September 4, 2010)* * i18n: bundle i18n 0.4.1 for forward compatibility with Rails 3. Deprecates {{foo}} interpolation syntax in favor of 1.9-native %{foo}. diff --git a/vendor/rails/activesupport/lib/active_support/core_ext/object/misc.rb b/vendor/rails/activesupport/lib/active_support/core_ext/object/misc.rb index 40611a67..554f44ab 100644 --- a/vendor/rails/activesupport/lib/active_support/core_ext/object/misc.rb +++ b/vendor/rails/activesupport/lib/active_support/core_ext/object/misc.rb @@ -38,7 +38,7 @@ class Object # # foo # => ['bar', 'baz'] def returning(value) - ActiveSupport::Deprecation.warn('Object#returning has been deprecated in favor of Object#tap.', caller) + ActiveSupport::Deprecation.warn('Kernel#returning has been deprecated in favor of Object#tap.', caller) yield(value) value end diff --git a/vendor/rails/activesupport/lib/active_support/memoizable.rb b/vendor/rails/activesupport/lib/active_support/memoizable.rb index aa33ef7e..68148a27 100644 --- a/vendor/rails/activesupport/lib/active_support/memoizable.rb +++ b/vendor/rails/activesupport/lib/active_support/memoizable.rb @@ -92,6 +92,8 @@ module ActiveSupport # if private_method_defined?(#{original_method.inspect}) # if private_method_defined?(:_unmemoized_mime_type) private #{symbol.inspect} # private :mime_type + elsif protected_method_defined?(#{original_method.inspect}) # elsif protected_method_defined?(:_unmemoized_mime_type) + protected #{symbol.inspect} # protected :mime_type end # end EOS end diff --git a/vendor/rails/activesupport/lib/active_support/testing/setup_and_teardown.rb b/vendor/rails/activesupport/lib/active_support/testing/setup_and_teardown.rb index aaf9f8f4..25c927dd 100644 --- a/vendor/rails/activesupport/lib/active_support/testing/setup_and_teardown.rb +++ b/vendor/rails/activesupport/lib/active_support/testing/setup_and_teardown.rb @@ -23,12 +23,12 @@ module ActiveSupport run_callbacks :setup result = super rescue Exception => e - result = runner.puke(self.class, self.name, e) + result = runner.puke(self.class, __name__, e) ensure begin run_callbacks :teardown, :enumerator => :reverse_each rescue Exception => e - result = runner.puke(self.class, self.name, e) + result = runner.puke(self.class, __name__, e) end end result diff --git a/vendor/rails/activesupport/lib/active_support/version.rb b/vendor/rails/activesupport/lib/active_support/version.rb index 571f467a..835a507d 100644 --- a/vendor/rails/activesupport/lib/active_support/version.rb +++ b/vendor/rails/activesupport/lib/active_support/version.rb @@ -2,7 +2,7 @@ module ActiveSupport module VERSION #:nodoc: MAJOR = 2 MINOR = 3 - TINY = 9 + TINY = 10 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/vendor/rails/activesupport/test/memoizable_test.rb b/vendor/rails/activesupport/test/memoizable_test.rb index 39420c5a..105bb6ec 100644 --- a/vendor/rails/activesupport/test/memoizable_test.rb +++ b/vendor/rails/activesupport/test/memoizable_test.rb @@ -34,6 +34,13 @@ class MemoizableTest < Test::Unit::TestCase memoize :name, :age + protected + + def memoize_protected_test + 'protected' + end + memoize :memoize_protected_test + private def is_developer? @@ -234,6 +241,13 @@ class MemoizableTest < Test::Unit::TestCase assert_raise(RuntimeError) { company.memoize :name } end + def test_protected_method_memoization + person = Person.new + + assert_raise(NoMethodError) { person.memoize_protected_test } + assert_equal "protected", person.send(:memoize_protected_test) + end + def test_private_method_memoization person = Person.new diff --git a/vendor/rails/activesupport/test/test_case_test.rb b/vendor/rails/activesupport/test/test_case_test.rb new file mode 100644 index 00000000..7e65c630 --- /dev/null +++ b/vendor/rails/activesupport/test/test_case_test.rb @@ -0,0 +1,57 @@ +require 'abstract_unit' + +module ActiveSupport + class TestCaseTest < ActiveSupport::TestCase + class FakeRunner + attr_reader :puked + + def initialize + @puked = [] + end + + def puke(klass, name, e) + @puked << [klass, name, e] + end + end + + if defined?(MiniTest::Assertions) && TestCase < MiniTest::Assertions + def test_callback_with_exception + tc = Class.new(TestCase) do + setup :bad_callback + def bad_callback; raise 'oh noes' end + def test_true; assert true end + end + + test_name = 'test_true' + fr = FakeRunner.new + + test = tc.new test_name + test.run fr + klass, name, exception = *fr.puked.first + + assert_equal tc, klass + assert_equal test_name, name + assert_equal 'oh noes', exception.message + end + + def test_teardown_callback_with_exception + tc = Class.new(TestCase) do + teardown :bad_callback + def bad_callback; raise 'oh noes' end + def test_true; assert true end + end + + test_name = 'test_true' + fr = FakeRunner.new + + test = tc.new test_name + test.run fr + klass, name, exception = *fr.puked.first + + assert_equal tc, klass + assert_equal test_name, name + assert_equal 'oh noes', exception.message + end + end + end +end diff --git a/vendor/rails/railties/CHANGELOG b/vendor/rails/railties/CHANGELOG index 34f81326..bdbec15b 100644 --- a/vendor/rails/railties/CHANGELOG +++ b/vendor/rails/railties/CHANGELOG @@ -1,3 +1,5 @@ +*2.3.10 (October 15, 2010)* + *2.3.9 (September 4, 2010)* * Deprecates config.load_(once_)paths in favor of autolaod_(once_)paths. [fxn] diff --git a/vendor/rails/railties/Rakefile b/vendor/rails/railties/Rakefile index 4bfe770d..20865bd4 100644 --- a/vendor/rails/railties/Rakefile +++ b/vendor/rails/railties/Rakefile @@ -313,11 +313,11 @@ spec = Gem::Specification.new do |s| EOF s.add_dependency('rake', '>= 0.8.3') - s.add_dependency('activesupport', '= 2.3.9' + PKG_BUILD) - s.add_dependency('activerecord', '= 2.3.9' + PKG_BUILD) - s.add_dependency('actionpack', '= 2.3.9' + PKG_BUILD) - s.add_dependency('actionmailer', '= 2.3.9' + PKG_BUILD) - s.add_dependency('activeresource', '= 2.3.9' + PKG_BUILD) + s.add_dependency('activesupport', '= 2.3.10' + PKG_BUILD) + s.add_dependency('activerecord', '= 2.3.10' + PKG_BUILD) + s.add_dependency('actionpack', '= 2.3.10' + PKG_BUILD) + s.add_dependency('actionmailer', '= 2.3.10' + PKG_BUILD) + s.add_dependency('activeresource', '= 2.3.10' + PKG_BUILD) s.rdoc_options << '--exclude' << '.' s.has_rdoc = false diff --git a/vendor/rails/railties/lib/rails/gem_dependency.rb b/vendor/rails/railties/lib/rails/gem_dependency.rb index 8a496ca7..4a2418c1 100644 --- a/vendor/rails/railties/lib/rails/gem_dependency.rb +++ b/vendor/rails/railties/lib/rails/gem_dependency.rb @@ -31,8 +31,10 @@ module Rails def self.from_directory_name(directory_name, load_spec=true) directory_name_parts = File.basename(directory_name).split('-') - name = directory_name_parts[0..-2].join('-') - version = directory_name_parts.last + + version = directory_name_parts.find { |s| s.match(/^\d(\.\d|\.\w+)*$/) } + name = directory_name_parts[0..directory_name_parts.index(version)-1].join('-') if version + result = self.new(name, :version => version) spec_filename = File.join(directory_name, '.specification') if load_spec diff --git a/vendor/rails/railties/lib/rails/vendor_gem_source_index.rb b/vendor/rails/railties/lib/rails/vendor_gem_source_index.rb index 91f61678..ea5147a8 100644 --- a/vendor/rails/railties/lib/rails/vendor_gem_source_index.rb +++ b/vendor/rails/railties/lib/rails/vendor_gem_source_index.rb @@ -101,8 +101,8 @@ module Rails end def version_for_dir(d) - matches = /-([^-]+)$/.match(d) - Gem::Version.new(matches[1]) if matches + version = d.split('-').find { |s| s.match(/^\d(\.\d|\.\w+)*$/) } + Gem::Version.new(version) end def load_specification(gem_dir) diff --git a/vendor/rails/railties/lib/rails/version.rb b/vendor/rails/railties/lib/rails/version.rb index 495bba2f..28ff027a 100644 --- a/vendor/rails/railties/lib/rails/version.rb +++ b/vendor/rails/railties/lib/rails/version.rb @@ -2,7 +2,7 @@ module Rails module VERSION #:nodoc: MAJOR = 2 MINOR = 3 - TINY = 9 + TINY = 10 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/vendor/rails/railties/lib/tasks/databases.rake b/vendor/rails/railties/lib/tasks/databases.rake index 0c83311f..1cf24343 100644 --- a/vendor/rails/railties/lib/tasks/databases.rake +++ b/vendor/rails/railties/lib/tasks/databases.rake @@ -46,14 +46,14 @@ namespace :db do $stderr.puts "Couldn't create database for #{config.inspect}" end end - return # Skip the else clause of begin/rescue + return # Skip the else clause of begin/rescue else ActiveRecord::Base.establish_connection(config) ActiveRecord::Base.connection end rescue case config['adapter'] - when 'mysql' + when /^mysql/ @charset = ENV['CHARSET'] || 'utf8' @collation = ENV['COLLATION'] || 'utf8_unicode_ci' begin @@ -159,7 +159,7 @@ namespace :db do task :charset => :environment do config = ActiveRecord::Base.configurations[RAILS_ENV || 'development'] case config['adapter'] - when 'mysql' + when /^mysql/ ActiveRecord::Base.establish_connection(config) puts ActiveRecord::Base.connection.charset when 'postgresql' @@ -174,7 +174,7 @@ namespace :db do task :collation => :environment do config = ActiveRecord::Base.configurations[RAILS_ENV || 'development'] case config['adapter'] - when 'mysql' + when /^mysql/ ActiveRecord::Base.establish_connection(config) puts ActiveRecord::Base.connection.collation else @@ -274,7 +274,7 @@ namespace :db do task :dump => :environment do abcs = ActiveRecord::Base.configurations case abcs[RAILS_ENV]["adapter"] - when "mysql", "oci", "oracle" + when /^mysql/, "oci", "oracle" ActiveRecord::Base.establish_connection(abcs[RAILS_ENV]) File.open("#{RAILS_ROOT}/db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump } when "postgresql" @@ -320,7 +320,7 @@ namespace :db do task :clone_structure => [ "db:structure:dump", "db:test:purge" ] do abcs = ActiveRecord::Base.configurations case abcs["test"]["adapter"] - when "mysql" + when /^mysql/ ActiveRecord::Base.establish_connection(:test) ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0') IO.readlines("#{RAILS_ROOT}/db/#{RAILS_ENV}_structure.sql").join.split("\n\n").each do |table| @@ -354,14 +354,14 @@ namespace :db do task :purge => :environment do abcs = ActiveRecord::Base.configurations case abcs["test"]["adapter"] - when "mysql" + when /^mysql/ ActiveRecord::Base.establish_connection(:test) ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"], abcs["test"]) when "postgresql" ActiveRecord::Base.clear_active_connections! drop_database(abcs['test']) create_database(abcs['test']) - when "sqlite","sqlite3" + when "sqlite", "sqlite3" dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"] File.delete(dbfile) if File.exist?(dbfile) when "sqlserver" @@ -408,7 +408,7 @@ end def drop_database(config) begin case config['adapter'] - when 'mysql' + when /^mysql/ ActiveRecord::Base.establish_connection(config) ActiveRecord::Base.connection.drop_database config['database'] when /^sqlite/ diff --git a/vendor/rails/railties/test/gem_dependency_test.rb b/vendor/rails/railties/test/gem_dependency_test.rb index a1650169..8bcce86b 100644 --- a/vendor/rails/railties/test/gem_dependency_test.rb +++ b/vendor/rails/railties/test/gem_dependency_test.rb @@ -113,6 +113,14 @@ class GemDependencyTest < Test::Unit::TestCase assert_not_nil DUMMY_GEM_C_VERSION assert_equal '0.6.0', DUMMY_GEM_C_VERSION end + + def test_gem_load_frozen_when_platform_string_is_present + dummy_gem = Rails::GemDependency.new "dummy-gem-l" + dummy_gem.add_load_paths + dummy_gem.load + assert_not_nil DUMMY_GEM_L_VERSION + assert_equal "1.0.0", DUMMY_GEM_L_VERSION + end def test_gem_load_missing_specification dummy_gem = Rails::GemDependency.new "dummy-gem-d" diff --git a/vendor/rails/railties/test/vendor/gems/dummy-gem-l-1.0.0-x86-mswin32/.specification b/vendor/rails/railties/test/vendor/gems/dummy-gem-l-1.0.0-x86-mswin32/.specification new file mode 100644 index 00000000..cb3ff922 --- /dev/null +++ b/vendor/rails/railties/test/vendor/gems/dummy-gem-l-1.0.0-x86-mswin32/.specification @@ -0,0 +1,28 @@ +--- !ruby/object:Gem::Specification +name: dummy-gem-l +version: !ruby/object:Gem::Version + version: 1.0.0 +platform: mswin32 +authors: +- "Nobody" +date: 2008-10-03 00:00:00 -04:00 +files: +- lib +- lib/dummy-gem-l.rb +require_paths: +- lib +required_ruby_version: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: "0" + version: +required_rubygems_version: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: "0" + version: +requirements: [] +specification_version: 2 +summary: Dummy Gem L diff --git a/vendor/rails/railties/test/vendor/gems/dummy-gem-l-1.0.0-x86-mswin32/lib/dummy-gem-l.rb b/vendor/rails/railties/test/vendor/gems/dummy-gem-l-1.0.0-x86-mswin32/lib/dummy-gem-l.rb new file mode 100644 index 00000000..edade803 --- /dev/null +++ b/vendor/rails/railties/test/vendor/gems/dummy-gem-l-1.0.0-x86-mswin32/lib/dummy-gem-l.rb @@ -0,0 +1 @@ +DUMMY_GEM_L_VERSION="1.0.0"