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.
Related
I have an html link 'localurl' pointing to an URL of an image (for example the current album artwork of the music playing on my sonos), so that when I give 'localurl' in my browser, it doesn't display the image directly but a path like 'http://image.png'. This last path links to the image.
I would like to display this image in an HTML file using the 'localurl'. I think it should look something like this:
<!DOCTYPE html>
<html>
<body >
<img src=getUrlFromHTML('localurl') >
<script type="text/javascript">
function getUrlFromHTML(url)
{
...
}
</script>
</body>
</html>
EDIT: the link 'http://image.png' is not always the same, I don't know it in advance, this is why in need to go with 'localurl'. The concept is the following: I have an openHAB installation with the Sonos Binding, I have a string item called Sonos_CurrentAlbumArtUrl and through the API of openHAB, i get the link http://openhab.local:8080/rest/items/Sonos_CurrentAlbumArtUrl/state (this is my 'localurl' and it is pointing to 'http://image.png' which depends on the music being played on the Sonos (using Spotify). I hope this is a bit more clear.
unless you want to refer selected files from <input type=file you dont need to use javascript.
you can just write the location. For locations you can drag image to your browser, copy from the address bar.
<img src="file:///C:/Users/nerkn/Documents/cobokin.jpg"
I took the time to learn some javascript and I found an answer that fits to my need. I share here the content of the HTML-body as I think it could help others.
<body>
<img id="SonosAlbumArt">
<script type="text/javascript">
var link = 'http://openhab.local:8080/rest/items/Sonos_CurrentAlbumArtUrl/state';
var img = document.getElementById('SonosAlbumArt');
var xhr = new XMLHttpRequest();
xhr.addEventListener('readystatechange', function () { refreshAlbumArt()} );
function sendAlbumArtRequest() {
xhr.open('GET', link);
xhr.send(null);
}
function refreshAlbumArt() {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
img.src = xhr.responseText;
}
}
setInterval(sendAlbumArtRequest, 1000);
</script>
</body>
I am not quite convinced that the setInterval is the best way to do it. I miss something like an event triggered when the album art changes, in order to not send requests each second. Any suggestions are welcome.
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();
I'm creating a website to tutor people at my school, and I need to embed a google doc so that anyone who visits the page can edit after they log in with their google account ofc. The way I have it now, it is not editable but it does embed. Does anyone know how to do this, can it even be done?
Here is what I have so far.
<iframe src="GOOGLE-DOC-URL" height = "1000" width = "1000"></iframe>
I made the page public and published it, I've done quite a lot of looking on this and found that adding "seamless" to the iframe statement used to work but now that is deprecated apparently and I tried that and it does not work. Thank you.
First you need to do add the URL google doc with this params :
https://docs.google.com/document/d/KEY/pub?embedded=true
Second i do an ajax call to get the information and the response from google doc api :
https://codepen.io/headmax/pen/dVeMmE
To create your own page : the API doc will print after the HR html element
html page :
<html>
<body>
<h1>The text below is pulled live from Google Docs</h1>
<h4>If there is an update to the doc and you refresh the page, it should update.</h4>
<hr>
<script>
function get_information(link, callback) {
var xhr = new XMLHttpRequest();
xhr.open("GET", link, true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
callback(xhr.responseText);
}
};
xhr.send(null);
};
//Now initilisation and call & working from the anonyme callback function with dom response :
get_information("https://docs.google.com/document/d/1yf5plpYBYsBMCaeeDpTkapgR8jZtg4XCfiTvRG5qRWY/pub?embedded=true", function(text) {
var div = document.createElement("div");
div.innerHTML = text;
// Remove css that comes with Google Doc embeds
// If you want the Google Doc styling, comment these out
div.removeChild(div.childNodes[1]);
div.removeChild(div.childNodes[0]);
document.body.appendChild(div);
document.body.appendChild(document.createElement("hr"));
}
);
</script>
</body>
</html>
Basically I'm trying to build a functionality in which I only really edit my index.php, I got a lot of other php files with just a form in them or just a few lines of text.
What I want to achieve is to load these other files in the contentwrapper of my index.php.
I have been successfull on doing this with an iframe and with a html <object>.
The problem with these though is that first of all they load an all new #document in the DOM, and also my webpage has no set height so height: 100% won't work on those and I would get these ugly scrollbars and stuff.
after searching a lot on SO today I found a few interesting solutions which I combined, this is what I'm trying now:
<script type="text/javascript" href="js/csi.min.js"></script>
<script type="text/javascript">
function load_content(target){
document.getElementById('contentwrapper').innerHTML='<div data-include="' + target + '" ></div>';
return false;
}
</script>
now you may question what data-include is, this is a very nice workaround I found on SO.
THIS is what it does, it basically calls a .js file that replaces the containing element with the data that is in the file (target in the above example)
I call this functionality like this:
Update profile
It works as far as adding this to the DOM:
<div id="contentwrapper">
<div data-include="update.php" ></div>
</div>
but besides that it does nothing, I think that it doesn't call the .js file for the data-include attribute. But I can't find a solution for this nowhere.
(BTW: the data-include attribute does work if I put it in a tag manually without javascript)
I Hope I didn't overexplain the situation, and I thank everyone that tries to help in advance!
The csi.js script is only run once after the page is loaded. It just goes over all the elements with the data-include attribute and runs the fragment function.
<script type="text/javascript">
function fragment(el, url) {
var localTest = /^(?:file):/,
xmlhttp = new XMLHttpRequest(),
status = 0;
xmlhttp.onreadystatechange = function() {
/* if we are on a local protocol, and we have response text, we'll assume
* things were sucessful */
if (xmlhttp.readyState == 4) {
status = xmlhttp.status;
}
if (localTest.test(location.href) && xmlhttp.responseText) {
status = 200;
}
if (xmlhttp.readyState == 4 && status == 200) {
el.outerHTML = xmlhttp.responseText;
}
}
try {
xmlhttp.open("GET", url, true);
xmlhttp.send();
} catch(err) {
/* todo catch error */
}
}
function load_content(target){
fragment(document.getElementById('contentwrapper'), target);
return false;
}
</script>
Then call it like this:
Update profile
So, the only thing you need is to call this function for the new created element. Pass the DOM element and the url to this function and it will take care of loading the contents of the requested resource in the corresponding element.
May we assume that you followed this advise from the repository: The only caveat is Chrome, which restricts access to local files via AJAX. To resolve this, simply add --allow-file-access-from-files to your Chrome runtime.
If you didn't, and you're using Chrome, then this stands out to me, and you didn't indicate that you'd corrected the security block that Chrome puts in place.
The csi.js only runs on window.onload.
Try
<a href="#" onclick="function() {load_content('update.php'); window.onload(); }">
Update profile</a>
Once a first page is loaded nomally in my website, I request all other pages body contents with javascript ajax (ajaxObject).
I simply grab the body innerHTML with ajaxObject (javascript) and replace the actual one:
<script type="text/javascript">
function get(url) {
var myRequest = new ajaxObject(url, uGotAResponse);
myRequest.update('','GET');
}
function uGotAResponse(responseText,responseStatus) {
//Create a temp div to be able to use getElementById on it.
var theTempDiv = document.createElement('div');
//put the grabbed body innerHTML into it.
theTempDiv.innerHTML = responseText;
//my pages are like <body><div id="divcontent">content of pages here</div></body>
//so i get that div containing the innerHTML i really need.
var allDiv = theTempDiv.getElementsByTagName('div');
for (var i=0; i<allDiv.length; i++) {
if (allDiv[i].getAttribute('id') == 'divcontent') {
//i now replace the actual body innerHTML by the one i requested.
document.getElementById('divcontent').innerHTML=allDiv[i].innerHTML;
}
}
}
</script>
On a page, I have youtube objects for embed videos:
<object type="application/x-shockwave-flash" data="http://www.youtube.com/v/1ahKNnolR30" height="315px" width="420px"><param name="movie" value="http://www.youtube.com/v/1ahKNnolR30"></object>
In Firefox everything is fine if I either load the page using the address or with that ajax code.
With IE, it works only if I go to the page using the address.
When I try to use the ajax code the videos appear as the image below.
I tried it with IE tester, all versions give me the same error behaviour.
Does anyone have a fix for this maybe?
As you can see, it looks like the object video is there, but looks like IE is not interpreting it because its loaded by ajax.