Handlebars duplicating ajax output on click - javascript

I'm using Handlebars to print out a list of books, where if you click on the title of a book you get a new div showing details. I'm able to print out the list and click on the book title to get details, but every title I click outputs the details from the first book that I clicked instead of the details for that book itself. I believe this has something to do with binding but haven't found a syntax that seems to work. Here's my HTML & Handlebars code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Library</title>
</head>
<body>
<div class="main"> <div id="book-list-items"></div></div>
<div id="book-details-items"></div>
<script src="js/jquery-1.11.1.min.js"></script>
<script src="js/handlebars-v1.3.0.js"></script>
<script src="js/main.js"></script>
<script id="book-list-template" type="text/x-handlebars-template">
<div class="book-list">
<h3 class='template title'>{{title}}</h3>
</div>
</script>
<script id="book-details-template" type="text/x-handlebars-template">
<div class="book-details">
<h3 class='template title'>{{title}}</h3>
<h4 class='template year'>{{year}}</h4>
<h4 class='template rating'>{{rating}}</h4>
</div>
</script>
</body>
</html>
And here's the JavaScript:
$(document).ready(function(){
var source = $('#book-list-template').html();
var source2 = $('#book-details-template').html();
var template = Handlebars.compile(source);
var template2 = Handlebars.compile(source2);
$.ajax({
type:'GET',
url: 'https://....',
data:{ api_key: '....'
}
}).done(
function(data){
populate_template(data)
});
var populate_template = function(data){
data.results.forEach(function(book){
var html = $(template(book));
$('.main').append(html);
html.click({book:book}, book_info)
})
}
var book_info = function(event){
id = event.data.book.id
$.ajax({
type:'GET',
url: 'https://....' + id,
data:{ api_key: '....'
}
}).done(function(data){
var html2 = template2(data);
$(document).trigger('change', event.currentTarget);
$(document).on('change', function(e, listing){
e.preventDefault();
$(listing).replaceWith(html2)
});
});
};
});
Can anyone tell me where I'm going wrong? I assume it's in the #book-details-template script but am stuck on what the syntax would be.

I suppose because the "change" listener on document stays active from the first call and in the followings call it's duplicated and so on...
Try to eliminate the listener and put the template into the book-details-items:
$("#book-details-items").html(html2);

Related

How to save website source code to a string using js

I need to save the source code of any website in a java script variable. For example, saving Google source code in a variable "GoogleSourceCode".
I tried some ways but I don't have enough knowledge for that.
<html>
<head>
<script src="http://code.jquery.com/jquery-1.12.1.min.js"></script>
</head>
<body>
<div id="container">
<button id="acessaSite">Acessa Site</button>
<button id="pegarHTMLagora">pegar HTML agora</button>
</div>
<script>
$('#acessaSite').on('click', function () {
$.getJSON('http://www.whateverorigin.org/get?url=' + encodeURIComponent('https://google.com.br') + '&callback=?', function(data){
alert(dados.conteudo);
});
});
$('#pegarHTMLagora').on('click', function () {
var htmlAgora = document.documentElement.innerHTML; // Javascript vanilla (sem jquery)
alert(htmlAgora);
});
let htmlPego = document.documentElement.innerHTML;
</script>
</body>
</html>

Add the ability to render comments when the comment-list elements should be filled with text "Loading..." and show results one by one

I'm trying to render results one by one with some text like "Loading..." and show results one by one. I found answers at one, two and tried to solve this but it shows only one loading text and renders, shows all results at a time. The results should appear one after the other, with the order preserved. If any error occurs during the loading, the tag should be left empty. How to solve this challenge? For full question please refer here
HTML
<!DOCTYPE html>
<html>
<head>
<title>Render Comments</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
</head>
<body>
<div class="comment-list" data-count=1></div>
<script type="text/javascript" src="./app.js"></script>
</body>
</html>
JS
"use-strict";
var commentList = $(".comment-list");
var count = $(".comment-list").data("count");
var url = "https://jsonplaceholder.typicode.com/comments?postId=" + count;
$.ajax({
url: url,
method: "GET",
beforeSend: function () {
commentList.html("Loading...");
},
success: function (data) {
commentList.empty();
data.forEach(function (comment) {
commentList.append(`
<div class="comment-item">
<div class="comment-item__username">${comment.id}</div>
<div class="comment-item__message">${comment.name}</div>
</div>`);
});
},
error: function () {
// commentList.empty();
data.forEach(function () {
commentList.append(`
<div class="comment-item">
<div>Oops! Error occured to show the results</div>
</div>`);
});
},
});
You might consider doing this with CSS instead of with javascript. There are many examples including link. If you insist on doing this with javascript you need to break up the code adding the elements to the page using setInterval or setTimeout.

Handlebars not populating template

I have a handlebars template and I'm trying to use it, but when I do, I get all the tags but with no text. Here's my HTML:
<script src="../static/js/main.js"></script>
<script src="https://cdn.jsdelivr.net/npm/handlebars#latest/dist/handlebars.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script>
<script id="template" type="text/x-handlebars-template">
<li class="message">
<h6>{{username}}</h6>
<p>{{message}}</p>
<p>{{date}}</p>
</li>
</script>
And in main.js:
socket.on('message', data => {
console.log('message recieved')
console.log(data.channel)
console.log(document.querySelector("#active").innerHTML)
if (data.channel === document.querySelector("#active").innerHTML) {
console.log(data.sent_by)
console.log(data.message)
console.log(data.time)
var template = Handlebars.compile(document.querySelector('#template').innerHTML);
console.log(document.querySelector('#template').innerHTML)
const context = {'username' : data.sent_by,
'message' : data.message,
'date' : data.time,};
var html = template(context);
console.log(context)
console.log(html)
document.querySelector('#view-message').innerHTML += html
}
})
All log messages are being run so the socket is receiving data and the if condition is being triggered. I've used handlebars in a previous section of the same project and it worked fine there so I'm not sure why it's not working here. Thanks!
move your script <script src="../static/js/main.js"></script> all the way to the bottom

(object Object) being returned as output of onclick function in JQuery when using EJS

So I have a JQuery function that on click of the current input element will change the value of the button. However, I need to be able to get the value of the objects in the li element, denoted by <%= chats[i].msg %>, so I can update my database with the respective data. However on a console.log of the object it keeps returning [object Object]. Is there any way for me to get the data? I'm new to JQuery and EJS so please point me to any duplicates.
JQuery Code
$(document).ready(function(){
$('form').on('submit', function(){ // hit submit
var item = $('form input');
var chat = {msg: item.val(), likes: ''}; //intially the post will have 0 likes
$.ajax({
type: 'POST',
url: '/',
data: chat,
success: function(data){
//do something with the data via front-end framework, so we can update in reall time
console.log(chat);
console.log('success! yes');
location.reload();
}
});
return false;
});
$('.likebutton').on('click', function(){ // hit like
console.log("like clicked?"); // works
// i need to find a way to connect this with code and make it update???
var curr = $('.display').val();
var item = $(this).val('Liked'); // selects approatiate like button
console.log("item: " + item); // return [object Object]?????
$.ajax({ //do something with the data via front-end framework, so we can update in reall time
type: 'GET',
url: '/',
success: function(err){
// here we will get the data, find it in the data base and update it. Changes will occur
// via a reload, either manually or when they create a post, for now. Later we can update
// the thing in real time.
// on click we must also change the color of the thing too to show that it was liked
console.log('success!');
}
});
return false;
});
});
EJS code
<!DOCTYPE html>
<html>
<head>
</head>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script src="/assets/chat.js"></script>
<body>
<h1> Ut whispers</h1>
<form action="/" method="POST">
<input type="text" placeholder = "say something" name="msg"> <input type="submit" value="Submit"> <br>
</form>
<ul>
<% for(var i = 0; i < chats.length; i++) { %>
<li class = "display"><%= chats[i].msg %> <input type="button" id = "changeit" class = "likebutton" value = "Like: (<%=chats[i].likes%>)" >
<ul>
<li>replies will go here</li>
</ul>
</li>
<% } %>
</ul>
</body>
</html>

AJAX: download new content every X seconds using jQuery

I have page with posts. Initially posts was added by server-side code.
I need every 60 seconds download and show new posts from server.
Server can return 0 to N posts. Page returned by server have this format for two posts (most recent on top):
<div class='post' data-id='456'>...</div>
<div class='post' data-id='123'>...</div>
There is my code:
<html>
<head>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
var lastPostID;
$(document).ready(function(){
var j = jQuery.noConflict();
j(document).ready(function() {
setInterval(function(i) {
lastPostID = j(".post div:last").data("id");
console.log(lastPostID, "lastPostID");
j.ajax({
url: "/post/"+lastPostID,
cache: false,
success: function(html){
j("#temp").html(html);
j('#temp').prependTo("#posts");
j("#temp").empty();
}
})
}, 10000)
});
});
</script>
</head>
<body>
<div id="temp" style="display: none;"></div>
<div id="posts">
<div class='post' data-id='100'>...</div>
<div class='post' data-id='20'>...</div>
<div class='post' data-id='1'>...</div>
</div>
</body>
</html>
Can you please recommend me any good jQuery timer plugin?
I see at JS console every 10s:
null "lastPostID"
Where I have an error?
Update:
If I use:
<script>
var divs = document.getElementsByClassName('post');
console.log(divs.length, "divs with class *post*");
for(var i=0; i<divs.length; i++) {
var id = divs[i].getAttribute('data-id');
console.log(id, "lastPostID");
}
</script>
Output is OK:
3 "divs with class *post*" jQuery_div_update.html:37
100 lastPostID jQuery_div_update.html:40
20 lastPostID jQuery_div_update.html:40
1 lastPostID
But with jQuery:
<script>
$(document).ready(function(){
var lastPostID = $(".post div:last").data("id");
console.log(lastPostID, "lastPostID");
});
</script>
Output is bad:
null "lastPostID"
Why?
If you want to poll some external resource (with an AJAX call, for example) you can follow the "Recursive setTimeout pattern" (from https://developer.mozilla.org/en-US/docs/Web/API/Window.setInterval). Example:
(function loop(){
setTimeout(function(){
// logic here
// recurse
loop();
}, 1000);
})();
use setInterval() instead of setTimeout()
something like:
setInterval(function(){
$.ajax({
url: "test.html",
context: document.body
}).done(function() {
//do something
});
},1000*60);
http://www.w3schools.com/jsref/met_win_setinterval.asp
https://api.jquery.com/jQuery.ajax/

Categories

Resources