I have a setup where divs that contain similar data (but ranked differently) need to dynamically load data on start up. To do this I load a PHP page through AJAX and pass a parameter so it knows what rank to query. However in order to load on start I need to call the same function 4 times in a row. Is this syntax correct? Or is there a way to write this without a big list of the same function being called
$(document).ready(function(){
getStuff(1);
getStuff(2);
getStuff(3);
getStuff(4);
});
function getStuff(type) {
$.ajax({
type: "GET"
..........
success: function(html) {
$('[data-id="' + type + '"]').html(html);
}
});
}
<div id="rank1" data-id="1"></div>
<div id="rank2" data-id="2"></div>
<div id="rank3" data-id="3"></div>
<div id="rank4" data-id="4"></div>
$(document).ready(function(){
// edit as per taseenb# comment for performance
var size = $("div[id^=rank]").size()
for(var i = 1; i <= size; i++){
getStuff(i);
}
});
Of course there is a way and it is called for loop :)
$(document).ready(function(){
for(i = 1; i < 5; i++){
getStuff(i);
}
});
Why don't you make getStuff take an array and make the AJAX calls in a loop?
Also, something to consider: AJAX is asynchronous (as implied by the name), so there's no guarantee that these calls will return in the same order you make them. If you need them to happen sequentially, you should make the calls recursively--make each subsequent call from the SUCCESS function of the previous call. That way you guarantee that the previous call has finished before you make the next call.
Select via [attribute] selector, iterate via $.each():
$('[data-id]').each(function(){
var $this = $(this);
$.get( '/some/url' {
..........
}).done(function(html){
$this.html(html);
});
})
Related
I'm using jQuery and ajax to open a bootstrap modal window. My code works perfectly when not in a loop, and my content is displayed appropriately in the modal window. But I have five modals on the page, and naturally I'd like to use a for loop so I don't repeat my code five times.
It seems like a no-brainer to write a for loop to execute the code five times, but somehow, there is a problem, and when I put the code into a for loop, the modal content will not show in the opened window.
Here is code that works how I need it, so the modal content from my modal1.php file shows in a modal popup window. Notice that the i variable is used three times; once in the jQuery selector, and twice in the $.ajax(...) area:
var i = 1;
$('#modal' + i).on('show.bs.modal', function(e) {
var id = e.relatedTarget.dataset.id;
$.ajax({
type:'post',
url:'modals/modal' + i + '.php',
data:{id:id},
success:function(data){
$('#modal' + i).html(data);
}
});
});
This code below uses the variable i the exact same way as the code above. However, with the code below, the modal1.php content does not show (nor do any of the other files named 'modal[i].php'). Instead, only a blank dark background appears when they are opened.
for (i = 1; i < 6; i++) {
$('#modal' + i).on('show.bs.modal', function(e) {
var id = e.relatedTarget.dataset.id;
$.ajax({
type:'post',
url:'modals/modal' + i + '.php',
data:{id:id},
success:function(data){
$('#modal' + i).html(data);
}
});
});
}
So I don't understand why the $.ajax() area of the code won't recognize the i variable in the for condition, but it will recognize it in the initial jQuery selector $('#modal' + i), which I've tested and found to be true. Is there a way I can write this loop so that the ajax area will recognize the i variable? Or is there a mistake in my code that I'm overlooking?
Incidentally, I've noticed that similar questions have been asked, but they have been downvoted for not being clearly written. I've read them all, and they don't answer the question that I have today.
The problem here is that you are (unintentionally) referencing a variable (i) via a closure.
Since scope is dictated by function in JavaScript, wrap your on usage with another (immediately invoked) function so a unique i is saved:
for (i = 1; i < 6; i++) {
(function() {
var iModalNumber = i;
$('#modal' + iModalNumber).on('show.bs.modal', function(e) {
var id = e.relatedTarget.dataset.id;
$.ajax({
type:'post',
url:'modals/modal' + iModalNumber + '.php',
data:{id:id},
success:function(data){
$('#modal' + iModalNumber).html(data);
}
});
});
}());
}
The reason that these questions get down-voted so much is because issues/misunderstanding of closures is so common. It is admittedly a difficult concept to grasp, and your question was well written.
More information: How do JavaScript closures work?
You could probably do this without using loop but using jQuery .each() and adding value attributes to your html elements. Warning... untested code ahead.
jQuery('.modal').each(function(){ // use a class instead of an id
$(this).on('show.bs.modal', function(e) { //use $(this) to target
var i = $(this).val(); // get the value id
var id = e.relatedTarget.dataset.id; // do your code
$.ajax({
type:'post',
url:'modals/modal' + i + '.php',
data:{id:id},
success:function(data){
$('#modal' + i).html(data);
}
});
});
});
var dagaData = ['Manok', 'Pusa', 'Daga', 'Ibon', 'Aso'];
$('#clicktest').on('click', function() {
$.each(dagaData, function(index, item) {
executeData(item);
alert(item);
});
});
function executeData(item) {
var items = $("<div></div>").text(item);
$('#pangtest').append(items);
}
Is it possible to execute the function on every iteration?
Right now when I run the code above it finished all iteration before the append happen.
That why I've put alert to see if every alert append each iteration.
Output of code above: alert('Manok'), alert('Pusa') ,alert('Daga'), alert('Ibon'), alert('Aso') executed append.
What I'm trying to achieve is alert('manok') append, alert('Pusa') append, alert('Daga') append, alert('Ibon') append, alert('Aso') append.
Thanks in advance.
In a general sense, although the DOM is updated each time you call .append() the browser won't actually repaint the screen until after the entire JS function finishes. (Though some browsers will repaint at the point when an alert is open, which is why using alert() for debugging is a bad idea: it can subtly change the behaviour in a way that calling console.log() doesn't.)
You can work around this by using a setTimeout-based pseudo-loop - in between timeouts the browser then gets a chance to repaint:
var dagaData = ['Manok', 'Pusa', 'Daga', 'Ibon', 'Aso'];
$('#clicktest').on('click', function() {
var i = 0;
(function doNext() {
var item = dagaData[i];
executeData(item);
alert(item);
if (++i < dagaData.length)
setTimeout(doNext, 5);
})();
});
function executeData(item) {
var items = $("<div></div>").text(item);
$('#pangtest').append(items);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button id="clicktest">Test</button>
<div id="pangtest"></div>
Or just use your original $.each() loop with the contents of the loop wrapped in a timeout, as per Bnrdo's answer. But I prefer to wait to schedule each timeout only after the previous one is done because that way the order of execution is guaranteed.
Wrap them in setTimeout
$.each(dagaData, function(index, item) {
setTimeout(function() {
executeData(item);
alert(item);
}, 1);
});
I am using following JavaScript code inside a page. The problem is that the code gets executed for the first time and fetches data from from elements.
During the subsequent calls, the changed data in the form elements is not available to this function as it uses data from its maiden call.
$(document).ready(function() {
$('<textarea id="message-clone"></textarea>').insertAfter("#form-message-compose");
var saveDraft = function () {
var originalStriped = $("#wysiwyg").val().replace(/(<([^>]+)>)/ig,"");
if((originalStriped.length) > 10) {
var input = $("<input>").attr("type", "hidden").attr("id", "savedraft")
.attr("name", "submit").val("savedraft");
$.ajax({
type: "POST",
url: $("#form-message-compose").attr("action"),
data: $("#form-message-compose").append(input).serialize(),
success: function(result){
var result = JSON.parse(result);
$("#subject").val(result.message_subject);
$('input[name="draft"]').val(1);
$("#id").val(result.message_id);
var flash = '<div id="flash" class="alert alert-success"><a data-dismiss="alert" class="close">×</a><strong>Yay!</strong> Message Auto saved to drafts!</div>';
$("#page-title").append(flash);
$("#flash").fadeOut(3000, function() { $(this).remove(); });
$("#savedraft").remove();
$("#message-clone").val($("#wysiwyg").val().replace(/(<([^>]+)>)/ig,""));
}
});
}
}
setInterval(saveDraft(), 2000);
});
The problem here is that for the first time, the function fetches correct data from input element #wysiwyg but during the subsequent, it doesnot update the data from the call $('#wysiwyg').val() which results in single execution of the code inside if block.
Kindly guide, where I am doing wrong.
setInterval(saveDraft(), 2000);
should be
setInterval(saveDraft, 2000);
The first argument of setInterval should be a function. You are not passing a function, what you're doing is executing saveDraft and passing the result as an argument.
The issue was with the Tiny MCE I was using. So instead of trying to get the value of texte area by
var originalStriped = $("#wysiwyg").val().replace(/(<([^>]+)>)/ig,"");
I had to use the tinyMCE method to fetch the text
var originalStriped = tinyMCE.get("wysiwyg").getContent({format : "text"});
Another problem with TinyMCE is that it doesnot update the data in textarea on an AJAX call, which otherwise, it does on form submit. So I had to call the trigger the save on tinyMCE manually by calling
tinyMCE.triggerSave();
And then firing the AJAX request with form data.
I have a function called "loadTimeTrackersGrid()", which loads a flexigrid.
The setup looks like this :
$(document).ready(function () {
var editTrackerID = 0;
loadTimeTrackersGrid();
)};
The beginning of the function looks like this :
function loadTimeTrackersGrid(caseStatus) {
var url = 'Utilities/DataViewHandlers/ViewTimeTrackers.ashx?CaseFileID=' + $('#hidCaseFile').val();
if ($('#hidTaskID').val() !== "")
url += '&TaskID=' + $('#hidTaskID').val();
if (caseStatus == "NI") {
url += '&NonInvoiced=1';
}
$('#viewTimeTrackersGrid').flexigrid({
url: url,
dataType: 'json',
method: 'get',
As you can see it calls another page which contains a stored procedure which returns a set of rows and a jsonwriter then puts the returned columns into the flexigrid.
But the problem I am having is outside the (document).ready(), when I have a function that calls the "loadTimeTrackersGrid()", it never reloads the flexigrid or makes a call to the file that contains the stored procedure.
My function(that I am trying to get to work) looks like this :
function returnInvoicedItems() {
loadTimeTrackersGrid();
$('.menuBtn img').parent().children('ul').removeClass('menuShow');
}
And this is how I am calling "returnInvoicedItems" function:
<li>Non Invoiced Tracker</li>
I am not sure, but I think I can see the problem. Your second function returnInvoicedItems() that calls loadTimeTrackersGrid(), it does have a jQuery code (in the line $('.menuBtn img').parent().children('ul').removeClass('menuShow');. Now, if you have a jQuery call, don't you have to do make that call inside $(document).ready()?
Try to move returnInvoicedItems() inside $(document).ready() and see what happens.
This works like a gem:
$('#viewTimeTrackersGrid').flexOptions({ url: 'Utilities/DataViewHandlers/ViewTimeTrackers.ashx?' + invoicedUrl + '&NonInvoiced=1' }).flexReload();
I have a problem with jQuery's $(this) object and make me miss the this element
in code :
$('.star').click(function (){
var id = $(this).parent().attr('id').split('rating')[1];
var vote = $(this).index() + 1;
var ThisStar = $(this);
alert(ThisStar.parent().html())
$.ajax({
type: 'POST',
url: EXECUTION_URL + 'ajax/rate.php',
data: {'article' :id ,'rate': vote},
success:function(data,tt,ff){
alert(ThisStar.parent().html())
}
});
the first alert fire : the true contents of the parents of the clicked node
the second alert fire : null !!!!
why it have been changed into the ajax ? or from another reason ? please tell me a good solution for this issue
ok actually i checked my code that there is two lines after the ajax function that delete the stored node in the this object and because of the ajax function is asynchronous function the two lines executed before the code inside the success function >> thanks for all
Your code should work fine, check the proof. The only difference would be this:
success:function(data,tt,ff){
alert(ThisStar.parent().html())
}
vs.
success:function(data,tt,ff){
alert(ThisStar.parent().html())
}});