How to update innerHTML without modifying the entire content? - javascript

I have a javascript (AJAX) that periodically makes an XMLHttpRequest to get some data from a PHP file and append the returned data to the innerHTML of a <p> tag. However, every time the new content gets added to the block, the entire content of the paragraph seems to reload: when I select some text, the selection disappears when the data is updated.
Here's the code:
<script>
function requestChange(){
setInterval(updateData, 2000);
}
function updateData(){
var req = new XMLHttpRequest();
var url = "content_provider.php";
req.open("POST", url, true);
req.send();
req.onreadystatechange = function(){
if(req.readyState == 4 && req.status == 200){
var data = req.responseText;
//updating the innerHTML content
document.getElementById('data').innerHTML += data;
}
};
}
</script>
<body onload="requestChange()">
<p id="data"></p>
</body>
How do I make the change in the innerHTML static?

You can try .insertAdjacentHTML()
It's what you need in this case because insertAdjacentHTML inserts the resulting nodes into the DOM tree at a specified position (first parameter), but does not reparse the hole tree.
document.getElementById('data').insertAdjacentHTML('beforeend', data);

Unfortunately using innerHTML will always destroy the previous content, if you are using jQuery you can instead use the append method, you haven't mentioned jQuery, so I'll assume that you're not using it.
You can instead use insertAdjacentHTML() instead of innerHTML, this method requires you to pass one of the positions below as the first argument and then the text you wish to add.
'beforebegin' // Before the element itself.
'afterbegin' // Just inside the element, before its first child.
'beforeend' //Just inside the element, after its last child.
'afterend' //After the element itself.
In your case here's how it would look:
document.getElementById('data').insertAdjacentHTML('beforeend', html_to_insert);

I didn't tested it but I think, this will work if you append a new container everytime you receive a new response:
function requestChange(){
setInterval(updateData, 2000);
}
function updateData(){
var req = new XMLHttpRequest();
var url = "content_provider.php";
req.open("POST", url, true);
req.send();
req.onreadystatechange = function(){
if(req.readyState == 4 && req.status == 200){
var data = req.responseText;
var newInfoBox = document.createElement('SPAN');
newInfoBox.innerHTML = data;
//updating the innerHTML content
document.getElementById('data').appendChild(newInfoBox);
}
};
}
</script>
<body onload="requestChange()">
<p id="data"></p>
</body>

Related

Click on link to navigate another page without header, footer change

my website has fixed header and footer components. I have a link on body page. when i click on link, it should navigate to another page without changing header and footer component. any one have idea about how to achieve it using jquery/javascript.
You can use a XMLHttpRequest directly to your desired html page, like this:
function load_htm()
{
var xml = new XMLHttpRequest();
//here your content to be loaded
var elem = document.getElementById('content');
//here goes your target html file...
url = "/yourfile.htm";
//this is not the better way to, but will clear the element...
elem.innerHTML = '';
if (xml !== null) {
xml.open('GET', url, true);
xml.send();
xml.onreadystatechange = function() {
if (xml.readyState === 4) {
//getting the results and assign to element
response = xml.responseText;
elem.innerHTML = response;
}
}
}
}
html:
<div id="footer"></div>
<div id="link" onclick="load_htm();"></div>
<div id="content"></div>
<div id="header"></div>

How to display image from another page in my page

I want to start a greasemonkey plugin to an existing page. The plugin should fetch and display some images automatically, each image from different pages.
I thought of using jQuery.get("link", function(data)) and hide the page and display the images only but on an average to display 4 images I should load 6 webpages into present webpage it is creating a delay in loading.
Is there any other work around to create a function that loads the page html of all image pages in background or in another tab and get the href of <a> tag's in that page, into my page and load only images into my page?
You can try this solution below.
Just put the URLs you want in the "pages" array. When the script runs, it makes Ajax calls in the background. When they are ready, it searches the source returned for images and picks one randomly. If found, it wraps the image in a link to the page where it found it (or if available, the image's url) and inserts the linked image to the top of the body of your own current page.
You can try the code by pasting it into your browser's JavaScript console and it will add the images to the current page.
You also see a demo here: http://jsfiddle.net/3Lcj3918/3/
//pages you want
var pages =
[
'https://en.wikipedia.org/wiki/Special:Random',
'https://en.wikipedia.org/wiki/Special:Random',
'https://en.wikipedia.org/wiki/Special:Random',
'https://en.wikipedia.org/wiki/Special:Random',
'https://en.wikipedia.org/wiki/Special:Random'
]
//a simple function used to make an ajax call and run a callback with the target page source as an argument when successful
function getSubPageSource(url, successCallback)
{
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function()
{
if (xhr.readyState == 4 && xhr.status == 200)
{
//when source returned, run callback with the response text
successCallback(xhr.responseText);
}
};
//requires a proxy url for CORS
var proxyURL = 'https://cors-anywhere.herokuapp.com/';
xhr.open('GET', proxyURL+url, true);
//set headers required by proxy
xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");
xhr.setRequestHeader("Access-Control-Allow-Origin","https://cors-anywhere.herokuapp.com/");
xhr.send();
}
//a function that extract images from given url and inserts into current page
function injectImagesFrom(url)
{
getSubPageSource(url, function(data)
{
//trim source code to body only
var bodySource = data.substr(data.indexOf('<body ')); //find body tag
bodySource = bodySource.substr(bodySource.indexOf('>') + 1); //finish removing body open tag
bodySource = bodySource.substring(0, bodySource.indexOf('</body')); //remove body close tag
//create an element to insert external source
var workingNode = document.createElement("span");
//insert source
workingNode.innerHTML = bodySource;
//find all images
var allImages = workingNode.getElementsByTagName('img');
//any images?
if (allImages.length > 0)
{
//grab random image
var randomIndex = Math.floor(Math.random() * allImages.length);
var randomImage = allImages.item(randomIndex);
//add border
randomImage.setAttribute('style', 'border: 1px solid red;');
//restrain size
randomImage.setAttribute('width', 200);
randomImage.setAttribute('height', 200);
//check if parent node is a link
var parentNode = randomImage.parentNode;
if (parentNode.tagName == 'A')
{
//yes, use it
var imageURL = parentNode.getAttribute('href');
}
else
{
//no, use image's page's url
var imageURL = url;
}
//add a link pointing to where image was taken from
var aLink = document.createElement("a");
aLink.setAttribute('href', imageURL);
aLink.setAttribute('target', '_blank');
//insert image into link
aLink.appendChild(randomImage);
/* INSERT INTO PAGE */
//insert image in beginning of body
document.body.insertBefore(aLink,document.body.childNodes[0]);
//remove working node children
while (workingNode.firstChild) {
workingNode.removeChild(workingNode.firstChild);
}
//unreference
workingNode = null;
}
});
}
for (var ii = 0, nn = pages.length; ii < nn; ii++)
{
injectImagesFrom(pages[ii]);
}

JQuery append() doesn't append

I've got html structure like this:
<div id="things">
<div class="whatever">
<div class="frame">content</div>
<div class="frame">content</div>
<div class="frame">content</div>
</div>
</div>
And I got JS with JQuery script that works on click on button on that page:
function intsaver(){
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", "intsaver.php", true);
var tosf = $('<div></div>');
$("#things").find(".frame").each(function(){
tosf.append($(this).innerHTML);
alert(''+tosf);
});
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("data=" + tosf.innerHTML);
}
I can see this contents in debugger, they are exactly what I'm looking for. But tosf remains undefined and on server side I recieve undefined.
I've tried some ways, for examle, I appended this itself. As result, div's disappeared from page, but tosf remained undefined.
I believe I've made some obvious mistake.
Change
tosf.append($(this).innerHTML);
To
tosf.append($(this).html());//$(this) a jQuery object
Or
tosf.append(this.innerHTML);//this a dom object
$(this) is a jQuery object not a dom object which doesn't have property innerHTML.Use .html() instead.
Try
function intsaver() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", "intsaver.php", true);
var tosf = $('<div></div>');
$("#things").find(".frame").each(function () {
tosf.append(this.innerHTML); //innerHTML is a property dom element
alert('' + tosf);
});
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send("data=" + tosf.html()); //tosf is a jQuery object os call .html()
}
$(this).innerHTML should be $(this).html(); and tosf.innerHTML should be tosf.html()
Reason is tosf and $(this) are jQuery style and innerHTML is pure javascript.
A bit more explanation 'why .innerHTML' did not work.
As it is stated in the answers, $(this).innerHTML would not work as jQuery does not have that property. But if you tweak your code you can benefit from .innerHTML as well. If you wrap an element with $(element) it creates jQuery specific object and you will need to get the element from it if you want to use .innerHTML like: $(this)[0].innerHTML. As the this is only element in that jQuery array, this.innerHTML will be sufficient, without making $(this). so your code can be:
function intsaver(){
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", "intsaver.php", true);
var tosf = $('<div></div>');
$("#things").find(".frame").each(function(){
tosf.append(this.innerHTML);
alert(''+tosf);
});
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("data=" + tosf[0].innerHTML);}

Get the text from an external HTML document

My goal is to get the text from a HTML document which does not call any functions from my .jsp file.
I've looked around and I thought I had found the answer to my problem but it doesn't seem to be working, and other answers consist of using jQuery (which I am both unfamiliar with and not allowed to use).
This is my code so far:
function getText(divID) {
var w = window.open("test.html");
var body = w.document.body;
var div = document.getElementById(divID);
var textContent = body.textContent || body.innerText;
console.log(textContent);
//div.appendChild(document.createTextNode(textContent));
}
So as you can see, I'm trying to get the body of one HTML document and have it appear in another. Am I on the right tracks?
EDIT: Ok so I seem to have made my problem quite confusing. I call the function in a HTML document called html.html, but I want to get the text from test.html, then have it appear in html.html. It has to be like this because I can't assume that the HTML document I want to read from will include my .jsp file in its head.
At the moment I am getting the following error.
Uncaught TypeError: Cannot read property 'body' of undefined
The reason document.body in the other window is undefined, is because the other window has not loaded and rendered the document yet.
One solution would be to wait for the onload event.
function getText(divID) {
var w = window.open("test.html");
w.addEventListener("load", function() {
var body = w.document.body;
var div = document.getElementById(divID);
var textContent = body.textContent || body.innerText;
console.log(textContent);
});
}
Make sure you run the getText function on a user event like a click, else window.open will fail.
If all you want to do is get the contents of the other window, using AJAX would probably be a better option.
function getText(divID) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 ) {
var body = xhr.response.body;
var div = document.getElementById(divID);
var textContent = body.textContent || body.innerText;
console.log(textContent);
}
};
xhr.open("GET", "test.html", true);
xhr.responseType = "document";
xhr.send();
}

How to get WHOLE content of iframe?

I need to get whole content of iframe from the same domain. Whole content means that I want everything starting from <html> (including), not only <body> content.
Content is modified after load, so I can't get it once again from server.
I belive I've found the best solution:
var document = iframeObject.contentDocument;
var serializer = new XMLSerializer();
var content = serializer.serializeToString(document);
In content we have full iframe content, including DOCTYPE element, which was missing in previous solutions. And in addition this code is very short and clean.
If it is on the same domain, you can just use
iframe.contentWindow.document.documentElement.innerHTML
to get the content of the iframe, except for the <html> and </html> tag, where
iframe = document.getElementById('iframeid');
$('input.test').click(function(){
$('textarea.test').text($('iframe.test').contents());
});
You can get the literal source of any file on the same domain with Ajax, which does not render the html first-
//
function fetchSource(url, callback){
try{
var O= new XMLHttpRequest;
O.open("GET", url, true);
O.onreadystatechange= function(){
if(O.readyState== 4 && O.status== 200){
callback(O.responseText);
}
};
O.send(null);
}
catch(er){}
return url;
}
function printSourceCode(text){
var el= document.createElement('textarea');
el.cols= '80';
el.rows= '20';
el.value= text;
document.body.appendChild(el);
el.focus();
}
fetchSource(location.href, printSourceCode);

Categories

Resources