Ajax: setInterval function doesn't update html (but it works) - javascript

I have several divs in code. I need to update the html inside, based on API request.
It works, but html doesn't refresh (i.e. if I get via API a new result, html remain same of first iterate, but in firebug I can read new HTML ready to inject in page).
$('div.show-gpio-state').each(function(i, obj) {
var id_gpio = $(this).data('id-gpio');
getGpioState(id_gpio,$(this));
setInterval(function(){getGpioState(id_gpio,$(this))}, 5000);
});
function getGpioState(id_gpio,box) {
$.ajax(
{ url: api_gpio_url+id_gpio,
cache:false,
success: function (result) {
box.html('');
var state = result;
var final_state = '';
if ( (state==='error') || (state==='') ) {
final_state = '<span class="text-danger"><i class="fa fa-fw fa-2x fa-exclamation-triangle"></i></span>';
} else {
if (state==1) {
final_state = '<p class="h2"><i class="fa fa-fire text-success"></i></p>';
} else {
final_state = '<p class="h2"><i class="fa fa-remove text-grey"></i></p>';
}
}
box.html('');
box.html(final_state);
// here in console I have right final state for right box
console.log(final_state);
console.log(box);
}
});
}

Change this
setInterval(function(){getGpioState(id_gpio,$(this))}, 5000);
to
setInterval(function(){getGpioState(id_gpio,$(this))}.bind(this), 5000);
or assign $(this) to variable and pass inside setInterval function

You could fix it like:
setInterval((function(_this){
return function(){
getGpioState(id_gpio,$(_this));
};
}(this)), 5000);
The issue is related to how scope and this keyword works in JavaScript.
Or you could even simply use a variable:
$('div.show-gpio-state').each(function(i, obj) {
var id_gpio = $(this).data('id-gpio');
var $this = $(this);
getGpioState(id_gpio,$this);
setInterval(function(){getGpioState(id_gpio,$this)}, 5000);
});
To learn more about the issue you could read this post: Understand JavaScript’s “this” With Clarity, and Master It

Related

Call javascript function when anchor tag(#) in html link is accessed or reloaded

I have a function that create a html page
function createVisuUsuario() {
var content = document.createElement("div");
content.className = "content";
content.id = "content-add";
content.innerHTML = '<h1>Visualizar Usuário</h1>'+
'<form>'+
'<br>'+
'<div id="res-visu"></div>'+
'</form>';
document.body.appendChild(content);
}
An another function that calls the function above and this uses ajax to connect to the php and bring information from the database
function visuUser() {
limpaTela();
createVisuUsuario();
var res_visu = $("#res-visu");
$.ajax ({
url: "php/cadastro.php",
type: "POST",
data: {"chave":"visu-teste"},
success: function(res) {
var str = res.substring(1,0);
res = res.substring(1);
if(str == 0) {
res_visu.html(res);
res_visu.css("text-align","center");
tabelaFiltro();
}
else if(str == 1) {
res_visu.html(res);
res_visu.css("color","red");
}
},
error: function() {
console.log("erro");
}
});
});
i have a button that calls this function when click it and put an anchor tag on the html link:
Button:
<a id="visu-user" class="menu-link">Visualizar Usuário</a>
link
localhost/teste.php#visu-user
Is there a possibility to when i access this link "localhost/teste.php#visu-user" or reload it, it calls my function visuUser() and create the page and etc.
You can first make an onload function, that does what Abbas says:
function check_hash() {
if(location.hash == '#visu-user') visuUser();
}
$(check_hash);
The you might want to bind the same function to the hashchanged event:
$(window).bind('hashchange', check_hash);
Perhaps you want to load other pages as well in this manner.
Actually, you then could simply change your button to:
Visualizar Usuário
Then you don't need a handler for your button: the hashchanged event will do it for you!
You can get the hash value using js, and check if it corresponds to the correct string like this:
if(location.hash == '#visu-user'){
visuUser();
}

Append the last message once

Hello guys i am trying to build a chat with Jquery , php , ajax and mysql
the problem that i am facing since few days is that when i get the value of the last message its keep getting append to the div what i want is to append the last message only once , and append again if there is a new message here is my ajax call
var chat = "";
$.ajax({
url: "php/gt_user.php",
type: "get",
success: function (result) {
var gtUser = $.parseJSON(result);
$.each(gtUser, function (idx, obj) {
var usrApp = "<span><i class='fa fa-user-circle-o' aria-hidden='true'></i>";
usrApp += "<p class='usr-name'>" + obj.Tables_in_chat + "</p></span>";
$('.userarea').append(usrApp);
}); // here i get all the username who sent a message and print them on a div
$('.userarea span').on('click', function () {
$('.msgarea').html("");
var usrName = $(this).text();
$('#usrname').text(usrName);
setInterval(function () {
$.ajax({
url: "php/admin_msg.php",
type: "post",
data: {
name: usrName
},
success: function (result) {
var lastmsg = result;
function appedn() {
var usrMsg = "<div class='usr-msg'><i class='fa fa-user-circle-o' aria-hidden='true'></i>";
usrMsg += "<span><p>" + lastmsg + "</p></span></div>";
$('.msgarea').append(usrMsg);
}
if (chat !== result) {
appedn();
} else {
chat = result;
}
}
});
}, 2000);
});
}
});
the respanse from php/admin_msg.php is working and i got the last message sucessfully the problem is that this script keep adding the same message to the message area , and what i want is to added the message only once if there is a new one
You need to somehow identify last message that is already appended to your html the best would be some id sent from server. So your message div should containt some data-id attribute, and then when you ask for next message get last children of $('.msgarea') element, read it data-id and compare with current one.
Another thing I would recommend to moving to some view library or framework, react, angular, vue or whatever. It gets complicated when you want to manage such features with pure jQuery.
i was finally able to fix the problem after 1 day of struggle so will post the answear here just in case it will help some one else facing the same issue
the part where i had to get all the username table from database i move it to my HTML and used a few line of php to echo the result like this(each user name has his own table)
// show all the user name that sent a message
$result = $con->query("show tables from chat");
while($row = mysqli_fetch_assoc($result)){
echo "<span><i class='fa fa-user-circle-o' aria-hidden='true'></i><p class='usr-name'>".$row['Tables_in_chat']."</p></span>";
}
then on my jquery script i moved the function that check for the last message every 2sec outside the click event so my Jquery script look more cleaner now
/* get the user name and added it to the header of the message box */
$('.userarea span').on('click', function () {
$('.msgarea').html("");
var usrName = $(this).text();
$('#usrname').text(usrName);
});
var chatdata = "";
/* check for new message and append the message area if there is a new one */
setInterval(function () {
var usrName = $('#usrname').text();
$.ajax({
url: "php/admin_msg.php",
type: "post",
data: {
name: usrName
},
success: function (result) {
function appedn() {
var usrMsg = "<div class='usr-msg'><i class='fa fa-user-circle-o' aria-hidden='true'></i>";
usrMsg += "<span><p>" + result + "</p></span></div>";
$('.msgarea').append(usrMsg);
}
if (chatdata !== result) {
appedn();
chatdata = result;
}
}
});
}, 2000);

Javascript. Creating two buttons with different urls. But the last button made overwrites the old button

My code have a button that can print a file to a pdf form (it works fine). Now I want to add another button that just print it in a html page. I have added the new button and it works too.
The problem is that now when I have created a new button, it will now overwrite it method on the old one. So both button will do the same thing. (Both print it in html form)
Here are some part of my code:
The function for the invoice datatable looks like this:
function invoiceDatatable(tableId, extras, url, optionParser) {
var options = $.extend(true, {}, documentOptions, {
tableId: tableId,
url: url || '/api/invoices/?type=i',
extras: extras
});
Here i create both buttons, with their url - the code always use the last created one:
options.tasks.push({
url: '/print_to_pdf',
queryParam: 'documents',
label: '<i class="fa fa-print"></i> Print pdf'
});
options.tasks.push({
url: '/print_to_html',
queryParam: 'documents',
label: '<i class="fa fa-print"></i> Print html'
});
Finally the code for the tasks of the buttons looks like this:
for (var i = 0; i < self.tasks.length; i++) {
var task = self.tasks[i];
var taskButton = $('<button type="button">' + (task.label || task) + '</button>');
taskButton.addClass('btn btn-default');
$(taskButtons).append(taskButton);
if (task.action) {
// An entry point for custom actions
$(taskButton).click(function(){
task.action(self.selected);
})
} else {
$(taskButton).click(function () {
var downloadUrl = task.url + '?' + task.queryParam + '=' + self.selected.join(',');
downloadUrl += "&ordering=" + self.ordering()['ordering'];
$(infoPanel + ' .alert').remove();
$(infoPanel).append('<div class="alert alert-info">' +
'<i class="fa fa-circle-o-notch fa-spin"></i> Building document' +
'</div>');
$.ajax(downloadUrl, {
success: function (data) {
function doPoll(url, success) {
$.ajax(jobUrl, {
type: "HEAD",
success: function (pdfData, status, xhr) {
if (xhr.status == 202) {
setTimeout(function () {
doPoll(url, success)
}, 2000);
} else {
success()
}
}
});
$.ajax(url, function (data) {
alert(data); // process results here
setTimeout(doPoll, 5000);
});
}
How do I fix my code so that each button have its own functionality?
I think it is the push method that overwrites the action. What do you guys think?
Seems like an encapsulation issue due to the fact that variable declarations are hoisted (and aren't scoped to the for loop). Instead of a for loop, use .forEach:
self.tasks.forEach(function(task) {
var taskButton = $('<button type="button">' + (task.label || task) + '</button>');
taskButton.addClass('btn btn-default');
...
});
This wraps your entire button building code into its own scope for each button.
If you can't support .forEach, use an immediately-invoked anonymous function:
for (var i = 0; i < self.tasks.length; i++) {
(function() {
var task = self.tasks[i];
var taskButton = $('<button type="button">' + (task.label || task) + '</button>');
taskButton.addClass('btn btn-default');
...
})();
}

Why my find('a') doesn't work in jquery?

I have a function in jquery:
function handleUpcomingUserTexts () {
$.ajax({
url: 'getjson.php',
type: "POST",
data: {
mail: '<?php echo htmlentities($_SESSION["email"]); ?>'
},
dataType:'text',
success: function(ans)
{
var data = JSON.parse(ans);
$.each(data, function(i, v) {
var upcomingText = $('<i class="fa fa-comment fa-fw"></i> '+v.Content+'<span class="pull-right text-muted small"><em>'+v.Date+'</em></span>');
$('#upcomingTexts').append(upcomingText);
var a = upcomingText.find('a').on('click',function(e){
e.preventDefault();
alert("here");
});
});
}});
};
and it fills the html nicely, but when I click the link - nothing happens and I don't see the alert message. What is wrong in here?
Because upcomingText is already a a. And you are trying to find a a in your a.
You can just write this :
var a = upcomingText.on('click',function(e){
When you write var variable = $('<a ...>...</a>');, the result is the root tag of the given html. So in your case, the <a>.
Because upcomingText is <a> and in this tag there are not any <a> tags, so you need use upcomingText like this
upcomingText.on('click',function(e) {});
but event delegation in this case better solution
// add this code before $.ajax
$('#upcomingTexts').on('click', 'a.list-group-item', function(e) {});
Try to use delegate function, on #upcomingTexts block
$('#upcomingTexts').delegate('a', 'click', function(e){
//your code here
});

Cyclo for with inside ajax, the callback return a wrong result

I tried to create a jquery plugIn that load multiple feed rss (they are flexible can be 1 or 2 or 3 ect...), for create an html that show the news feed loaded. My target is having the possibility to load multiple rss feed (xml) and display them by html. When I tried seem that the callback is overwrite,I received 2 results but equal.
Example:
(function($){
$.fn.getFeed = function(Obj){
var
arrOpt = Obj.arrayOptions,
arrOptLng = arrOpt.length;
for(var i = 0; i < arrOptLng; i++){
var
index = i,
Opt = arrOpt[i],
feedUrl = Opt.feed,
sucFnc = Opt.callback,
$cnt = this;
console.log(index);
// here:
// 0
// 1
$.ajax({
url:feedUrl,
dataType: "jsonp",
success:function(data){
sucFnc(data,$cnt,Opt,index);
},
error:function(){
$cnt.html('error');
}
});
}
}
})(jQuery);
function feedManipulation(){
console.log(index)
// here:
// 1
// 1
}
/* DOM LOADED */
$(function(){
$('.news').getFeed({ // Activation getFeed
arrayOptions:[{
feed:'http://feed',
callback:feedManipulation,
imgDefault:'http://img',
nArtc:1
},{
feed:'http://feed',
callback:feedManipulation,
imgDefault:'http://img',
nArtc:1
}]
});
});
Ciao, I wrote this question and I created the solution so I would explain.
In this code I removed the cyclo for and I create a function that contain the ajax call.
The first time that I trigger the ajax function I pass an argument to the ajax function with inside an object that I used to set the plugIn (lock on the bottom) whereas my ajax function is itself calls, before sending the same object to the ajax function I change some information like "Opt.index" creating in this way a ajax cyclo. Is it really usefull ;) use it.
(function($){
$.fn.getFeed = function(Obj){
// Options object
Opt = new Object();
Opt.index = 0;
Opt.$cnt = this;
Opt.arrOpts = Obj.arrayOptions;
Opt.arrOptLng = Opt.arrOpts.length;
Opt.arrOpt = Opt.arrOpts[Opt.index];
Opt.feedUrl = Opt.arrOpts[Opt.index].feedUrl;
// ajax call
cycloAjax(Opt);
}
/* ajax cyclo */
function cycloAjax(Obj){
$.ajax({
url: Obj.feedUrl,
dataType: "jsonp",
success:function(data){
feedManipulation(data,Obj.$cnt,Obj);
if(Obj.index < Obj.arrOptLng - 1){
Obj.index++;
Obj.arrOpt = Obj.arrOpts[Obj.index];
Obj.feedUrl = Obj.arrOpts[Obj.index].feedUrl;
cycloAjax(Obj);
}
else{
completeLoadFeeds(Obj.$cnt,Obj);
}
},
error:function(){
Obj.$cnt.html('<p>error</p>');
}
});
}
.
.
.
})(jQuery);
/* DOM LOADED */
$(function(){
$('.news').getFeed({ // Activation getFeed
arrayOptions:[{
feed:'http://feed',
callback:feedManipulation,
imgDefault:'http://img',
nArtc:1
},{
feed:'http://feed',
callback:feedManipulation,
imgDefault:'http://img',
nArtc:1
}]
});
});

Categories