ajax() call in javascript function - javascript

i have a jquery .click() function that executes an .ajax() method call
$(".btn-play").live("click", function () {
//set globalSortNumber
globalSortNumber = $(this).parents("[sortnumber]").attr("sortnumber");//.attr("value") ; //change should be some type of input like mediaid //see if its possible to add the sortID to the handle span
// alert(globalSortNumber);
//set title
//set mediaID
var mediaID = $(this).parents("[mediaid]").attr("mediaid");
// alert(mediaID);
//ajax query to get link and excute code to launch music
$.ajax({
type:"POST",
url:"ajax/AB3Ajax.asmx/GenerateLink",
data:"{'mediaId':" + mediaId + ",'userId':" + "0" + "}",
contentType:"application/json; charset=utf-8",
dataType:"json",
success:function (msg) {
if (msg.d != "") {
playsong(msg.d,null);
}
else {
soundManager.stopAll();
//look at what is already in place in mystudio
}
},
error: function (err) {
//add code later look at what is already in place in mystudio
}
})
when the .ajax() method executes succesfully it calls a javascript function
function playsong(sortNumber,url) {
if (soundManager.supported()) {
globalSortNumber = sortNumber;
var aSoundObject = soundManager.createSound({
id: 'mySound' + sortNumber,
url: url,//'/Music/mafiamusicpt2rickross.mp3',
whileplaying: function () {
if (count == 0) {
if (this.position > 1000) {
this.pause();
pos = this.position;
count++;
this.resume();
}
} else if (count == 1) {
soundManager._writeDebug('old position: ' + pos);
soundManager._writeDebug('new position: ' + this.position);
// See that this.position is less than pos!
count++;
}
},
onfinish: function () {
//find the next song in the list
//var nextSongPosition=
this.destruct();
$.ajax({
type:"POST",
url:"ajax/AB3Ajax.asmx/GenerateLink",
data:"{'mediaId':" + mediaId + ",'userId':" + "0" + "}",
contentType:"application/json; charset=utf-8",
dataType:"json",
success:function (msg) {
if (msg.d != "") {
playsong(msg.d,null);
}
else {
soundManager.stopAll();
//look at what is already in place in mystudio
}
},
error: function (err) {
//add code later look at what is already in place in mystudio
}
})
playsong(sortNumber++,url)
}
});
aSoundObject.play();
}
}
as you can see i have an .ajax() method inside my javascript function, is this possible?
I am creating loop that starts on the finish listener of the soundmanager object. So when I need to make the ajax call to get he next url I need. If my way isnt correct can you please tell me what is the best way to accomplish what i am trying to do.

Think it's fine but i would make a separate function for the ajax call so you dont need to duplicate the code twice. Easier to maintain.
$(".btn-play").live("click", function () {
//set globalSortNumber
globalSortNumber = $(this).parents("[sortnumber]").attr("sortnumber");//.attr("value"); //change should be some type of input like mediaid //see if its possible to add the sortID to the handle span
//alert(globalSortNumber);
//set title
//set mediaID
var mediaID = $(this).parents("[mediaid]").attr("mediaid");
//alert(mediaID);
//ajax query to get link and excute code to launch music
getAudio(mediaID);
}
function playsong(sortNumber,url) {
if (soundManager.supported()) {
globalSortNumber = sortNumber;
var aSoundObject = soundManager.createSound({
id: 'mySound' + sortNumber,
url: url,//'/Music/mafiamusicpt2rickross.mp3',
whileplaying: function () {
if (count == 0) {
if (this.position > 1000) {
this.pause();
pos = this.position;
count++;
this.resume();
}
} else if (count == 1) {
soundManager._writeDebug('old position: ' + pos);
soundManager._writeDebug('new position: ' + this.position);
// See that this.position is less than pos!
count++;
}
},
onfinish: function () {
//find the next song in the list
//var nextSongPosition=
this.destruct();
getAudio(mediaId);
playsong(sortNumber++,url)
}
});
aSoundObject.play();
}
}
function getAudio(mediaID) {
$.ajax({
type:"POST",
url:"ajax/AB3Ajax.asmx/GenerateLink",
data:"{'mediaId':" + mediaId + ",'userId':" + "0" + "}",
contentType:"application/json; charset=utf-8",
dataType:"json",
success:function (msg) {
if (msg.d != "") {
playsong(msg.d,null);
}
else {
soundManager.stopAll();
//look at what is already in place in mystudio
}
},
error: function (err) {
//add code later look at what is already in place in mystudio
}
});
}

Related

How to disable form button until function has fully complete

So everything in script works perfectly. However there is an issue in this part of the code:
var min = 1;
while (min < 200) {
var max = min + 30;
scan(fruitID, min, max);
var min = max;
}
What I want from this loop:
Computes max value
Calls scan() function
Waits until the ajax in scan has successfully gotten the data, and displayed it up on the screen.
Computes min value
Repeats the loop
The mistake is in step 3. It doesn't wait for ajax to get the data back and process it. It just straight away repeats the loop. How do I make the loop wait until the scan() function has fully finished.
$(document).ready(function() {
$('#submit').click(function(e){
e.preventDefault();
$("#submit").attr("disabled", true);
$("#submit").html("Verifying Username");
var fruitName = $("#fruit-name").val();
$.ajax({
type: "POST",
url: "verify-input.php",
dataType: "json",
data: {fruitName:fruitName},
success : function(data){
if (data.code == 200){
$("#submit").html("Running Scan");
var fruitID = data.fruitId;
//alert("Fruit ID: " + fruitID);
var min = 1;
while (min < 200) {
var max = min + 30;
scan(fruitID, min, max);
var min = max;
}
} else {
$("#submit").attr("disabled", false);
$("#submit").html("Submit");
$(".display-error").html("<ul>"+data.msg+"</ul>");
$(".display-error").css("display","block");
}
}
});
});
});
function scan(vFruitId, min, max) {
$.ajax({
type: "POST",
url: "scanner.php",
dataType: "json",
data: {vFruitId: vFruitId, min: min, max: max},
success : function(data){
data.forEach((item, idx) => {
$("#results").append(`
<div class="fruit-item" data-item="${idx}">
<div class="f-calories">calories: ${item.sweetness}</div>
<div class="f-sweetness">sweeteness: ${item.calories}</div>
<div class="f-bitterness">bitterness: ${item.bitterness}</div>
</div>
`);
})
}
});
}
<form>
<label for="fname">Fruit (only correct input is: banana)</label><br>
<input type="text" id="fruit-name" name="fruit" value="banana"><br>
<button type="submit" id="submit" value="Submit">Submit</button>
</form>
<div id="results">
</div>
note: your original code does not re-enable the form button, so the question title is a bit misleading
The solution is to use the Promise-like object returned by $.ajax
The following code uses arrow notation like in the question, but does not use async/await so would work anywhere the code in the question works
$(document).ready(function () {
$('#submit').click(function (e) {
e.preventDefault();
$("#submit").attr("disabled", true);
$("#submit").html("Verifying Username");
var fruitName = $("#fruit-name").val();
$.ajax({
type: "POST",
url: "verify-input.php",
dataType: "json",
data: {
fruitName: fruitName
},
success: function (data) {
if (data.code == 200) {
$("#submit").html("Running Scan");
var fruitID = data.fruitId;
//alert("Fruit ID: " + fruitID);
function runscan(min) {
return scan(fruitID, min, min+30)
.then(() => {
min = min + 30;
if (min < 200) {
return runscan(min);
}
});
}
runscan(1)
.then(() => {
// all done here
});
} else {
$("#submit").attr("disabled", false);
$("#submit").html("Submit");
$(".display-error").html("<ul>" + data.msg + "</ul>");
$(".display-error").css("display", "block");
}
}
});
});
});
function scan(vFruitId, min, max) {
return $.ajax({
type: "POST",
url: "scanner.php",
dataType: "json",
data: {
vFruitId: vFruitId,
min: min,
max: max
},
success: function (data) {
data.forEach((item, idx) => {
$("#results").append(`
<div class="fruit-item" data-item="${idx}">
<div class="f-calories">calories: ${item.sweetness}</div>
<div class="f-sweetness">sweeteness: ${item.calories}</div>
<div class="f-bitterness">bitterness: ${item.bitterness}</div>
</div>
`);
})
}
});
}
Alternatively, using async/await, the main success code can be written
success: function(data) {
if (data.code == 200) {
$("#submit").html("Running Scan");
(async function() { // `success` can't be async, because jquery doesn't like that
var fruitID = data.fruitId;
//alert("Fruit ID: " + fruitID);
var min = 1;
while (min < 200) {
await scan(fruitID, min, min + 30);
min = min + 30;
}
})();
} else {
$("#submit").attr("disabled", false);
$("#submit").html("Submit");
$(".display-error").html("<ul>" + data.msg + "</ul>");
$(".display-error").css("display", "block");
}
}
Important note: you still MUST return $.ajax in function scan as per first code snippet

Delay the loop process in displaying the data

I would like to delay the for loop process so that the loading of data looks like a progress bar.
In this code, the moment i click the button, it will directly display this data: 20/20 Records Rendered.
I would like to see the record start with 1/20 Records Rendered then after 3 seconds it will become 2/20 Records Rendered and so on.
Here is the code:
<button name="subject" type="submit" value="6" onClick="Run(this.value)">Run</button>
<script>
function Run(value) {
custRecordsRendered = 0;
$.ajax({
type: 'Post',
url: "/Tasks/RunSample",
success: function (data) {
totalRecords = data[0].Total;
console.log("Total: " + data[0].Total);
console.log("Records: " + Object.keys(data).length);
for (var key in data) {
(function iterator() {
console.log("logs: "+data[key].Records);
setTimeout(iterator, 3000);
})();
if (data.hasOwnProperty(key)) {
custRecordsRendered = data[key].Records;
updateProgress();
}
}
}
});
function updateProgress() {
$("#completeCount").text(custRecordsRendered + "/" + totalRecords + " Records Rendered");
}
}
</script>
Controller:
public JsonResult RunSample()
{
List<object> countData = new List<object>();
int count = 20;
for (int i = 1; i <= count; i++)
{
countData.Add(new { Total = count, Records = i });
}
return Json(countData);
}
Thank you for helping me.
if I got what you mean correctly .. this code may do the trick
function Run(value) {
custRecordsRendered = 0;
$.ajax({
type: 'Post',
url: "/Home/RunSample",
success: function (data) {
totalRecords = data[0].Total;
console.log("Total: " + data[0].Total);
console.log("Records: " + Object.keys(data).length);
var itemCount = 0;
var progressInterval = setInterval(function () {
if (itemCount < data.length) {
console.log(itemCount);
console.log("logs: " + data[itemCount].Records);
custRecordsRendered = data[itemCount].Records;
updateProgress();
itemCount++;
}
else {
clearInterval(progressInterval);
}
}, 500);
}
});
function updateProgress() {
$("#completeCount").text(custRecordsRendered + "/" + totalRecords + " Records Rendered");
}
}
in your code you are treating the setTimeout function as if it causes the Thread to sleep but actually, it does not what it does is setting a delayed asynchronous event that will be fired after the specified interval and execute the handler function, but the execution of the code which is after the setTimeout call will continue .. so setInterval will serve the purpose for you

clearInterval not working | undefined

I have such jQuery code and have problem with clearing intervals.
var secs = 50, width = 100;
var counter = function() {
if(secs > 0) {
secs--;
width = width - 2;
$('#time').css('width', width + '%').attr('aria-valuenow', width);
$('.seconds').html(secs);
} else if(secs == 0){
$('.questions').addClass('hidden');
$('.results').removeClass('hidden');
clearInterval(counter);
setInterval(winner, 3000);
}
};
var winner = function() {
$.ajax({
type: "POST",
url: "ajax.php",
data: {
func: "game_results"
},
error: function() {
swal("Błąd", "Serwer nie odpowiada, spróbuj ponownie", "error")
},
success: function(data) {
if (data == "you") {
$('.waiting').addClass('hidden');
$('.you').removeClass('hidden');
} else if (data == "opponent") {
$('.waiting').addClass('hidden');
$('.opponent').removeClass('hidden');
}
}
});
console.log(clearInterval(winner)); // heer
}
function answer(question_id, answer, question) {
var question_higher = question_id + 1;
$.ajax({
type: "POST",
url: "ajax.php",
data: {
func: "play",
answer: answer,
question: question
},
error: function() {
swal("Błąd", "Serwer nie odpowiada, spróbuj ponownie", "error")
},
success: function(data) {
if (data == "wrong") {
$.playSound('build/sounds/wrong');
$('*[data-question="' + question_id + '"]').find('.' + answer + '').removeClass('btn-primary').addClass('btn-danger');
$('*[data-question="' + question_id + '"]').find('.col-sm-12').addClass('dimmed');
setTimeout(function() {
$('*[data-question="' + question_id + '"]').addClass('hidden');
$('*[data-question="' + question_higher + '"]').removeClass('hidden');
}, 750);
} else if (data == "correct") {
$.playSound('build/sounds/correct');
$('*[data-question="' + question_id + '"]').find('.' + answer + '').removeClass('btn-primary').addClass('btn-success');
$('*[data-question="' + question_id + '"]').find('.col-sm-12').addClass('dimmed');
setTimeout(function() {
$('*[data-question="' + question_id + '"]').addClass('hidden');
$('*[data-question="' + question_higher + '"]').removeClass('hidden');
}, 750);
}
}
});
if(question_id == 5) {
clearInterval(counter);
setTimeout(function() {
//$('.questions').addClass('hidden');
$('.results').removeClass('hidden');
}, 750);
setInterval(winner, 3000);
}
}
$(document).ready(function() {
$('*[data-question="1"]').removeClass('hidden');
setInterval(counter, 1000);
});
Im trying to get this work for almost 5 hours without results.
Both clearInterval(counter); and clearInterval(winner) are not working and flooding my server with requets.
Thanks in advance for any help.
Let's see how you're clearing the interval.
clearInterval(winner)
where, winner is the function. To clear the interval, the ID of the interval should be passed as parameter.
When setting the interval, catch the interval ID in a variable
winnerInterval = setInterval(winner, 3000);
and use this variable to clear interval.
clearInterval(winnerInterval);
Make sure the variable containing interval ID is in the scope when clearing the interval.
See clearInterval.

Jquery Close autoComplete list

I have the following JQuery to display an autocomplete list:
var displayNum = 10;
var pointer = displayNum;
function DelegateSearch(txtBox)
{
$("#" + txtBox).attr("placeholder", "Search by Last Name");
$(".ajaxcompanyRefreshImage").attr("src", "/images/refresh.jpg");
$(".ajaxcompanyRefreshImage").hide();
$("#" +txtBox).parents().find('.ajaxcompanyRefreshImage').click(function () { $("#" +txtBox).autocomplete("search"); });
$("#" +txtBox).dblclick(function () { $(this).autocomplete("search"); });
$("#" +txtBox).autocomplete({
change: function (event, ui) {
if ($(this).val() == '') {
$(this).parents().find('.ajaxcompanyRefreshImage').hide();
}
},
close: function (event, ui) {
return false;
},
select: function (event, ui) {
var addr = ui.item.value.split('-');
var label = addr[0];
var value = addr[1];
value += addr[2];
if (label == null || label[1] == null ||(label.length < 1 && value == '' && value.length < 1)) {
$(this).autocomplete("option", "readyforClose", false);
}
else {
if (value[1]!= 0) {
$(this).autocomplete("option", "readyforClose", true);
delegateSearchPostBack(value, label, txtBox);
}
}
return false;
},
response: function (event, ui) {
var more = { label : "<b><a href='javascript:showmoreNames();' id='showmore'>Show more Names...</a></b>", value: '' };
ui.content.splice(ui.content.length, 0, more);
},
open: function(event, ui) {
showmoreNames();
},
search : function (event, ui) {
if ($(this).val().length < 3) {
$(this).parents().find('.ajaxcompanyRefreshImage').hide();
return false;
}
$(".ui-menu-item").remove();
},
source: function (request, response) {
$.ajax({
url: "/ajax/ajaxservice.asmx/GetDelegateListBySearch",
data: "{ prefixText: " + "'" +request.term + "'}",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
dataFilter: function (data) {
return data; },
minLength: 2,
success: function (data) {
pointer = displayNum;
response($.map(data.d, function (val, key) {
return {
label: DelegateSearchMenulayout(key, val),
value: val
};
}));
},
error: function (XMLHttpRequest, textStatus, errorThrown) {}
});
}
});
}
function DelegateSearchMenulayout(key, val) {
var net = '';
var userData = val.split('-');
var table = "<table width=350px' style='border-bottom-style:solid;' class='menutable'>";
table += "<tr><th width='300px'></th>";
table += "<tr><td><b>" + userData[1] + "" + userData[2] + "</b></td></tr>";
table += "<tr><td>" + userData[4] + " - " + userData[3] + "</td></tr>";
table += "</table>";
return table;
}
function delegateSearchPostBack(userName, userId, txtBox) {
$("#" + txtBox).autocomplete("destroy");
$("#" + txtBox).val(userId +"-" + userName );
pointer = displayNum;
__doPostBack(txtBox, "");
}
function showmoreNames() {
$(".menutable").each(function (index) {
if (index >= pointer) {
$(this).parent().hide();
}
else {
$(this).parent().show();
}
});
if ($(".menutable").length <= pointer) {
$("#showmore").attr("href", "javascript: function () {return false;}");
$("#showmore").text("End of Users");
}
else pointer += displayNum;
}
It displays 10 names by default. If the list is longer, "Show more names" is displayed on click of which,10 more names are displayed. With the initial 10 names, the JQuery works perfect.When I click outside or hit ESC, the list of names disappears. But with a longer list, when I click on Show More Names, a longer list is displayed but on click of ESC or clicking outside the list, it does not disappear! How can I make this work?
I tried the following solution:
how to make the dropdown autocomplete to disappear onblur or click outside in jquery?
But with this solution, the list disappears when I click on Show More!
$(document).bind('click', function (event) {
// Check if we have not clicked on the search box
if (!($(event.target).parents().andSelf().is('#showmore'))) {
$(".ui-menu-item").remove();
}
});
The above worked. I did an additional check on document click whether the option 'Show More' is clicked. The has id= 'showmore'. Hence checking if user did not click on it.

Accessing and modifing a variable in and out of functions

Hello i am trying to modify the variable popText but failing on the ajax function, i cant get the output on popText :(
What am i doing wrong?
function nariTooltip(){
var popTime;
var fading;
var popboxIsActive = false;
var mouseIsHoverPopbox = false;
var popText;
//Using Event Delegation to cover late AJAX inserted DOM elements
//no need to recall function after each AJAX run
//Mouseenter / Mouseout
$("body").on(
{
mouseenter: function(e){
$hoverElem = $(this);
//Define Variables
var popDelay = 250;
if ($hoverElem.attr("popdelay")){
var popDelay = $hoverElem.attr("popdelay");
}
popTime = setTimeout(function() {
popText = $hoverElem.attr("poptext");
if ($hoverElem.next().hasClass("poptext")) {
popText = $hoverElem.next(".poptext").html();
}
var popAjax = $hoverElem.attr("popajax");
if (popAjax){
var popAjax = popAjax.split(':');
popAjaxType = popAjax[0];
if (popAjaxType == 'general')
{
popAjaxUrl = 'tooltip_gen.php';
}
else if (popAjaxType == 'item')
{
popAjaxUrl = 'tooltip_items.php';
}
if (popAjaxUrl){
$.ajax({ url: 'ajax/'+popAjaxUrl,
data: {id: popAjax[1]},
type: 'get',
success: function(output)
{
popText = output;
},
error:function (xhr, ajaxOptions, thrownError){
popText = html(xhr.statusText);
},
});
}
//alert(outputs);
}
//Create Popup
$hoverElem.append('<div class="popbox">' + popText + '</div>');
popText always end up with the value assigned on popText = $hoverElem.next(".poptext").html();
It seems that you create the div with the text before ajax has returned. Make function that sets the popText and call it when you've got it from ajax
function setPopText( elem, txt ) {
$(elem).append('<div class="popbox">' + txt + '</div>')
}
And in your ajax
success: function ( output ) {
setPopText( $hoverElem, output );
}

Categories

Resources