Ajax auto-load by counter - javascript

I got this code from some template, it gets executed by clicking on the tabs to fetch posts into the page. All I want is to have an edited copy of this code to fetch posts by timer aside from clicking on the tabs. I have tried the setInterval but it didn't work, I appreciate any help I am so new to Ajax and JQuery.
jQuery(document).ready(function($) {
setInterval(function(){
e.preventDefault();
var bt = $(this);
var bts = bt.parent().parent();
var where = $(this).parent().parent().parent().next();
var nbs = bt.parent().parent().data('nbs');
var nop = bt.parent().parent().data('number_of_posts');
cat = bt.data('cat_id');
if (cat === '') {
cat = bt.data('parent_cat');
}
where.parent().find('.show-more').find('.nomoreposts').remove();
jQuery.ajax({
type: "post",
url: nbtabs.url,
dataType: 'html',
data: "action=nbtabs&nonce="+nbtabs.nonce+"&cat="+cat+"&nbs="+nbs+"&number_of_posts="+nop,
cach: false,
beforeSend : function () {
where.parent().append('<i class="nb-load"></i>');
},
success: function(data){
where.hide().html(data).fadeIn('slow');
bts.find('li').removeClass('active');
bt.parent().addClass('active');
where.parent().find('.nb-load').remove();
}
});
}, 5000)
})

You have to get started to some degree before we can really help you code-wise. We can't just write the code for you because we do not know what elements you want updated and how.
All I can advise you is the Jquery Ajax method is how this code retrieves url responses:
jQuery.ajax({
type: "post",
url: "<name of your url or maybe servlet>"
success: function(data){
// data is the response from your url
// in the code sample, data was html that was inserted to an element
}
});
You can put this ajax call in a function and use setInterval. You can place the setInterval call on your Jquery.ready() function.

Your first issue is that you're trying to call jQuery.setInterval, not setInterval. jQuery.setInterval is not a function, so calling it will just give you an error.
The next issue is that your script tries to alter a bunch of elements, using the clicked element as a starting point. This is bad practice because of situations like this, where changing how to function is invoked can completely break the script. Without knowing what all of this:
var bt = $(this);
var bts = bt.parent().parent();
var where = $(this).parent().parent().parent().next();
var nbs = bt.parent().parent().data('nbs');
var nop = bt.parent().parent().data('number_of_posts');
is, it's pretty difficult to give advice. The safest bet is to replace $(this) with jQuery(".nb-tabbed-head li a"), but that might cause issues because $(this) refers to only one element, whereas jQuery(".nb-tabbed-head li a") may refer to multiple.
Really the biggest issue is that you're trying to use code that a) is poorly-written and b) you don't understand yet. I highly recommend learning about AJAX, events, the DOM, and jQuery before you make a serious attempt at this. It's almost impossible to create a good product when you're gluing together pieces of code that you don't understand that were written by someone that you don't know.

Related

Ajax call in "for" loops skips odd/even iterations

If I am here asking it is because we are stuck on something that we do not know how to solve. I must admit, we already searched in StackOverflow and search engines about a solution.. but we didn't manage to implement it / solve the problem.
I am trying to create a JavaScript function that:
detects in my html page all the occurrences of an html tag: <alias>
replaces its content with the result of an Ajax call (sending the
content of the tag to the Ajax.php page) + localStorage management
at the end unwraps it from <alias> tag and leaves the content returned from ajax call
the only problem is that in both cases it skips some iterations.
We have made some researches and it seems that the "problem" is that Ajax is asynchronous, so it does not wait for the response before going on with the process. We even saw that "async: false" is not a good solution.
I leave the part of my script that is interested with some brief descriptions
// includes an icon in the page to display the correct change
function multilingual(msg,i) {
// code
}
// function to make an ajax call or a "cache call" if value is in localStorage for a variable
function sendRequest(o) {
console.log(o.variab+': running sendRequest function');
// check if value for that variable is stored and if stored for more than 1 hour
if(window.localStorage && window.localStorage.getItem(o.variab) && window.localStorage.getItem(o.variab+'_exp') > +new Date - 60*60*1000) {
console.log(o.variab+': value from localStorage');
// replace <alias> content with cached value
var cached = window.localStorage.getItem(o.variab);
elements[o.counter].innerHTML = cached;
// including icon for multilingual post
console.log(o.variab+': calling multilingual function');
multilingual(window.localStorage.getItem(o.variab),o.counter);
} else {
console.log(o.variab+': starting ajax call');
// not stored yet or older than a month
console.log('variable='+o.variab+'&api_key='+o.api_key+'&lang='+o.language);
$.ajax({
type: 'POST',
url: my_ajax_url,
data: 'variable='+o.variab+'&api_key='+o.api_key+'&lang='+o.language,
success: function(msg){
// ajax call, storing new value and expiration + replace <alias> inner html with new value
window.localStorage.setItem(o.variab, msg);
var content = window.localStorage.getItem(o.variab);
window.localStorage.setItem(o.variab+'_exp', +new Date);
console.log(o.variab+': replacement from ajax call');
elements[o.counter].innerHTML = content;
// including icon for multilingual post
console.log(o.variab+': calling multilingual function');
multilingual(msg,o.counter);
},
error: function(msg){
console.warn('an error occured during ajax call');
}
});
}
};
// loop for each <alias> element found
//initial settings
var elements = document.body.getElementsByTagName('alias'),
elem_n = elements.length,
counter = 0;
var i = 0;
for(; i < elem_n;i++) {
var flag = 0;
console.info('var i='+i+' - Now working on '+elements[i].innerHTML);
sendRequest({
variab : elements[i].innerHTML,
api_key : settings.api_key,
language : default_lang,
counter : i
});
$(elements[i]).contents().unwrap().parent();
console.log(elements[i].innerHTML+': wrap removed');
}
I hope that some of you may provide me some valid solutions and/or examples, because we are stuck on this problem :(
From our test, when the value is from cache, the 1st/3rd/5th ... values are replaced correctly
when the value is from ajax the 2nd/4th .. values are replaced
Thanks in advance for your help :)
Your elements array is a live NodeList. When you unwrap things in those <alias> tags, the element disappears from the list. So, you're looking at element 0, and you do the ajax call, and then you get rid of the <alias> tag around the contents. At that instant, element[0] becomes what used to be element[1]. However, your loop increments i, so you skip the new element[0].
There's no reason to use .getElementsByTagName() anyway; you're using jQuery, so use it consistently:
var elements = $("alias");
That'll give you a jQuery object that will (mostly) work like an array, so the rest of your code won't have to change much, if at all.
To solve issues like this in the past, I've done something like the code below, you actually send the target along with the function running the AJAX call, and don't use any global variables because those may change as the for loop runs. Try passing in everything you'll use in the parameters of the function, including the target like I've done:
function loadContent(target, info) {
//ajax call
//on success replace target with new data;
}
$('alias').each(function(){
loadContent($(this), info)
});

jQuery in a wordpress template page

I am developing a tool for my Wordpress website using jQuery, I am quite new at this but what I'm trying to do is not that hard.
My script is enqueued, i've read that with the NoConflict mode i can't use $ so I use jQuery instead.
function Calculator()
{
var result = jQuery('result');
if (jQuery('day').value == "" || jQuery('month').value == "" || jQuery('year').value == "") {
return;
}
result.update('<span class="result">processing</span>');
jQuery('form').request({
onComplete: function(transport) {
result.hide();
result.update(transport.responseText);
new Effect.Appear(result, { duration: 0.5 } );
}
});
}
My problem is I got error everywhere :
update is not function
request is not function
etc...
There is something i'm obviously doing wrong but can't figure out what...
thanks a lot !
The errors you are seeing ("update is not function request is not function") describe the problem - those really are not jQuery functions.
It looks like you're trying to update an HTML element with ID or class "result". To do that, use .html():
var result = jQuery('.result'); // "." to select the element with class result
result.html('something');
For .request, it looks like you are trying to do a POST or GET of a form. If so, use .ajax(), .post(), or .get(). Note though you'll need to add a few more details, eg:
jQuery('form').ajax({
type: "POST",
url: someurl,
data: somedata,
onComplete: ...
});
Also, if your Calculator() function can be called while the page is loading, make sure it (or whatever calls it) is wrapped in document.ready:
jQuery(document).ready(function () {
...
});
An unrelated issue, to check the value of say a form input with class "day", you need to use:
jQuery('.day').val()
if you are fetching the value using class then you have to do it like this:
jQuery('.result').val()
or if using id use it like:
jQuery('#result').val()
in jquery we use .val() function to get value instead of value.
Is update, request exists in jquery?
you can use like this rather than writing again and again.
var j = jQuery.noConflict();
j(".result").html("<span>Processing..</span>");

ajax loading of search results

I have setup a search funtionality that will search in an XSLT file. This works flawlessly but I have a little trouble returning the search results dynamically with ajax.
This is my JS:
var SearchHandler = function(frm) {
frm = $(frm);
var data = frm.find(".search-field").val();
$.ajax({
method: 'GET',
url: '/',
data: { query: data },
dataType: 'xml',
success: SearchSuccessHandler,
error: SearchSuccessHandler
});
};
var SearchSuccessHandler = function(html) {
};
What I want is the SearchSuccessHandler to dynamically load the search result from index.php?query=searchword
I just can't seem to figure out the right way to handle it.
Based on your comment:
Bah.. Sorry... The ajax call will return some new html based on the
query ... I want the existing html to be replaced I have tried
$('body').html(html.responseText); but then I cannot search again
because javascript is not loaded correctly
It's not the AJAX which is the issue but rather event delegation
When you bind a function to an element directly like this:
$('.my-element').on('whatever', function() { ... })
the handler will work as long as the element exists however if you replace the contents of the entire body you'll run into trouble as your original .my-element no longer exists.
You can overcome that by using event delegation to make sure your function keeps searching e.g.
$(body).on('whatever', '.my-element', function() { ... })
This basically says: "If I click on body and the target is .my-element then execute this function"
Instead of a directly bound handler which says: "If I click on this specific element then execute this function"
the body will always exist and therefore you'll always be able to delegate down from the body but if you can do it on some more specific element that would obviously be better since then you won't have an onclick handler on the entire body.
I think this is what your issue is since you're replacing the entire body.
Try this
success:function(data) {
// do your stuff here
}
Of course, you need to be sure your function is returning some values.
To make it easier for your, encode the values as json on your index.php
return json_encode($values)
Then, inside your success function, just parse it with eval()

Dynamic table onclick

I have the following issue i would like to get some help for.
There is a combobox (select) where i choose an item and i get back a dinamic table from php. The table contains example names. Firstname, Lastname and ID(which is hidden). When i click on the table i get the value of the ID of the selected row. So far it is works fine. The problem that the event doesnt want to fire for first. After that it works fine but i need it for first as i have a function which auto click on the first row but this doesnt work until i solve this problem. I made a code which works fine with a html table. But not with the dinamic one. Please help.
Here is the code works fine with dinamic table but just after 2nd click:
function nametableclick() {
var rows = document.getElementById("nametable").rows;
for(var i = 0; i < rows.length; i++)
{
rows[i].onclick = function()
{
data=(this.cells[3].innerHTML);
var data = data;
$.ajax({
type: "POST",
url: "list.php",
data: "data="+data,
Type: "json",
success: function(msg) {
msg = JSON.parse(msg);
$("#dob").html(msg.dob);
$("#age").html(msg.age);
$("#sex").html(msg.sex);
}
});
};
};
};
And here is the code works well but just with html table:
(Actually is same but i use onload)
onload = function() {
var rows = document.getElementById("nametable").rows;
for(var i = 0; i < rows.length; i++)
{
rows[i].onclick = function()
{
data=(this.cells[3].innerHTML);
var data = data;
$.ajax({
type: "POST",
url: "list.php",
data: "data="+data,
Type: "json",
success: function(msg) {
msg = JSON.parse(msg);
$("#dob").html(msg.dob);
$("#age").html(msg.age);
$("#sex").html(msg.sex);
}
});
};
};
$("#nametable tr:eq(0) td:first-child").click();
};
When i use the onload function for the dinamic table it just doesnt work at all.
Thanks for any help in advance.
This question does not suit well for an answer. Instead, I'll do some code analysis.
onload = function() ... - well not terrible but kinda sloppy. Also looks like this is possible a global namespace leak. I'm going to assume this should be window.onload in which case I'd wonder why jQuery's ready event isn't used $(function() { ... }).
var rows = document.getElementById("nametable").rows;
for(var i = 0; i < rows.length; i++) {
rows[i].onclick = function() { ... };
}
Ok now were again running away from jQuery as if it was diseased some how. And then were looping over the array of rows only to construct a new function each time and attach them to the onclick (again avoiding jQuery)? Constructing functions inside a loop is a very bad idea and most linters will complain loudly about that. A suggestion:
$('#nametable tr').on('click', function() { ... });
This will attach the click handler to all the <TR> rows in the table with the id="nametable" attribute.
data=(this.cells[3].innerHTML);
var data = data;
My heart skipped a beat here!. First your pulling out the HTML content into (what I thought was a global variable) until I saw the next line and realized we have variable hoisting. But wait your assigning data to itself. Lastly, the name data doesn't provide any context as to the content of the innerHTML. Since I don't have the data I could only guess so in these examples I'll leave it as data. In the future think about picking names which provide context to their content and use. That way when you read the code you don't have to hunt for what the variables are for or how to use them.
var data = $(this, 'td:eq(3)').text();
Finally, the use of data is to directly concatenate it into a post request. I would assume HTML is not desired in that server API. Not to mention the avoidance of jQuery's parameter building by forcing the data to a string. Instead use a JS object:
$.ajax({
type: 'POST',
url: 'list.php',
data: {data: data} // This is a very poorly designed server API
}).then(function(data) {
...
});
Also, the use of Type: 'json' suggests that your server is not returning proper HTTP headers. First off there is no Type property for jQuery's ajax instead I think you wanted dataType. However the need for a dataType suggests the server is not sending the proper headers. If the PHP script were to return application/json instead of plain/text then jQuery could parse the response for you avoiding the need for JSON.parse on your own which can be a bit error prone.
$("#dob").html(msg.dob);
$("#age").html(msg.age);
$("#sex").html(msg.sex);
Be warned by using html() your directly injecting HTML into the DOM that you received from a third party. This is a big cross site scripting vulnerability. Use text() instead to push data into the DOM unless you know and can assert the trust of your server and the connection to it (SSL to avoid man in the middle). Probably not important for this example but still worth keeping in mind because it's far to easy to have this show up in the wild.
$("#nametable tr:eq(0) td:first-child")
When you have a selector like this it is far easier and readable to instead provide contextual hooks instead of relying on the make up of the DOM. Add things like class="clickable-row" or class="person-data dob" to your HTML markup. It makes for maintenance and readability.
Thanks for the quick reply. Im sure if there are lot of mistakes as i just started to learn this(i mean php html ajax ect.) a few weeks ago so i dont clearly understand everything and i use things i should not use or should do it another way. But there is a simple program i would like to make it done and learn from that. So when i dont know something im trying to get some info (like: w3schools.com) or check other topics which similar what im looking for.
Sorry i left there the
Var data = data;
My mistake. Dont need there. i was trying out something before and left there. Does not make any different anyway.
next:
The onload = function() {
i found in another topic as solved result and it works with a static table but not with dynamic.
I have tried the following. i did not mentioned:
window.onload = nametableclick;
function nametableclick() {
data here
}
But does not work with dynamic table either.
Next:
var rows = document.getElementById("nametable").rows;
for(var i = 0; i < rows.length; i++)
{
rows[i].onclick = function()
{
data2=(this.cells[3].innerHTML);
What it does for me it finds the selected row and comes back with the value of the 3rd(actually 4th) cell which is the ID in my prog. I need this cos i want to sent this value to the php to get all the data from the table where ID = the value. And it works fine.
As i mentioned the prog works fine even if it is not the best way to do it. Slowly i gonna learn how to do it better way. But at the moment the only problem with that is that the dynamic table onclick event fires only after the 1st click.
Thanks and sorry if im a bit hard case. :-)))
Oh 1 more thing:
"First off there is no Type property for jQuery's ajax instead I think you wanted dataType."
For some reason if i type dataType it just does not work at all. I have no idea why. I watched some training videos and read some short courses about ajax and some of them mentioned using dataType some of them just simple type. I followed everything but did not worked for me. i spent like 5 hours another day to find out why actually i have a topics here with that question as well.
get data from mysql with ajax and json into different textareas
And accidently i tried with uppercase T once and it worked. Have no idea why.

Update <head> balise on Jquery/Ajax navigation Wordpress

I am doing an ajax navigation for a wordpress website. I update the #content with fade, this is ok, but I want to just update my head with my new page head, I don't find!
$(document).ready(function () {
//hash change
$(window).hashchange(function () {
//on retrouve le vrai lien
var arg = window.location.hash.substring(3);
var link = 'http://ladresse.graphsynergie.com/' + arg;
$.ajax({
url: link,
processData: true,
dataType: 'html',
success: function (data) {
data = innerShiv(data, false);
var contenu = $(data).find("#contenu");
//problem part
var head = $(data).find('head').text();
document.head = head;
//problem part end
$('#contenu').fadeOut('200', function () {
$(this).html(contenu.html()).fadeIn('200');
});
}
});
});
//end
//détection d'un hash onload
if (window.location.hash.substring(3) != '') {
$(window).trigger('hashchange');
}
});
Have in consideration that .text() will only retrieve the "text" contained inside the html tags, review the jQuery documentation. I think that what you actually want is to use the .html() method.
So, I think that you may want to replace those 2 problematic lines of code with this:
$("head").html($(data).find("head").html());
Update:
Apparently all browsers strip out anything that it's not inside the "body" when they create the DOM object. The thing is that when you do: "$(data)" jQuery creates a DOM object with the content of the "data" variable, and your browser decides to ignore all the elements that are not inside the "body" tag, therefore in the internal DOM object that jQuery handles the "head" element is not there anymore. So you will have to find a workaround.
Try this, put these lines of code just after the line "success: function (data) {":
var headIni = data.toLowerCase().indexOf("<head");
var headEnd = data.toLowerCase().indexOf("</head>");
headIni = data.indexOf(">", headIni + 1) + 1;
var headHTML = data.substring(headIni, headEnd);
And then, replace the line that I initially suggested for this one:
$("head").html(headHTML);
This should do the job. I'm sure that there must be more elegant ways to do it, but hopefully this will be good enough for you.
Update 2:
If you follow this link you will find a much better way to do it. Just add the library "jquery.ba-htmldoc.js" that you will find there, and then do this:
$("head").html($.htmlDoc(data).find('head').html());
To overwrite the content of your "< head >" tag use
$("head").html('NEW STUFF IN HEAD');

Categories