How to pause between two javascript commands during the same onchange event - javascript

I have a input with an onchange event:
<input type="text" value="2014-01-01" class="datepicker dateDashboard" onchange="repartiteur('DatesDashboard',$(this));document.location.href='index.php?menu=17|30&options=opt';" name="DateDebutDashboard">
function appelAjax(data)
{$.ajax(
{type: "post",
data: data,
url: 'index_ajax.php'
});
}
function repartiteur(action,this)
{switch (action)
{case 'DatesDashboard':
data = (
{'action' : action,
'champ' : this.attr('name'),
'date' : this.val()
});
break;}
appelAjax(data);}
the desired goal is that when I change the date in the input, the date is sent via AJAX to change a value in the database, then the page is reloaded according to new values in database.
the problem is that sometimes, the ajax call by repartiteur takes longer to react and when the page reloads (with the second inline javascript call), the changes have not yet occured in the database.
the QUESTION: How can I, if it is in any way possible, delay the second javascript part (the reload document) to make sure the ajax call have finished updating the database before the page reloads?
checking this answer How to implement a lock in JavaScript I feel there some way to do that, but this answer applies to different events, while I want the delay to happen in the same event but between different javascript lines.
I know about event.stopPropagation but I don't want the event to stop, it must continue after the ajax call.
EDIT - here the php codes which receives the call:
$action = $_POST['action'];
switch ($action)
{case 'DatesDashboard':
$codeUSR = $_SESSION['usr'];
$champ = $_POST['champ'];
$date = $_POST['date'];
$env = unserialize(getValue('Preferences','ps_personnes',"codeUSR='$codeUSR'"));
$env['nav']['Contrat']['dates'][$champ] = $date;
sauverEnvironnement($env,$oDB,'Preferences');
break;}
the database definition:
$oDB = new PDO("mysql:host=$gSERV;dbname=$gBASE;charset=utf8",$gUSER,$gPASS);
$oDB->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
$oDB->setAttribute(PDO::ATTR_EMULATE_PREPARES,FALSE);

You want a nested callback function, something like this:
$.ajax({
url: 'blahblah'
}).done(function() {
$.ajax({
url: 'secondlayer'
}).done(function() {
innerstuff();
});
})
});
The explanation is, you only do your second function after your first function is done (or completes successfully, up to you). Conversely, you only call your final (innerstuff) function when the second function has fully completed as well.
Source: http://api.jquery.com/jquery.ajax/

so with timeout() I set the javascript to reload the page so that it "waits" before taking action:
<input type="text" value="2014-01-01" class="datepicker dateDashboard" onchange="repartiteur('DatesDashboard',$(this));setTimeout(document.location.href='index.php?menu=17|30&options=opt',500);" name="DateDebutDashboard">
hence the changes in the db are now done when the page reloads.

Related

Bootstrap modal does not work correctly with my ajax code

I created a partial view called ModalReq, which needs to be populated with data from the database.
The controller and view is working correctly.
But when you click on an element with the class '.car-box', nothing happens at first, after the second press, the correctly filled modal appears, but it doesn’t want to close in any way, how to make the modal work correctly?
Ajax code in main view:
<script>
function ajaxReq(url,type,selector) {
$.ajax({
url: url,
type: type,
contentType: 'application/json',
success: function (data) {
$(selector).html(data);
}
});
}
</script>
<script>
$(document).on('click', '.car-box', function () {
var objText = $(this).children('.box-his').children("span").text();
var objId = objText.substring(1, objText.length);
ajaxReq("#Url.Action("ModalReq")" + "?productId=" + objId, "POST", '#result');
$('#myModal').modal('show')
});
</script>
And I create a div with it at the very bottom of this view( but still above the Ajax code )
<div id="result"></div>
When you click on an element with the class '.car-box', the Ajax code creates an object that receives its number with a string type inside the card. It then leaves only a number with the same type of string. Then I call ajaxReq in which I transmit my partial view that accepts the Id specified by us. Then includes the created modal ...
I never use ajax before, so I need your help =)
In the current iteration $('#myModal').modal('show') is not waiting for the Ajax response.
How about moving it to your success function?
success: function (data) {
$(selector).html(data);
$('#myModal').modal('show')
}
Then the modal will get the data after one press.
Or: this answer jQuery ajax with ES6 Promises should give you guidance setting it up as a Promise.

How to select option from second select after it loads with javascript?

Yeah, I know, likely been answered, but can't find it or figure out how to successfully search for it, so, 45 minutes later i am succumbing to the potential of flaming...so go easy on me, ok?
It is a simple problem, and my issue is timing. One select holds Countries, it is bound to State/Province select. Change Country, State/Province loads appropriately via a separate function. Use a mouse to select from State/Province, perfection. Use JavaScript ..uh oh. Problem is I need to force my JavaScript to wait for the browser to load the State/Province data before I can target and select it. SetTimeout or using a Promise just seems... inelegant? How many seconds does a browser need to load 50 states or 8 provinces - on a new rocket or an old turtle? Is there a way to just know when the second select finishes loading when the load is in a separate function? Example is jquery, but any flavor will do.
$('#country option[value=US]').prop('selected', 'selected').change();
$('#stp option[value=VT]').prop('selected', 'selected').change();
Adding more clarification based on the responses so far.
Whena user changes the Country, the State/Province loads in the time it takes them to move their mouse down the page allowing them to select.
Now I have implemented a helper that pulls the user's address from BigData using a phone number. This happens in a dialog box. When the user clicks "Accept" this code then fires
function setFormwithDF(){
d={};
// data from dialog
d.address=$('#oaddress').text();
d.city=$('#ocity').text();
d.state=$('#ostate').text();
d.zip=$('#ozip').text();
d.country=$('#ocountry').text();
$('#s_country option[value='+d.country+']').prop('selected', 'selected').trigger('change');
// doesn't matter if this is .change() or .trigger('change')
$('#s_addr1').val(d.address).change();
$('#s_addr2').val('').change();
$('#s_city').val(d.city).change();
$('#s_st option[value='+d.state+']').delay(3000).prop('selected', 'selected');console.log(d.state);//getting a good value here - delay is desperation
$('#s_zip').val(d.zip);
$('#s_phone').val($('#dfsearch').val());
$( "#dfsearchdialog" ).dialog('close');
}
And for completeness, here is the loading code. Bunch of extras in here that don't pertain to the issue though
$('#s_country,#b_country').change(function(e){
var st="";
var addrType="S";
var loadObj=$('#shipstp');
if( $(this).attr("id") == 'b_country'){
loadObj=$('#billstp');
addrType="B";
}
if( typeof(e.st) != 'undefined'){st=e.st;console.log(5)}// this data is passed during the trigger() code
uObj={c:$(this).val(),nc:Math.random(),t:addrType,p:st};
uParam=$.param(uObj);
loadObj.load('/stubs/state-n-province.cfm',uParam);
});
As per my understanding, you dont want user to select state until the state's are getting loaded. After loading only user should be able to select the state.
And I am assuming you are using AJAX to load the State.
If this is the issue :
you can use loading image, which will be displayed until the success has not been return and data has not been map to element.
In this case you can use below sample code :
function getData(p){
.......
$('#loadingmessage').show(); // show the loading message.
$.ajax({
url: "loadData.php?id=<? echo $id; ?>",
type: "POST",
cache: false,
data: "&page="+ page,
success : function(html){
$(".content").html(html);
$('#loadingmessage').hide(); // hide the loading message
}
});
I believe a Promise is what you need. It will allow you exactly
to just know when the second select finishes loading when the load is
in a separate function
$('#country').change(function() {
$("#stp").empty().append("<option>...</option>");
loadStates($(this).val())
.then(states => $("#stp")
.empty()
.append(states.reduce((acc, cur) => acc + `<option>${cur}</option>`, "")));
});
$('#country').change();
function loadStates(country) {
console.log(`Loading states for country: ${country}...`);
//setTimeout here just emulates your long loading process
return new Promise((res, rej) => setTimeout(() => {
console.log(`States for country: ${country} are loaded!`);
res(["state1", "state2", "state3"]);
}, 3000));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="country">
<option>US</option>
<option>UK</option>
<option>RU</option>
</select>
<select id="stp">
</select>
For your actual use case you would write something like:
return new Promise((resolve, reject) => {
var states = yourLoadingFunction();
resolve(states);
});
UPDATE: Given your latest example, I think I understand your problem now. I suggest you to put your loading code into a separate function, for example:
function countryChanged(e, callback) {
var st="";
var addrType="S";
var loadObj=$('#shipstp');
if( $(this).attr("id") == 'b_country'){
loadObj=$('#billstp');
addrType="B";
}
loadObj.prop("disabled", true);
// this data is passed during the trigger() code
if( typeof(e.st) != 'undefined'){st=e.st;console.log(5)}
uObj={c:$(this).val(),nc:Math.random(),t:addrType,p:st};
uParam=$.param(uObj);
loadObj.load('/stubs/state-n-province.cfm', uParam, function() {
// when the loading is complete, we enable the second select and
// call the callback function
loadObj.prop("disabled", false);
if (callback) callback();
});
}
Note that jQuery .load() method has a third argument which is a callback function that will be called when the loading is complete.
Then you can use this function in two ways:
1) when the user changes the country:
$('#s_country,#b_country').change(countryChanged);
2) in your setFormwithDF() function:
function setFormwithDF(){
d={};
// data from dialog
d.address=$('#oaddress').text();
d.city=$('#ocity').text();
d.state=$('#ostate').text();
d.zip=$('#ozip').text();
d.country=$('#ocountry').text();
$('#s_country option[value='+d.country+']').prop('selected', 'selected');
//instead of calling .trigger('change') just call countryChanged function
countryChanged({st: "whatever you pass during the trigger() code"}, function() {
//this will happen only after .load() is complete
$('#s_st option[value='+d.state+']').prop('selected', 'selected');
});
$('#s_addr1').val(d.address).change();
$('#s_addr2').val('').change();
$('#s_city').val(d.city).change();
$('#s_zip').val(d.zip);
$('#s_phone').val($('#dfsearch').val());
$( "#dfsearchdialog" ).dialog('close');
}

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)
});

submitting a form via ajax upon stop event of jquery

UPDATE
Added this error, just says "Error caught"
<script type="text/javascript">
window.onerror = function() {
alert("Error caught");
};
xxx();
</script>
This is not working, I don't understand why.
My php script inserts data properly if called by itself without an if{method=post} statement
I tried with and without an if method = post argument on the php side to get the ajax below to work but I can't tell if the script is being called at all.
My aim is to submit the data without the user knowing, it's a coordinate / dimension update for a variable design interface.
This is my ajax insert which is supposed to work when a function is invoked after the stop is triggered eg. after an object is done moving which the function is invoked properly as I have set up sequential alerts to pop up after certain lines.
$("#form").submit(function(event){
event.preventDefault();
var $form = $( this ),
url = $form.attr( 'action' );
var posting = $.post( url, {
id: $('#id').val(),
name: $('#name').val(),
wname: $('#wname').val(),
xcor: $('#xcor').val(xcor),
ycor: $('#ycor').val(ycor),
xwid: $('#xwid').val(xwid),
yhei: $('#yhei').val(yhei),
photo: $('#photo').val(),
targeturl: $('#targeturl').val()
});
posting.done(function( data ){
alert('success');
});
});
This is wrong
xcor: $('#xcor').val(xcor),
ycor: $('#ycor').val(ycor),
xwid: $('#xwid').val(xwid),
yhei: $('#yhei').val(yhei),
Those object are holding jQuery objects, not a value.
Looks like you want to set the value and use the new value. This makes me cringe, but it would do the job
xcor: $('#xcor').val(xcor).val(),
ycor: $('#ycor').val(ycor).val(),
xwid: $('#xwid').val(xwid).val(),
yhei: $('#yhei').val(yhei).val(),
You would be better off updating them before the call and just using the variable when setting the object. Or just use jQuery serialize() and don't deal with grabbing the elements.

How do I get my jquery post request to work with the variable stored from a function on a click?

I have been banging my head against the wall trying to pass a game's name through to my php function as soon as a user clicks a button. The idea is the user clicks a button, which has a value of its videogame name, then the php script checks that game's ranking and returns that ranking to the html. I have made post requests work before, and even here when I manually set the variable name to one of the Games to test it, it works. Please help!
<script>
$(document).ready(function(){
//global n variable
n = $();
$('#target').click(function(){
//set value of n to the game's name
n = $(this).val();
});
//then send the name as term to my php function to deal with it and return
//the ranking
$.post('getTotal.php', {term: n}, function(data){
//been trying to see if anything comes through for debugging purposes
alert(data);
//commented this out for now, just puts it in the div I left open
//$('#total').html(data);
});
});
</script>
simply when the user clicks the button. inside the click handler, obtain the value and perform an http post
$ajax or $POST
eg -
$(document).ready(function() {
$('#target').click(function()
$.ajax({
type: "POST",
url: "url...",
data: "n="+nVal+",
success: function(html){
alert( "Submitted");
}
});
});
});
You should put the $.post into your click handler... so it will only run when you actually click the button... now your code sets up an n variable, its value is an empty jQuery object (why?). Then it attaches a click handler on the button. Then it runs a $.post request - n is still an empty jQuery object. Clicking the button happens much later...
Also, using globals should be avoided. The var keyword should be used when declaring variables.

Categories