change the html content after getting it from a url with javascript - javascript

i am using javascript code to get html content from one the pages, while at the same time i also want to change the content i get from html (inside the carttitle id). how can i change the value of id=carttitle on the cartbox.html below dynamically?
this is the code (div where the html will be located)
<!-- index.html -->
<!-- button to trigger the function -->
<button onclick="getcontent('cartbox.html','#cartboxes','#cartbox');">getcontent</button> <!-- the cartbox.html will fill the content below -->
<ul class="cartboxes" id="cartboxes">
</ul>
this is the javascript code function to get the html
// select.js
function getcontent(url, from, to) {
var cached = sessionStorage[url];
if (!from) {
from = "body";
} // default to grabbing body tag
if (to && to.split) {
to = document.querySelector(to);
} // a string TO turns into an element
if (!to) {
to = document.querySelector(from);
} // default re-using the source elm as the target elm
if (cached) {
return to.innerHTML = cached;
} // cache responses for instant re-use re-use
var XHRt = new XMLHttpRequest; // new ajax
XHRt.responseType = 'document'; // ajax2 context and onload() event
XHRt.onload = function() {
sessionStorage[url] = to.innerHTML = XHRt.response.querySelector(from).innerHTML;
};
XHRt.open("GET", url, true);
XHRt.send();
return XHRt;
}
this is the html code that i will get the content from
<!-- cartbox.html -->
<div id="cartbox">
<li>
<div class="cartbox">
<div class="cartboxleft">
<img src="img/search.png" width="60px" height="60px">
</div>
<div class="cartboxright">
<!-- i want to change the value of the carttitle below dynamically -->
<b class="carttitle" id="carttitle">nice Pizza</b>
<p class="cartdescription">Number: <b>1</b></p>
<p class="cartdescription">Price: <b>$ 11.22</b></p>
</div>
<div class="cartboxdelete">
<button class="deletebutton" onclick="deleteitem(this);">X</button>
</div>
</div>
</li>
</div>

You should use responseType = 'text' as document responseType is not recommended to avoids wasting time parsing HTML uselessly. Now regarding your issue, you can do like this:
function getcontent(url, fromSelector, toSelector) {
var cached = sessionStorage[url];
if (cached) {
return toSelector.innerHTML = cached;
}
fromSelector = fromSelector || 'body';
toSelector = toSelector && document.querySelector(toSelector) || document.querySelector(fromSelector);
var XHRt = new XMLHttpRequest();
XHRt.open("GET", url, true);
XHRt.responseType = 'text';
XHRt.onload = function() {
if (XHRt.readyState === XHRt.DONE && XHRt.status === 200) {
toSelector.innerHTML = XHRt.responseText;
document.getElementById('carttitle').innerHTML = 'your new value';
sessionStorage[url] = toSelector.innerHTML; // Now it will work after loading from session storage.
}
};
XHRt.send();
}

Your cache process will not work because you are selecting a property with the brackets operator [] on the session storage object.
Instead use the getItem() method to get the key that you are looking for.
var cached = sessionStorage.getItem(url);
In your second if statement you check to and to.split. Unless the to string has a split property, this will fail. Your intentions here seem unknown. Instead just check for the string to be a valid string instead.
if (to && 'string' === typeof to) {
The part where you create a new instance of XMLHttpRequest will fail because you are missing the parenthesis to call the constructor.
var XHRt = new XMLHttpRequest();
Then in your onload callback you have to save the innerHTML of your result in the session storage using the setItem() method.
But before doing that, select the cart title element with querySelector and change the content of the element if you need it to.
XHRt.onload = function() {
let element = this.response.querySelector(from);
if (element !== null) {
let cartTitle = element.querySelector('#carttitle');
cartTitle.textContent = 'An even better pizza';
let html = element.innerHTML;
to.innerHTML = html;
sessionStorage.setItem(url, html);
}
};

Related

How to clear the value of an input if there is no results or if it has a null value?

I am trying to clear the value of an input depending if it finds or not an id, if it finds an existing id, js updates the value of an input, but if it doesn't it keeps the last one found but I need to have the value clear, can someone tell me what is wrong:
function driverdata(valueid)
{
var numero_id = valueid;
//console.log(valueid)
var idselect = document.getElementById('driver'+id_number).value;
document.getElementById("idinsearch"+ id_number).value = idselect;
//console.log(idselect);
var placa = document.getElementById("searchable"+idselect).value;
console.log(placa);
if (placa != null) {
document.getElementById("placa"+ id_number).value = placa;
} else {
document.getElementById("placa"+ id_number).value = "";
}
}
In the method driverdata you don't define variable id_number so it's undefined when you try get element by id
So if id_number is equal to the parameter of the method you can directly use it
moreover to clear value you are right it's elem.value = ""
withour yout html i can propose you the following one => your script run
function driverdata(numberId)
{
var idselect = document.getElementById('driver'+numberId).value;
document.getElementById("idinsearch"+ numberId).value = idselect;
var placa = document.getElementById("searchable"+idselect).value;
if (placa != null) {
document.getElementById("placa"+ numberId).value = placa;
} else {
document.getElementById("placa"+ numberId).value = "";
}
}
<div onclick="driverdata(1)">
click me<br/>
driver<input id="driver1" value="1"/><br/>
idinsearch<input id="idinsearch1"/><br/>
<div id="searchable1">
input that will be clear <input id="placa1" value="test"/>
</div>
</div>

Replace div contents javascript (no jquery)

Every time a selection is made from a dropdown menu, specific data is pulled from facebook and added to different divs. I am trying to update the contents of the div every time a different selection is made, however at the minute, the contents are just appended on after the initial contents.
This is the code that gets data based on a selection and creates the list from the returned data
<script>
city = document.getElementById("citySelection")
city.addEventListener("change", function() {
var selected = this.value;
var eventsList = document.getElementById("events");
if (selected == "None") {
eventsList.style.display = "none";
} else {
eventsList.style.display = "block";
};
if (selected == 'Bristol') {
getBristolEvents();
};
if (selected == 'Leeds') {
getLeedsEvents();
};
if (selected == 'Manchester') {
getManchesterEvents();
};
if (selected == 'Newcastle') {
getNewcastleEvents();
};
});
function createList(response, listId) {
var list = document.createElement('UL')
for (var i = 0; i < 10; i++) {
var events = response.data[i].name
var node = document.createElement('LI');
var textNode = document.createTextNode(events);
node.appendChild(textNode);
list.appendChild(node)
listId.appendChild(list);
}};
</script
This is the div being targeted:
<html>
<div id="events" style="display: none">
<div id="eventsDiv" style="display: block">
<div id="eventsListOne">
<h3 id='headerOne'></h3>
</div>
<div id="eventsListTwo">
<h3 id='headerTwo'></h3>
</div>
<div id="eventsListThree">
<h3 id='headerThree'></h3>
</div>
</div>
</div>
</div>
</html>
I have tried resetting the innerHtml of the div every time the function to get the data from facebook is called:
<script>
function getEventsThree(fbUrl, title) {
var listId = document.getElementById('eventsListThree');
var headerThree = document.getElementById('headerThree');
listId.innerHtml = "";
headerThree.append(title)
FB.api(
fbUrl,
'GET', {
access_token
},
function(response) {
listId.innerHtml = createList(response, listId)
}
)};
</script>
However, that still doesn't reset the contents of the div.
I've looked at other response but they all use jquery which I am not using.
Can anyone advise on the best way to fix this? Thanks.
I think your Hennessy approach is fine. Generate the inner content, then set .innerHTML.
At least one of your problems, maybe the only one, appears to be that you set .innerHTML to the return value of createList, but that function does not return anything.

Restore exact innerHTML to DOM

I'd like to save the html string of the DOM, and later restore it to be exactly the same. The code looks something like this:
var stringified = document.documentElement.innerHTML
// later, after serializing and deserializing
document.documentElement.innerHTML = stringified
This works when everything is perfect, but when the DOM is not w3c-comliant, there's a problem. The first line works fine, stringified matches the DOM exactly. But when I restore from the (non-w3c-compliant) stringified, the browser does some magic and the resulting DOM is not the same as it was originally.
For example, if my original DOM looks like
<p><div></div></p>
then the final DOM will look like
<p></p><div></div><p></p>
since div elements are not allowed to be inside p elements. Is there some way I can get the browser to use the same html parsing that it does on page load and accept broken html as-is?
Why is the html broken in the first place? The DOM is not controlled by me.
Here's a jsfiddle to show the behavior http://jsfiddle.net/b2x7rnfm/5/. Open your console.
<body>
<div id="asdf"><p id="outer"></p></div>
<script type="text/javascript">
var insert = document.createElement('div');
var text = document.createTextNode('ladygaga');
insert.appendChild(text);
document.getElementById('outer').appendChild(insert);
var e = document.getElementById('asdf')
console.log(e.innerHTML);
e.innerHTML = e.innerHTML;
console.log(e.innerHTML); // This is different than 2 lines above!!
</script>
</body>
If you need to be able to save and restore an invalid HTML structure, you could do it by way of XML. The code which follows comes from this fiddle.
To save, you create a new XML document to which you add the nodes you want to serialize:
var asdf = document.getElementById("asdf");
var outer = document.getElementById("outer");
var add = document.getElementById("add");
var save = document.getElementById("save");
var restore = document.getElementById("restore");
var saved = undefined;
save.addEventListener("click", function () {
if (saved !== undefined)
return; /// Do not overwrite
// Create a fake document with a single top-level element, as
// required by XML.
var parser = new DOMParser();
var doc = parser.parseFromString("<top/>", "text/xml");
// We could skip the cloning and just move the nodes to the XML
// document. This would have the effect of saving and removing
// at the same time but I wanted to show what saving while
// preserving the data would look like
var clone = asdf.cloneNode(true);
var top = doc.firstChild;
var child = asdf.firstChild;
while (child) {
top.appendChild(child);
child = asdf.firstChild;
}
saved = top.innerHTML;
console.log("saved as: ", saved);
// Perform the removal here.
asdf.innerHTML = "";
});
To restore, you create an XML document to deserialize what you saved and then add the nodes to your document:
restore.addEventListener("click", function () {
if (saved === undefined)
return; // Don't restore undefined data!
// We parse the XML we saved.
var parser = new DOMParser();
var doc = parser.parseFromString("<top>" + saved + "</top>", "text/xml");
var top = doc.firstChild;
var child = top.firstChild;
while (child) {
asdf.appendChild(child);
// Remove the extra junk added by the XML parser.
child.removeAttribute("xmlns");
child = top.firstChild;
}
saved = undefined;
console.log("inner html after restore", asdf.innerHTML);
});
Using the fiddle, you can:
Press the "Add LadyGaga..." button to create the invalid HTML.
Press "Save and Remove from Document" to save the structure in asdf and clear its contents. This prints to the console what was saved.
Press "Restore" to restore the structure that was saved.
The code above aims to be general. It would be possible to simplify the code if some assumptions can be made about the HTML structure to be saved. For instance blah is not a well-formed XML document because you need a single top element in XML. So the code above takes pains to add a top-level element (top) to prevent this problem. It is also generally not possible to just parse an HTML serialization as XML so the save operation serializes to XML.
This is a proof-of-concept more than anything. There could be side-effects from moving nodes created in an HTML document to an XML document or the other way around that I have not anticipated. I've run the code above on Chrome and FF. I don't have IE at hand to run it there.
This won't work for your most recent clarification, that you must have a string copy. Leaving it, though, for others who may have more flexibility.
Since using the DOM seems to allow you to preserve, to some degree, the invalid structure, and using innerHTML involves reparsing with (as you've observed) side-effects, we have to look at not using innerHTML:
You can clone the original, and then swap in the clone:
var e = document.getElementById('asdf')
snippet.log("1: " + e.innerHTML);
var clone = e.cloneNode(true);
var insert = document.createElement('div');
var text = document.createTextNode('ladygaga');
insert.appendChild(text);
document.getElementById('outer').appendChild(insert);
snippet.log("2: " + e.innerHTML);
e.parentNode.replaceChild(clone, e);
e = clone;
snippet.log("3: " + e.innerHTML);
Live Example:
var e = document.getElementById('asdf')
snippet.log("1: " + e.innerHTML);
var clone = e.cloneNode(true);
var insert = document.createElement('div');
var text = document.createTextNode('ladygaga');
insert.appendChild(text);
document.getElementById('outer').appendChild(insert);
snippet.log("2: " + e.innerHTML);
e.parentNode.replaceChild(clone, e);
e = clone;
snippet.log("3: " + e.innerHTML);
<div id="asdf">
<p id="outer">
<div>ladygaga</div>
</p>
</div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Note that just like the innerHTML solution, this will wipe out event handlers on the elements in question. You could preserve handlers on the outermost element by creating a document fragment and cloning its children into it, but that would still lose handlers on the children.
This earlier solution won't apply to you, but may apply to others in the future:
My earlier solution was to track what you changed, and undo the changes one-by-one. So in your example, that means removing the insert element:
var e = document.getElementById('asdf')
console.log("1: " + e.innerHTML);
var insert = document.createElement('div');
var text = document.createTextNode('ladygaga');
insert.appendChild(text);
var outer = document.getElementById('outer');
outer.appendChild(insert);
console.log("2: " + e.innerHTML);
outer.removeChild(insert);
console.log("3: " + e.innerHTML);
var e = document.getElementById('asdf')
snippet.log("1: " + e.innerHTML);
var insert = document.createElement('div');
var text = document.createTextNode('ladygaga');
insert.appendChild(text);
var outer = document.getElementById('outer');
outer.appendChild(insert);
snippet.log("2: " + e.innerHTML);
outer.removeChild(insert);
snippet.log("3: " + e.innerHTML);
<div id="asdf">
<p id="outer">
<div>ladygaga</div>
</p>
</div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Try utilizing Blob , URL.createObjectURL to export html ; include script tag in exported html which removes <div></div><p></p> elements from rendered html document
html
<body>
<div id="asdf">
<p id="outer"></p>
</div>
<script>
var insert = document.createElement("div");
var text = document.createTextNode("ladygaga");
insert.appendChild(text);
document.getElementById("outer").appendChild(insert);
var elem = document.getElementById("asdf");
var r = document.querySelectorAll("[id=outer] ~ *");
// remove last `div` , `p` elements from `#asdf`
for (var i = 0; i < r.length; ++i) {
elem.removeChild(r[i])
}
</script>
</body>
js
var e = document.getElementById("asdf");
var html = e.outerHTML;
console.log(document.body.outerHTML);
var blob = new Blob([document.body.outerHTML], {
type: "text/html"
});
var objUrl = window.URL.createObjectURL(blob);
var popup = window.open(objUrl, "popup", "width=300, height=200");
jsfiddle http://jsfiddle.net/b2x7rnfm/11/
see this example: http://jsfiddle.net/kevalbhatt18/1Lcgaprc/
MDN cloneNode
var e = document.getElementById('asdf')
console.log(e.innerHTML);
backupElem = e.cloneNode(true);
// Your tinkering with the original
e.parentNode.replaceChild(backupElem, e);
console.log(e.innerHTML);
You can not expect HTML to be parsed as a non-compliant HTML. But since the structure of compiled non-compliant HTML is very predictable you can make a function which makes the HTML non-compliant again like this:
function ruinTheHtml() {
var allElements = document.body.getElementsByTagName( "*" ),
next,
afterNext;
Array.prototype.map.call( allElements,function( el,i ){
if( el.tagName !== 'SCRIPT' && el.tagName !== 'STYLE' ) {
if(el.textContent === '') {
next = el.nextSibling;
afterNext = next.nextSibling;
if( afterNext.textContent === '' ) {
el.parentNode.removeChild( afterNext );
el.appendChild( next );
}
}
}
});
}
See the fiddle:
http://jsfiddle.net/pqah8e25/3/
You have to clone the node instead of copying html. Parsing rules will force the browser to close p when seeing div.
If you really need to get html from that string and it is valid xml, then you can use following code ($ is jQuery):
var html = "<p><div></div></p>";
var div = document.createElement("div");
var xml = $.parseXML(html);
div.appendChild(xml.documentElement);
div.innerHTML === html // true
You can use outerHTML, it perseveres the original structure:
(based on your original sample)
<div id="asdf"><p id="outer"></p></div>
<script type="text/javascript">
var insert = document.createElement('div');
var text = document.createTextNode('ladygaga');
insert.appendChild(text);
document.getElementById('outer').appendChild(insert);
var e = document.getElementById('asdf')
console.log(e.outerHTML);
e.outerHTML = e.outerHTML;
console.log(e.outerHTML);
</script>
Demo: http://jsfiddle.net/b2x7rnfm/7

"FORBIDDEN You don't have permission to access /greenfloyd/php/bm_edit_xml.php on this server."

I've been sweating over this the last three days, I am baffled!
The input html launches an xml scan of a web site to gather text, images and links which populate a form for the user to select what they want to save. (The output eventually becomes a bookmark stored at greenfloyd.org.) The problem began a month or so ago, the scan started crashing with a "Forbidden 403" error pointing to my php code file, on the gf server (dir/file permission at 0644). The problem revolves around the links (url and text) gathered and placed into a box , the url is put in the value, and the link text into the innerHTML. The default is that none of the links are selected, the user can then select one or more links from this box, or manually add a link via two fields that get put into the select box, and become part of the form.
<form id = "bmInputForm" onsubmit = "bmSub(); return false;" onreset = "bmInputFormReset();" action = "http://greenfloyd.org/greenfloyd/php/bm_input_xml.php" method = "post" enctype = "multipart/form-data" class = "readerBox">...
<code><input type = "url" id = "link1Url" class = "input_size" size = "40" maxlength = "250" value ="" onclick = "this.select();" title = "Enter a standard url for this related link.">
<input id = "link1Title" class = "input_size" size = "40" maxlength = "150" value = "" onclick = "this.select();" title = "Enter a short title for this related link.">
<button type = "button" onclick = "relatedAdd()" title = "Add to related links list.">[+]</button>
<hr style="width:25%;">
<select id = "relatedSelect" name = "related_select[]" multiple title = "To select/unselect hold down the Ctrl key and click an option." onchange = "relatedCheck();" style = "width:80%;"></select></code>
The scan is an ajax xml call and returns elements from the target url, including the following:
<code>//echo "<related url='".rawurlencode($valid_url)."' txt='".htmlspecialchars($related_text, ENT_QUOTES,'UTF-8')."'></related>";
err = false;
try { var relatedNode = ( xmlDoc.getElementsByTagName("related") ) ? xmlDoc.getElementsByTagName("related") : false; }
catch(err) { err = true; relatedNode = false; }
result += ( !relatedNode ) ? "<li>Scanner unable to retrieve relatedNode || "+err+"</li>" : "<li>Link scan found: "+relatedNode.length+" entries.</li>";
if( relatedNode.length > 0 )
{
clearCache("relatedSelect");
var selObj = document.getElementById("relatedSelect");
for(var i = 0; i < relatedNode.length; i++)
{
val = unescape(relatedNode[i].getAttribute("url"));
str = unescape(relatedNode[i].getAttribute("txt"));
opt = document.createElement("option");
opt.value = val;
opt.innerHTML= ( str.length > 50 ) ? str.substring(0,48)+"..." : str;
selObj.appendChild(opt);
}
}
</code>
All the above is working fine. But everything goes south at submit time when the urls, (the value), are external relative to greenfloyd.org. Then, I get the "Go away and don't come back message..." On the other hand, if the urls point to greenfloyd there's no problem and the bookmark is published, with links. It's almost like I were trying to call the local script from some other domain. The uls are not in any linkable context, they are treated as plain text in the value attribute of the option. Although I do combine the url with the text using a seperator (,) between them so that php can unpack the value to produce seperate url and text fields that are stored on msqli... it's hacky, but it works, or at least it use to and I've yet to find a better alternative. One other odd thing: when I gather the links in greenfloyd.org there are a couple external links and they are accepted!?
<code>
function bmSub()
{
...
var selObj = document.getElementById("relatedSelect");
var url, txt, val, sendCt=0;
for ( var i = 0; i < selObj.options.length; i++ )
{
if ( selObj.options[i].selected )
{
url = selObj.options[i].value.trim();
txt = selObj.options[i].innerHTML;
val = url+"*,*"+txt; // pack url and txt into the value attribute, php unpacks it into 2 db fields
selObj.options[i].value = val;
sendCt +=1;
}
}
resultDisplay("Link count: "+sendCt);
var formElement = document.getElementById("bmInputForm");
var formData = new FormData(formElement);
var urlX = encodeURI("http://greenfloyd.org/greenfloyd/php/bm_input_xml.php?sid="+Math.random());
xmlObj = GetXmlHttpObject();
xmlObj.open("POST", urlX, false);
xmlObj.send(formData);
// pause echo "<return err='$err' msg='$msg'></return>";
try
{
xmlDoc = xmlObj.responseXML;
var returnNode = xmlDoc.getElementsByTagName("return");
err = ( returnNode[0].getAttribute("err") == "1" ) ? true : false;
msg = unescape(returnNode[0].getAttribute("msg"));
}
catch(e)
{
msg = "bmSub status : "+e+"<br>xml: "+xmlObj.statusText+", "+xmlObj.status+", size: "+xmlObj.responseText.length;
err = true;
}
resultDisplay(msg);
if ( err ) return;
</code>

Need help Ajax / Javascript

I'm stumped on this one. I am going to have an unknown number of hidden and unhidden (depending the amount of information the user has in my database) with an Onclick function. when each of the unhidden div's are clicked i pass the value of them through AJAX and grab some text from a php file.
function selectProduct(index) {
var option = document.getElementById('sel'+index).value;
var queryStringOne = "?option="+option;
http.open("GET", "product.php" +
queryStringOne, true);
http.onreadystatechange = getHttpResOne+index;
http.send(null);
}
function getHttpResOne(index) {
if (http.readyState == 4) {
resOne = http.responseText; // These following lines get the response and update the page
document.getElementById('prohidden'+index).innerHTML = resOne;
}
}
HTML
<div id="sel1" value="sel1" onClick="selectProduct(1); return false;">Select Item</div>
<div id="prohidden1" class="sel"></div> <!-- hidden -->
<div id="sel2" value="sel2" onClick="selectProduct(2); return false;">Select Item</div>
<div id="prohidden2" class="sel"></div><!-- hidden -->
I need the response text from each div clicked, to replace the hidden div right underneath it. I am having trouble passing the (index) to the getHttpRequestOne() function.
You can always add custom properties to the native objects. It might not be the best way. but you can try this.
function selectProduct(index) {
var option = document.getElementById('sel'+index).value;
var queryStringOne = "?option="+option;
http.open("GET", "product.php" +
queryStringOne, true);
http.onreadystatechange = getHttpResOne;
http.myCustomValue = index;
http.send(null);
}
function getHttpResOne() {
if (http.readyState == 4) {
resOne = http.responseText; // These following lines get the response and update the page
var index = http.myCustomValue;
document.getElementById('prohidden'+index).innerHTML = resOne;
}
}

Categories

Resources