svg is an xml based graphics and you can add JavaScripts to it. I have tried to access to the script functions defined in a svg. The script in my svg is something like this:
<svg ... onload="RunScript(evt);"...>
<script type="text/javascript">
...
function RunScript(loadEvent) {
// Get object in my html by id
var objElement = top.document.getElementById('objid1');
if (objElement)
{
// Extend object tag object's methods
objElement.SVGsetDimension = setDimension;
...
}
function setDimention(w, h) {...}
In my main html file, the svg is embedded in an object tag like this:
<object id="objid1" data="mygrahic.svg" ... >
<a href="#" onclick="document.getElementById('objid1').SVGsetDimention(10, 10);
return false;"
...>Set new dimention</a>...
This one works fine. However if the svg xml file is referenced by a full URL (on another site) like this:
<object id="objid1" data="http://www.artlibrary.net/myaccount/mygrahic.svg" ... >
the codes do not work any more. It looks like that I cannot attach the method defined in my svg script to a method in my main html object tag element, or the top or document is not available in this case, or getElementById(..) just cannot find my object element in my svg script. Is there any way I can do in the svg xml script to find my html element?
Not sure if this problem is caused by the different DOMs, and there is no way for my svg script codes to figure out another DOM's object or element. It would be nice if there is any solution.
I think the clue might be in 'on another site'. There are strict rules about when JavaScript programs from different sites are allowed to communicate with teach other. The embedded SVG is being treated the same way a document inside an iframe would.
So, what you're doing is, from the point of view of a browser, equivalent to the following:
<script>
function stealPassword() {
var passwordInput = document.querySelector('input[type="password"]');
var value = passwordInput.value; // My password!
sendPasswordToServerToStealMyMoney(value);
}
</script>
<iframe src=mybank.com onload=stealPassword()></iframe>
I think you'll understand why this isn't desirable. (There should probably be a warning or an exception in your error console, though.)
pdc has this one right. Browsers work hard to prevent cross site scripting attacks (XSS) and this is the result. You cannot execute scripts in a document loaded from another domain, or using another port or protocol. For more info you can see: http://en.wikipedia.org/wiki/Same_origin_policy
From my experiense;
Your Code is true ,so that run exactly.
My PC Windows 7,IE9,installed Adobe Viewer.
Both unless SVG Viewer,IE9 SVG drawed,but can't run SVG TAG Animation,
only can run Javascript Animation.
So,under Windows XP,IE8,installed Adobe SVG Viewer, Same result(run exactly).
Firefox SVG can't run(SVG ecmascript animation) exactly under my PC.
Related
Say you have this in your HTML:
<img src='example.svg' />
How would you access the contents ( ie. <rect>, <circle>, <ellipse>, etc.. ) of the example.svg via JavaScript?
It's not possible to get the DOM of a referenced svg from the img element.
If you use <object>, <embed> or <iframe> however then you can use .contentDocument (preferred) to get the referenced svg, or .getSVGDocument which may be more compatible with old svg plugins.
Here's an example showing how to get the DOM of a referenced svg.
I'm pretty sure this isn't possible. The external SVG is not part of the DOM in the way an inline SVG is, and I don't believe you can access the SVG DOM tree from the loading document.
What you can do is load the SVG as XML, using an AJAX request, and insert it into the DOM as an inline SVG you can then walk and manipulate. This D3 example demonstrates the technique. I think the d3.xml() function used here is more or less equivalent to jQuery's $.ajax() with dataType: "xml".
No, not possible but you can convert <img> to <svg> as mentioned HERE (same code available below) and you can access the nodes of svg in the DOM.
<script type="text/javascript">
$(document).ready(function() {
$('#img').each(function(){
var img = $(this);
var image_uri = img.attr('src');
$.get(image_uri, function(data) {
var svg = $(data).find('svg');
svg.removeAttr('xmlns:a');
img.replaceWith(svg);
}, 'xml');
});
});
</script>
<img id='img' src="my.svg" />
If you are using inlining of SVG into CSS url(data:...) or just using url(*.svg) background, you can embed them into DOM with svg-embed.
Support Chrome 11+, Safari 5+, FireFox 4+ and IE9+.
If you’re using a back end language that can go fetch the file and insert it, at least you can clean up the authoring experience. Like:
<?php echo file_get_contents("kiwi.svg"); ?>
A little PHP-specific thing here… it was demonstrated to me that file_get_contents() is the correct function here, not include() or include_once() as I have used before. Specifically because SVG sometimes is exported with that as the opening line, which will cause the PHP parser to choke on it.
(Information taken out of CSS-tricks)
I'm trying to load a parent page into an object tag, and whilst I can get an alert to show I've got the code, I cannot get it into the <object> Any clues?
var page=parent.document.documentElement.innerHTML;
alert(page);
document.getElementById('close_skin').style.visibility="visible";
document.getElementById('show_skin').style.visibility="visible";
document.getElementById('show_skin').setAttribute("data",page);
Assuming I can get the code to appear, how can I "toggle" to a different set of styles? The parent uses ".xxx_fixed" classes, but the code in the object needs to use the ".xxx_float" classes that are also in the template CSS at top of page. (When I did it in another PERL program, it was easy just to rename the tags in the <body> from "class='xxx_fixed' " to "class='xxx_float' " (Can't do that so easily with global javascript replace as that would also rename the classes at top of code as well!)
I have just tried adding some script to the top of the var page object - which MAY work if I can get the code to appear ...
+'document.getElementById(\'icon_outer\').setAttribute(\'class\', \'icon_outer_float\')'
If you're interested as to the "why", the "fixed" keep menu / top bar fixed in one place when viewed in full screen browser, but the 'float' makes everything move in unison within the <object> "window" allowing viewer to pan around the template page like a static magnifying glass;
.menu_back_float{position:relative;top:0px;background-color:#f5eca4;min-height:520px;height:auto}
.menu_back_fixed{position:relative;top:35px;background-color:#f5eca4;min-height:550px;height:auto}
To load the parent page into an <object> element, you have to specify the URL of the page. To get the code and place it in a alert box, you can use jQuery's $.get() method (as long as you load it via a proxy domain), like this:
HTML:
// I'm just using W3Schools just to save time
<object data="http://www.w3schools.com/" width="1500" height="1200">
<embed src="http://www.w3schools.com/" width="1500" height="1200"></embed>
Your browser does not support the object tag.
</object>
JavaScript:
window.jQuery.get("http://www.yourdomain.com/?url=www.w3schools.com", function(response) {
window.alert(response);
}
For the second part of your question, you can use jQuery to change the name of the class from .xxx_fixed to .xxx_float:
function main() {
$('object').removeClass('xxx_fixed').addClass('xxx_float');
}
$(document).ready(main);
Hopefully I have answered your question correctly and thouroughly, and if I haven't, feel free to let me know so I can edit this.
I have a function that modifies the contents of an SVG based on some values I calculate from the SVG file. Namely, it calculates the length of each path in the file. As such, the SVG file must be completely loaded before running the script to calculate this.
I have the script inside $("#logoSVG").load(function(), but this is never run, for some reason. I have also tried $(window).load(function(), and this runs, but before the SVG is loaded (because the amount of paths in the document still returns 0 at this point). Here is the full script:
<script>
$("#logoSVG").load(function(){
var path = document.getElementsByTagName('path');
var length;
var anim = document.getElementsByTagName('animate');
for(i = 0; i < path.length; i++){
length = path[i].getTotalLength().toString();
path[i].setAttribute('stroke-dasharray',length+','+length);
anim[i].setAttribute('values','-'+length+';0');
}
});
</script>
I know the script works because I've tested it in another document in which the SVG is written inline. In this case, I am loading it into an <object>:
<object id="logoSVG" data="imgs/logo.svg" type="image/svg+xml" style="display:block;">
<img src="imgs/fallback.png" width="100%" style="display:block;"/>
</object>
How can I get the script to not run until after the SVG is loaded?
NOTE: It's possible I may be completely wrong on this, and it actually is being called after loading. If that's the case however, for some reason none of the <path> elements are being detected. Why would this be? Is there something else I have to do to access these elements once they have been inserted into the page?
Did not realize there was a certain way to handle svg files loaded into an <object>. See here.
You're not using the correct document object for getElementsByTagName(), so you won't get the matches you expect. It works fine in the inline case because then there's only one document. When you use <object> you create a separate document with the referenced content. If you want to access the referenced document from a script in the top-level document just make sure to get the proper document object.
By using the contentDocument attribute on the embedding element (e.g object or iframe) you can get the right document object for the content.
I have some crazy app done almost 100% by manipulating the DOM and I find myself in the unfortunate position of changing something in it. As there are probably around 100 different scripts that do God knows what, I have no clue in which file should I look to make my changes. So, I want to ask, is there a way (using Firebug maybe or something similar) to know where a specific piece of html was generated? I'm a C developer, so I'm not very good at this, it drives me crazy.
Are all the elements added at the page load, or partially in the response to the user input? (clicking etc.)
for stuff added with the response to your actions, you can use Firebug's "Break On Next" button in the "Script" tab. To active BON you have to click it, or, in just-shipped Firebug 1.10.0a8, use keyboard shortcut ALT-CTRL-B (useful when you have event listeners bound to mouse movements). Then, when any piece of JS is going to be executed in reaction to your click etc., you will hit a breakpoint.
for stuff added at page load time, you may use the trick of extending the native functions (this might sound crazy - yeah it is, don't do it in production!) like appendChild, insertBefore, replaceChild. Just insert the appropriate code at the very top of your main HTML file, so all the code below will "see" the change.
Unfortunately, this does not work in Firefox due to a bug. But works in Opera and I guess in Chrome as well.
When you extend the native function, you can inject any code before really adding the node to the page. For instance, call console.log or create a breakpoint, to inspect the current page state. You can try playing with breakpoints to see the available variables properties inside those function to adjust what you push to console.log.
For this code:
<!doctype html>
<html>
<head>
<script type="text/javascript">
// this should work in Firefox but it does not -- https://bugzilla.mozilla.org/show_bug.cgi?id=618379
// works at least in Opera, probably Chrome too
Node.prototype._appendChild = Node.prototype.appendChild;
Node.prototype.appendChild = function(child) {
console.log("appending " + child + " to " + this);
return this._appendChild(child); // call the original function with the original parameters
}
// this works in Firefox
document._createElement = document.createElement;
document.createElement = function(tagName){
console.log("creating " + tagName);
return this._createElement(tagName);
}
</script>
</head>
<body>
<script type="text/javascript">
var p = document.createElement("p");
p.appendChild( document.createTextNode("abc"));
document.body.appendChild(p);
</script>
</body>
</html>
Opera outputs:
creating p appendChild.html:14
appending [object Text] to [object HTMLParagraphElement] appendChild.html:7
appending [object HTMLParagraphElement] to [object HTMLBodyElement] appendChild.html:7
To overcome the weakness of Firefox (that you can't override appendChild), you may use the trick: place the code below instead in the top of your HTML
<script>
Node.prototype._appendChild = function(child) {
console.log("appending " + child + " to " + this);
return this.appendChild(child)
};
</script>
and then, use Fiddler proxy by creating auto-responders (WMV tutorial, 9.9 MB) where you manually replace all calls to .appendChild with ._appendChild (you can use Notepad++ for "find replace in all opened files"). Creating auto-responders and hand-tampering requests can be mundane, but it's extremely powerful. To quickly create auto-responder rule, load the page when Fiddler is active, then drag'n'drop files as in the picture below. For each file, right click and choose "Generate File" from menu (this will put a file on the desktop) or create a file by yourself in different location. (it's good to open Fiddler-generated files and remove response headers from them; BTW "Generate file" puts real contents only if the response header was 200, so make sure to load the page with CTRL-F5 to skip the cache).
In Chrome you can inspect an element and right click on it. This menu gives you some options to break when something below the element is changed or when it's own attributes change. Maybe one of those breakpoints will find what you are looking for?
Assuming you've got access to the raw (hopefully un-minified/obfuscated) JS files, maybe just search them for text strings related to DOM manipulation and/or attributes of the node you're trying to find the creation of? I'd try things like "appendChild" "createElement" and the node's ID/class names.
You could also set break points all over the script files, and step through them as the page loads to help you narrow down where to look. Might help to start by just "pausing" the JS execution and stepping through from the very beginning.
If you can share the code (a link to the live site would do fine) I'd be happy to take a look.
If you are using the jQuery framework in your javascript to make the DOM changes then you may find the fireQuery plugin for FireBug in the firefox browser may get you the information you need.
Example:
It adds additional information to the standard HTML view by superimposing additional jquery element information to the display to provide a deeper insight into how your javascript is amending the page content.
I hope that helps you out.
I have the non-standard element
<testele></testele>
In every browser except IE, this bit of JavaScript will successfully change the content of the above element
document.getElementsByTagName("testele")[0].innerHTML = 'hi';
However, if I change the <testele> to just a <span> (in the HTML and the JavaScript), it now successfully changes the content of the element in every browser, including IE.
Is there any fix? I have searched around and tried a bunch to no avail.
Use document.createElement("testele") before it is rendered. This script must be included before the document encouters a <testele>:
http://jsfiddle.net/gilly3/LjwbA/
document.createElement("testele");
window.onload = function() {
document.getElementsByTagName("testele")[0].innerHTML = 'hi';
};
If you try to do document.createElement("testele") after a <testele> has been parsed by the browser, it's too late.
Take a look at innerShiv, a Javascript plugin which aims to solve this.