git-svn-id: http://svg-edit.googlecode.com/svn/trunk@2644 eee81c28-f429-11dd-99c0-75d572ba1ddd
master
Brett Zamir 2014-01-31 02:13:37 +00:00
parent d12694f9fa
commit 75bd787023
11 changed files with 338 additions and 263 deletions

View File

@ -1,3 +1,5 @@
/*globals $, svgroot */
/*jslint vars: true, eqeq: true, forin: true*/
/** /**
* Coords. * Coords.
* *
@ -15,7 +17,7 @@
var svgedit = svgedit || {}; var svgedit = svgedit || {};
(function() { (function() {'use strict';
if (!svgedit.coords) { if (!svgedit.coords) {
svgedit.coords = {}; svgedit.coords = {};
@ -39,18 +41,24 @@ svgedit.coords.init = function(editorContext) {
// changes - Object with changes to be remapped // changes - Object with changes to be remapped
// m - Matrix object to use for remapping coordinates // m - Matrix object to use for remapping coordinates
svgedit.coords.remapElement = function(selected, changes, m) { svgedit.coords.remapElement = function(selected, changes, m) {
var remap = function(x, y) { return svgedit.math.transformPoint(x, y, m); }, var i, type,
remap = function(x, y) { return svgedit.math.transformPoint(x, y, m); },
scalew = function(w) { return m.a * w; }, scalew = function(w) { return m.a * w; },
scaleh = function(h) { return m.d * h; }, scaleh = function(h) { return m.d * h; },
doSnapping = editorContext_.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg', doSnapping = editorContext_.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg',
finishUp = function() { finishUp = function() {
if (doSnapping) for (var o in changes) changes[o] = svgedit.utilities.snapToGrid(changes[o]); var o;
if (doSnapping) {
for (o in changes) {
changes[o] = svgedit.utilities.snapToGrid(changes[o]);
}
}
svgedit.utilities.assignAttributes(selected, changes, 1000, true); svgedit.utilities.assignAttributes(selected, changes, 1000, true);
}, },
box = svgedit.utilities.getBBox(selected); box = svgedit.utilities.getBBox(selected);
for (var i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
var type = i === 0 ? 'fill' : 'stroke'; type = i === 0 ? 'fill' : 'stroke';
var attrVal = selected.getAttribute(type); var attrVal = selected.getAttribute(type);
if (attrVal && attrVal.indexOf('url(') === 0) { if (attrVal && attrVal.indexOf('url(') === 0) {
if (m.a < 0 || m.d < 0) { if (m.a < 0 || m.d < 0) {
@ -84,6 +92,7 @@ svgedit.coords.remapElement = function(selected, changes, m) {
} }
var elName = selected.tagName; var elName = selected.tagName;
var chlist, mt;
if (elName === 'g' || elName === 'text' || elName == 'tspan' || elName === 'use') { if (elName === 'g' || elName === 'text' || elName == 'tspan' || elName === 'use') {
// if it was a translate, then just update x,y // 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) ) { if (m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 && (m.e != 0 || m.f != 0) ) {
@ -95,14 +104,14 @@ svgedit.coords.remapElement = function(selected, changes, m) {
changes.y = parseFloat(changes.y) + t_new.f; changes.y = parseFloat(changes.y) + t_new.f;
} else { } else {
// we just absorb all matrices into the element and don't do any remapping // we just absorb all matrices into the element and don't do any remapping
var chlist = svgedit.transformlist.getTransformList(selected); chlist = svgedit.transformlist.getTransformList(selected);
var mt = svgroot.createSVGTransform(); mt = svgroot.createSVGTransform();
mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m)); mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m));
chlist.clear(); chlist.clear();
chlist.appendItem(mt); chlist.appendItem(mt);
} }
} }
var c, pt, pt1, pt2, len;
// now we have a set of changes and an applied reduced transform list // now we have a set of changes and an applied reduced transform list
// we apply the changes directly to the DOM // we apply the changes directly to the DOM
switch (elName) { switch (elName) {
@ -112,13 +121,13 @@ svgedit.coords.remapElement = function(selected, changes, m) {
// Allow images to be inverted (give them matrix when flipped) // Allow images to be inverted (give them matrix when flipped)
if (elName === 'image' && (m.a < 0 || m.d < 0)) { if (elName === 'image' && (m.a < 0 || m.d < 0)) {
// Convert to matrix // Convert to matrix
var chlist = svgedit.transformlist.getTransformList(selected); chlist = svgedit.transformlist.getTransformList(selected);
var mt = svgroot.createSVGTransform(); mt = svgroot.createSVGTransform();
mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m)); mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m));
chlist.clear(); chlist.clear();
chlist.appendItem(mt); chlist.appendItem(mt);
} else { } else {
var pt1 = remap(changes.x, changes.y); pt1 = remap(changes.x, changes.y);
changes.width = scalew(changes.width); changes.width = scalew(changes.width);
changes.height = scaleh(changes.height); changes.height = scaleh(changes.height);
changes.x = pt1.x + Math.min(0, changes.width); changes.x = pt1.x + Math.min(0, changes.width);
@ -129,7 +138,7 @@ svgedit.coords.remapElement = function(selected, changes, m) {
finishUp(); finishUp();
break; break;
case 'ellipse': case 'ellipse':
var c = remap(changes.cx, changes.cy); c = remap(changes.cx, changes.cy);
changes.cx = c.x; changes.cx = c.x;
changes.cy = c.y; changes.cy = c.y;
changes.rx = scalew(changes.rx); changes.rx = scalew(changes.rx);
@ -139,7 +148,7 @@ svgedit.coords.remapElement = function(selected, changes, m) {
finishUp(); finishUp();
break; break;
case 'circle': case 'circle':
var c = remap(changes.cx,changes.cy); c = remap(changes.cx,changes.cy);
changes.cx = c.x; changes.cx = c.x;
changes.cy = c.y; changes.cy = c.y;
// take the minimum of the new selected box's dimensions for the new circle radius // take the minimum of the new selected box's dimensions for the new circle radius
@ -147,11 +156,12 @@ svgedit.coords.remapElement = function(selected, changes, m) {
var w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y; var w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y;
changes.r = Math.min(w/2, h/2); changes.r = Math.min(w/2, h/2);
if (changes.r) changes.r = Math.abs(changes.r); if (changes.r) {changes.r = Math.abs(changes.r);}
finishUp(); finishUp();
break; break;
case 'line': case 'line':
var pt1 = remap(changes.x1, changes.y1), pt2 = remap(changes.x2, changes.y2); pt1 = remap(changes.x1, changes.y1);
pt2 = remap(changes.x2, changes.y2);
changes.x1 = pt1.x; changes.x1 = pt1.x;
changes.y1 = pt1.y; changes.y1 = pt1.y;
changes.x2 = pt2.x; changes.x2 = pt2.x;
@ -170,87 +180,87 @@ svgedit.coords.remapElement = function(selected, changes, m) {
break; break;
case 'polyline': case 'polyline':
case 'polygon': case 'polygon':
var len = changes.points.length; len = changes.points.length;
for (var i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
var pt = changes.points[i]; pt = changes.points[i];
pt = remap(pt.x, pt.y); pt = remap(pt.x, pt.y);
changes.points[i].x = pt.x; changes.points[i].x = pt.x;
changes.points[i].y = pt.y; changes.points[i].y = pt.y;
} }
var len = changes.points.length; len = changes.points.length;
var pstr = ''; var pstr = '';
for (var i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
var pt = changes.points[i]; pt = changes.points[i];
pstr += pt.x + ',' + pt.y + ' '; pstr += pt.x + ',' + pt.y + ' ';
} }
selected.setAttribute('points', pstr); selected.setAttribute('points', pstr);
break; break;
case 'path': case 'path':
var seg;
var segList = selected.pathSegList;
len = segList.numberOfItems;
changes.d = new Array(len);
for (i = 0; i < len; ++i) {
seg = segList.getItem(i);
changes.d[i] = {
type: seg.pathSegType,
x: seg.x,
y: seg.y,
x1: seg.x1,
y1: seg.y1,
x2: seg.x2,
y2: seg.y2,
r1: seg.r1,
r2: seg.r2,
angle: seg.angle,
largeArcFlag: seg.largeArcFlag,
sweepFlag: seg.sweepFlag
};
}
var segList = selected.pathSegList; len = changes.d.length;
var len = segList.numberOfItems; var firstseg = changes.d[0],
changes.d = new Array(len); currentpt = remap(firstseg.x, firstseg.y);
for (var i = 0; i < len; ++i) { changes.d[0].x = currentpt.x;
var seg = segList.getItem(i); changes.d[0].y = currentpt.y;
changes.d[i] = { for (i = 1; i < len; ++i) {
type: seg.pathSegType, seg = changes.d[i];
x: seg.x, type = seg.type;
y: seg.y,
x1: seg.x1,
y1: seg.y1,
x2: seg.x2,
y2: seg.y2,
r1: seg.r1,
r2: seg.r2,
angle: seg.angle,
largeArcFlag: seg.largeArcFlag,
sweepFlag: seg.sweepFlag
};
}
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;
for (var i = 1; i < len; ++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 absolute or first segment, we want to remap x, y, x1, y1, x2, y2
// if relative, we want to scalew, scaleh // if relative, we want to scalew, scaleh
if (type % 2 == 0) { // absolute if (type % 2 == 0) { // absolute
var thisx = (seg.x != undefined) ? seg.x : currentpt.x, // for V commands var thisx = (seg.x != undefined) ? seg.x : currentpt.x, // for V commands
thisy = (seg.y != undefined) ? seg.y : currentpt.y, // for H commands thisy = (seg.y != undefined) ? seg.y : currentpt.y; // for H commands
pt = remap(thisx,thisy), pt = remap(thisx,thisy);
pt1 = remap(seg.x1, seg.y1), pt1 = remap(seg.x1, seg.y1);
pt2 = remap(seg.x2, seg.y2); pt2 = remap(seg.x2, seg.y2);
seg.x = pt.x; seg.x = pt.x;
seg.y = pt.y; seg.y = pt.y;
seg.x1 = pt1.x; seg.x1 = pt1.x;
seg.y1 = pt1.y; seg.y1 = pt1.y;
seg.x2 = pt2.x; seg.x2 = pt2.x;
seg.y2 = pt2.y; seg.y2 = pt2.y;
seg.r1 = scalew(seg.r1), seg.r1 = scalew(seg.r1);
seg.r2 = scaleh(seg.r2); seg.r2 = scaleh(seg.r2);
} }
else { // relative else { // relative
seg.x = scalew(seg.x); seg.x = scalew(seg.x);
seg.y = scaleh(seg.y); seg.y = scaleh(seg.y);
seg.x1 = scalew(seg.x1); seg.x1 = scalew(seg.x1);
seg.y1 = scaleh(seg.y1); seg.y1 = scaleh(seg.y1);
seg.x2 = scalew(seg.x2); seg.x2 = scalew(seg.x2);
seg.y2 = scaleh(seg.y2); seg.y2 = scaleh(seg.y2);
seg.r1 = scalew(seg.r1), seg.r1 = scalew(seg.r1);
seg.r2 = scaleh(seg.r2); seg.r2 = scaleh(seg.r2);
} }
} // for each segment } // for each segment
var dstr = ''; var dstr = '';
var len = changes.d.length; len = changes.d.length;
for (var i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
var seg = changes.d[i]; seg = changes.d[i];
var type = seg.type; type = seg.type;
dstr += pathMap[type]; dstr += pathMap[type];
switch (type) { switch (type) {
case 13: // relative horizontal line (h) case 13: // relative horizontal line (h)
@ -287,12 +297,12 @@ case 'path':
case 16: // absolute smooth cubic (S) case 16: // absolute smooth cubic (S)
dstr += seg.x2 + ',' + seg.y2 + ' ' + seg.x + ',' + seg.y + ' '; dstr += seg.x2 + ',' + seg.y2 + ' ' + seg.x + ',' + seg.y + ' ';
break; break;
} }
} }
selected.setAttribute('d', dstr); selected.setAttribute('d', dstr);
break; break;
} }
}; };
})(); }());

View File

@ -1,3 +1,5 @@
/*globals $, svgedit*/
/*jslint vars: true, eqeq: true*/
/** /**
* Package: svgedit.draw * Package: svgedit.draw
* *
@ -11,7 +13,7 @@
// 2) browser.js // 2) browser.js
// 3) svgutils.js // 3) svgutils.js
(function() { (function() {'use strict';
if (!svgedit.draw) { if (!svgedit.draw) {
svgedit.draw = {}; svgedit.draw = {};
@ -169,7 +171,7 @@ svgedit.draw.Drawing.prototype.clearNonce = function() {
svgedit.draw.Drawing.prototype.getId = function() { svgedit.draw.Drawing.prototype.getId = function() {
return this.nonce_ ? return this.nonce_ ?
this.idPrefix + this.nonce_ + '_' + this.obj_num : this.idPrefix + this.nonce_ + '_' + this.obj_num :
this.idPrefix + this.obj_num; this.idPrefix + this.obj_num;
}; };
/** /**
@ -225,7 +227,7 @@ svgedit.draw.Drawing.prototype.releaseId = function(id) {
return false; return false;
} }
// extract the obj_num of this id // extract the obj_num of this id
var num = parseInt(id.substr(front.length)); var num = parseInt(id.substr(front.length), 10);
// if we didn't get a positive number or we already released this number // if we didn't get a positive number or we already released this number
// then return false. // then return false.
@ -251,8 +253,9 @@ svgedit.draw.Drawing.prototype.getNumLayers = function() {
// Function: svgedit.draw.Drawing.hasLayer // Function: svgedit.draw.Drawing.hasLayer
// Check if layer with given name already exists // Check if layer with given name already exists
svgedit.draw.Drawing.prototype.hasLayer = function(name) { svgedit.draw.Drawing.prototype.hasLayer = function(name) {
for(var i = 0; i < this.getNumLayers(); i++) { var i;
if(this.all_layers[i][0] == name) return true; for (i = 0; i < this.getNumLayers(); i++) {
if(this.all_layers[i][0] == name) {return true;}
} }
return false; return false;
}; };
@ -287,7 +290,8 @@ svgedit.draw.Drawing.prototype.getCurrentLayer = function() {
// Returns: // Returns:
// The name of the currently active layer. // The name of the currently active layer.
svgedit.draw.Drawing.prototype.getCurrentLayerName = function() { svgedit.draw.Drawing.prototype.getCurrentLayerName = function() {
for (var i = 0; i < this.getNumLayers(); ++i) { var i;
for (i = 0; i < this.getNumLayers(); ++i) {
if (this.all_layers[i][1] == this.current_layer) { if (this.all_layers[i][1] == this.current_layer) {
return this.getLayerName(i); return this.getLayerName(i);
} }
@ -305,7 +309,8 @@ svgedit.draw.Drawing.prototype.getCurrentLayerName = function() {
// Returns: // Returns:
// true if the current layer was switched, otherwise false // true if the current layer was switched, otherwise false
svgedit.draw.Drawing.prototype.setCurrentLayer = function(name) { svgedit.draw.Drawing.prototype.setCurrentLayer = function(name) {
for (var i = 0; i < this.getNumLayers(); ++i) { var i;
for (i = 0; i < this.getNumLayers(); ++i) {
if (name == this.getLayerName(i)) { if (name == this.getLayerName(i)) {
if (this.current_layer != this.all_layers[i][1]) { if (this.current_layer != this.all_layers[i][1]) {
this.current_layer.setAttribute("style", "pointer-events:none"); this.current_layer.setAttribute("style", "pointer-events:none");
@ -346,7 +351,8 @@ svgedit.draw.Drawing.prototype.identifyLayers = function() {
var orphans = [], layernames = []; var orphans = [], layernames = [];
var a_layer = null; var a_layer = null;
var childgroups = false; var childgroups = false;
for (var i = 0; i < numchildren; ++i) { var i;
for (i = 0; i < numchildren; ++i) {
var child = this.svgElem_.childNodes.item(i); var child = this.svgElem_.childNodes.item(i);
// for each g, find its layer name // for each g, find its layer name
if (child && child.nodeType == 1) { if (child && child.nodeType == 1) {
@ -383,7 +389,7 @@ svgedit.draw.Drawing.prototype.identifyLayers = function() {
// create a new layer and add all the orphans to it // create a new layer and add all the orphans to it
var svgdoc = this.svgElem_.ownerDocument; var svgdoc = this.svgElem_.ownerDocument;
if (orphans.length > 0 || !childgroups) { if (orphans.length > 0 || !childgroups) {
var i = 1; i = 1;
// TODO(codedread): What about internationalization of "Layer"? // TODO(codedread): What about internationalization of "Layer"?
while (layernames.indexOf(("Layer " + i)) >= 0) { i++; } while (layernames.indexOf(("Layer " + i)) >= 0) { i++; }
var newname = "Layer " + i; var newname = "Layer " + i;
@ -391,7 +397,8 @@ svgedit.draw.Drawing.prototype.identifyLayers = function() {
var layer_title = svgdoc.createElementNS(NS.SVG, "title"); var layer_title = svgdoc.createElementNS(NS.SVG, "title");
layer_title.textContent = newname; layer_title.textContent = newname;
a_layer.appendChild(layer_title); a_layer.appendChild(layer_title);
for (var j = 0; j < orphans.length; ++j) { var j;
for (j = 0; j < orphans.length; ++j) {
a_layer.appendChild(orphans[j]); a_layer.appendChild(orphans[j]);
} }
this.svgElem_.appendChild(a_layer); this.svgElem_.appendChild(a_layer);
@ -435,13 +442,14 @@ svgedit.draw.Drawing.prototype.createLayer = function(name) {
svgedit.draw.Drawing.prototype.getLayerVisibility = function(layername) { svgedit.draw.Drawing.prototype.getLayerVisibility = function(layername) {
// find the layer // find the layer
var layer = null; var layer = null;
for (var i = 0; i < this.getNumLayers(); ++i) { var i;
for (i = 0; i < this.getNumLayers(); ++i) {
if (this.getLayerName(i) == layername) { if (this.getLayerName(i) == layername) {
layer = this.all_layers[i][1]; layer = this.all_layers[i][1];
break; break;
} }
} }
if (!layer) return false; if (!layer) {return false;}
return (layer.getAttribute('display') != 'none'); return (layer.getAttribute('display') != 'none');
}; };
@ -461,16 +469,17 @@ svgedit.draw.Drawing.prototype.setLayerVisibility = function(layername, bVisible
} }
// find the layer // find the layer
var layer = null; var layer = null;
for (var i = 0; i < this.getNumLayers(); ++i) { var i;
for (i = 0; i < this.getNumLayers(); ++i) {
if (this.getLayerName(i) == layername) { if (this.getLayerName(i) == layername) {
layer = this.all_layers[i][1]; layer = this.all_layers[i][1];
break; break;
} }
} }
if (!layer) return null; if (!layer) {return null;}
var oldDisplay = layer.getAttribute("display"); var oldDisplay = layer.getAttribute("display");
if (!oldDisplay) oldDisplay = "inline"; if (!oldDisplay) {oldDisplay = "inline";}
layer.setAttribute("display", bVisible ? "inline" : "none"); layer.setAttribute("display", bVisible ? "inline" : "none");
return layer; return layer;
}; };
@ -486,7 +495,8 @@ svgedit.draw.Drawing.prototype.setLayerVisibility = function(layername, bVisible
// The opacity value of the given layer. This will be a value between 0.0 and 1.0, or null // The opacity value of the given layer. This will be a value between 0.0 and 1.0, or null
// if layername is not a valid layer // if layername is not a valid layer
svgedit.draw.Drawing.prototype.getLayerOpacity = function(layername) { svgedit.draw.Drawing.prototype.getLayerOpacity = function(layername) {
for (var i = 0; i < this.getNumLayers(); ++i) { var i;
for (i = 0; i < this.getNumLayers(); ++i) {
if (this.getLayerName(i) == layername) { if (this.getLayerName(i) == layername) {
var g = this.all_layers[i][1]; var g = this.all_layers[i][1];
var opacity = g.getAttribute('opacity'); var opacity = g.getAttribute('opacity');
@ -510,7 +520,8 @@ svgedit.draw.Drawing.prototype.setLayerOpacity = function(layername, opacity) {
if (typeof opacity != typeof 1.0 || opacity < 0.0 || opacity > 1.0) { if (typeof opacity != typeof 1.0 || opacity < 0.0 || opacity > 1.0) {
return; return;
} }
for (var i = 0; i < this.getNumLayers(); ++i) { var i;
for (i = 0; i < this.getNumLayers(); ++i) {
if (this.getLayerName(i) == layername) { if (this.getLayerName(i) == layername) {
var g = this.all_layers[i][1]; var g = this.all_layers[i][1];
g.setAttribute("opacity", opacity); g.setAttribute("opacity", opacity);
@ -519,4 +530,4 @@ svgedit.draw.Drawing.prototype.setLayerOpacity = function(layername, opacity) {
} }
}; };
})(); }());

View File

@ -98,12 +98,13 @@ function EmbeddedSVGEdit(frame){
if (typeof e.data !== 'string') { if (typeof e.data !== 'string') {
return; return;
} }
var data = e.data && JSON.parse(e.data); var result, cbid,
data = e.data && JSON.parse(e.data);
if (!data || typeof data !== 'object' || data.namespace !== 'svg-edit') { if (!data || typeof data !== 'object' || data.namespace !== 'svg-edit') {
return; return;
} }
var result = data.result || data.error, result = data.result || data.error;
cbid = data.id; cbid = data.id;
if(t.callbacks[cbid]){ if(t.callbacks[cbid]){
if(data.result){ if(data.result){
t.callbacks[cbid](result); t.callbacks[cbid](result);

View File

@ -1,3 +1,5 @@
/*globals svgedit*/
/*jslint vars: true, eqeq: true, continue: true, forin: true*/
/** /**
* Package: svedit.history * Package: svedit.history
* *
@ -11,7 +13,7 @@
// 2) svgtransformlist.js // 2) svgtransformlist.js
// 3) svgutils.js // 3) svgutils.js
(function() { (function() {'use strict';
if (!svgedit.history) { if (!svgedit.history) {
svgedit.history = {}; svgedit.history = {};
@ -253,10 +255,11 @@ svgedit.history.ChangeElementCommand = function(elem, attrs, text) {
this.text = text ? ("Change " + elem.tagName + " " + text) : ("Change " + elem.tagName); this.text = text ? ("Change " + elem.tagName + " " + text) : ("Change " + elem.tagName);
this.newValues = {}; this.newValues = {};
this.oldValues = attrs; this.oldValues = attrs;
for (var attr in attrs) { var attr;
if (attr == "#text") this.newValues[attr] = elem.textContent; for (attr in attrs) {
else if (attr == "#href") this.newValues[attr] = svgedit.utilities.getHref(elem); if (attr == "#text") {this.newValues[attr] = elem.textContent;}
else this.newValues[attr] = elem.getAttribute(attr); else if (attr == "#href") {this.newValues[attr] = svgedit.utilities.getHref(elem);}
else {this.newValues[attr] = elem.getAttribute(attr);}
} }
}; };
svgedit.history.ChangeElementCommand.type = function() { return 'svgedit.history.ChangeElementCommand'; }; svgedit.history.ChangeElementCommand.type = function() { return 'svgedit.history.ChangeElementCommand'; };
@ -275,11 +278,12 @@ svgedit.history.ChangeElementCommand.prototype.apply = function(handler) {
} }
var bChangedTransform = false; var bChangedTransform = false;
for (var attr in this.newValues ) { var attr;
for (attr in this.newValues ) {
if (this.newValues[attr]) { if (this.newValues[attr]) {
if (attr == "#text") this.elem.textContent = this.newValues[attr]; if (attr == "#text") {this.elem.textContent = this.newValues[attr];}
else if (attr == "#href") svgedit.utilities.setHref(this.elem, this.newValues[attr]); else if (attr == "#href") {svgedit.utilities.setHref(this.elem, this.newValues[attr]);}
else this.elem.setAttribute(attr, this.newValues[attr]); else {this.elem.setAttribute(attr, this.newValues[attr]);}
} }
else { else {
if (attr == "#text") { if (attr == "#text") {
@ -298,6 +302,8 @@ svgedit.history.ChangeElementCommand.prototype.apply = function(handler) {
if (!bChangedTransform) { if (!bChangedTransform) {
var angle = svgedit.utilities.getRotationAngle(this.elem); var angle = svgedit.utilities.getRotationAngle(this.elem);
if (angle) { if (angle) {
// TODO: These instances of elem either need to be declared as global
// (which would not be good for conflicts) or declare/use this.elem
var bbox = elem.getBBox(); var bbox = elem.getBBox();
var cx = bbox.x + bbox.width/2, var cx = bbox.x + bbox.width/2,
cy = bbox.y + bbox.height/2; cy = bbox.y + bbox.height/2;
@ -323,17 +329,20 @@ svgedit.history.ChangeElementCommand.prototype.unapply = function(handler) {
} }
var bChangedTransform = false; var bChangedTransform = false;
for (var attr in this.oldValues ) { var attr;
for (attr in this.oldValues ) {
if (this.oldValues[attr]) { if (this.oldValues[attr]) {
if (attr == "#text") this.elem.textContent = this.oldValues[attr]; if (attr == "#text") {this.elem.textContent = this.oldValues[attr];}
else if (attr == "#href") svgedit.utilities.setHref(this.elem, this.oldValues[attr]); else if (attr == "#href") {svgedit.utilities.setHref(this.elem, this.oldValues[attr]);}
else this.elem.setAttribute(attr, this.oldValues[attr]); else {
this.elem.setAttribute(attr, this.oldValues[attr]);
}
} }
else { else {
if (attr == "#text") { if (attr == "#text") {
this.elem.textContent = ""; this.elem.textContent = "";
} }
else this.elem.removeAttribute(attr); else {this.elem.removeAttribute(attr);}
} }
if (attr == "transform") { bChangedTransform = true; } if (attr == "transform") { bChangedTransform = true; }
} }
@ -398,8 +407,9 @@ svgedit.history.BatchCommand.prototype.apply = function(handler) {
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this); handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
} }
var len = this.stack.length; var i,
for (var i = 0; i < len; ++i) { len = this.stack.length;
for (i = 0; i < len; ++i) {
this.stack[i].apply(handler); this.stack[i].apply(handler);
} }
@ -415,7 +425,8 @@ svgedit.history.BatchCommand.prototype.unapply = function(handler) {
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this); handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
} }
for (var i = this.stack.length-1; i >= 0; i--) { var i;
for (i = this.stack.length-1; i >= 0; i--) {
this.stack[i].unapply(handler); this.stack[i].unapply(handler);
} }
@ -433,7 +444,7 @@ svgedit.history.BatchCommand.prototype.elements = function() {
var thisElems = this.stack[cmd].elements(); var thisElems = this.stack[cmd].elements();
var elem = thisElems.length; var elem = thisElems.length;
while (elem--) { while (elem--) {
if (elems.indexOf(thisElems[elem]) == -1) elems.push(thisElems[elem]); if (elems.indexOf(thisElems[elem]) == -1) {elems.push(thisElems[elem]);}
} }
} }
return elems; return elems;
@ -560,7 +571,7 @@ svgedit.history.UndoManager.prototype.beginUndoableChange = function(attrName, e
var oldValues = new Array(i), elements = new Array(i); var oldValues = new Array(i), elements = new Array(i);
while (i--) { while (i--) {
var elem = elems[i]; var elem = elems[i];
if (elem == null) continue; if (elem == null) {continue;}
elements[i] = elem; elements[i] = elem;
oldValues[i] = elem.getAttribute(attrName); oldValues[i] = elem.getAttribute(attrName);
} }
@ -586,7 +597,7 @@ svgedit.history.UndoManager.prototype.finishUndoableChange = function() {
var batchCmd = new svgedit.history.BatchCommand("Change " + attrName); var batchCmd = new svgedit.history.BatchCommand("Change " + attrName);
while (i--) { while (i--) {
var elem = changeset.elements[i]; var elem = changeset.elements[i];
if (elem == null) continue; if (elem == null) {continue;}
var changes = {}; var changes = {};
changes[attrName] = changeset.oldValues[i]; changes[attrName] = changeset.oldValues[i];
if (changes[attrName] != elem.getAttribute(attrName)) { if (changes[attrName] != elem.getAttribute(attrName)) {
@ -597,4 +608,4 @@ svgedit.history.UndoManager.prototype.finishUndoableChange = function() {
return batchCmd; return batchCmd;
}; };
})(); }());

21
editor/jquery-svg.js vendored
View File

@ -1,3 +1,5 @@
/*globals $, jQuery */
/*jslint vars: true */
/** /**
* jQuery module to work with SVG. * jQuery module to work with SVG.
* *
@ -8,7 +10,7 @@
// Dependencies: // Dependencies:
// 1) jquery // 1) jquery
(function() { (function() {'use strict';
// This fixes $(...).attr() to work as expected with SVG elements. // This fixes $(...).attr() to work as expected with SVG elements.
// Does not currently use *AttributeNS() since we rarely need that. // Does not currently use *AttributeNS() since we rarely need that.
@ -24,9 +26,10 @@
// TODO use NS.SVG instead // TODO use NS.SVG instead
svgns = "http://www.w3.org/2000/svg"; svgns = "http://www.w3.org/2000/svg";
jQuery.fn.attr = function(key, value) { jQuery.fn.attr = function(key, value) {
var len = this.length; var i, attr;
if (!len) return proxied.apply(this, arguments); var len = this.length;
for (var i = 0; i < len; ++i) { if (!len) {return proxied.apply(this, arguments);}
for (i = 0; i < len; ++i) {
var elem = this[i]; var elem = this[i];
// set/get SVG attribute // set/get SVG attribute
if (elem.namespaceURI === svgns) { if (elem.namespaceURI === svgns) {
@ -39,7 +42,7 @@
while (j--) { while (j--) {
var aname = key[j]; var aname = key[j];
var attr = elem.getAttribute(aname); attr = elem.getAttribute(aname);
// This returns a number when appropriate // This returns a number when appropriate
if (attr || attr === "0") { if (attr || attr === "0") {
attr = isNaN(attr) ? attr : (attr - 0); attr = isNaN(attr) ? attr : (attr - 0);
@ -47,14 +50,16 @@
obj[aname] = attr; obj[aname] = attr;
} }
return obj; return obj;
} else if (typeof key === "object") { }
if (typeof key === "object") {
// Setting attributes form object // Setting attributes form object
for (var v in key) { var v;
for (v in key) {
elem.setAttribute(v, key[v]); elem.setAttribute(v, key[v]);
} }
// Getting attribute // Getting attribute
} else { } else {
var attr = elem.getAttribute(key); attr = elem.getAttribute(key);
if (attr || attr === "0") { if (attr || attr === "0") {
attr = isNaN(attr) ? attr : (attr - 0); attr = isNaN(attr) ? attr : (attr - 0);
} }

View File

@ -1,3 +1,5 @@
/*globals svgedit*/
/*jslint vars: true, eqeq: true */
/** /**
* Package: svedit.math * Package: svedit.math
* *
@ -10,7 +12,7 @@
// Dependencies: // Dependencies:
// None. // None.
(function() { (function() {'use strict';
if (!svgedit.math) { if (!svgedit.math) {
svgedit.math = {}; svgedit.math = {};
@ -66,12 +68,12 @@ svgedit.math.matrixMultiply = function() {
var m1 = args[i-1]; var m1 = args[i-1];
m = m1.multiply(m); m = m1.multiply(m);
} }
if (Math.abs(m.a) < NEAR_ZERO) m.a = 0; if (Math.abs(m.a) < NEAR_ZERO) {m.a = 0;}
if (Math.abs(m.b) < NEAR_ZERO) m.b = 0; if (Math.abs(m.b) < NEAR_ZERO) {m.b = 0;}
if (Math.abs(m.c) < NEAR_ZERO) m.c = 0; if (Math.abs(m.c) < NEAR_ZERO) {m.c = 0;}
if (Math.abs(m.d) < NEAR_ZERO) m.d = 0; if (Math.abs(m.d) < NEAR_ZERO) {m.d = 0;}
if (Math.abs(m.e) < NEAR_ZERO) m.e = 0; if (Math.abs(m.e) < NEAR_ZERO) {m.e = 0;}
if (Math.abs(m.f) < NEAR_ZERO) m.f = 0; if (Math.abs(m.f) < NEAR_ZERO) {m.f = 0;}
return m; return m;
}; };
@ -85,11 +87,11 @@ svgedit.math.matrixMultiply = function() {
// Returns: // Returns:
// Boolean on whether or not a matrix transform was found // Boolean on whether or not a matrix transform was found
svgedit.math.hasMatrixTransform = function(tlist) { svgedit.math.hasMatrixTransform = function(tlist) {
if (!tlist) return false; if (!tlist) {return false;}
var num = tlist.numberOfItems; var num = tlist.numberOfItems;
while (num--) { while (num--) {
var xform = tlist.getItem(num); var xform = tlist.getItem(num);
if (xform.type == 1 && !svgedit.math.isIdentity(xform.matrix)) return true; if (xform.type == 1 && !svgedit.math.isIdentity(xform.matrix)) {return true;}
} }
return false; return false;
}; };
@ -166,7 +168,8 @@ svgedit.math.transformListToTransform = function(tlist, min, max) {
max = parseInt(max, 10); max = parseInt(max, 10);
if (min > max) { var temp = max; max = min; min = temp; } if (min > max) { var temp = max; max = min; min = temp; }
var m = svg.createSVGMatrix(); var m = svg.createSVGMatrix();
for (var i = min; i <= max; ++i) { var i;
for (i = min; i <= max; ++i) {
// if our indices are out of range, just use a harmless identity matrix // if our indices are out of range, just use a harmless identity matrix
var mtom = (i >= 0 && i < tlist.numberOfItems ? var mtom = (i >= 0 && i < tlist.numberOfItems ?
tlist.getItem(i).matrix : tlist.getItem(i).matrix :
@ -238,4 +241,4 @@ svgedit.math.rectsIntersect = function(r1, r2) {
(r2.y+r2.height) > r1.y; (r2.y+r2.height) > r1.y;
}; };
})(); }());

View File

@ -942,10 +942,11 @@
if (toolButtonClick(show_sel)) { if (toolButtonClick(show_sel)) {
options.fn(); options.fn();
} }
var icon;
if (options.icon) { if (options.icon) {
var icon = $.getSvgIcon(options.icon, true); icon = $.getSvgIcon(options.icon, true);
} else { } else {
var icon = $(options.sel).children().eq(0).clone(); icon = $(options.sel).children().eq(0).clone();
} }
icon[0].setAttribute('width', shower.width()); icon[0].setAttribute('width', shower.width());
@ -1169,7 +1170,7 @@
// Add buttons given by extension // Add buttons given by extension
$.each(ext.buttons, function(i, btn) { $.each(ext.buttons, function(i, btn) {
var icon; var icon, svgicon;
var id = btn.id; var id = btn.id;
var num = i; var num = i;
@ -1182,7 +1183,7 @@
icon = $('<img src="' + btn.icon + '">'); icon = $('<img src="' + btn.icon + '">');
} else { } else {
fallback_obj[id] = btn.icon; fallback_obj[id] = btn.icon;
var svgicon = btn.svgicon || btn.id; svgicon = btn.svgicon || btn.id;
if (btn.type == 'app_menu') { if (btn.type == 'app_menu') {
placement_obj['#' + id + ' > div'] = svgicon; placement_obj['#' + id + ' > div'] = svgicon;
} else { } else {
@ -1212,7 +1213,7 @@
parent = '#main_menu ul'; parent = '#main_menu ul';
break; break;
} }
var flyout_holder, cur_h, show_btn;
var button = $((btn.list || btn.type == 'app_menu') ? '<li/>' : '<div/>') var button = $((btn.list || btn.type == 'app_menu') ? '<li/>' : '<div/>')
.attr('id', id) .attr('id', id)
.attr('title', btn.title) .attr('title', btn.title)
@ -1230,12 +1231,12 @@
// // opts.button, default, position // // opts.button, default, position
var ref_btn = $(button); var ref_btn = $(button);
var flyout_holder = ref_btn.parent(); flyout_holder = ref_btn.parent();
// Create a flyout menu if there isn't one already // Create a flyout menu if there isn't one already
if (!ref_btn.parent().hasClass('tools_flyout')) { if (!ref_btn.parent().hasClass('tools_flyout')) {
// Create flyout placeholder // Create flyout placeholder
var tls_id = ref_btn[0].id.replace('tool_', 'tools_'); var tls_id = ref_btn[0].id.replace('tool_', 'tools_');
var show_btn = ref_btn.clone() show_btn = ref_btn.clone()
.attr('id',tls_id + '_show') .attr('id',tls_id + '_show')
.append($('<div>', {'class': 'flyout_arrow_horiz'})); .append($('<div>', {'class': 'flyout_arrow_horiz'}));
@ -1252,7 +1253,7 @@
// TODO: Find way to set the current icon using the iconloader if this is not default // TODO: Find way to set the current icon using the iconloader if this is not default
// Include data for extension button as well as ref button // Include data for extension button as well as ref button
var cur_h = holders['#'+flyout_holder[0].id] = [{ cur_h = holders['#'+flyout_holder[0].id] = [{
sel: '#'+id, sel: '#'+id,
fn: btn.events.click, fn: btn.events.click,
icon: btn.id, icon: btn.id,
@ -1282,7 +1283,7 @@
$('#' + btn.list + '_opts').append(button); $('#' + btn.list + '_opts').append(button);
if (btn.isDefault) { if (btn.isDefault) {
$('#cur_' + btn.list).append(button.children().clone()); $('#cur_' + btn.list).append(button.children().clone());
var svgicon = btn.svgicon || btn.id; svgicon = btn.svgicon || btn.id;
placement_obj['#cur_' + btn.list] = svgicon; placement_obj['#cur_' + btn.list] = svgicon;
} }
} else if (btn.includeWith) { } else if (btn.includeWith) {
@ -1291,12 +1292,12 @@
// opts.button, default, position // opts.button, default, position
var ref_btn = $(opts.button); var ref_btn = $(opts.button);
var flyout_holder = ref_btn.parent(); flyout_holder = ref_btn.parent();
// Create a flyout menu if there isn't one already // Create a flyout menu if there isn't one already
if (!ref_btn.parent().hasClass('tools_flyout')) { if (!ref_btn.parent().hasClass('tools_flyout')) {
// Create flyout placeholder // Create flyout placeholder
var tls_id = ref_btn[0].id.replace('tool_', 'tools_'); var tls_id = ref_btn[0].id.replace('tool_', 'tools_');
var show_btn = ref_btn.clone() show_btn = ref_btn.clone()
.attr('id',tls_id + '_show') .attr('id',tls_id + '_show')
.append($('<div>', {'class': 'flyout_arrow_horiz'})); .append($('<div>', {'class': 'flyout_arrow_horiz'}));
@ -1314,7 +1315,7 @@
// TODO: Find way to set the current icon using the iconloader if this is not default // TODO: Find way to set the current icon using the iconloader if this is not default
// Include data for extension button as well as ref button // Include data for extension button as well as ref button
var cur_h = holders['#'+flyout_holder[0].id] = [{ cur_h = holders['#'+flyout_holder[0].id] = [{
sel: '#'+id, sel: '#'+id,
fn: btn.events.click, fn: btn.events.click,
icon: btn.id, icon: btn.id,
@ -1355,7 +1356,9 @@
} }
if (btn.key) { if (btn.key) {
$(document).bind('keydown', btn.key, func); $(document).bind('keydown', btn.key, func);
if (btn.title) button.attr('title', btn.title + ' ['+btn.key+']'); if (btn.title) {
button.attr('title', btn.title + ' ['+btn.key+']');
}
} }
} else { } else {
button.bind(name, func); button.bind(name, func);
@ -1370,8 +1373,9 @@
addAltDropDown(this.elem, this.list, this.callback, {seticon: true}); addAltDropDown(this.elem, this.list, this.callback, {seticon: true});
}); });
if (svgicons) if (svgicons) {
cb_ready = false; // Delay callback cb_ready = false; // Delay callback
}
$.svgIcons(svgicons, { $.svgIcons(svgicons, {
w:24, h:24, w:24, h:24,
@ -1415,6 +1419,7 @@
// updates the toolbar (colors, opacity, etc) based on the selected element // updates the toolbar (colors, opacity, etc) based on the selected element
// This function also updates the opacity and id elements that are in the context panel // This function also updates the opacity and id elements that are in the context panel
var updateToolbar = function() { var updateToolbar = function() {
var i;
if (selectedElement != null) { if (selectedElement != null) {
switch (selectedElement.tagName) { switch (selectedElement.tagName) {
case 'use': case 'use':
@ -1426,7 +1431,7 @@
// Look for common styles // Look for common styles
var gWidth = null; var gWidth = null;
var childs = selectedElement.getElementsByTagName('*'); var childs = selectedElement.getElementsByTagName('*');
for (var i = 0, len = childs.length; i < len; i++) { for (i = 0, len = childs.length; i < len; i++) {
var swidth = childs[i].getAttribute('stroke-width'); var swidth = childs[i].getAttribute('stroke-width');
if (i === 0) { if (i === 0) {
@ -1451,13 +1456,15 @@
var attr = selectedElement.getAttribute('stroke-linejoin') || 'miter'; var attr = selectedElement.getAttribute('stroke-linejoin') || 'miter';
if ($('#linejoin_' + attr).length != 0) if ($('#linejoin_' + attr).length != 0) {
setStrokeOpt($('#linejoin_' + attr)[0]); setStrokeOpt($('#linejoin_' + attr)[0]);
}
attr = selectedElement.getAttribute('stroke-linecap') || 'butt'; attr = selectedElement.getAttribute('stroke-linecap') || 'butt';
if ($('#linecap_' + attr).length != 0) if ($('#linecap_' + attr).length != 0) {
setStrokeOpt($('#linecap_' + attr)[0]); setStrokeOpt($('#linecap_' + attr)[0]);
}
} }
} }
@ -1473,7 +1480,9 @@
}; };
var setImageURL = Editor.setImageURL = function(url) { var setImageURL = Editor.setImageURL = function(url) {
if (!url) url = defaultImageURL; if (!url) {
url = defaultImageURL;
}
svgCanvas.setImageURL(url); svgCanvas.setImageURL(url);
$('#image_url').val(url); $('#image_url').val(url);
@ -1502,15 +1511,16 @@
var updateContextPanel = function() { var updateContextPanel = function() {
var elem = selectedElement; var elem = selectedElement;
// If element has just been deleted, consider it null // If element has just been deleted, consider it null
if (elem != null && !elem.parentNode) elem = null; if (elem != null && !elem.parentNode) {elem = null;}
var currentLayerName = svgCanvas.getCurrentDrawing().getCurrentLayerName(); var currentLayerName = svgCanvas.getCurrentDrawing().getCurrentLayerName();
var currentMode = svgCanvas.getMode(); var currentMode = svgCanvas.getMode();
var unit = curConfig.baseUnit !== 'px' ? curConfig.baseUnit : null; var unit = curConfig.baseUnit !== 'px' ? curConfig.baseUnit : null;
var is_node = currentMode == 'pathedit'; //elem ? (elem.id && elem.id.indexOf('pathpointgrip') == 0) : false; var is_node = currentMode == 'pathedit'; //elem ? (elem.id && elem.id.indexOf('pathpointgrip') == 0) : false;
var menu_items = $('#cmenu_canvas li'); var menu_items = $('#cmenu_canvas li');
$('#selected_panel, #multiselected_panel, #g_panel, #rect_panel, #circle_panel,\ $('#selected_panel, #multiselected_panel, #g_panel, #rect_panel, #circle_panel,'+
#ellipse_panel, #line_panel, #text_panel, #image_panel, #container_panel, #use_panel, #a_panel').hide(); '#ellipse_panel, #line_panel, #text_panel, #image_panel, #container_panel,'+
' #use_panel, #a_panel').hide();
if (elem != null) { if (elem != null) {
var elname = elem.nodeName; var elname = elem.nodeName;
// If this is a link with no transform and one child, pretend // If this is a link with no transform and one child, pretend
@ -1736,7 +1746,7 @@
// Set up editor background functionality // Set up editor background functionality
// TODO add checkerboard as "pattern" // TODO add checkerboard as "pattern"
var color_blocks = ['#FFF', '#888', '#000']; // ,'url(data:image/gif;base64,R0lGODlhEAAQAIAAAP%2F%2F%2F9bW1iH5BAAAAAAALAAAAAAQABAAAAIfjG%2Bgq4jM3IFLJgpswNly%2FXkcBpIiVaInlLJr9FZWAQA7)']; var color_blocks = ['#FFF', '#888', '#000']; // ,'url(data:image/gif;base64,R0lGODlhEAAQAIAAAP%2F%2F%2F9bW1iH5BAAAAAAALAAAAAAQABAAAAIfjG%2Bgq4jM3IFLJgpswNly%2FXkcBpIiVaInlLJr9FZWAQA7)'];
var str = ''; str = '';
$.each(color_blocks, function() { $.each(color_blocks, function() {
str += '<div class="color_block" style="background-color:' + this + ';"></div>'; str += '<div class="color_block" style="background-color:' + this + ';"></div>';
}); });
@ -1785,8 +1795,8 @@
}; };
var changeZoom = function(ctl) { var changeZoom = function(ctl) {
var zoomlevel = ctl.value / 100; var zoomlevel = ctl.value / 100;
if (zoomlevel < .001) { if (zoomlevel < 0.001) {
ctl.value = .1; ctl.value = 0.1;
return; return;
} }
var zoom = svgCanvas.getZoom(); var zoom = svgCanvas.getZoom();
@ -1803,7 +1813,7 @@
}; };
var changeOpacity = function(ctl, val) { var changeOpacity = function(ctl, val) {
if (val == null) val = ctl.value; if (val == null) {val = ctl.value;}
$('#group_opacity').val(val); $('#group_opacity').val(val);
if (!ctl || !ctl.handle) { if (!ctl || !ctl.handle) {
$('#opac_slider').slider('option', 'value', val); $('#opac_slider').slider('option', 'value', val);
@ -1812,7 +1822,7 @@
}; };
var changeBlur = function(ctl, val, noUndo) { var changeBlur = function(ctl, val, noUndo) {
if (val == null) val = ctl.value; if (val == null) {val = ctl.value;}
$('#blur').val(val); $('#blur').val(val);
var complete = false; var complete = false;
if (!ctl || !ctl.handle) { if (!ctl || !ctl.handle) {
@ -1853,7 +1863,7 @@
var destLayer = this.options[this.selectedIndex].value; var destLayer = this.options[this.selectedIndex].value;
var confirmStr = uiStrings.notification.QmoveElemsToLayer.replace('%s', destLayer); var confirmStr = uiStrings.notification.QmoveElemsToLayer.replace('%s', destLayer);
var moveToLayer = function(ok) { var moveToLayer = function(ok) {
if (!ok) return; if (!ok) {return;}
promptMoveLayerOnce = true; promptMoveLayerOnce = true;
svgCanvas.moveSelectedToLayer(destLayer); svgCanvas.moveSelectedToLayer(destLayer);
svgCanvas.clearSelection(); svgCanvas.clearSelection();

View File

@ -1,3 +1,5 @@
/*globals $, svgedit*/
/*jslint vars: true, eqeq: true*/
/** /**
* SVGTransformList * SVGTransformList
* *
@ -10,7 +12,7 @@
// Dependencies: // Dependencies:
// 1) browser.js // 1) browser.js
(function() { (function() {'use strict';
if (!svgedit.transformlist) { if (!svgedit.transformlist) {
svgedit.transformlist = {}; svgedit.transformlist = {};
@ -30,8 +32,8 @@ function transformToString(xform) {
text = 'translate(' + m.e + ',' + m.f + ')'; text = 'translate(' + m.e + ',' + m.f + ')';
break; break;
case 3: // SCALE case 3: // SCALE
if (m.a == m.d) text = 'scale(' + m.a + ')'; if (m.a == m.d) {text = 'scale(' + m.a + ')';}
else text = 'scale(' + m.a + ',' + m.d + ')'; else {text = 'scale(' + m.a + ',' + m.d + ')';}
break; break;
case 4: // ROTATE case 4: // ROTATE
var cx = 0, cy = 0; var cx = 0, cy = 0;
@ -80,7 +82,8 @@ svgedit.transformlist.SVGTransformList = function(elem) {
this._update = function() { this._update = function() {
var tstr = ''; var tstr = '';
var concatMatrix = svgroot.createSVGMatrix(); var concatMatrix = svgroot.createSVGMatrix();
for (var i = 0; i < this.numberOfItems; ++i) { var i;
for (i = 0; i < this.numberOfItems; ++i) {
var xform = this._list.getItem(i); var xform = this._list.getItem(i);
tstr += transformToString(xform) + ' '; tstr += transformToString(xform) + ' ';
} }
@ -90,7 +93,7 @@ svgedit.transformlist.SVGTransformList = function(elem) {
this._init = function() { this._init = function() {
// Transform attribute parser // Transform attribute parser
var str = this._elem.getAttribute('transform'); var str = this._elem.getAttribute('transform');
if (!str) return; if (!str) {return;}
// TODO: Add skew support in future // TODO: Add skew support in future
var re = /\s*((scale|matrix|rotate|translate)\s*\(.*?\))\s*,?\s*/; var re = /\s*((scale|matrix|rotate|translate)\s*\(.*?\))\s*,?\s*/;
@ -134,9 +137,11 @@ svgedit.transformlist.SVGTransformList = function(elem) {
// Check if this transform is already in a transformlist, and // Check if this transform is already in a transformlist, and
// remove it if so. // remove it if so.
var found = false; var found = false;
for (var id in listMap_) { var id;
for (id in listMap_) {
var tl = listMap_[id]; var tl = listMap_[id];
for (var i = 0, len = tl._xforms.length; i < len; ++i) { var i, len;
for (i = 0, len = tl._xforms.length; i < len; ++i) {
if (tl._xforms[i] == item) { if (tl._xforms[i] == item) {
found = true; found = true;
tl.removeItem(i); tl.removeItem(i);
@ -176,11 +181,13 @@ svgedit.transformlist.SVGTransformList = function(elem) {
this._removeFromOtherLists(newItem); this._removeFromOtherLists(newItem);
var newxforms = new Array(this.numberOfItems + 1); var newxforms = new Array(this.numberOfItems + 1);
// TODO: use array copying and slicing // TODO: use array copying and slicing
for ( var i = 0; i < index; ++i) { var i;
for (i = 0; i < index; ++i) {
newxforms[i] = this._xforms[i]; newxforms[i] = this._xforms[i];
} }
newxforms[i] = newItem; newxforms[i] = newItem;
for ( var j = i+1; i < this.numberOfItems; ++j, ++i) { var j;
for (j = i+1; i < this.numberOfItems; ++j, ++i) {
newxforms[j] = this._xforms[i]; newxforms[j] = this._xforms[i];
} }
this.numberOfItems++; this.numberOfItems++;
@ -210,10 +217,11 @@ svgedit.transformlist.SVGTransformList = function(elem) {
if (index < this.numberOfItems && index >= 0) { if (index < this.numberOfItems && index >= 0) {
var retValue = this._xforms[index]; var retValue = this._xforms[index];
var newxforms = new Array(this.numberOfItems - 1); var newxforms = new Array(this.numberOfItems - 1);
for (var i = 0; i < index; ++i) { var i, j;
for (i = 0; i < index; ++i) {
newxforms[i] = this._xforms[i]; newxforms[i] = this._xforms[i];
} }
for (var j = i; j < this.numberOfItems-1; ++j, ++i) { for (j = i; j < this.numberOfItems-1; ++j, ++i) {
newxforms[j] = this._xforms[i+1]; newxforms[j] = this._xforms[i+1];
} }
this.numberOfItems--; this.numberOfItems--;
@ -278,4 +286,4 @@ svgedit.transformlist.getTransformList = function(elem) {
return null; return null;
}; };
})(); }());

View File

@ -1,3 +1,5 @@
/*globals $, svgedit, unescape, DOMParser, ActiveXObject, getStrokedBBox*/
/*jslint vars: true, eqeq: true, bitwise: true, continue: true, forin: true*/
/** /**
* Package: svgedit.utilities * Package: svgedit.utilities
* *
@ -13,7 +15,7 @@
// 3) svgtransformlist.js // 3) svgtransformlist.js
// 4) units.js // 4) units.js
(function() { (function() {'use strict';
if (!svgedit.utilities) { if (!svgedit.utilities) {
svgedit.utilities = {}; svgedit.utilities = {};
@ -74,7 +76,7 @@ svgedit.utilities.fromXml = function(str) {
// Base64 code from Tyler Akins -- http://rumkin.com // Base64 code from Tyler Akins -- http://rumkin.com
// schiller: Removed string concatenation in favour of Array.join() optimization, // schiller: Removed string concatenation in favour of Array.join() optimization,
// also precalculate the size of the array needed. // also precalculate the size of the array needed.
// Function: svgedit.utilities.encode64 // Function: svgedit.utilities.encode64
// Converts a string to base64 // Converts a string to base64
@ -158,32 +160,33 @@ svgedit.utilities.decode64 = function(input) {
// Currently not being used, so commented out for now // Currently not being used, so commented out for now
// based on http://phpjs.org/functions/utf8_encode:577 // based on http://phpjs.org/functions/utf8_encode:577
// codedread:does not seem to work with webkit-based browsers on OSX // codedread:does not seem to work with webkit-based browsers on OSX
// 'encodeUTF8': function(input) { // 'encodeUTF8': function(input) {
// //return unescape(encodeURIComponent(input)); //may or may not work // //return unescape(encodeURIComponent(input)); //may or may not work
// var output = ''; // var output = '';
// for (var n = 0; n < input.length; n++){ // for (var n = 0; n < input.length; n++){
// var c = input.charCodeAt(n); // var c = input.charCodeAt(n);
// if (c < 128) { // if (c < 128) {
// output += input[n]; // output += input[n];
// } // }
// else if (c > 127) { // else if (c > 127) {
// if (c < 2048){ // if (c < 2048){
// output += String.fromCharCode((c >> 6) | 192); // output += String.fromCharCode((c >> 6) | 192);
// } // }
// else { // else {
// output += String.fromCharCode((c >> 12) | 224) + String.fromCharCode((c >> 6) & 63 | 128); // output += String.fromCharCode((c >> 12) | 224) + String.fromCharCode((c >> 6) & 63 | 128);
// } // }
// output += String.fromCharCode((c & 63) | 128); // output += String.fromCharCode((c & 63) | 128);
// } // }
// } // }
// return output; // return output;
// }, // },
// Function: svgedit.utilities.convertToXMLReferences // Function: svgedit.utilities.convertToXMLReferences
// Converts a string to use XML references // Converts a string to use XML references
svgedit.utilities.convertToXMLReferences = function(input) { svgedit.utilities.convertToXMLReferences = function(input) {
var output = ''; var n,
for (var n = 0; n < input.length; n++){ output = '';
for (n = 0; n < input.length; n++){
var c = input.charCodeAt(n); var c = input.charCodeAt(n);
if (c < 128) { if (c < 128) {
output += input[n]; output += input[n];
@ -202,18 +205,22 @@ svgedit.utilities.text2xml = function(sXML) {
sXML = sXML.replace(/<(\/?)svg:/g, '<$1').replace('xmlns:svg', 'xmlns'); sXML = sXML.replace(/<(\/?)svg:/g, '<$1').replace('xmlns:svg', 'xmlns');
} }
var out; var out, dXML;
try{ try{
var dXML = (window.DOMParser)?new DOMParser():new ActiveXObject('Microsoft.XMLDOM'); dXML = (window.DOMParser)?new DOMParser():new ActiveXObject('Microsoft.XMLDOM');
dXML.async = false; dXML.async = false;
} catch(e){ } catch(e){
throw new Error('XML Parser could not be instantiated'); throw new Error('XML Parser could not be instantiated');
} }
try{ try{
if(dXML.loadXML) out = (dXML.loadXML(sXML)) ? dXML : false; if (dXML.loadXML) {
else out = dXML.parseFromString(sXML, 'text/xml'); out = (dXML.loadXML(sXML)) ? dXML : false;
}
else {
out = dXML.parseFromString(sXML, 'text/xml');
}
} }
catch(e){ throw new Error('Error parsing XML string'); } catch(e2){ throw new Error('Error parsing XML string'); }
return out; return out;
}; };
@ -286,10 +293,10 @@ svgedit.utilities.getUrlFromAttr = function(attrVal) {
return attrVal.substring(5, attrVal.indexOf('"',6)); return attrVal.substring(5, attrVal.indexOf('"',6));
} }
// url('#somegrad') // url('#somegrad')
else if (attrVal.indexOf("url('") === 0) { if (attrVal.indexOf("url('") === 0) {
return attrVal.substring(5, attrVal.indexOf("'",6)); return attrVal.substring(5, attrVal.indexOf("'",6));
} }
else if (attrVal.indexOf("url(") === 0) { if (attrVal.indexOf("url(") === 0) {
return attrVal.substring(4, attrVal.indexOf(')')); return attrVal.substring(4, attrVal.indexOf(')'));
} }
} }
@ -349,10 +356,11 @@ svgedit.utilities.getPathBBox = function(path) {
var start = seglist.getItem(0); var start = seglist.getItem(0);
var P0 = [start.x, start.y]; var P0 = [start.x, start.y];
for(var i=0; i < tot; i++) { var i;
for (i = 0; i < tot; i++) {
var seg = seglist.getItem(i); var seg = seglist.getItem(i);
if(typeof seg.x == 'undefined') continue; if(typeof seg.x == 'undefined') {continue;}
// Add actual points to limits // Add actual points to limits
bounds[0].push(P0[0]); bounds[0].push(P0[0]);
@ -363,7 +371,8 @@ svgedit.utilities.getPathBBox = function(path) {
P2 = [seg.x2, seg.y2], P2 = [seg.x2, seg.y2],
P3 = [seg.x, seg.y]; P3 = [seg.x, seg.y];
for(var j=0; j < 2; j++) { var j;
for (j = 0; j < 2; j++) {
var calc = function(t) { var calc = function(t) {
return Math.pow(1-t,3) * P0[j] return Math.pow(1-t,3) * P0[j]
@ -376,22 +385,22 @@ svgedit.utilities.getPathBBox = function(path) {
var a = -3 * P0[j] + 9 * P1[j] - 9 * P2[j] + 3 * P3[j]; var a = -3 * P0[j] + 9 * P1[j] - 9 * P2[j] + 3 * P3[j];
var c = 3 * P1[j] - 3 * P0[j]; var c = 3 * P1[j] - 3 * P0[j];
if(a == 0) { if (a == 0) {
if(b == 0) { if (b == 0) {
continue; continue;
} }
var t = -c / b; var t = -c / b;
if(0 < t && t < 1) { if (0 < t && t < 1) {
bounds[j].push(calc(t)); bounds[j].push(calc(t));
} }
continue; continue;
} }
var b2ac = Math.pow(b,2) - 4 * c * a; var b2ac = Math.pow(b,2) - 4 * c * a;
if(b2ac < 0) continue; if (b2ac < 0) {continue;}
var t1 = (-b + Math.sqrt(b2ac))/(2 * a); var t1 = (-b + Math.sqrt(b2ac))/(2 * a);
if(0 < t1 && t1 < 1) bounds[j].push(calc(t1)); if (0 < t1 && t1 < 1) {bounds[j].push(calc(t1));}
var t2 = (-b - Math.sqrt(b2ac))/(2 * a); var t2 = (-b - Math.sqrt(b2ac))/(2 * a);
if(0 < t2 && t2 < 1) bounds[j].push(calc(t2)); if (0 < t2 && t2 < 1) {bounds[j].push(calc(t2));}
} }
P0 = P3; P0 = P3;
} else { } else {
@ -426,10 +435,10 @@ function groupBBFix(selected) {
} }
var ref = $.data(selected, 'ref'); var ref = $.data(selected, 'ref');
var matched = null; var matched = null;
var ret; var ret, copy;
if(ref) { if(ref) {
var copy = $(ref).children().clone().attr('visibility', 'hidden'); copy = $(ref).children().clone().attr('visibility', 'hidden');
$(svgroot_).append(copy); $(svgroot_).append(copy);
matched = copy.filter('line, path'); matched = copy.filter('line, path');
} else { } else {
@ -446,7 +455,7 @@ function groupBBFix(selected) {
}); });
if(issue) { if(issue) {
var elems = ref ? copy : $(selected).children(); var elems = ref ? copy : $(selected).children();
ret = getStrokedBBox(elems); ret = getStrokedBBox(elems); // getStrokedBBox defined in svgcanvas
} else { } else {
ret = selected.getBBox(); ret = selected.getBBox();
} }
@ -467,7 +476,7 @@ function groupBBFix(selected) {
// elem - Optional DOM element to get the BBox for // elem - Optional DOM element to get the BBox for
svgedit.utilities.getBBox = function(elem) { svgedit.utilities.getBBox = function(elem) {
var selected = elem || editorContext_.geSelectedElements()[0]; var selected = elem || editorContext_.geSelectedElements()[0];
if (elem.nodeType != 1) return null; if (elem.nodeType != 1) {return null;}
var ret = null; var ret = null;
var elname = selected.nodeName; var elname = selected.nodeName;
@ -485,7 +494,7 @@ svgedit.utilities.getBBox = function(elem) {
if(!svgedit.browser.supportsPathBBox()) { if(!svgedit.browser.supportsPathBBox()) {
ret = svgedit.utilities.getPathBBox(selected); ret = svgedit.utilities.getPathBBox(selected);
} else { } else {
try { ret = selected.getBBox();} catch(e){} try { ret = selected.getBBox();} catch(e2){}
} }
break; break;
case 'g': case 'g':
@ -498,7 +507,7 @@ svgedit.utilities.getBBox = function(elem) {
ret = groupBBFix(selected, true); ret = groupBBFix(selected, true);
} }
if(elname === 'use' || ( elname === 'foreignObject' && svgedit.browser.isWebkit() ) ) { if(elname === 'use' || ( elname === 'foreignObject' && svgedit.browser.isWebkit() ) ) {
if(!ret) ret = selected.getBBox(); if(!ret) {ret = selected.getBBox();}
// This is resolved in later versions of webkit, perhaps we should // This is resolved in later versions of webkit, perhaps we should
// have a featured detection for correct 'use' behavior? // have a featured detection for correct 'use' behavior?
// —————————— // ——————————
@ -512,13 +521,13 @@ svgedit.utilities.getBBox = function(elem) {
//} //}
} else if(~visElems_arr.indexOf(elname)) { } else if(~visElems_arr.indexOf(elname)) {
try { ret = selected.getBBox();} try { ret = selected.getBBox();}
catch(e) { catch(e3) {
// Check if element is child of a foreignObject // Check if element is child of a foreignObject
var fo = $(selected).closest('foreignObject'); var fo = $(selected).closest('foreignObject');
if(fo.length) { if(fo.length) {
try { try {
ret = fo[0].getBBox(); ret = fo[0].getBBox();
} catch(e) { } catch(e4) {
ret = null; ret = null;
} }
} else { } else {
@ -548,9 +557,10 @@ svgedit.utilities.getRotationAngle = function(elem, to_rad) {
var selected = elem || editorContext_.getSelectedElements()[0]; var selected = elem || editorContext_.getSelectedElements()[0];
// find the rotation transform (if any) and set it // find the rotation transform (if any) and set it
var tlist = svgedit.transformlist.getTransformList(selected); var tlist = svgedit.transformlist.getTransformList(selected);
if(!tlist) return 0; // <svg> elements have no tlist if(!tlist) {return 0;} // <svg> elements have no tlist
var N = tlist.numberOfItems; var N = tlist.numberOfItems;
for (var i = 0; i < N; ++i) { var i;
for (i = 0; i < N; ++i) {
var xform = tlist.getItem(i); var xform = tlist.getItem(i);
if (xform.type == 4) { if (xform.type == 4) {
return to_rad ? xform.angle * Math.PI / 180.0 : xform.angle; return to_rad ? xform.angle * Math.PI / 180.0 : xform.angle;
@ -604,12 +614,13 @@ if (svgedit.browser.supportsSelectors()) {
// suspendLength - Optional integer of milliseconds to suspend redraw // suspendLength - Optional integer of milliseconds to suspend redraw
// unitCheck - Boolean to indicate the need to use svgedit.units.setUnitAttr // unitCheck - Boolean to indicate the need to use svgedit.units.setUnitAttr
svgedit.utilities.assignAttributes = function(node, attrs, suspendLength, unitCheck) { svgedit.utilities.assignAttributes = function(node, attrs, suspendLength, unitCheck) {
if(!suspendLength) suspendLength = 0; if(!suspendLength) {suspendLength = 0;}
// Opera has a problem with suspendRedraw() apparently // Opera has a problem with suspendRedraw() apparently
var handle = null; var handle = null;
if (!svgedit.browser.isOpera()) svgroot_.suspendRedraw(suspendLength); if (!svgedit.browser.isOpera()) {svgroot_.suspendRedraw(suspendLength);}
for (var i in attrs) { var i;
for (i in attrs) {
var ns = (i.substr(0,4) === 'xml:' ? NS.XML : var ns = (i.substr(0,4) === 'xml:' ? NS.XML :
i.substr(0,6) === 'xlink:' ? NS.XLINK : null); i.substr(0,6) === 'xlink:' ? NS.XLINK : null);
@ -621,7 +632,7 @@ svgedit.utilities.assignAttributes = function(node, attrs, suspendLength, unitCh
svgedit.units.setUnitAttr(node, i, attrs[i]); svgedit.units.setUnitAttr(node, i, attrs[i]);
} }
} }
if (!svgedit.browser.isOpera()) svgroot_.unsuspendRedraw(handle); if (!svgedit.browser.isOpera()) {svgroot_.unsuspendRedraw(handle);}
}; };
// Function: cleanupElement // Function: cleanupElement
@ -645,7 +656,8 @@ svgedit.utilities.cleanupElement = function(element) {
'ry':0 'ry':0
}; };
for(var attr in defaults) { var attr;
for (attr in defaults) {
var val = defaults[attr]; var val = defaults[attr];
if(element.getAttribute(attr) == val) { if(element.getAttribute(attr) == val) {
element.removeAttribute(attr); element.removeAttribute(attr);
@ -668,4 +680,4 @@ svgedit.utilities.snapToGrid = function(value) {
return value; return value;
}; };
})(); }());

View File

@ -1,7 +1,8 @@
// http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript/ // http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript/
function touchHandler(event) { function touchHandler(event) {'use strict';
var touches = event.changedTouches, var simulatedEvent,
touches = event.changedTouches,
first = touches[0], first = touches[0],
type = ""; type = "";
switch (event.type) { switch (event.type) {
@ -15,7 +16,7 @@ function touchHandler(event) {
// screenX, screenY, clientX, clientY, ctrlKey, // screenX, screenY, clientX, clientY, ctrlKey,
// altKey, shiftKey, metaKey, button, relatedTarget); // altKey, shiftKey, metaKey, button, relatedTarget);
var simulatedEvent = document.createEvent("MouseEvent"); simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent(type, true, true, window, 1, simulatedEvent.initMouseEvent(type, true, true, window, 1,
first.screenX, first.screenY, first.screenX, first.screenY,
first.clientX, first.clientY, false, first.clientX, first.clientY, false,

View File

@ -1,3 +1,5 @@
/*globals $, svgedit*/
/*jslint vars: true, eqeq: true*/
/** /**
* Package: svgedit.units * Package: svgedit.units
* *
@ -10,7 +12,7 @@
// Dependencies: // Dependencies:
// 1) jQuery // 1) jQuery
(function() { (function() {'use strict';
if (!svgedit.units) { if (!svgedit.units) {
svgedit.units = {}; svgedit.units = {};
@ -133,7 +135,7 @@ svgedit.units.convertUnit = function(val, unit) {
// attr - String with the name of the attribute associated with the value // attr - String with the name of the attribute associated with the value
// val - String with the attribute value to convert // val - String with the attribute value to convert
svgedit.units.setUnitAttr = function(elem, attr, val) { svgedit.units.setUnitAttr = function(elem, attr, val) {
if (!isNaN(val)) { // if (!isNaN(val)) {
// New value is a number, so check currently used unit // New value is a number, so check currently used unit
// var old_val = elem.getAttribute(attr); // var old_val = elem.getAttribute(attr);
@ -163,7 +165,7 @@ svgedit.units.setUnitAttr = function(elem, attr, val) {
// //
// val += unit; // val += unit;
// } // }
} // }
elem.setAttribute(attr, val); elem.setAttribute(attr, val);
}; };
@ -187,18 +189,20 @@ svgedit.units.convertAttrs = function(element) {
var elName = element.tagName; var elName = element.tagName;
var unit = elementContainer_.getBaseUnit(); var unit = elementContainer_.getBaseUnit();
var attrs = attrsToConvert[elName]; var attrs = attrsToConvert[elName];
if (!attrs) return; if (!attrs) {return;}
var len = attrs.length; var len = attrs.length;
for (var i = 0; i < len; i++) { var i;
for (i = 0; i < len; i++) {
var attr = attrs[i]; var attr = attrs[i];
var cur = element.getAttribute(attr); var cur = element.getAttribute(attr);
if (cur) { if (cur) {
if (!isNaN(cur)) { if (!isNaN(cur)) {
element.setAttribute(attr, (cur / typeMap_[unit]) + unit); element.setAttribute(attr, (cur / typeMap_[unit]) + unit);
} else {
// Convert existing?
} }
// else {
// Convert existing?
// }
} }
} }
}; };
@ -212,11 +216,11 @@ svgedit.units.convertAttrs = function(element) {
// val - String with the attribute value to convert // val - String with the attribute value to convert
svgedit.units.convertToNum = function(attr, val) { svgedit.units.convertToNum = function(attr, val) {
// Return a number if that's what it already is // Return a number if that's what it already is
if (!isNaN(val)) return val-0; if (!isNaN(val)) {return val-0;}
var num;
if (val.substr(-1) === '%') { if (val.substr(-1) === '%') {
// Deal with percentage, depends on attribute // Deal with percentage, depends on attribute
var num = val.substr(0, val.length-1)/100; num = val.substr(0, val.length-1)/100;
var width = elementContainer_.getWidth(); var width = elementContainer_.getWidth();
var height = elementContainer_.getHeight(); var height = elementContainer_.getHeight();
@ -229,7 +233,7 @@ svgedit.units.convertToNum = function(attr, val) {
return num * Math.sqrt((width*width) + (height*height))/Math.sqrt(2); return num * Math.sqrt((width*width) + (height*height))/Math.sqrt(2);
} }
var unit = val.substr(-2); var unit = val.substr(-2);
var num = val.substr(0, val.length-2); num = val.substr(0, val.length-2);
// Note that this multiplication turns the string into a number // Note that this multiplication turns the string into a number
return num * typeMap_[unit]; return num * typeMap_[unit];
}; };
@ -250,9 +254,9 @@ svgedit.units.isValidUnit = function(attr, val, selectedElement) {
// Not a number, check if it has a valid unit // Not a number, check if it has a valid unit
val = val.toLowerCase(); val = val.toLowerCase();
$.each(typeMap_, function(unit) { $.each(typeMap_, function(unit) {
if (valid) return; if (valid) {return;}
var re = new RegExp('^-?[\\d\\.]+' + unit + '$'); var re = new RegExp('^-?[\\d\\.]+' + unit + '$');
if (re.test(val)) valid = true; if (re.test(val)) {valid = true;}
}); });
} }
} else if (attr == 'id') { } else if (attr == 'id') {
@ -269,11 +273,10 @@ svgedit.units.isValidUnit = function(attr, val, selectedElement) {
result = (elem == null || elem === selectedElement); result = (elem == null || elem === selectedElement);
} catch(e) {} } catch(e) {}
return result; return result;
} else {
valid = true;
} }
valid = true;
return valid; return valid;
}; };
})(); }());