I'm currently trying to build my first Chrome extension but I'm having a slight issue with my code.
I want to use XMLHTTPRequest and xpath to display a specific number from an external website as a badge on my icon. The code I'm using in my background.js file is as follows:
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://www.example.com", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// innerText does not let the attacker inject HTML elements.
document.getElementById("resp").innerText = xhr.responseText;
}
}
xhr.send();
var xmlDoc = xhr.responseXML;
xmlDoc.setProperty('SelectionLanguage', 'XPath');
var badgeText = xmldoc.documentElement.selectSingleNode("//[#id='main']/div/div/section/div[1]/div[2]");
chrome.browserAction.setBadgeText({text: badgeText});
chrome.browserAction.setBadgeBackgroundColor({color: "#1f729f"});
I know this code is probably pretty horrible but this is my first extension and I'd really appreciate any help.
Thanks in advance.
It looks like you are expecting some immediate response after xhr.send();
Here the code snipet which is working in one of my extensions (notice this in the callback function):
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://www.example.com", true);
xhr.onreadystatechange = function() {
console.log("XHR callback readyState = " + this.readyState);
if (this.readyState == 4) {
// innerText does not let the attacker inject HTML elements.
document.getElementById("resp").innerText = this.responseText;
var xmlDoc = this.responseXML;
xmlDoc.setProperty('SelectionLanguage', 'XPath');
var badgeText = xmldoc.documentElement.selectSingleNode("//[#id='main']/div/div/section/div[1]/div[2]");
chrome.browserAction.setBadgeText({text: badgeText});
chrome.browserAction.setBadgeBackgroundColor({color: "#1f729f"});
}
}
xhr.send();
This way the code would be executed only after the response is available.
Hope this helps ;-)
Related
I've really searched for days, but couldn't find a solution:
I have an external SVG (800k) which i need to load completely before calling the following function. Someone helped me with the code to load the SVG but I cant figure out how to detect when the SVG is completely loaded. (I am not using jQuery). I need the function initialSvgSettings() to run after the SVG has finished loading completely. Where I have it right now, it just runs when the SVG starts loading but not when it has completed.
This is the code I am using to load the SVG:
// LOAD SVG
var svgOverlay = viewer.svgOverlay();
var path = "images/elementosV6.svg";
function loadSVG(path, callback) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(e) {
try {
if (xhr.readyState == 4 && xhr.status == 200) {
callback(xhr.responseXML.documentElement);
initialSvgSettings();
}
} catch (e) {
console.log(e);
}
};
xhr.open("GET", path, true);
xhr.overrideMimeType("text/xml");
xhr.responseType = "document";
xhr.send();
}
loadSVG(path, function(data) {
var g = data.getElementById("elements");
svgOverlay.node().appendChild(g);
}); // FIN LOAD SVG
The answer nearest to your question would be to point out that instead of using XMLHttpRequest.onreadystatechange, you could use the .onload event handler, which is called only after the resource has been completely loaded.
But you can also simplify your code by loading the image into an offscreen <object>. Attach your callback to .onload, and with .contentDocument you can access the DOM of the SVG.
var svgContainer = document.createElement('object');
svgContainer.type = 'image/svg+xml';
svgContainer.onload = function () {
var g = svgContainer.contentDocument.getElementById("elements");
svgOverlay.node().appendChild(g);
}
svgContainer.data = 'images/elementosV6.svg';
I am going to pass a url as a GET parameter to the restful API, but it can not match the url pattern, therefore 404 returns.
I use the django-rest framework as the server side.
Here is the urls.py
url(r'^method/?P<url>(https?:\/\/(www\.)?[-a-zA-Z0-9#:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9#:%_\+.~#?&//=]*))$',views.Method.as_view()), name='method'),
And the client xhr code is something like this.
var xhr = new XMLHttpRequest();
// url is like https://storage.googleapis.com/xxx/cccc/abc.txt
xhr.open('GET', 'method/' + url, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
if (this.status == 200) {
// do something
}
};
xhr.send();
The regex is ok, but still returns 404 by the server.
Even though I pass the request url something like
xhr.open('GET', 'method?=' + url, true);
It still returns 404 not found.
What is the proper way to do this?
Thank you!
Change your client xhr code like:
var xhr = new XMLHttpRequest();
var url = 'https://storage.googleapis.com/xxx/cccc/abc.txt';
xhr.open('GET', 'method/?url=' + encodeURIComponent(url), true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
if (this.status == 200) {
// do something
}
};
xhr.send();
I am using XDomainRequest to send a cross domain request. The onerror handler is firing; however, nothing is logged and when tracing network in developer tools I can see the response in the response body.
Anyone have any ideas? Below is the code I am using. Thanks in advance for any help.
var createCORSRequest = function(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// Most browsers.
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined") {
// IE8 & IE9
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// CORS not supported.
xhr = null;
}
return xhr;
};
var url = 'https://myurl';
var method = 'GET';
var xhr = createCORSRequest(method, url);
xhr.onload = function() {
// Success code goes here.
//alert("load");
alert(xhr.responseText);
};
xhr.onprogress = function(){
alert("Progress");
}
xhr.onerror = function() {
alert("error");
};
xhr.send();
XDomainRequest object does not provide anyway to determine what is the status code of error, and returns empty string in xdr.responseText.
I am having problems with using Ajax and Fancybox.js photo viewer together.
I have a website set up first as web 1.0 with the standard navigation with hyperlinks.
but for html5 browsers I'm am using javascript that creates a web 2.0 experience.
The javascript first highjacks the links onclick event which makes a XMLHttpRequest that calls a php script that parses the html and sends back just the part of the html that I want to replace. I am using pushState and popState to get the back and forward buttons to function.
It is working great, it creates the Ajax effect, while persevering all the advantages of web 1.0 including SEO, because the links as far as the search engine spiders are concerned the links are just standard links to standard html pages.
The problem is that one of the pages uses Fancybox.js to show photos, it works fine when the page is accessed via the standard url, but when the html is accessed via the Ajax scripts if breaks it.
Here is code for the Ajax,
if (history.pushState) {
function changeContent(url) {
var xmlhttp;
if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else { // code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
document.getElementById('content').innerHTML = xmlhttp.responseText;
}
};
xmlhttp.open("GET", "getContents.php?url=" + url, true);
xmlhttp.send();
}
$(document).ready(function() {
var elems = null,
links = null,
link = null,
i;
elems = document.getElementById('nav');
links = elems.getElementsByTagName('a');
if (links) {
for (i = 0; i < links.length; i++) {
links[i].addEventListener("click", function(e) {
url = $(this).attr("href");
var pathArray = window.location.pathname.split( '/' );
var n = pathArray.length;
changeContent(url);
history.pushState(null, null, url);
e.preventDefault();
var urlstr = window.location,
index = /index/g,
program = /program/g,
photos = /photos/g,
testimonials = /testimonials/g,
about = /about/g,
contact = /contact/g;
if (program.test(urlstr)){
changeCurrentPage('#program');
document.title = "Our Programs Kolibri Daycare";
}else if (photos.test(urlstr)){
changeCurrentPage('#photos');
document.title = "Photos Kolibri Daycare";
slideShow();
}else if (testimonials.test(urlstr)){
changeCurrentPage('#testimonials');
document.title = "Tesimonials Kolibri Daycare";
}else if (about.test(urlstr)){
changeCurrentPage('#about');
document.title = "About Kolibri Daycare";
}else if (contact.test(urlstr)){
changeCurrentPage('#contact');
document.title = "Contact Kolibri Daycare";
}else {
changeCurrentPage('#home');
document.title = "Kolibri Daycare";
}
}, false);
}
}
window.setTimeout(function() {
window.addEventListener("popstate", function(e) {
var pathArray = window.location.pathname.split( '/' );
var n = pathArray.length;
if (pathArray[n-1]){
changeContent(pathArray[n-1]);
}else {
changeContent('index.html');
}
}, false);
}, 1);
});
}
and her is the script that calls Fancybox.js,
<script type="text/javascript">
//<![CDATA[
$(document).ready(function() {
$("a[rel=example_group]").fancybox({
'overlayShow' : false,
'cyclic' : true,
'transitionIn' : 'elastic',
'transitionOut' : 'elastic'
});
});
//]]>
</script>
It is in the head section of the page.
When the html that has the photo links is brought in via Ajax the script that calls fancybox.js is not included. I have tried calling it in different places but nothing seems to work. Does anyone have any ideas?
You need to re-initialize fancybox on the new elements added from ajax. I'm not sure why you don't just upgrade the entire page to HTML5 and use some of the ajax functions provided by jQuery, but I think the re-initialization should be inserted after this line (not tested!):
document.getElementById('content').innerHTML = xmlhttp.responseText;
$('#content').find("a[rel=example_group]").fancybox();
I am pretty new to Ajax. I'm trying to put some specific portions of an XML file into a div on my page, and the following works in every recent browser except IE:
var xhr = false;
//Executed to request content from the server
function setContent(){
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
} else {
if(window.ActiveXObject){
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
}
xhr.onreadystatechange = showContent;
xhr.open("GET", "ajax/art.xml", true);
xhr.send(null);
}
//Executed to set the appropriate text once the server has gathered the data
function showContent(){
if(xhr.readyState == 4){
if(xhr.status == 200 || window.location.href.indexOf("http") == -1){
var newData = xhr.responseXML.getElementsByTagName(curPage).textContent;
}
var textBox = document.getElementById("textBox");
textBox.innerHTML = newData;
}
}
(The value of curPage is set elsewhere in the code and seems to have the correct value)
When I execute this code in IE on the server I get the word "undefined" in the textBox Div instead of the content grabbed from the XML document. How do I resolve this?
Thanks in advance <><
Thanks bobince, but that doesn't seem to work either.
That's an interesting note about textContent. I tried:
if(xhr.responseXML.getElementsByTagName(allPages[curPage])[curStage].textContent != undefined){
var newText = xhr.responseXML.getElementsByTagName(curPage)[curStage].textContent;
} else {
var newText = xhr.responseXML.getElementsByTagName(curPage)[curStage].innerText
}
}
since innerText should work in every browser except FF and textContent should work in every browser except IE, but I still get "undefined" in IE.
Furthermore, if I just use innerText and forget about FF compatibility, I get "undefined" in every browser, not only IE.
Not sure how to remedy this...
Here's the live site if that helps:
www.tcmulder.com/art
(Oh, and notice I'm using (curPage)[curStage], fixes the first problem you noted)
getElementsByTagName(curPage).textContent
shouldn't work in any browser. getElementsByTagName returns a list of elements, not a single element. A NodeList has no textContent property.
Anyway, IE doesn't support the DOM Level 3 Core property textContent. If you're sure there's exactly one text node inside the element, you can read its content using:
var el= xhr.responseXML.getElementsByTagName(curPage)[0];
var text= el.firstChild.data;
If the element might be empty you could check for that (el.firstChild!==null); if there's mixed text and element content you would need to write a text-extractor function that emulates textContent.
Switch your initial conditional to check for the MS specific object first and then check for XMLHTTPRequest.
Later versions of IE "support" XMLHttpRequest but it doesn't work. If you switch your conditional, your code should work.
function setContent(){
if(window.ActiveXObject){
xhr = new ActiveXObject("Microsoft.XMLHTTP");
} else {
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}
}
xhr.onreadystatechange = showContent;
xhr.open("GET", "ajax/art.xml", true);
xhr.send(null);
}
Thanks for your help; I've run out of time on this site so I had to go with jQuery after all.
function setContent(){
$.ajax({
type: "GET",
url: "ajax/art.xml",
dataType: "xml",
success: function(xml){
var curData = curPage + ":eq(" + [curStage] + ")";
var theText = $(xml).find(curData).text();
$("#textBox span").replaceWith("<span>" + theText + "</span>");
ajaxReady = true;
}
});
}