Merge branch 'bzr/golem' of /Users/distler/Sites/code/instiki
17
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
|
||||
|
||||
|
|
2
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"
|
||||
|
|
|
@ -282,7 +282,7 @@ module Instiki
|
|||
module VERSION #:nodoc:
|
||||
MAJOR = 0
|
||||
MINOR = 19
|
||||
TINY = 0
|
||||
TINY = 1
|
||||
SUFFIX = '(MML+)'
|
||||
PRERELEASE = false
|
||||
if PRERELEASE
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
var x_off = win.width() - menu.width(),
|
||||
y_off = win.height() - menu.height();
|
||||
|
||||
if(x > x_off) x = x_off-15;
|
||||
if(y > y_off) y = y_off-15;
|
||||
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);
|
||||
|
|
|
@ -289,10 +289,11 @@ svgEditor.addExtension("imagelib", function() {
|
|||
|
||||
var leftBlock = $('<span>').css({position:'absolute',top:5,left:10}).appendTo(browser);
|
||||
|
||||
var back = $('<button>Show libraries</button>').appendTo(leftBlock).click(function() {
|
||||
var back = $('<button hidden>Show library list</button>').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('<span>' + opts.description + '</span>');
|
||||
});
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
1
public/svg-edit/editor/jgraduate/css/jPicker.css
Normal file
|
@ -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}
|
Before Width: | Height: | Size: 349 B After Width: | Height: | Size: 382 B |
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 268 B After Width: | Height: | Size: 552 B |
Before Width: | Height: | Size: 94 B After Width: | Height: | Size: 76 B |
1
public/svg-edit/editor/jgraduate/jpicker.min.js
vendored
Normal file
|
@ -61,7 +61,7 @@ $.jGraduate = {
|
|||
Paint:
|
||||
function(opt) {
|
||||
var options = opt || {};
|
||||
this.alpha = options.alpha || 100;
|
||||
this.alpha = isNaN(options.alpha) ? 100 : options.alpha;
|
||||
// copy paint object
|
||||
if (options.copy) {
|
||||
this.type = options.copy.type;
|
||||
|
@ -567,8 +567,8 @@ jQuery.fn.jGraduate =
|
|||
images: { clientPath: $settings.images.clientPath },
|
||||
color: { active: color, alphaSupport: true }
|
||||
}, function(color){
|
||||
beginColor = color.get_Hex() ? ('#'+color.get_Hex()) : "none";
|
||||
beginOpacity = color.get_A() ? color.get_A()/100 : 1;
|
||||
beginColor = color.val('hex') ? ('#'+color.val('hex')) : "none";
|
||||
beginOpacity = color.val('ahex') ? color.val('ahex')/100 : 1;
|
||||
colorbox.css('background', beginColor);
|
||||
$('#'+id+'_jGraduate_beginOpacity').html(parseInt(beginOpacity*100)+'%');
|
||||
stops[0].setAttribute('stop-color', beginColor);
|
||||
|
@ -591,8 +591,8 @@ jQuery.fn.jGraduate =
|
|||
images: { clientPath: $settings.images.clientPath },
|
||||
color: { active: color, alphaSupport: true }
|
||||
}, function(color){
|
||||
endColor = color.get_Hex() ? ('#'+color.get_Hex()) : "none";
|
||||
endOpacity = color.get_A() ? color.get_A()/100 : 1;
|
||||
endColor = color.val('hex') ? ('#'+color.val('hex')) : "none";
|
||||
endOpacity = color.val('ahex') ? color.val('ahex')/100 : 1;
|
||||
colorbox.css('background', endColor);
|
||||
$('#'+id+'_jGraduate_endOpacity').html(parseInt(endOpacity*100)+'%');
|
||||
stops[1].setAttribute('stop-color', endColor);
|
||||
|
@ -605,29 +605,8 @@ jQuery.fn.jGraduate =
|
|||
});
|
||||
});
|
||||
|
||||
// --------------
|
||||
var thisAlpha = ($this.paint.alpha*255/100).toString(16);
|
||||
while (thisAlpha.length < 2) { thisAlpha = "0" + thisAlpha; }
|
||||
color = $this.paint.solidColor == "none" ? "" : $this.paint.solidColor + thisAlpha;
|
||||
colPicker.jPicker(
|
||||
{
|
||||
window: { title: $settings.window.pickerTitle },
|
||||
images: { clientPath: $settings.images.clientPath },
|
||||
color: { active: color, alphaSupport: true }
|
||||
},
|
||||
function(color) {
|
||||
$this.paint.type = "solidColor";
|
||||
$this.paint.alpha = color.get_A() ? color.get_A() : 100;
|
||||
$this.paint.solidColor = color.get_Hex() ? color.get_Hex() : "none";
|
||||
$this.paint.linearGradient = null;
|
||||
okClicked();
|
||||
},
|
||||
null,
|
||||
function(){ cancelClicked(); }
|
||||
);
|
||||
}());
|
||||
|
||||
|
||||
// Radial gradient
|
||||
(function() {
|
||||
var svg = document.getElementById(id + '_rg_jgraduate_svg');
|
||||
|
@ -984,8 +963,8 @@ jQuery.fn.jGraduate =
|
|||
images: { clientPath: $settings.images.clientPath },
|
||||
color: { active: color, alphaSupport: true }
|
||||
}, function(color){
|
||||
centerColor = color.get_Hex() ? ('#'+color.get_Hex()) : "none";
|
||||
centerOpacity = color.get_A() ? color.get_A()/100 : 1;
|
||||
centerColor = color.val('hex') ? ('#'+color.val('hex')) : "none";
|
||||
centerOpacity = color.val('ahex') ? color.val('ahex')/100 : 1;
|
||||
colorbox.css('background', centerColor);
|
||||
$('#'+id+'_rg_jGraduate_centerOpacity').html(parseInt(centerOpacity*100)+'%');
|
||||
stops[0].setAttribute('stop-color', centerColor);
|
||||
|
@ -1008,8 +987,8 @@ jQuery.fn.jGraduate =
|
|||
images: { clientPath: $settings.images.clientPath },
|
||||
color: { active: color, alphaSupport: true }
|
||||
}, function(color){
|
||||
outerColor = color.get_Hex() ? ('#'+color.get_Hex()) : "none";
|
||||
outerOpacity = color.get_A() ? color.get_A()/100 : 1;
|
||||
outerColor = color.val('hex') ? ('#'+color.val('hex')) : "none";
|
||||
outerOpacity = color.val('ahex') ? color.val('ahex')/100 : 1;
|
||||
colorbox.css('background', outerColor);
|
||||
$('#'+id+'_jGraduate_outerOpacity').html(parseInt(outerOpacity*100)+'%');
|
||||
stops[1].setAttribute('stop-color', outerColor);
|
||||
|
@ -1025,7 +1004,14 @@ jQuery.fn.jGraduate =
|
|||
// --------------
|
||||
var thisAlpha = ($this.paint.alpha*255/100).toString(16);
|
||||
while (thisAlpha.length < 2) { thisAlpha = "0" + thisAlpha; }
|
||||
thisAlpha = thisAlpha.split(".")[0];
|
||||
color = $this.paint.solidColor == "none" ? "" : $this.paint.solidColor + thisAlpha;
|
||||
|
||||
// This should be done somewhere else, probably
|
||||
$.extend($.fn.jPicker.defaults.window, {
|
||||
alphaSupport: true, effects: {type: 'show',speed: 0}
|
||||
});
|
||||
|
||||
colPicker.jPicker(
|
||||
{
|
||||
window: { title: $settings.window.pickerTitle },
|
||||
|
@ -1034,8 +1020,8 @@ jQuery.fn.jGraduate =
|
|||
},
|
||||
function(color) {
|
||||
$this.paint.type = "solidColor";
|
||||
$this.paint.alpha = color.get_A() ? color.get_A() : 100;
|
||||
$this.paint.solidColor = color.get_Hex() ? color.get_Hex() : "none";
|
||||
$this.paint.alpha = color.val('ahex') ? Math.round((color.val('a') / 255) * 100) : 100;
|
||||
$this.paint.solidColor = color.val('hex') ? color.val('hex') : "none";
|
||||
$this.paint.radialGradient = null;
|
||||
okClicked();
|
||||
},
|
||||
|
@ -1051,7 +1037,6 @@ jQuery.fn.jGraduate =
|
|||
$(idref + " > 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);
|
||||
});
|
||||
};
|
||||
})();
|
|
@ -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 ."
|
||||
}
|
||||
}
|
||||
]
|
|
@ -5,7 +5,7 @@
|
|||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1"/>
|
||||
<link rel="icon" type="image/png" href="images/logo.png"/>
|
||||
<link rel="stylesheet" href="jgraduate/css/jPicker-1.0.12.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="jgraduate/css/jPicker.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="jgraduate/css/jgraduate.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="svg-editor.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="spinbtn/JQuerySpinBtn.css" type="text/css"/>
|
||||
|
@ -37,7 +37,7 @@ script type="text/javascript" src="locale/locale.min.js"></script-->
|
|||
|
||||
<!-- always minified scripts -->
|
||||
<script type="text/javascript" src="jquery-ui/jquery-ui-1.8.custom.min.js"></script>
|
||||
<script type="text/javascript" src="jgraduate/jpicker-1.0.12.min.js"></script>
|
||||
<script type="text/javascript" src="jgraduate/jpicker.min.js"></script>
|
||||
|
||||
<!-- feeds -->
|
||||
<link rel="alternate" type="application/atom+xml" title="SVG-edit General Discussion" href="http://groups.google.com/group/svg-edit/feed/atom_v1_0_msgs.xml" />
|
||||
|
@ -664,6 +664,7 @@ script type="text/javascript" src="locale/locale.min.js"></script-->
|
|||
<option id="lang_fr" value="fr">Français</option>
|
||||
<option id="lang_fy" value="fy">Frysk</option>
|
||||
<option id="lang_hi" value="hi">हिन्दी, हिंदी</option>
|
||||
<option id="lang_it" value="it">Italiano</option>
|
||||
<option id="lang_ja" value="ja">日本語</option>
|
||||
<option id="lang_nl" value="nl">Nederlands</option>
|
||||
<option id="lang_pt-BR" value="pt-BR">Português (BR)</option>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
paintBox[picker].setPaint(paint);
|
||||
svgCanvas.setPaint(picker, paint);
|
||||
|
||||
if (picker == 'stroke') {
|
||||
svgCanvas.setPaint('stroke', paint);
|
||||
strokePaint = paint;
|
||||
}
|
||||
else {
|
||||
svgCanvas.setPaint('fill', paint);
|
||||
fillPaint = paint;
|
||||
}
|
||||
updateToolbar();
|
||||
$('#color_picker').hide();
|
||||
},
|
||||
function(p) {
|
||||
|
@ -3260,39 +3208,103 @@
|
|||
operaRepaint();
|
||||
};
|
||||
|
||||
// set up gradients to be used for the buttons
|
||||
var svgdocbox = new DOMParser().parseFromString(
|
||||
'<svg xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%"\
|
||||
fill="#' + curConfig.initFill.color + '" opacity="' + curConfig.initFill.opacity + '"/>\
|
||||
<linearGradient id="gradbox_">\
|
||||
<stop stop-color="#000" offset="0.0"/>\
|
||||
<stop stop-color="#FF0000" offset="1.0"/>\
|
||||
</linearGradient></svg>', '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) );
|
||||
var PaintBox = function(container, type) {
|
||||
var cur = curConfig[type === 'fill' ? 'initFill' : 'initStroke'];
|
||||
|
||||
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
|
||||
});
|
||||
// set up gradients to be used for the buttons
|
||||
var svgdocbox = new DOMParser().parseFromString(
|
||||
'<svg xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%"\
|
||||
fill="#' + cur.color + '" opacity="' + cur.opacity + '"/>\
|
||||
<defs><linearGradient id="gradbox_"/></defs></svg>', '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));
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
switch (selected.tagName)
|
||||
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 + ')');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
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 <use> 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 <defs> or a <symbol>,
|
||||
// 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;
|
||||
|
@ -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);
|
||||
}());
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<head>
|
||||
<link rel="stylesheet" href="qunit/qunit.css" type="text/css"/>
|
||||
<script src="../editor/jquery.js"></script>
|
||||
<script type="text/javascript" src="../editor/jquery-ui/jquery-ui-1.8.custom.min.js"></script>
|
||||
<script type="text/javascript" src="../editor/svgicons/jquery.svgicons.js"></script>
|
||||
<script type="text/javascript" src="../editor/locale/locale.js"></script>
|
||||
<script type="text/javascript" src="../editor/svgcanvas.js"></script>
|
||||
|
@ -67,7 +68,7 @@
|
|||
// "m 0,0 l 200,0 l 0,100 L 0,100"
|
||||
|
||||
svgCanvas.setSvgString("<svg xmlns='http://www.w3.org/2000/svg' width='400' x='300'>" +
|
||||
"<path id='p1' d='M100,100 L200,100 Z'/>" +
|
||||
"<path id='p1' d='M100,100 L200,100 L100,100Z'/>" +
|
||||
"<path id='p2' d='m 0,0 l 200,0 l 0,100 L 0,100'/>" +
|
||||
"</svg>");
|
||||
|
||||
|
@ -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('<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:se="http://svg-edit.googlecode.com" xmlns:foo="http://example.com">'+
|
||||
var setStr = svgCanvas.setSvgString('<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:se="http://svg-edit.googlecode.com" xmlns:foo="http://example.com">'+
|
||||
'<image xlink:href="../editor/images/logo.png"/>' +
|
||||
'<polyline id="se_test_elem" se:foo="bar"/>' +
|
||||
'<polyline id="se_test_elem" se:foo="bar" foo:bar="baz"/>' +
|
||||
'</svg>');
|
||||
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 ' ?
|
||||
});
|
||||
|
||||
|
|
2
vendor/plugins/rails_xss/init.rb
vendored
|
@ -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'
|
||||
|
|
1
vendor/rails/actionmailer/CHANGELOG
vendored
|
@ -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)*
|
||||
|
|
2
vendor/rails/actionmailer/Rakefile
vendored
|
@ -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'
|
||||
|
|
|
@ -2,7 +2,7 @@ module ActionMailer
|
|||
module VERSION #:nodoc:
|
||||
MAJOR = 2
|
||||
MINOR = 3
|
||||
TINY = 9
|
||||
TINY = 10
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||
end
|
||||
|
|
2
vendor/rails/actionpack/CHANGELOG
vendored
|
@ -1,3 +1,5 @@
|
|||
*2.3.10 (October 15, 2010)*
|
||||
|
||||
*2.3.9 (September 4, 2010)*
|
||||
|
||||
* Version bump.
|
||||
|
|
2
vendor/rails/actionpack/Rakefile
vendored
|
@ -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'
|
||||
|
|
|
@ -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 <tt>redirect_to :back</tt>, if there is no referrer,
|
||||
# RedirectBackError will be raised. You may specify some fallback
|
||||
# When using <tt>redirect_to :back</tt>, 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?
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -101,8 +101,9 @@ module ActionController
|
|||
|
||||
session_data = env[ENV_SESSION_KEY]
|
||||
options = env[ENV_SESSION_OPTIONS_KEY]
|
||||
request = ActionController::Request.new(env)
|
||||
|
||||
if !session_data.is_a?(AbstractStore::SessionHash) || session_data.loaded? || options[:expire_after]
|
||||
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)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
require 'uri'
|
||||
|
||||
module ActionController
|
||||
# In <b>routes.rb</b> one defines URL-to-controller mappings, but the reverse
|
||||
# is also possible: an URL can be generated from one of your routing definitions.
|
||||
|
|
|
@ -2,7 +2,7 @@ module ActionPack #:nodoc:
|
|||
module VERSION #:nodoc:
|
||||
MAJOR = 2
|
||||
MINOR = 3
|
||||
TINY = 9
|
||||
TINY = 10
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -95,6 +99,12 @@ class CookieTest < ActionController::TestCase
|
|||
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
|
||||
assert_equal 2, @response.cookies.size
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,13 +170,17 @@ 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
|
||||
|
|
|
@ -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(
|
||||
'<input id="developer_name" name="developer[name]" size="30" type="text" value="Santiago" />', text_field("developer", "name")
|
||||
)
|
||||
end
|
||||
|
||||
def test_hidden_field
|
||||
assert_dom_equal '<input id="post_title" name="post[title]" type="hidden" value="Hello World" />',
|
||||
hidden_field("post", "title")
|
||||
|
|
4
vendor/rails/activerecord/CHANGELOG
vendored
|
@ -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)*
|
||||
|
|
2
vendor/rails/activerecord/Rakefile
vendored
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 <tt>:reject_if</tt> 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
|
||||
|
|
|
@ -2,7 +2,7 @@ module ActiveRecord
|
|||
module VERSION #:nodoc:
|
||||
MAJOR = 2
|
||||
MINOR = 3
|
||||
TINY = 9
|
||||
TINY = 10
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||
end
|
||||
|
|
|
@ -363,6 +363,11 @@ 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
1
vendor/rails/activeresource/CHANGELOG
vendored
|
@ -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)*
|
||||
|
|
2
vendor/rails/activeresource/Rakefile
vendored
|
@ -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'
|
||||
|
|
|
@ -2,7 +2,7 @@ module ActiveResource
|
|||
module VERSION #:nodoc:
|
||||
MAJOR = 2
|
||||
MINOR = 3
|
||||
TINY = 9
|
||||
TINY = 10
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||
end
|
||||
|
|
3
vendor/rails/activesupport/CHANGELOG
vendored
|
@ -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}.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -2,7 +2,7 @@ module ActiveSupport
|
|||
module VERSION #:nodoc:
|
||||
MAJOR = 2
|
||||
MINOR = 3
|
||||
TINY = 9
|
||||
TINY = 10
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
57
vendor/rails/activesupport/test/test_case_test.rb
vendored
Normal file
|
@ -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
|
2
vendor/rails/railties/CHANGELOG
vendored
|
@ -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]
|
||||
|
|
10
vendor/rails/railties/Rakefile
vendored
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
2
vendor/rails/railties/lib/rails/version.rb
vendored
|
@ -2,7 +2,7 @@ module Rails
|
|||
module VERSION #:nodoc:
|
||||
MAJOR = 2
|
||||
MINOR = 3
|
||||
TINY = 9
|
||||
TINY = 10
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||
end
|
||||
|
|
16
vendor/rails/railties/lib/tasks/databases.rake
vendored
|
@ -53,7 +53,7 @@ namespace :db do
|
|||
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/
|
||||
|
|
|
@ -114,6 +114,14 @@ class GemDependencyTest < Test::Unit::TestCase
|
|||
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"
|
||||
dummy_gem.add_load_paths
|
||||
|
|
28
vendor/rails/railties/test/vendor/gems/dummy-gem-l-1.0.0-x86-mswin32/.specification
vendored
Normal file
|
@ -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
|
1
vendor/rails/railties/test/vendor/gems/dummy-gem-l-1.0.0-x86-mswin32/lib/dummy-gem-l.rb
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
DUMMY_GEM_L_VERSION="1.0.0"
|