diff --git a/editor/embedapi.html b/editor/embedapi.html index 1d9ff98e..d6fd32fc 100644 --- a/editor/embedapi.html +++ b/editor/embedapi.html @@ -1,19 +1,23 @@ - - + + + Embed API - - - - + + - - + + + +
- + diff --git a/editor/embedapi.js b/editor/embedapi.js index f16e3dd0..120ccbe5 100644 --- a/editor/embedapi.js +++ b/editor/embedapi.js @@ -1,42 +1,10 @@ /* -function embedded_svg_edit(frame){ - //initialize communication - this.frame = frame; - this.stack = []; //callback stack - - var editapi = this; - - window.addEventListener("message", function(e){ - if(e.data.substr(0,5) == "ERROR"){ - editapi.stack.splice(0,1)[0](e.data,"error") - }else{ - editapi.stack.splice(0,1)[0](e.data) - } - }, false) -} - -embedded_svg_edit.prototype.call = function(code, callback){ - this.stack.push(callback); - this.frame.contentWindow.postMessage(code,"*"); -} - -embedded_svg_edit.prototype.getSvgString = function(callback){ - this.call("svgCanvas.getSvgString()", callback) -} - -embedded_svg_edit.prototype.setSvgString = function(svg){ - this.call("svgCanvas.setSvgString('"+svg.replace(/'/g, "\\'")+"')"); -} -*/ - - -/* Embedded SVG-edit API General usage: - Have an iframe somewhere pointing to a version of svg-edit > r1000 - Initialize the magic with: -var svgCanvas = new embedded_svg_edit(window.frames['svgedit']); +var svgCanvas = new EmbeddedSVGEdit(window.frames['svgedit']); - Pass functions in this format: svgCanvas.setSvgString("string") - Or if a callback is needed: @@ -52,15 +20,33 @@ Everything is done with the same API as the real svg-edit, and all documentation is unchanged. The only difference is when handling returns, the callback notation is used instead. -var blah = new embedded_svg_edit(window.frames['svgedit']); +var blah = new EmbeddedSVGEdit(window.frames['svgedit']); blah.clearSelection("woot","blah",1337,[1,2,3,4,5,"moo"],-42,{a: "tree",b:6, c: 9})(function(){console.log("GET DATA",arguments)}) */ -function embedded_svg_edit(frame){ - //initialize communication +(function () {'use strict'; + +var cbid = 0; + +function getCallbackSetter (d) { + return function(){ + var t = this, // new callback + args = [].slice.call(arguments), + cbid = t.send(d, args, function(){}); // the callback (currently it's nothing, but will be set later) + + return function(newcallback){ + t.callbacks[cbid] = newcallback; // set callback + }; + }; +} + +function EmbeddedSVGEdit(frame){ + if (!(this instanceof EmbeddedSVGEdit)) { // Allow invocation without "new" keyword + return new EmbeddedSVGEdit(frame); + } + // initialize communication this.frame = frame; - //this.stack = [] //callback stack - this.callbacks = {}; //successor to stack + this.callbacks = {}; // successor to stack //List of functions extracted with this: //Run in firebug on http://svg-edit.googlecode.com/svn/trunk/docs/files/svgcanvas-js.html @@ -72,7 +58,9 @@ function embedded_svg_edit(frame){ //Newer, well, it extracts things that aren't documented as well. All functions accessible through the normal thingy can now be accessed though the API //var l=[];for(var i in svgCanvas){if(typeof svgCanvas[i] == "function"){l.push(i)}}; //run in svgedit itself - var functions = ["updateElementFromJson", "embedImage", "fixOperaXML", "clearSelection", "addToSelection", + var i, + t = this, + functions = ["updateElementFromJson", "embedImage", "fixOperaXML", "clearSelection", "addToSelection", "removeFromSelection", "addNodeToSelection", "open", "save", "getSvgString", "setSvgString", "createLayer", "deleteCurrentLayer", "getCurrentDrawing", "setCurrentLayer", "renameCurrentLayer", "setCurrentLayerPosition", "setLayerVisibility", "moveSelectedToLayer", "clear", "clearPath", "getNodePoint", "clonePathNode", "deletePathNode", @@ -88,51 +76,41 @@ function embedded_svg_edit(frame){ "getNextRedoCommandText", "undo", "redo", "cloneSelectedElements", "alignSelectedElements", "getZoom", "getVersion", "setIconSize", "setLang", "setCustomHandlers"]; - //TODO: rewrite the following, it's pretty scary. - for(var i = 0; i < functions.length; i++){ - this[functions[i]] = (function(d){ - return function(){ - var t = this; //new callback - for(var g = 0, args = []; g < arguments.length; g++){ - args.push(arguments[g]); - } - var cbid = t.send(d, args, function(){}); //the callback (currently it's nothing, but will be set later - - return function(newcallback){ - t.callbacks[cbid] = newcallback; //set callback - }; - }; - })(functions[i]); + // TODO: rewrite the following, it's pretty scary. + for(i = 0; i < functions.length; i++){ + this[functions[i]] = getCallbackSetter(functions[i]); } - //TODO: use AddEvent for Trident browsers, currently they dont support SVG, but they do support onmessage - var t = this; + + // Older IE may need a polyfill for addEventListener, but so it would for SVG window.addEventListener("message", function(e){ - if(e.data.substr(0,4) == "SVGe"){ //because svg-edit is too longish - var data = e.data.substr(4); - var cbid = data.substr(0, data.indexOf(";")); - if(t.callbacks[cbid]){ - if(data.substr(cbid.length + 1,6) != "error:"){ - t.callbacks[cbid](eval("("+data.substr(cbid.length+1)+")")); - }else{ - t.callbacks[cbid](data, "error"); - } + if (!e.data || typeof e.data !== "object" || e.data.namespace !== "svg-edit") { + return; + } + var data = e.data.result || e.data.error, + cbid = e.data.id; + if(t.callbacks[cbid]){ + if(e.data.result){ + t.callbacks[cbid](data); + }else{ + t.callbacks[cbid](data, "error"); } } - //this.stack.shift()[0](e.data,e.data.substr(0,5) == "ERROR"?'error':null) //replace with shift }, false); } -embedded_svg_edit.prototype.send = function(name, args, callback){ - var cbid = Math.floor(Math.random()*31776352877+993577).toString(); - //this.stack.push(callback); - this.callbacks[cbid] = callback; - for(var argstr = [], i = 0; i < args.length; i++){ - argstr.push(JSON.stringify(args[i])); - } +EmbeddedSVGEdit.prototype.send = function(name, args, callback){ var t = this; - setTimeout(function(){//delay for the callback to be set in case its synchronous - t.frame.contentWindow.postMessage(cbid+";svgCanvas['"+name+"']("+argstr.join(",")+")","*"); + cbid++; + + this.callbacks[cbid] = callback; + setTimeout(function(){ // delay for the callback to be set in case its synchronous + // Todo: Handle non-JSON arguments and return values (undefined, nonfinite numbers, functions, and built-in objects like Date, RegExp), etc.? + t.frame.contentWindow.postMessage({namespace: "svgCanvas", id: cbid, name: name, args: args}, '*'); }, 0); return cbid; - //this.stack.shift()("svgCanvas['"+name+"']("+argstr.join(",")+")") }; + +window.embedded_svg_edit = EmbeddedSVGEdit; // Export old, deprecated API +window.EmbeddedSVGEdit = EmbeddedSVGEdit; // Follows common JS convention of CamelCase and, as enforced in JSLint, of initial caps for constructors + +}()); diff --git a/editor/extensions/ext-imagelib.js b/editor/extensions/ext-imagelib.js index 9b2d3d29..5e9c27b3 100644 --- a/editor/extensions/ext-imagelib.js +++ b/editor/extensions/ext-imagelib.js @@ -64,7 +64,7 @@ svgEditor.addExtension("imagelib", function() { // Receive postMessage data var response = evt.data; - if(!response) { + if(!response || typeof response !== "string") { // Todo: Should namespace postMessage API for this extension and filter out here // Do nothing return; } diff --git a/editor/svg-editor.js b/editor/svg-editor.js index 1466bfbd..e13cd2e5 100644 --- a/editor/svg-editor.js +++ b/editor/svg-editor.js @@ -4571,11 +4571,16 @@ // Callback handler for embedapi.js try { window.addEventListener('message', function(e) { - var cbid = parseInt(e.data.substr(0, e.data.indexOf(';')), 10); + if (!e.data || typeof e.data !== 'object' || e.data.namespace !== 'svgCanvas') { + return; + } + var cbid = e.data.id, + name = e.data.name, + args = e.data.args; try { - e.source.postMessage('SVGe'+cbid+';'+JSON.stringify(eval(e.data)), '*'); + e.source.postMessage({namespace: 'svg-edit', id: cbid, result: svgCanvas[name](args)}, '*'); } catch(err) { - e.source.postMessage('SVGe'+cbid+';error:'+err.message, '*'); + e.source.postMessage({namespace: 'svg-edit', id: cbid, error: err.message}, '*'); } }, false); } catch(err) {