I am trying to load a svg via javascript. All I am getting is a blank screen, if I inspect it I see the code, but the svg is not rendering out. If you paste the link into the browser you can see the image. Any help is appreciated.
Thanks
var ajax = new XMLHttpRequest();
ajax.open("GET", "https://edit.meridianapps.com/api/floors/5649391675244544.svg?namespace=4906933713108992_1&hash=8f1c6699ad05ff6ca0ba9414884546b1&style=6711e01fe4271fa2fd1f299eff4296da&default_style=original", true);
ajax.send();
ajax.onload = function(e) {
var div = document.getElementById("svgContainer");
div.innerHTML = ajax.responseText;
}
<div id="svgContainer"></div>
As told by enxaneta in the comment div.innerHTML =ajax.responseText.replace(/ns0:/g,"") solves the problem as follows;
var ajax = new XMLHttpRequest();
ajax.open("GET", "https://edit.meridianapps.com/api/floors/5649391675244544.svg?namespace=4906933713108992_1&hash=8f1c6699ad05ff6ca0ba9414884546b1&style=6711e01fe4271fa2fd1f299eff4296da&default_style=original", true);
ajax.send();
ajax.onload = function(e) {
var div = document.getElementById("svgContainer");
div.innerHTML = ajax.responseText.replace(/ns0:/g,"");
}
<div id="svgContainer"></div>
This issue seems to be unrelated to the Ajax call. Your code works with another image URL.
The problem appears to be with the SVG in question. Including it via an img tag works fine. Direct inclusion of the SVG markup inside the HTML shows the same problem as you described.
Chrome and Firefox both display the large viewbox, but do not render any image contents.
The SVG in question prefixes all SVG tags with the namespace prefix ns0. As a commenter suggested, removing this prefix from all tags is successful - Chrome and Firefox display the image.
However, a simple text replacement as suggested is a weak solution: if the prefix changes (it's an arbitrary string set by the creator of the SVG), the image will again not be displayed. Furthermore, the text replacement may remove occurrences of ns0 in the image source that are not a namespace prefix, possibly breaking the image or altering its contents.
While I could not find an answer to the canonical way to go about inlining this kind of SVG files, I'd recommend using an image tag and setting the source to the URL.
<img id="svgContainer">
var img = document.getElementById("svgContainer");
img.src = "https://example.com/image.svg";
Check your CSS file for the id 'svgContainer' whether you had given some style or not.
Your issue more or less seems like a styling issue.
The issue is you need to first import the document i.e the responseXML is in another DOM document.
To insert into your document you need to use document.importNode
For more clarification, you can follow this answer.
var ajax = new XMLHttpRequest();
ajax.open("GET", "https://edit.meridianapps.com/api/floors/5649391675244544.svg?namespace=4906933713108992_1&hash=8f1c6699ad05ff6ca0ba9414884546b1&style=6711e01fe4271fa2fd1f299eff4296da&default_style=original", true);
ajax.onload = function() {
var svg = ajax.responseXML.documentElement;
var div = document.getElementById("svgContainer");
svg = document.importNode(svg, true); // tried and tested in Chrome only . Need to check for other browsers
div.appendChild(svg);
};
ajax.send();
Related
Good evening,
I have developed a JavaScript that is responsible for inserting all the HTML content of Google Docs published on the web in a div with id attribute, something similar to an iframe, but without cloning the Google stylesheet.
Here is an example!
// script to grab googledoc info & inject it directly onto the page
function get_googledoc(link, callback) {
var xhr = new XMLHttpRequest();
xhr.open("GET", link, true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
callback(xhr.responseText);
}
};
xhr.send(null);
}
get_googledoc (
"https://docs.google.com/document/d/e/2PACX-1vQFFMz6wwmc0TTQ7upeSvs1DxKSpPlagB_bvtqdXPSIlShCX4FE57fowgRBdY34pDw24GYhZ_G2W_lX/pub?embedded=true",
function(text) {
var div = document.getElementById("test");
div.innerHTML = text;
// and remove css that comes with google doc
div.removeChild(div.childNodes[1]);
div.removeChild(div.childNodes[0]);
}
);
<div id="test"></div>
The problem arises when, after publishing the document on the web, and transforming it into HTML inside the div with id attribute, it does not use b, i, strong, em tags for the words in bold or italics, but uses a div with class attribute where it resorts to alternatives such as font-weight or font-style.
Google Docs updates every so often, so if I get to style, for example, the class c4, when the document is updated it will change that class value to another one, and so on.
I've been thinking about a solution, but I can't come up with one.
Can you think of anything?
Thank you very much in advance.
I am using CasperJS to scrape some items, so I can't get on the page early enough to add load and error events on img tags. I would also prefer to not have to do a new XHR request for each image to determine it's validity.
Is there any way to select an image tag and determine if there is an image actually there or if it is not in which the alt text is displayed? JS only, after the page is fully loaded.
This is NOT A DUPLICATE. I am specifically asking if there is a way to do this without another network request. Other questions only have answers that require creating a new image with a new source and thus another network request.
/ Edit
Specifically looking for asserting if am image is loaded after it is complete (document.querySelector('#myImage').complete // returns true:
No new network request (includes creating a new image with a new source)
No onload/onerror events (requires doing so before page is loaded)
Assert that #myImage is broken without the above
I don't know how exactly you would use it , but here is the code snippet from w3schools.
<!DOCTYPE html>
<html>
<body>
<p>This example uses the HTML DOM to assign an "onerror" event to an img element.</p>
<img id="myImg" src="image.gif">
<p id="demo"></p>
<script>
document.getElementById("myImg").onerror = function() {myFunction()};
function myFunction() {
document.getElementById("demo").innerHTML = "The image could not be loaded.";
}
</script>
</body>
</html>
With a bit of working, I was able to find two methods that seem to work:
HTML
<img id="imageA" src="https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png">
<img id="imageB" src="https://www.google.com/broken.png">
Setup
var imageA = document.querySelector('#imageA');
var imageB = document.querySelector('#imageB');
console.log(imageIsValid(imageA)); // returns true
console.log(imageIsValid(imageB)); // returns false
JavaScript Method 1
function imageIsValid(img) {
return !!img.naturalHeight && !!img.naturalWidth;
}
The natural height and width of broken images will always be 0.
https://jsfiddle.net/2xLsenpp/
JavaScript Method 2
function imageIsValid(img) {
if (img.complete) {
var canvas = document.createElement('canvas'),
context = canvas.getContext('2d');
try {
context.drawImage(img, 0, 0);
return true;
} catch(e) {
return false;
}
}
return false;
}
https://jsfiddle.net/8gdp8nzw/
I'm evaluating Featherlight lightbox and I'm not able to implement code that satisfies my use case. I need a lightbox that will be used as a report viewer which displays dynamically created content assigned to a JavaScript variable. The value of the string is a valid HMTL5 page.
I've looked at the iframe example, but it depends upon a static iframe being in the DOM. That's not what I need.
I've reviewed this GitHub issue and this jsfiddle and I'm not able to successfully modify the fiddle to display a string.
This is an example of the string I would like to display:
var s = '<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Title of the document</title></head><body><p>Content of the document......</p></body></html>';
Is this possible and if so how?
I expect that $.featherlight() will be called manually in response to a button click.
The solution I came up with was to modify the Featherlight source code in 2 places as indicated in this block of code (currently around line 383).
iframe: {
process: function(url) {
var deferred = new $.Deferred();
var $content = $('<iframe/>')
.hide()
.attr('src', url)
.attr('id', this.namespace + '-id') // [KT] 10/31/2016
.css(structure(this, 'iframe'))
.on('load', function() {if ($content.show()) {deferred.resolve($content.show()) } else {deferred.resolve($content)} ; }) // [KT] 10/31/2016
// We can't move an <iframe> and avoid reloading it,
// so let's put it in place ourselves right now:
.appendTo(this.$instance.find('.' + this.namespace + '-content'));
return deferred.promise();
}
},
The id attribute is added to the iframe so content can be added by JavaScript, like this:
var s = '<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Title of the document</title></head><body><p>Content of the document......</p></body></html>';
var oIframe = document.getElementById('featherlight-id'); // Featherlight's iframe
var iframeDoc = (oIframe.contentDocument || oIframe.contentWindow.document);
iframeDoc.open();
iframeDoc.write(s);
iframeDoc.close();
This then works:
$.featherlight({iframe: 'about:blank', iframeWidth: '96%' });
The 2nd modification is required so that the url 'about:blank' doesn't raise an error.
I also modified the css so as to get the scroll bars to work as needed.
Edit: the issue with Featherlight not opening an iframe when the url is abount:blank has been fixed as of version 1.5.1.
Edit 2: Using v1.5.1, this works without having to make a modification to Featherlight to add an id to to the iframe:
var s = '<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Title of the document</title></head><body><p>Content of the document......</p></body></html>';
$.featherlight({iframe: 'about:blank'});
var $iframe = $('.featherlight iframe');
$iframe.ready(function () {
$iframe.contents().find("body").append(s);
});
The accepted SO answer was used for this solution.
I'm trying to build out a pretty basic widget system that renders some content and videos depending on the widget's ID. I thought I had a pretty solid method of doing this until I've run into a bug that is preventing my videos from loading.
I'd like to know if 1) the method I'm using is an ideal approach and 2) if the bug I'm experiencing is something on my end that can be fixed. Here's how I have it setup.
You place the following code on your website where you want the widget to render:
<script type="text/javascript" src="http://testing.womensforum.com/widgets/example.js"></script>
<div id="wf_widget"></div>
<script>Widget.Load('098f6bcd4621d373cade4e832627b4f6', 'wf_widget');</script>
That'll call the JS code below, which sends an AJAX request to the server asking for the HTML code that it should render. Once I have that, I insert a blank iframe into the div element (wf_widget) which I use to write the HTML code I got from the server into the iframes document.
var host = 'http://testing.womensforum.com/widgets/example.php';
var Widget = {
Load: function(widget_hash, element_id) {
var http = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("MSXML2.XMLHTTP");
http.onreadystatechange = function() {
if (http.readyState == 4 && http.status == 200) {
var html = http.responseText;
var iframe = "<iframe allowtransparency=\"false\" style=\"border: 1px solid #8c8b8b; z-index:10;\" width=\"300\" height=\"600\" marginwidth=\"0\" marginheight=\"0\" frameborder=\"0\" scrolling=\"no\"></iframe>";
var div = document.getElementById(element_id);
div.innerHTML = iframe;
var frame = div.getElementsByTagName("iframe")[0];
var doc = frame.contentDocument || frame.contentWindow.document || frame.contentWindow.window.document;
doc.write(html);
}
}
http.open("POST", host, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.send("widget_hash=" + encodeURIComponent(widget_hash));
}
};
This seems to work really well up until I tried loading a video. To see a live example, you can go here:
http://testing.womensforum.com/widgets/example.html
You'll notice that the video player loads, but no video is playing. But if you check out the HTML that the JS code is getting here:
http://testing.womensforum.com/widgets/example.php
You see that the video is loading just fine, it's only when I pipe that HTML code through our JS that it stops working.
Can anyone give any insight as to what the issue is and if there is a better approach for something like this?
Possibly this reason?? With Ajax - it has cross-domain policy where ajax will function/operate given that the file or callback is within the same domain of server. If you are trying to achieve the cross-domain approach, then explore different avenue, not ajax - if I am correct.
I have a page that loads with initially just a form within an iframe, something like this:
<iframe id="oIframe" ...src='somePage>'
<form ... />
</iframe>
When you click a button in the form, some javascript is invoked that builds a url and then I want to do the following:
frame.src = 'somePage?listId=1';
This works in IE to "reload" the frame with the new contents.
However, in Safari this does not work.
I have jQuery available, but I don't want to replace the existing iframe because there are events attached to it. I also can not modify the id of the iframe because it is referenced throughout the application.
I have seen some similar issues but no solutions that seem to work well for my exact issue.
Any assistance anyone can provide would be great!
Some browsers don't use "src" when calling the javascript object directly from the javascript hierarchy and others use "location" or "href" instead of "src" to change the url . You should try these two methods to update your iframe with a new url.
To prevent browser cache add a pseudo-random string like a number and timestamp to the url to prevent caching. For example add "new Date().getTime()" to your url.
Some calling examples:
document.getElementById(iframeId).src = url;
or
window.frames[iframeName].location = url;
I recommend the first option using document.getElementById
Also you can force the iframe to reload a page using
document.getElementById(iframeId).reload(true);
So the answer is very simple:
1. put a <div id="container"> </div> on your page
2. when reload needed use following jQuery:
$("#container").empty();
$("#container").append("<iframe src='" + url + "' />");
and that's it.
Of course there is more elegant way of creating DOM with jQuery but this gives the idea of "refreshing" iframe.
Works in FF18, CH24, IE9, O12 (well it's jQuery so it will work almost always :)
I found a better solution (albeit not paticularly eloquent) for this using jQuery.ajax:
jQuery.ajax({
type: 'GET',
url: "/somePage?someparms",
success: function() {
frameObj.src = "/somePage?someparms";
}
});
This forces the DOM to be read within the frame object, and reloads it once the server is ready to respond.
Try this
form.setAttribute('src', 'somePage?listId=1');
Well, I was able to find what appears to be a feasible solution -- it's a work in progress, but this is basically what I ended up doing:
var myFrame = document.getElementById('frame'); // get frame
myFrame.src = url; // set src attribute of original frame
var originalId = myFrame.id; // retain the original id of the frame
var newFrameId = myFrame.id + new Date().getTime(); // create a new id
var newFrame = "<iframe id=\"" + newFrameId + "\"/>"; // iframe string w/ new id
myFrameParent = myFrame.parentElement; // find parent of original iframe
myFrameParent.innerHTML = newFrame; // update innerHTML of parent
document.getElementById(newFrameId).id = originalId; // change id back
I ran into this issue using React, passing the key as props.src solved it
const KeyedIframe = ({children, ...props}) => <iframe key={props.src} { ...props}>
{children}
</iframe>