JavaScript Document.Write Replaces All Body Content When Using AJAX - javascript

I am creating a simple ajax call that retrieves the content of a specified url and writes it to the page. The problem I am having is that it replaces the entire body contents with this information
here is the JS:
(function(){
var mb = window.mb = {};
function get_ad(url, parameters){
var result = "";
var http_request = false;
if (window.XMLHttpRequest) { // Mozilla, Safari,...
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/html');
}
} else if (window.ActiveXObject) { // IE
var avers = ["Microsoft.XmlHttp", "MSXML2.XmlHttp", "MSXML2.XmlHttp.3.0", "MSXML2.XmlHttp.4.0", "MSXML2.XmlHttp.5.0"];
for (var i = avers.length -1; i >= 0; i--) {
try {
http_request = new ActiveXObject(avers[i]);
if (http_request){
break;
}
} catch(e) {}
}
}
if (!http_request) {
alert('Cannot create XMLHTTP instance');
return false;
}
http_request.onreadystatechange = function(){
if (http_request.readyState == 4) {
if (http_request.status == 200) {
gen_output(http_request.responseText);
} else {
alert('Error');
}
}
}
http_request.open('GET', url + parameters, true);
http_request.send(null);
}
function gen_output(ad_content){
document.write("<div id=\"mb_ad\">");
document.write(ad_content);
document.write("</div>");
}
get_ad("http://localhost/test/test.html", "");
})();
and here is the html:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>
<body>
i am text before <br/>
<script type="text/javascript" src="mb.js"></script>
<br />
i am text after
</body>
</html>
using firebug to inspect, i do not see the text before or the text after, just the <div id="mb_ad"> and the content from the test.html page. If i remove the ajax call and just do 3 document.writes the text before and the text after will display properly. jQuery is not an option, I have to do this without the help of a large library as size and speed are of the essence.

You can't use document.write once the document has completed loading. If you do, the browser will open a new document that replaces the current.
Use the innerHTML property to put HTML code inside an element:
function gen_output(ad_content){
document.getElementById('mb_ad').innerHTML = ad_content;
}
Put the element before the script, so that you are sure that it exists when the callback function is called:
i am text before
<div id="mb_ad"></div>
i am text after
<script type="text/javascript" src="mb.js"></script>
It doesn't matter much where you place the script, as nothing will be written to the document where it is.

in case you cant control the remote script you might be able to write something like so:
<script>
var tmp = document.write;
document.write = function () {
document.getElementById('someId').innerHTML = [].concat.apply([], arguments).join('');
};
</script>
<script .....>
document.write = tmp;
Well it is a nasty hack but it seems to work...

var div = document.createElement('div');
div.id = 'mb_ad';
div.innerHTML = ad_content;
Now, you can append this node wherever you want it to be.

you can use <script>document.body.innerHTML+="//Your HTML Code Here";</script>

Same Leon Fedotov answer but more jQuery
{
var old_write = document.write;
var $zone = $('.zone.zone_' + name);
// redefine document.write in this closure
document.write = function () {
$zone.append([].concat.apply([], arguments).join(''));
};
// OA_output[name] contains dangerous document.write
$zone.html(OA_output[name]);
document.write = old_write;
}

I had the same problem with the following code :
$html[] = '<script>
if($("#mf_dialogs").length == 0) {
document.write("<div id=\"mf_dialogs\"></div>");
}
</script>';
The following code replaces document.write efficiently :
$html = '<div id="dialogHolder"></div>
<script>
if($("#mf_dialogs").length == 0) {
document.getElementById("dialogHolder").innerHTML="<div id=\"mf_dialogs\"></div>";
}
</script>';

The way you can emulate document.write somewhat is the following code:
<script>
(function(script) {
var parent = script.parentNode;
var node = document.createTextNode('Surprise!');
parent.replaceChild(node, script);
})(document.currentScript);
</script>
This way you can put arbitrary HTML in place of a script element. If you have a simpler case, like you can wrap a script in another tag, you can do even simpler version.
<script>
document.currentScript.parentElement.innerHTML = 'Surprise!';
</script>

Related

Trouble querying Solr from JavaScript and displaying results, getting nothing

I am trying working off of https://wiki.apache.org/solr/SolJSON tutorial. I have put my url for solr in the code, copied from solr admin query result to make sure the query should return something.
I try typing in "title:Asian" into text box (that field/search term combo returned results in the admin console query) but when the button is hit, textbox just clears and nothing in output spot.
I used the dev tools from [F12] key of browser to check console and see there was no errors given there, such as for syntax, so not due to that.
Perhaps I am understanding how the url for query works or should be here? If I leave out local host part as shown I just get error for not specifying local full path.
Does anyone see anything wrong here, or have any ideas/tips of what more to do to try and solve the issue?
[ If I must do/add anything else to make good/better post here, please do explain so I can fix :) ]
<html>
<head>
<title>Solr Ajax Example</title>
<meta charset="UTF-8">
<script language="Javascript">
// derived from http://www.degraeve.com/reference/simple-ajax-example.php
function xmlhttpPost(strURL)
{
var xmlHttpReq = false;
var self = this;
if (window.XMLHttpRequest) { // Mozilla/Safari
self.xmlHttpReq = new XMLHttpRequest();
}
else if (window.ActiveXObject) { // IE
self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
self.xmlHttpReq.open('POST', strURL, true);
self.xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
self.xmlHttpReq.onreadystatechange = function() {
if (self.xmlHttpReq.readyState == 4) {
updatepage(self.xmlHttpReq.responseText);
}
};
var params = getstandardargs().concat(getquerystring());
var strData = params.join('&');
self.xmlHttpReq.send(strData);
//document.getElementById("raw").innerHTML = strData;
return false;
}
function getstandardargs() {
var params = [
'wt=json'
, 'indent=on'
, 'hl=true'
];
return params;
}
function getquerystring() {
var form = document.forms['f1'];
var query = form.query.value;
qstr = 'q=' + escape(query);
return qstr;
}
// this function does all the work of parsing the solr response and updating the page.
function updatepage(str)
{
document.getElementById("raw").innerHTML = str;
var rsp = eval("("+str+")"); // use eval to parse Solr's JSON response
var html = "<br>numFound=" + rsp.response.numFound;
var first = rsp.response.docs[0];
html += "<br>product name=" + first.name;
var hl = rsp.highlighting[first.id];
if (hl.name != null) { html += "<br>name highlighted: " + hl.name[0]; }
if (hl.features != null) { html += "<br>features highligted: " + hl.features[0]; }
document.getElementById("result").innerHTML = html;
}
</script>
</head>
<body>
<form name="f1" onsubmit='xmlhttpPost("http://localhost:8983/solr/myCore/select?")'>
<p>query: <input name="query" type="text">
<input value="Go" type="submit"></p>
<div id="result"></div>
<p/><pre>Raw JSON String/output: <div id="raw"></div></pre>
</form>
</body>
</html>

document.write() after window.onload [duplicate]

I am creating a simple ajax call that retrieves the content of a specified url and writes it to the page. The problem I am having is that it replaces the entire body contents with this information
here is the JS:
(function(){
var mb = window.mb = {};
function get_ad(url, parameters){
var result = "";
var http_request = false;
if (window.XMLHttpRequest) { // Mozilla, Safari,...
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/html');
}
} else if (window.ActiveXObject) { // IE
var avers = ["Microsoft.XmlHttp", "MSXML2.XmlHttp", "MSXML2.XmlHttp.3.0", "MSXML2.XmlHttp.4.0", "MSXML2.XmlHttp.5.0"];
for (var i = avers.length -1; i >= 0; i--) {
try {
http_request = new ActiveXObject(avers[i]);
if (http_request){
break;
}
} catch(e) {}
}
}
if (!http_request) {
alert('Cannot create XMLHTTP instance');
return false;
}
http_request.onreadystatechange = function(){
if (http_request.readyState == 4) {
if (http_request.status == 200) {
gen_output(http_request.responseText);
} else {
alert('Error');
}
}
}
http_request.open('GET', url + parameters, true);
http_request.send(null);
}
function gen_output(ad_content){
document.write("<div id=\"mb_ad\">");
document.write(ad_content);
document.write("</div>");
}
get_ad("http://localhost/test/test.html", "");
})();
and here is the html:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>
<body>
i am text before <br/>
<script type="text/javascript" src="mb.js"></script>
<br />
i am text after
</body>
</html>
using firebug to inspect, i do not see the text before or the text after, just the <div id="mb_ad"> and the content from the test.html page. If i remove the ajax call and just do 3 document.writes the text before and the text after will display properly. jQuery is not an option, I have to do this without the help of a large library as size and speed are of the essence.
You can't use document.write once the document has completed loading. If you do, the browser will open a new document that replaces the current.
Use the innerHTML property to put HTML code inside an element:
function gen_output(ad_content){
document.getElementById('mb_ad').innerHTML = ad_content;
}
Put the element before the script, so that you are sure that it exists when the callback function is called:
i am text before
<div id="mb_ad"></div>
i am text after
<script type="text/javascript" src="mb.js"></script>
It doesn't matter much where you place the script, as nothing will be written to the document where it is.
in case you cant control the remote script you might be able to write something like so:
<script>
var tmp = document.write;
document.write = function () {
document.getElementById('someId').innerHTML = [].concat.apply([], arguments).join('');
};
</script>
<script .....>
document.write = tmp;
Well it is a nasty hack but it seems to work...
var div = document.createElement('div');
div.id = 'mb_ad';
div.innerHTML = ad_content;
Now, you can append this node wherever you want it to be.
you can use <script>document.body.innerHTML+="//Your HTML Code Here";</script>
Same Leon Fedotov answer but more jQuery
{
var old_write = document.write;
var $zone = $('.zone.zone_' + name);
// redefine document.write in this closure
document.write = function () {
$zone.append([].concat.apply([], arguments).join(''));
};
// OA_output[name] contains dangerous document.write
$zone.html(OA_output[name]);
document.write = old_write;
}
I had the same problem with the following code :
$html[] = '<script>
if($("#mf_dialogs").length == 0) {
document.write("<div id=\"mf_dialogs\"></div>");
}
</script>';
The following code replaces document.write efficiently :
$html = '<div id="dialogHolder"></div>
<script>
if($("#mf_dialogs").length == 0) {
document.getElementById("dialogHolder").innerHTML="<div id=\"mf_dialogs\"></div>";
}
</script>';
The way you can emulate document.write somewhat is the following code:
<script>
(function(script) {
var parent = script.parentNode;
var node = document.createTextNode('Surprise!');
parent.replaceChild(node, script);
})(document.currentScript);
</script>
This way you can put arbitrary HTML in place of a script element. If you have a simpler case, like you can wrap a script in another tag, you can do even simpler version.
<script>
document.currentScript.parentElement.innerHTML = 'Surprise!';
</script>

How in JavaScript fetch line from which the function was called?

The code below shows my almost complete page source (without doctype) and line number from where test() was called. Because code does not contain doctype then I when I do alert(code[line]) I don't get the right line.
<script>
function test(what)
{
var err = new Error;
var line = err.stack.split("\n")[1].split(':')[2];
var code = document.documentElement.outerHTML.split("\n");
console.log(code);
alert(line);
}
test('hello there');
<script>
How do I get 'test('hello there');' from my test function as a string?
The problem is with line numbering. My line returns the correct line number as in the source file, but my code returns page source with different numbering (it misses DOCTYPE and have different line breaks). So the question is: how to get the "real" page source?
A solution is to look not in the whole HTML document but in the right script element. It works but you'd need some care before to use it :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<script>
function test(what) {
var err = new Error;
console.log(err.stack.split("\n"))
var line = err.stack.split("\n")[2].split(':')[1];
var script = document.scripts[0];
var code = (script.innerText||script.textContent).split(/<br>|\n/);
console.log(line);
console.log(code, code.length);
console.log(code[+line]); // this logs "test('hello there');"
}
test('hello there');
</script>
</body>
</html>
The first thing to do would probably be to give an id to your script element instead of relying on the number.
And I really wouldn't use such a thing apart for some short tests.
Demonstration (click "Run with JS")
Here's a working, but ugly solution. Ugly because:
1. Loads the same page again
2. Uses async ajax
<script>
function getSource()
{
var request = new XMLHttpRequest();
request.open('GET', location.href, false);
request.send(null);
if (request.status === 200)
{
return request.responseText;
}
return '';
}
function test(what)
{
var err = new Error;
var line = err.stack.split("\n")[1].split(':')[2];
var code = getSource().split("\n");
alert(code[line-1]);
}
test('hello there');
</script>

How can I parse a text file using javascript

The code below is to read a text file using javascript. it works.
However, I just want to read part of the content.
For example, the content of the file is :"Hello world!"
I just want to display "Hello".
I tried function split(), but it only works on strings. I don't know how to insert it here.
var urls = ["data.txt"];
function loadUrl() {
var urlToLoad = urls[0];
alert("load URL ... " + urlToLoad);
browser.setAttributeNS(xlinkNS, "href", urlToLoad);
}
thank you!!!
I used
jQuery.get('http://localhost/foo.txt', function(data) {
var myvar = data;
});
, and got data from my text file.
Or try this
JQuery provides a method $.get which can capture the data from a URL. So to "read" the html/text document, it needs to be accessible through a URL. Once you fetch the HTML contents you should just be able to wrap that markup as a jQuery wrapped set and search it as normal.
Untested, but the general gist of it...
var HTML_FILE_URL = '/whatever/html/file.html';
$(document).ready(function() {
$.get(HTML_FILE_URL, function(data) {
var fileDom = $(data);
fileDom.find('h2').each(function() {
alert($(this).text());
});
});
});
Try this to read separate words if I understood correctly what you need.
Create a file with the contents "hello world" and browse to it with the example script.
The output is "hello".
<html>
<head>
<input type="file" id="fileinput" />
<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 ct = r.result;
var words = ct.split(' ');
alert(words[0]);
}
r.readAsText(f);
} else {
alert("Failed to load file");
}
}
document.getElementById('fileinput').addEventListener('change', readSingleFile, false);
</script>
</head>
<body>
</body>
</html>
Reading directly has to be with an ajax request due to the javascript restrictions regarding safety.
This code shoudl perform the requested operation:
<html>
<head>
<input type="file" id="fileinput" />
<script type="text/javascript">
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function(){
if(xmlhttp.status==200 && xmlhttp.readyState==4){
var words = xmlhttp.responseText.split(' ');
alert(words[0]);
}
}
xmlhttp.open("GET","FileName.txt",true);
xmlhttp.send();
</script>
</head>
<body>
</body>
</html>
Opening a file in javascript with ajax (without using any framework)
var urls = ["data.txt"];
xhrDoc= new XMLHttpRequest();
xhrDoc.open('GET', urls[0] , async)
if (xhrDoc.overrideMimeType)
xhrDoc.overrideMimeType('text/plain; charset=x-user-defined')
xhrDoc.onreadystatechange =function()
{
if (this.readyState == 4)
{
if (this.status == 200)
{
var data= this.response; //Here is a string of the text data
}
}
}
xhrDoc.send() //sending the request

Need help to improve this largest common substring implementation

I have scanned the web for largest substring implementations to use in my xmlhttp request, however I found that only 1 has worked, in other cases the responsetext hasn't been treated as a string no matter what I have written:
txt = txt + ""; // or
txt = new string(txt);)
This function works, but it is terrible slow. I am just wondering if you code gurus out there could help me improve this algorithm.
The site that I'm calling a xmlhttprequest is looking like this
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title>Index of /</title>
</head>
<body>
<h1>Index of /</h1>
<ul><li> Parent Directory</li>
<li> random/</li>
<li> random_1/</li>
<li> random/</li>
<li> random_1/</li>
<li> random/</li>
<li> random_1/</li>
</ul>
</body></html>
In other words you can strip of all the html tags for better speed, I will just search for the plain text in the html text document.
You can watch the script in action here at tdsoft.se
<html>
<head>
<script type="text/javascript">
var txt;
var buildName = "";
var xmlhttp;
function lcs(a, b) {
var aSub = a.substr(0, a.length-1);
var bSub = b.substr(0, b.length-1);
if (a.length == 0 || b.length == 0) {
return "";
} else if (a.charAt(a.length-1) == b.charAt(b.length-1)) {
return lcs(aSub, bSub) + a.charAt(a.length-1);
} else {
var x = lcs(a, bSub);
var y = lcs(aSub, b);
return (x.length > y.length) ? x : y;
}
}
function loadXMLDoc(url,cfunc)
{
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=cfunc;
xmlhttp.open("GET",url,true);
xmlhttp.send();
}
function myFunction()
{
loadXMLDoc("http://tdsoft.se/testni.html",handleXML);
}
var checkState = function(xmlhttp, callback) {
try{
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
callback();
}
else {
// Check back again 1 sec later
setTimeout(checkState, 1000);
}
}
catch(err){
setTimeout(checkState, 1000);
}
};
function handleXML()
{
checkState(xmlhttp, function() {
txt=xmlhttp.responseText;
buildName = "random";
txt = txt.replace(/<[^>]*>/g, "");
var myvar = "";
myvar = lcs(txt, "random");
document.write(myvar);
});
}
</script>
</head>
<body onLoad="myFunction()">
</body>
</html>
Seems like you would want to take a different approach at this.
I'm not exactly sure the point of what you are trying to do but it seems like something like this would be what you want:
You request a Document
Parse the links in the document and store them in an object keyed by their ids with values being their text
Change your lookup function to go after the link list
Here's a code example (using jQuery for simplicity):
//untested!
var links = {};
function successFunction(data) {
var aTags = data.find('a');
aTags.each(function() {
var $this = $(this);
links[$this.attr('href')] = $this.text();
});
}
function lookup(id) {
return links[id] || '';
}
$.ajax({
url: 'requestPage.htm',
success: successFunction
});
EDIT:
If you want to do this non-jquery you can just replace the following things:
$.ajax to your XMLHttpRequest method
data.find('a') to getElementsByTagName
.each(function(){...}) to var i = aTags.length; while(i--) { links[aTags[i].href] = aTags[i].innerHTML; }

Categories