This is a bit of a vague notion which I have been running over in my head, and which I am very curious if there is an elegant method of solving. Perhaps it should be taken as a thought experiment.
Imagine you have an XML schema with a corresponding XSL transform, which renders the XML as SVG in the browser. The XSL generates SVG with appropriate Javascript handlers that, ultimately, implement editing-like functionality such that properties of the objects or their locations on the SVG canvas can be edited by the user. For instance, an element can be dragged from one location to another.
Now, this isn't particularly difficult - the drag/drop example is simply a matter of changing the (x,y) coordinates of the SVG object, or a resize operation would be a simple matter of changing its width or height.
But is there an elegant way to have Javascript work on the DOM of the source XML document instead of the rendered SVG? Why, you ask? Well, imagine you have very complex XSL transforms, where the modification of one property results in complex changes to the SVG. You want to maintain simplicity in your Javascript code, but also a simple way to persist the modified XML back to the server.
Some possibilities of how this may function:
After modification of the source DOM, simply re-run the XSL transform and replace the original. Downside: brute force, potentially expensive operation.
Create id/class naming conventions in the source and target XML/SVG so elements can be related back to each other, and do an XSL transform on only a subset of the new DOM. In other words, modify temporary DOM, apply XSL to it, remove changed elements from SVG, and insert the new one. Downside: May not be possible to apply XSL to temporary in-browser DOMs(?). Also, perhaps a bit convoluted or ugly to maintain.
I think that it may be possible to come up with a framework that handles the second scenario, but the challenge would be making it lightweight and not heavily tied to the actual XML schema. Any ideas or other possibilities? Or is there maybe an existing method of doing this which I'm not aware of?
UPDATE: To clarify, as I mentioned in a comment below, this aids in separating the draw code from the edit code. For a more concrete example of how this is useful, imagine an element which determines how it is drawn dependent on the value of a property of an adjacent element. It's better to condense that logic directly in the draw code instead of also duplicating it in the edit code.
We have done this in our in-browser XML editor Xopus. You can see an example here.
We load the XML source document, an XML Schema and an XSLT that outputs HTML+SVG. Internally we rewrite your XSLT into XSLT' which will allow us to track the output HTML+SVG back to the original XML that was the context in the XSL to output that HTML or SVG node. This is the framework you're referring to.
To facilitate editing we position a cursor over your XSLT output and update the XML DOM when you type or insert elements. After each change we will rerun the XSLT. For performance reasons we will compare the XSLT output with the previous output and apply the changes using HTML DOM operations to the WYSIWYG view.
We diff the two XSLT outputs using another XSLT. We can do so because we have modified the original XSLT (resulting in XSLT') so that is will output unique and persistant IDs for each output node. So all new nodes will have new IDs and missing IDs are removed nodes.
XSLT' is the rewritten version of the original XSLT you provide. It is still XSLT, but we've added a few things to it so it outputs IDs for all output nodes (we do so with yet another XSLT). Other than that it is functionally equivalent to your original XSLT.
Maybe use can AJAX: Instead of editing the document locally, send editing commands for the original XML to the server which transforms again and then sends the new SVG back.
The main problem here will be what happens when you update the SVG element on the current page. Will drag'n'drop still feel smooth? If not, then you might have to resort to some mix of the two methods: Drag the SVG node using JavaScript and when the user drops the node, send an update to the server for a new SVG.
You will want to avoid trying to synchronize updates in XML and the local SVG (which would mean to replicate part of the XSLT in JavaScript -> stay on one world, don't mix).
Related
I'm developing an application where users draw stuff on SVG dynamically with the use of RaphaelJS. JQuery & PHP are also involved. The stuff being drawn is pretty lightweight, just some paths and lines. I have noticed that the "drawings" can be easily accessed and stored by simply calling $('svg').html() and this made me wonder whether it's possible and feasible to build a mechanism that allows the users to store their drawings using web storage, then load them for further editing. The challenge, as I see it, is loading that saved content into a new SVG and making Raphael work with it. JQuery html() obviousy won't work and appending every single path and line with createElementNS is pretty cumbersome. Is there any way, a library perhaps, that can take html() from one SVG and simply insert it into another?
First of, I'd like to mention that I'm aware of XSLT and XML DOM. I'm learning XML and know the basics (proper syntax, some DOM, etc.). For efficiency purposes, I need to figure out whether to begin learning XSLT in detail first or DOM.
Here is what I'm trying to do...
A table comparing home vs. competitor:
first column holding names of different features
second column of a static company
last column of a competitor that can be chosen from a drop down.
Would it be best to draw this table using XSLT or would it be better to do it using javascript (this approach?
I know both are easily done, but I need to be able to make a single column visible or invisible so that only one competitor column shows up, which will make it easier for me?
Thank you!
EDIT: I have this pretty much done using data islands/tabular data control (CSV files), but since it's only IE compatible, I thought I'd learn some XML instead.
Definition of XSLT:
XSLT (Extensible Stylesheet Language Transformations) is a declarative, XML-based language used for the transformation of XML documents.
Its designed to transform XML from one form to an other, i would use it.
Is there a way to convert an html snippet to svg?
for example:
<b>This is bolded</b>
I want to make an svg document with the html snippet above... is this possible?
I would suggest that you should edit your question to describe the actual use case and goal you are trying to achieve, as directly implementing what you seem to ask for is hard (see below). Some combination of SVG-in-XHTML or XHTML-in-SVG (for example, this) are far more likely to give you want you want.
We can only help you achieve your goals if you tell us your goals instead of asking us help you to solve a particular implementation you thought of to achieve them.
As I mentioned above, There is not an easy way to do what you suggest. In particular, HTML has automatic line wrapping, floating and general positioning concepts, as well as explicit z-indexing, that are not present in SVG.
The following madness would mostly work, however:
Create an iframe or div on your page and set the HTML to your snippet.
Loop through every element and convert wrap a margin:0;padding:0;border:0 span around every word in the text.
Loop through every element (including your created spans) and calculate the absolute position on the page. (jQuery has a method to do this, or you could use the combination of offsetLeft/offsetTop and offsetParent to walk up the positioned tree and calculate it yourself.)
Calculate the equivalent z-index for each element by walking up the tree and using the getComputedStyle() and creating a chain of the local z-index.
For each of these elements, create the equivalent element in SVG with absolute positioning.
Re-sort the SVG elements you created by the hierarchy of z-indices.
Check this html to SVG demo, (using HiQPDF, a commercial product). You can find there code samples for C# and VB.NET. You can convert an URL or a HTML code snippet as you requested.
There are JS libs, that convert html to canvas:
http://html2canvas.hertzen.com/
But until now, I did not found something similar for svg.
So for example if we have a flash video already buffered and playing, or an autocomplete active with input, focus, and a dropdown visible (and maybe even loading something) but only have HTML of the full document and a copy of the HTML earlier, how can we merge them into the live DOM without the user's state being interrupted?
Ordinarily I'd just program a specific fix, specifying the right area to change given it's div name, manually but that is not a known variable for the situation at hand (I'm programming a Pythonic MVC framework with AJAX).
I want to change the smallest amount of nodes, and probably the deepest nodes that I can get away with.
It's ok to require ID's for some of the nodes (e.g: flash or autocomplete widget) but not possible to expect this for all nodes - so in some situations perhaps node position and types will be available to compare documents.
I understand this will not be a complete solution but in some cases it will be all that is required.
Is it possible to use Raphael to manipulate an embedded SVG image? I used Raphael in the past to draw shapes, but haven't actually seen it being used to manipulate an existing SVG image. If not, is there anything else that allows me to easily change colours, add events, etc. to polygons of an embedded SVG image?
From my experience reading the Raphael.js source, I have to agree with previous posts. The only way I can think of to replace or modify the SVG is by replacing/modifying the markup/DOM itself.
All I want to add in my answer is a short, general explanation of why this is so. Raphael is designed as an SVG/VML generator. That is, Raphael makes JavaScript objects and appends their corresponding SVG/VML markup to the DOM as they are made. The objects have lots of additional properties that make them work within the Raphael framework.
It may be possible to write a plugin that can construct a Raphael object around an SVG element by reading its properties, but, I suspect that such an object may not have all the information it needs to coexist with the other Raphael objects. Certainly, no such parsing/reconstruction functionality currently exists.
Funny, yesterday I found the glitchsvgicons page doing that.
Although in a very primitive way, just using a regex replace of parts.
It can be hint, though: apparently you can use good old search/replace of text parts on SVG icons. But it is more prone to issues than using a real Dom tree...