Possible to use getElementsByClassName with an external HTML file? - javascript

I have a test.html file that looks like this:
<!DOCTYPE html>
<html>
<body>
<div class="outside">
<div class="inside">
FOO
</div>
</div>
<div class="outside">
<div class="inside">
BAR
</div>
</div>
</body>
</html>
Which I can simply parse like this:
<script>
var x = document.getElementsByClassName("outside");
for (var i=0;i<x.length;i++)
document.write(x[i].getElementsByClassName("inside")[0].childNodes[0].nodeValue);
</script>
To get the result I want:
FOO
BAR
But I would like to parse the content of test.html in another HTML file. I've tried using XMLHttpRequest like this:
if (window.XMLHttpRequest) {
xmlhttp=new XMLHttpRequest();
}
xmlhttp.open("GET","test.html",false);
xmlhttp.send();
xmlDoc=xmlhttp.responseXML;
var x=xmlDoc.getElementsByClassName("outside");
for (var i=0;i<x.length;i++)
document.write(x[i].getElementsByClassName("inside")[0].childNodes[0].nodeValue);
But that gives me the following error:
TypeError: null is not an object (evaluating 'xmlDoc.getElementsByClassName')
Using all files on my local web server so shouldn't be any issues with access. I know that this certainly isn't the most modern way of parsing but its something I'm just gonna be using locally for a hobby project. But if you have any suggestions on how to solve this with jQuery for example, I'm open to any ideas.

It is hard to use responseXML when the document is not HTML.
You would need to set the html of a div with the responseText and query that.
var str = "<ul><li>1</li><li>2</li>"; //xmlhttp.responseText;
var div = document.createElement("div");
div.innerHTML = str;
var lis = div.getElementsByTagName("li");
for (var i=0;i<lis.length; i++) {
console.log(lis[i].textContent);
}

Related

Getting text from file using FileReader on Load

So, I've been working on a page that uses only local files (server is not an option, unfortunately. Not even a localhost. The struggle is real.) and I've come to a situation where I need to grab text from a .csv file and populate it to the page. I have this bit of code that works, but I need to have a file set within the function when a button is pressed. Looking up the file manually isn't an option (to visualize what I'm doing, I'm making a mock database file in the most annoying way possible (because I have to, not because I want to)).
In the page I would have something like:
<button id="myButton" onclick="getText()"></button>
<script>
var myFile = "dataset.csv";
...
</script>
The following bit of code works (in regards to having it pull the data from the csv file), but, as I said, I need to pull the text from the file when a button is pressed and just have the file name set in the script, not pulling it up manually.
<!DOCTYPE html>
<html>
<body>
<input type="file" id="fileinput" />
<div id="outputdiv"></div>
<script type="text/javascript">
function readSingleFile(evt) {
var f = evt.target.files[0];
if (f) {
var r = new FileReader();
r.onload = function(e) {
var contents = e.target.result;
var splited = contents.split(/\r\n|\n|\r|,/g);
for (i=0; i<splited.length; i++){
document.getElementById("outputdiv").innerHTML = document.getElementById("outputdiv").innerHTML + splited[i] + "<br>";
}
}
r.readAsText(f);
} else {
alert("Failed to load file");
}
}
document.getElementById('fileinput').addEventListener('change', readSingleFile, false);
</script>
</body>
</html>
From what I can tell from the API, I would need to set the file attributes to a blob in order to pass it to FileReader. How I can do this without using an input box, I have no idea. There's also a 50% chance that I am completely wrong about this since I obviously don't know how to get this done.
If someone could show me how to achieve this with regards to what I'm looking for, it would be very much appreciated. I'm absolutely stumped.
Thank you.
Note: CORS restrictons will prevent this from working in most browsers. You can use FireFox Developer Edition, which disables CORS validation.
You can use an XMLHttpRequest to load a local file:
<!DOCTYPE html>
<html>
<body>
<button onclick="readSingleFile()">Click Me</button>
<div id="outputdiv"></div>
<script type="text/javascript">
function readSingleFile() {
let xhr = new XMLHttpRequest();
let url = "relative/path/to/file.txt;
if (!url) return;
xhr.onload = dataLoaded;
xhr.onerror = _ => "There was an error loading the file.";
xhr.overrideMimeType("text/plain");
xhr.open("GET",url);
xhr.send();
}
function dataLoaded(e){
var contents = e.target.responseText;
var splited = contents.split(/\r\n|\n|\r|,/g);
for (i=0; i<splited.length; i++){
document.getElementById("outputdiv").innerHTML = document.getElementById("outputdiv").innerHTML + splited[i] + "<br>";
}
</script>
</body>
</html>

Javascript not executing when loaded via XMLHttpRequest but does when loaded with jQuery.load

While converting a script to not require jQuery, I've discovered that if I load my content (a partial html page with html and javascript) via XMLHttpRequest, the javascript in the partial page does not work. But if I load the partial using jQuery.load, it does work.
I've tried digging through jQuery's load function to see if it's doing anything special and nothing jumped out at me. I've been banging my head against the wall and searching for an answer for a couple of days now to no avail.
What am I doing wrong/how can I make it work like it does when loaded with jQuery.load?
EDIT
I got the XMLHttpRequest method to work by splitting out out my javascript from the html in the fragment and loading the javascript using the suggested technique here: https://stackoverflow.com/a/11695198/362958. However, that still does not provide an explanation of why jQuery.load works. Is jQuery umtimately parsing the HTML and doing the same thing for any scripts it finds within the content it loads?
I've set up a plunker (https://plnkr.co/edit/wE9RuULx251C5ARnUbCh) with the following code that demonstrates the issue. Note: once you load the fragment with jQuery, it will continue to work and you'll have to restart the plunk for the XMLHttpRequest method to fail again.
index.html:
<!DOCTYPE html>
<html>
<head>
<script data-require="jquery#*" data-semver="3.0.0" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<h3>Buttons</h3>
<div>
<input type="button" value="Load with XMLHttpRequest" onclick="loadXMLDoc('ajaxContentDiv', 'fragmentToLoad.html');"> (Links do not work if loaded this way... Script from fragmentToLoad.html not loaded in DOM?) <br/><br/>
<input type="button" value="Load with JQuery" onclick="jQuery('#ajaxContentDiv').load('fragmentToLoad.html');"> (Links will work if loaded this way)
</div>
<br/>
<br/>
<br/>
<div id="ajaxContentDiv">Content will load here...</div>
</body>
</html>
script.js:
function loadXMLDoc(targetDivName, url) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", url, true);
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status == 200) {
document.getElementById(targetDivName).innerHTML = xmlhttp.responseText;
}
}
};
xmlhttp.send();
}
fragmentToLoad.html:
<div id="divToBeUpdated">
<span id="stringBox">String here</span>
</div>
<br/>
<h3>Links</h3>
<div>
Link 1<br>
Link 2<br>
Link 3<br>
</div>
<script>
function updateDiv(string){
var stringBox = document.getElementById('stringBox');
stringBox.innerHTML = string;
}
</script>
You can use single .html file, and you are on the correct track by splitting the html content - though you can also split the html content of a single file, rather than requesting two files. #Barmar explains the functionality of jQuery's .load() method at this comment.
script.js
function loadXMLDoc(targetDivName, url) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", url, true);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status == 200) {
// create a `div` elemenent, append response to `div` element
// get specific elements by `id`, append `script` element to `document.body`
var content = document.createElement("div");
content.innerHTML = xmlhttp.responseText
var div = content.querySelector("#htmlContent");
var contentScript = content.querySelector("#contentScript");
var script = document.createElement("script");
script.textContent = contentScript.textContent;
document.getElementById(targetDivName).innerHTML = div.innerHTML;
document.body.appendChild(script);
}
}
};
xmlhttp.send();
}
fragmentToLoad.html
<div id="htmlContent">
<div id="divToBeUpdated">
<span id="stringBox">String here</span>
</div>
<br/>
<h3>Links</h3>
<div class="links">
Link 1
<br>
Link 2
<br>
Link 3
<br>
</div>
</div>
<script type="text/javascript" id="contentScript">
function updateDiv(string) {
var stringBox = document.getElementById('stringBox');
stringBox.innerHTML = string;
}
// attach `click` event to `.link a` elements here
var links = document.querySelectorAll(".links a");
for (var i = 0; i < links.length; i++) {
(function(link, i) {
console.log(i)
link.addEventListener("click", function(e) {
e.preventDefault();
updateDiv("Hello World " + i)
})
})(links[i], i)
}
</script>
plnkr https://plnkr.co/edit/7fLtGRSV7WlH2enLbwSW?p=preview

Scrape html with js

I'm trying to get the html of www.soccerway.com. In particular this:
that have the label-wrapper class I also tried with: select.nav-select but I can't get any content. What I did is:
1) Created a php filed called grabber.php, this file have this code:
<?php echo file_get_contents($_GET['url']); ?>
2) Created a index.html file with this content:
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<meta charset=utf-8 />
<title>test</title>
</head>
<body>
<div id="response"></div>
</body>
<script>
$(function(){
var contentURI= 'http://soccerway.com';
$('#response').load('grabber.php?url='+ encodeURIComponent(contentURI) + ' #label-wrapper');
});
var LI = document.querySelectorAll(".list li");
var result = {};
for(var i=0; i<LI.length; i++){
var el = LI[i];
var elData = el.dataset.value;
if(elData) result[el.innerHTML] = elData; // Only if element has data-value attr
}
console.log( result );
</script>
</html>
in the div there is no content grabbed, I tested my js code for get all the link and working but I've inserted the html page manually.
I see a couple issues here.
var contentURI= 'http:/soccerway.com #label-wrapper';
You're missing the second slash in http://, and you're passing a URL with a space and an ID to file_get_contents. You'll want this instead:
var contentURI = 'http://soccerway.com/';
and then you'll need to parse out the item you're interested in from the resulting HTML.
The #label-wrapper needs to be in the jQuery load() call, not the file_get_contents, and the contentURI variable needs to be properly escaped with encodeURIComponent:
$('#response').load('grabber.php?url='+ encodeURIComponent(contentURI) + ' #label-wrapper');
Your code also contains a massive vulnerability that's potentially very dangerous, as it allows anyone to access grabber.php with a url value that's a file location on your server. This could compromise your database password or other sensitive data on the server.

Why is this JavaScript code giving me error "undefined"?

I also tried using loadXML() of Microsoft, but it doesn't work. It is most likely deprecated. What perceives to be wrong here. Is there any other way to write it?
The HTML code:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>childNode Property</title>
<script type="text/javascript" src="allfeaturetest.js"></script>
</head>
<body>
<h1>childNode Property</h1>
<hr/>
<form name="input">
<input type="button" value="Press me for XML" onclick="return xmlly()"/>
</form>
<div id="pop">
</div>
</body>
</html>
The JavaScript Code:
function xmlly(){
var resul ="";
var dom = new DOMParser();
var xmlDoc = dom.parseFromString("address.xml","application/xml");
var myElem = xmlDoc.getElementsByTagName("address").childNodes;
alert(myElem); //gives me undefined
alert(xmlDoc); //gives me [Object XMLDocument]
document.getElementById("pop").innerHTML = xmlDoc.documentElement.childNodes[0].attributes[0].nodeValue;
}
The XML file :
<address>
<street>Roble Ave</street>
<mtfcc>S1400</mtfcc>
<streetNumber>649</streetNumber>
<lat>37.45127</lat>
<lng>-122.18032</lng>
<distance>0.04</distance>
<postalcode>94025</postalcode>
<placename>Menlo Park</placename>
<adminCode2>081</adminCode2>
<adminName2>San Mateo</adminName2>
<adminCode1>CA</adminCode1>
<adminName1>California</adminName1>
<countryCode>US</countryCode>
</address>
The error shown to me:
Uncaught TypeError: Cannot read property 'nodeValue' of undefined
parseFromString will not load the data from the address.xml file. As the name says, it will only parse an XML doc from a string, like this:
var dom = new DOMParser();
var xmlDoc = dom.parseFromString("<address>test</address>","application/xml");
You'll need a separate XHR (Ajax) request to load the data from that file.
Also, you should be using console.log instead of an alert to debug this. You'll be able to actually see what's in that object (an error message in your case).
If your sole purpose is to read a node, use below functions -
function xmlly()
{
var xmlDoc=loadXMLDoc("address.xml");
var elm = xmlDoc.getElementsByTagName("street")[0]; // tag name you want to read
var node =elm.childNodes[0];
alert(node.nodeValue)
}
function loadXMLDoc(filename)
{
if (window.XMLHttpRequest)
{
xhttp=new XMLHttpRequest();
}
else // code for IE5 and IE6
{
xhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xhttp.open("GET",filename,false);
xhttp.send();
return xhttp.responseXML;
}

Trying to parse xml file for javascript quiz

I am trying to create a javascript quiz, that gets the questions from a xml file. At the moment I am only starting out trying to parse my xml file without any success. Can anyone point me to what I am doing wrong?
<html>
<head>
<title>Test</title>
<script type="text/javascript" src="prototype.js"></script>
</head>
<body>
<div class="spmArr">
</div>
<script type="text/javascript">
var quizXML = '<quiz><Sporsmal tekst="bla bla bla"/><alternativer><tekst>bla</tekst><tekst>bli</tekst><tekst correct="yes">ble</tekst></alternativer><Sporsmal tekst="More blah"/><alternativer><tekst>bla bla</tekst><tekst correct="yes">bli bli</tekst><tekst>ble ble</tekst></alternativer></quiz>'
var quizDOM = $.xmlDOM( quizXML );
quizDOM.find('quiz > Sporsmal').each(function() {
var sporsmalTekst = $(this).attr('tekst');
var qDiv = $("<div />")
.addClass("item")
.addClass("sporsmal")
.appendTo($(".spmArr"));
var sTekst = $("<h2/>")
.html(sporsmalTekst)
.appendTo(qDiv);
});
</script>
</body>
</html>
When I try this in my browser the classes and div are not being created. And the page is just blank. Am i doing something wrong when I intialize the xml?
edited to add prototype.js and close function
Looks like you're forgetting to close your .each call. append ); after the statement for sTekst and your call will parse correctly.

Categories