Jquery function inside dynamically inserted element doesn't work - javascript

I have an index which shows a list of orders with a button that calls a function (to simplify i've reduced the function that button calls to just an alert), but also every minute an ajax function executes that searches for new orders and appends them on top, with the exact same code as the ones initially loaded. The button works perfectly in the elements that are loaded initially but doesn't work at all in the elements generated dynamically.
This is the index with one initial order inside, BEFORE newOrders runs for the first time. The button on that order functions properly
<div id="content">
<div id="pedido_4126" class="pedido">
<h4>Pedido 4126</h4>
<button id="btn4126">Alert</button>
<script>
$("body").on("click","#btn4126",function(){
alert("Pedido 4126");
});
</script>
</div>
</div>
<script>
function newOrders() {
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "simplereq.php", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var response = JSON.parse(this.responseText);
console.log(response);
var element = document.querySelector('#content');
var content = element.innerHTML;
ultimoid = response.ultimoid;
element.innerHTML = response.contenido + content;
}
};
xhttp.send("ultimoid="+encodeURIComponent(ultimoid));
}
setInterval(newOrders, 60000);
</script>
And this is the index when the function has executed once and appended a new order on top:
<div id="content">
<div id="pedido_4255" class="pedido">
<h4>Pedido 4255</h4>
<button id="btn4255">Alert</button>
<script>
$("body").on("click","#btn4255",function(){
alert("Pedido 4255");
});
</script>
</div>
<div id="pedido_4126" class="pedido">
<h4>Pedido 4126</h4>
<button id="btn4126">Alert</button>
<script>
$("body").on("click","#btn4126",function(){
alert("Pedido 4126");
});
</script>
</div>
</div>
<script>
function newOrders() {
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "simplereq.php", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var response = JSON.parse(this.responseText);
console.log(response);
var element = document.querySelector('#content');
var content = element.innerHTML;
ultimoid = response.ultimoid;
element.innerHTML = response.contenido + content;
}
};
xhttp.send("ultimoid="+encodeURIComponent(ultimoid));
}
setInterval(newOrders, 60000);
</script>
As you can see, the button and function are exactly the same, but the one on the new order brought by the ajax call, doesn't work, and the other one still works properly.
EDIT: I have seen the other questions on event binding to dynamically generated elements, and am in fact already applying what I saw in those answers, by binding the function to the descendants of a a static ancestor:
$("body").on("click","#btn4126",function(){
alert("Pedido 4126");
});

Related

Parsing JSON Array to print specific elements

Im currently trying to parse JSON data from this api in JS but im not sure how to. As of right now when I press any buttons to give me the data, it prints the arrays out rather than the specific data I want. Ive tried to use the JSON Parse function to retrieve the specific data but it seems its not working. Any help would be greatly appreciated! URL to the API docs: https://www.balldontlie.io/#get-all-players
//Loads Player Data
function loadPlayers() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("players").innerHTML =
this.responseText;
}
};
xhttp.open("GET", "https://www.balldontlie.io/api/v1/players", true);
var data = JSON.parse(xhttp.responseText);
console.log(data["last_name"])
xhttp.send();
}
//Loads Game Data
function loadGames() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("games").innerHTML =
this.responseText;
}
};
xhttp.open("GET", "https://www.balldontlie.io/api/v1/games", true);
xhttp.send();
}
//Loads Team Data
function loadTeams() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("teams").innerHTML =
this.responseText;
}
};
xhttp.open("GET", "https://www.balldontlie.io/api/v1/teams", true);
xhttp.send();
}
<!DOCTYPE html>
<html>
<body style="background-color:peachpuff;" >
<center>NBA STATS</center>
<center><marquee behavior="scroll" direction="right" scrollamount="12.5">Data Extracted From BDL API</marquee></center>
<center> View API Docs </center>
<script src="main.js"></script>
<div id="players">
<button type="button" onclick="loadPlayers()">View Players</button>
</div>
<div id = "teams" >
<button type="button2" onclick="loadTeams()">View Teams</button>
</div>
<div id ="games">
<button type="button3" onclick="loadGames()">View Games</button>
<div>
</body>
</html>
You should parse JSON in xhttp.onreadystatechange, that's a callback when request data success.
For the players data as example, it is an object with data and meta, and the players is in data key which is an Array, so you need to loop inside the array to print the values that you needed.
Here's the example for loadPlayers(). You can apply the same concept to loadGames and loadTeams, please let me know if you still having questions.
function loadPlayers() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
// parse JSON after response
var players = JSON.parse(this.responseText);
// get 'data' key inside response
var playersData = players.data;
// loop all the players
for (var player of playersData) {
// print last_name to the #players element
document.getElementById("players").innerHTML += "<br />" + player['last_name'];
}
}
};
xhttp.open("GET", "https://www.balldontlie.io/api/v1/players", true);
xhttp.send();
}
In function loadPlayers()
data is an array not object

jQuery inside dynamically generated element doesn't run

I have an index which shows a list of orders, each of which calls a function (named dynamically with PHP when I brought the data from the db), to simplify I've reduced the function that each div contains to just an alert. But also every minute an ajax function executes that searches for new orders and appends them on top, with the exact same code as the ones initially loaded. The jQuery works perfectly in the elements that are loaded initially but doesn't work at all in the elements generated dynamically.
This is the index with one initial order inside, BEFORE newOrders runs for the first time. The alert on that order functions properly
<div id="content">
<div id="pedido_4126" class="pedido">
<h4>Pedido 4126</h4>
<button id="btn4126">Alert</button>
<script>
alert("Pedido 4126");
</script>
</div>
</div>
<script>
function newOrders() {
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "simplereq.php", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var response = JSON.parse(this.responseText);
console.log(response);
var element = document.querySelector('#content');
var content = element.innerHTML;
ultimoid = response.ultimoid;
element.innerHTML = response.contenido + content;
}
};
xhttp.send("ultimoid="+encodeURIComponent(ultimoid));
}
setInterval(newOrders, 60000);
</script>
And this is the index when the function has executed once and appended a new order on top with it's corresponding script, dynamically generated and received from the AJAX call:
<div id="content">
<div id="pedido_4255" class="pedido">
<h4>Pedido 4255</h4>
<button id="btn4255">Alert</button>
<script>
alert("Pedido 4255");
</script>
</div>
<div id="pedido_4126" class="pedido">
<h4>Pedido 4126</h4>
<button id="btn4126">Alert</button>
<script>
alert("Pedido 4126");
</script>
</div>
</div>
<script>
function newOrders() {
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "simplereq.php", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var response = JSON.parse(this.responseText);
console.log(response);
var element = document.querySelector('#content');
var content = element.innerHTML;
ultimoid = response.ultimoid;
element.innerHTML = response.contenido + content;
}
};
xhttp.send("ultimoid="+encodeURIComponent(ultimoid));
}
setInterval(newOrders, 60000);
</script>
As you can see, the html and script are exactly the same, but the one on the new order brought by the ajax call, doesn't work.
Ok, so doing more research I came upon the best answer for my case, I'll leave it here in case it helps someone:
In the content I generate in the AJAX call, I print the scripts like this, and obviously hide it with css:
<div class="javascript">
$("body").on("click","#btn4255",function(){
alert("Pedido 4255");
});
</div>
And then I execute this function every time the AJAX call is returned
$('.javascript').each(function() {
eval($(this).text());
});
I only evaluate strings I generate myself so in this case I think it's not unsafe to use eval().

Can someone help me parse value of element from nested JSON response. I want to display value or "priceInCents" on html page here is my script

Can someone help me parse the value of an element from nested JSON response. I want to display value or "priceInCents" on HTML page here is my script
<!DOCTYPE html>
<html>
<body>
<div id="demo1">
<h1>Product price</h1>
<button type="button" onclick="loadDoc1()">check price</button>
</div>
<script>
function loadDoc1() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var obj = JSON.parse(this.responseText);
document.getElementById("demo1").innerHTML = obj.results.price.priceInCents;
}
};
xhttp.open("GET", "http://search.mobile.walmart.com/search?query=329264833&store=148", true);
xhttp.send();
}
</script>
</body>
</html>
results is an array, so you have to specify that you want the first element of the array.
function loadDoc1() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var obj = JSON.parse(this.responseText);
document.getElementById("demo1").innerHTML = obj.results[0].price.priceInCents;
}
};
xhttp.open("GET", "https://search.mobile.walmart.com/search?query=329264833&store=148", true);
xhttp.send();
}
<div id="demo1">
<h1>Product price</h1>
<button type="button" onclick="loadDoc1()">check price</button>
</div>

How can I load a spinning icon when using xmlhttprequest object

How can I load a spinning icon when using xmlhttprequest in JavaScript while Ajax is processing and I want to direct it to an innerHTML of a tag
Instead of 'Loading...' just use your spinner image and correct the path to your_file.txt to get a response from server:
function loadXMLDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var res = this.responseText;
setTimeout(function(){
document.getElementById("demo").innerHTML = res;
}, 2000);
} else {
document.getElementById("demo").innerHTML = 'Loading...';
}
};
xhttp.open("GET", "your_file.txt", true);
xhttp.send();
}
<div id="demo">
<button type="button" onclick="loadXMLDoc()">Change Content</button>
</div>
You don't need the setTimeout either - it's just for demo purposes, so you can actually see and verify the spinner when the response comes back way to fast, i.e. on localhost.

How do I append HTML from a document loaded with AJAX?

I am trying to append the contents of a .html file to the body of my main page. Basically, I am trying to make a reusable chunk of html that I can load into any page with a simple JavaScript function.
Here is the content of my nav bar, the content I want to reuse:
<div id = "navbar">
<div class = "Tab">
<h1>Home</h1>
</div>
<div class = "Tab">
<h1>Contact</h1>
</div
</div>
That is in a file called navbar.html
Now in my main index.html I want to import it by doing something like this:
<head>
<script src = "importHTML.js" type = "text/javascript"></script>
</head>
<body>
<script type = "text/javascript">
importHTML("navbar.html");
</script>
</body>
That should take care of importing the html in navbar.html.
The content of importHTML.js is this:
function importHTML(url_) {
var request = new XMLHttpRequest();
request.addEventListener("load", function(event_) {
//This is the problem line of code
//How do I get the contents of my response to act like an element?
document.body.appendChild(this.responseText);
}, false);
xmlhttprequest.open("POST", url_, true);
xmlhttprequest.send(null);
}
So, I guess my question is pretty simple: How do I convert that response text to an HTML element so I can append all of it to the body?
Ajax HTML Injection
jQuery $.get() and JavaScript XMLHttpRequest()
This is a demonstration of 2 ways to inject, include, import, etc. There's 3 pages:
index.html
It has 2 links and 2 divs
data1.html
It's data will be imported to index.html by $.get()
data2.html
It's data will be imported to index.html by XMLHttpRequest()
I added jQuery to show the difference in complexity, but they do the same thing. The live demo is at the end of this mess.
jQuery $.get() Setup
HTML on index.html
div#data1 is the element that'll have the HTML of data1.html appended to it.
<h3 id="import1">
Import data1.html by jQuery<code>$.get()</code>
</h3>
<div id="data1"></div>
jQuery on index.html
$('#import1').on('click', function(e) {
e.preventDefault();
$.get('data1.html', function(data) {
$("#data1").html(data);
});
});
JavaScript XMLHttpRequest() Setup
HTML on index.html
div[data-x] is the element that'll have the HTML of data2.html appended to it.
<h3 id="import2">
<a href="">
Import data2.html by JavaScript<code>XMLHttpRequest()</code>
</a></h3>
<div data-x="data2.html"></div>
javaScript on index.html
function xhr() {
var tags, i, clone, file, xhttp;
tags = document.getElementsByTagName("*");
for (i = 0; i < tags.length; i++) {
if (tags[i].getAttribute("data-x")) {
clone = tags[i].cloneNode(false);
file = tags[i].getAttribute("data-x");
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
clone.removeAttribute("data-x");
clone.innerHTML = xhttp.responseText;
tags[i].parentNode.replaceChild(clone, tags[i]);
xhr();
}
}
xhttp.open("GET", file, true);
xhttp.send();
return;
}
}
}
document.getElementById('import2').addEventListener('click', function(e) {
e.preventDefault();
xhr();
}, false);
README.md
Plunker
Note: This demo relies on user interaction via anchor links. This of course is probably not exactly what you need. You probably want it automatically loaded, so the following modifications are needed:
jQuery
$(function() {
$.get('data1.html', function(data) {
$("#data1").html(data);
});
});
JavaScript
(function xhr() {
xhr();
var tags, i, clone, file, xhttp;
tags = document.getElementsByTagName("*");
for (i = 0; i < tags.length; i++) {
if (tags[i].getAttribute("data-x")) {
clone = tags[i].cloneNode(false);
file = tags[i].getAttribute("data-x");
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
clone.removeAttribute("data-x");
clone.innerHTML = xhttp.responseText;
tags[i].parentNode.replaceChild(clone, tags[i]);
xhr();
}
}
xhttp.open("GET", file, true);
xhttp.send();
return;
}
}
})();
Interestingly there is an upcoming W3C draft for HTML imports
https://www.w3.org/TR/html-imports/
Until then we can append the required markup to the DOM using Javascript.
JQuery approach
$(document).ready(function(){
$( "body" ).load( "navbar.html" );
});
Js haven't native method for this task, but you can use jquery method load
${element}.load('./template.html');
Or, create element-container, and use innerHTML prop
request.addEventListener("load", function(event_) {
//This is the problem line of code
//How do I get the contents of my response to act like an element?
var container = document.createElement("div");
container.innerHTML = this.responseText;
document.body.appendChild(container);
}, false);
UPD
Convert string to DOM.
function strToDom(str) {
var tempEl = document.createElement('div');
tempEl.innerHTML = str;
return tempEl.children[0];
}
NOTE: string element should be one root element, that wraps others
<div> ... </div>
not
<div></div><div></div>
The importHTML.js file will look like this :
function importHTML(url_) {
var request = new XMLHttpRequest();
request.addEventListener("load", function(event_) {
var iDiv = document.createElement('div');
iDiv.innerHTML = this.responseText;
document.getElementsByTagName('body')[0].appendChild(iDiv);
}, false);
request.open("POST", url_, true);
request.send(null);
}
I assume you can create a div and then modify the div.innerHTML to have the content of the response:
function importHTML(url_) {
var request = new XMLHttpRequest();
request.addEventListener("load", function(event_) {
var myDiv = document.createElement("div")
myDiv.innerHTML = this.responseText
document.body.appendChild(myDiv);
}, false);
xmlhttprequest.open("POST", url_, true);
xmlhttprequest.send(null);
}
you need a reference to DOM to know where to innest your loaded page. in your case you could think about appending it to body like this:
function importHTML(url_) {
var request = new XMLHttpRequest();
request.addEventListener("load", function(event_) {
document.body.innerHTML += this.responseText
}, false);
xmlhttprequest.open("POST", url_, true);
xmlhttprequest.send(null);
}

Categories