ajax get null value - javascript

My code can get data in Chrome console
but cant get data in my program
code like this:
$(document).ready(function () {
var theme = '';
var source = [];
var rsps = '';
$.ajax({
url: '#Url.Content("~/Home/RoleMenus")',
type: "GET",
cache: false,
success: function(response, status, xhr) {
rsps = response;
source = eval(response);
},
error: function(XMLHttpRequest,textStattus,errorThrown) {
$('#jqxErrorMsg').html(errorThrown);
}
});
for(var src in source) {
if (src.items.legth > 0) {
src.expanded = true;
}
}
// Create jqxTree
$('#jqxTree').jqxTree({ source: source, theme: theme});
$('#jqxTree').bind('select', function (event) {
var args = event.args;
var item = $('#jqxTree').jqxTree('getItem', args.element);
for (var menu in source[0]) {
if (item.label == menu.label) {
window.location = menu.actionUrl;
//break;
}
}
});
});
=====update=====
the response is right, if i move
// Create jqxTree
$('#jqxTree').jqxTree({ source: source, theme: theme});
into success: function(response, status, xhr) {}
the menu shows correctly
but the source variable still has no value outside
=====solved====
for (var menu in source[0])
should be
for (int i=0;i<source[0].length;i++)

The ajax call is async so source variable may not be initialized yet. Try putting
for(var src in source) {
if (src.items.legth > 0) {
src.expanded = true;
}
}
// Create jqxTree
$('#jqxTree').jqxTree({ source: source, theme: theme});
in the succes function.

Related

Global variable update AJAX POST

Below is my full JS file beginning to end. I set a variable 'rendered' outside all functions. Then, since it is required in the if check just before issuing a POST request I want to use it as flag and update it's value to be true upon post request completion. The issue is that all the console.log calls do print the changed value but it does not persist. When again the position coordinates are fetched automatically in the watchPosition function, calculateDistance function is invoked again. Then, the previous saved value with "window.rendered = true" is not there, it is actually false and it enters the if condition. How can I achieve the goal of not issuing the post request again until another post request changes this flag variable back to false?
var rendered = false;
function myfunc() {
rendered = true;
console.log(window.rendered);
}
function updatePosition() {
if(navigator.geolocation) {
navigator.geolocation.watchPosition(calculateDistance);
}
else {
console.log("Geolocation is not supported by this browser.")
}
}
function calculateDistance(position) {
var pos = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
var target = new google.maps.LatLng(55.85365783555865, -4.288739944549508);
var dis = google.maps.geometry.spherical.computeDistanceBetween(pos, target);
console.log(window.rendered);
var self = this;
if(dis <= 1000 && dis >= 0 && window.rendered == false) {
console.log("Distance"+dis);
var url = '/dogpark/near_park/';
var csrftoken = getCookie('csrftoken');
$.ajax({
url: url,
type: "POST",
data: {
csrfmiddlewaretoken: csrftoken,
in_proximity : 1
},
async: false,
success: function(data) {
myfunc();
self.rendered = true;
window.rendered = true;
alert(window.rendered);
window.location = '/dogpark/near_park/';
},
complete: function(data) {
console.log("Trying");
window.rendered = true;
alert(window.rendered);
},
error: function(xhr, errmsg, err) {
console.log(xhr.status+": "+xhr.responseText);
},
});
}
window.onload = updatePosition()
A simple way is to use another variable to track the ajax call completion. So that you don't make another Ajax call until the previous one returns a repsonse(success/failure).
var isWaitingForResponse = false;
...
function calculateDistance(position) {
...
if(dis <= 1000 && dis >= 0 && window.rendered == false && !isWaitingForResponse) {
isWaitingForResponse = true;
...
success: function(data) {
isWaitingForResponse = false
...
},
complete: function(data) {
isWaitingForResponse = false
...
},
error: function(xhr, errmsg, err) {
isWaitingForResponse = false
...
}
...

Cannot POST more than one value with AJAX

I stucked on one thing. I have a 2 grid inside checkboxes. When I selected that checkboxes I want to POST that row data values like array or List. Actually when i send one list item it's posting without error but when i get more than one item it couldn't post values.
Example of my grid
Here my ajax request and how to select row values function
var grid = $("#InvoceGrid").data('kendoGrid');
var sel = $("input:checked", grid.tbody).closest("tr");
var items = [];
$.each(sel, function (idx, row) {
var item = grid.dataItem(row);
items.push(item);
});
var grid1 = $("#DeliveryGrid").data('kendoGrid');
var sel1 = $("input:checked", grid1.tbody).closest("tr");
var items1 = [];
$.each(sel1, function (idx, row) {
var item1 = grid1.dataItem(row);
items1.push(item1);
});
$.ajax({
url: '../HeadOffice/CreateInvoice',
type: 'POST',
data: JSON.stringify({ 'items': items, 'items1': items1, 'refnum': refnum }),
contentType: 'application/json',
traditional: true,
success: function (msg) {
if (msg == "0") {
$("#lblMessageInvoice").text("Invoices have been created.")
var del = $("#InvoiceOKWindow").data("kendoWindow");
del.center().open();
var del1 = $("#InvoiceDetail").data("kendoWindow");
del1.center().close();
$("#grdDlvInv").data('kendoGrid').dataSource.read();
}
else {
$("#lblMessageInvoice").text("Problem occured. Please try again later.")
var del = $("#InvoiceOKWindow").data("kendoWindow");
del.center().open();
return false;
}
}
});
This is my C# part
[HttpPost]
public string CreateInvoice(List<Pm_I_GecisTo_Result> items, List<Pm_I_GecisFrom_Result> items1, string refnum)
{
try
{
if (items != null && items1 != null)
{
//do Something
}
else
{
Log.append("Items not selected", 50);
return "-1";
}
}
catch (Exception ex)
{
Log.append("Exception in Create Invoice action of HeadOfficeController " + ex.ToString(), 50);
return "-1";
}
}
But when i send just one row it works but when i try to send more than one value it post null and create problem
How can i solve this? Do you have any idea?
EDIT
I forgot to say but this way is working on localy but when i update server is not working proper.
$.ajax({
url: '../HeadOffice/CreateInvoice',
type: 'POST',
async: false,
data: { items: items, items1: items1 }
success: function (msg) {
//add codes
},
error: function () {
location.reload();
}
});
try to call controller by this method :)

When submitting an ajax request, how can you "put the original request on hold" temporarily until a condition is met?

I am wanting to implement a recaptcha process that captures all ajax requests before they go through - the desired process would be as follows:
User completes an action which is going to cause an ajax request of some sort.
If the user has already completed the recaptcha process, the ajax request proceeds without further delay
If the user has not completed the recaptcha process, put the ajax request "on hold" temporarily until the recaptcha process is completed, then continue the ajax request.
I have got things to a state where I intercept the call, however I don't know how to put it on hold temporarily. Here's the relevant code:
<script>
var captchaValidated = null;
var currentRequests = [];
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
if (options.url != "/ValidateCaptcha") {
if (captchaValidated == null || captchaValidated == false) {
if (captchaValidated == null){
openRecaptcha();
} else {
verifyCaptcha(); //see async question in method
}
if (!captchaValidated) {
jqXHR.abort();
} else {
//let the original request proceed now - but how?!
}
}
}
});
function verifyCaptcha() {
var grecaptcha = $("g-recaptcha-response");
var encodedResponse;
if (grecaptcha != null) {
encodedResponse = grecaptcha.val();
$.ajax({
async: false, //set to false so that the calling method completes rather than async - what do you think?
headers: headers,
cache: false,
url: "/ValidateCaptcha",
type: 'POST',
contentType: 'application/json',
success: function (data) {
//parse the data - did we get back true?
captchaValidated = data;
},
error: function (raw, textStatus, errorThrown) { captchaValidated = null; alert("Validate ReCaptcha Error: " + JSON.stringify(raw)); },
data: JSON.stringify({ "encodedResponse": encodedResponse })
});
}
}
function invalidateCaptcha(){
captchaValidated = null;
}
function openRecaptcha() {
grecaptcha.render('recaptcha', {
'sitekey': "thekey",
'callback': verifyCaptcha,
'expired-callback': invalidateCaptcha,
'type': 'audio image'
});
$("#recaptchaModal").modal('show');
}
</script>
Any suggestions of how to proceed would be appreciated, thanks in advance!
Thank you #Loading and #guest271314 for your help in pointing me in the right direction that helped me get things figured out. I've pasted how I accomplished it below - perhaps it will be of help to someone else. Of course if anyone would like to weigh in on my implementation please do.
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCaptcha&render=explicit&hl=en" async defer></script>
<script>
var captchaValidated = null;
var currentRequests = [];
var captchaPrompted = false;
var captchaReady = false;
var resetCaptcha = false;
function onloadCaptcha() {
captchaReady = true;
captcha = grecaptcha.render('recaptcha', {
'sitekey': '<yoursitekey>',
'callback': verifyCaptcha,
'expired-callback': invalidateCaptcha,
'type': 'audio image'
});
}
var deferredCaptcha = null;
var promiseCaptcha = null;
var captcha = null;
function openRecaptcha() {
if (!captchaReady) {
setTimeout(openRecaptcha, 50);
}
if (captchaPrompted) {
return;
}
captchaPrompted = true;
var captchaTimer = setInterval(function () {
if (captchaValidated != null) {
if (captchaValidated) {
deferredCaptcha.resolve();
} else {
deferredCaptcha.reject();
captchaValidated = null;
}
}
}, 100);
if (resetCaptcha) {
captcha.reset();
}
deferredCaptcha = $.Deferred();
promiseCaptcha = deferredCaptcha.promise();
promiseCaptcha.done(function () {
//captcha was successful
clearInterval(captchaTimer);
//process the queue if there's items to go through
if (currentRequests.length > 0) {
for (var i = 0; i < currentRequests.length; i++) {
//re-request the item
$.ajax(currentRequests[i]);
}
}
});
promiseCaptcha.fail(function () {
//captcha failed
clearInterval(captchaTimer);
currentRequests = []; //clear the queue
});
$("#recaptchaModal").modal('show');
}
function verifyCaptcha() {
resetCaptcha = true;
var response = $("#g-recaptcha-response").val();
var encodedResponse;
// confirm its validity at the server end
$.ajax({
headers: headers,
cache: false,
url: "/ValidateCaptcha",
type: 'POST',
contentType: 'application/json',
success: function (data) {
captchaValidated = data;
if (!data) {
captchaPrompted = false;
}
},
error: function (raw, textStatus, errorThrown) { captchaValidated = false; captchaPrompted = false; alert("WTF Validate ReCaptcha Error?!: " + JSON.stringify(raw)); },
data: JSON.stringify({ "encodedResponse": response })
});
}
function invalidateCaptcha(){
deferredCaptcha.reject();
captchaValidated = null;
resetCaptcha = true;
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (settings.url == '/ValidateCaptcha' || captchaValidated) {
// we're validating the captcha server side now or it's already been validated - let it through
} else {
if (typeof settings.nested === 'undefined'){
settings.nested = true; //this flag is to determine whether it's already in the queue
currentRequests.push(settings); //add the request to the queue to be resubmitted
//prompt them with the captcha
openRecaptcha();
}
return false; // cancel this request
}
}
});
</script>
At $.ajaxPrefilter() use .then() chained to openCaptcha to call verifyCaptcha
if (captchaValidated == null){
openRecaptcha().then(verifyCaptcha);
}
at verifyCaptcha use .is() with parameter "*" to check if an element exists in document
if (grecaptcha.is("*")) {
at openRecaptcha(), if grecaptcha.render does not return asynchronous result return jQuery promise object using .promise(); else chain to grecaptcha.render and $("#recaptchaModal").modal('show'); using $.when()
return $("#recaptchaModal").modal('show').promise()
or
return $.when(grecaptcha.render(/* parameters */)
, $("#recaptchaModal").modal('show').promise())
Something like this? (pseudo-code)
verified = false;
$('#myButton').click(function(){
if (!verified) verify_by_captcha();
if (verified){
$.ajax(function(){
type: 'post',
url: 'path/to/ajax.php',
data: your_data
})
.done(function(recd){
//ajax completed, do what you need to do next
alert(recd);
});
}
});//end myButton.click

Close the Chrome Extension automatically

I am trying to close the extension automatically after saving my data.
Here is the code which is used to save the data:
$(function(){
function displayMessage(string){
alert(string);
}
var submit = $('#submit');
$('#create').submit(function(){
$('#loading_image').html('<img src="images/wait.gif">');
var user_email = localStorage.getItem('email');
var api = localStorage.getItem("user_api_key");
var auth = "apikey" +' ' +(user_email+":"+api);
var favicon_key = localStorage.getItem("favicon_image_key");
var peoples = [];
var tags_peoples = $("#s2id_people .select2-choices .select2-search-choice");
for (i=0; i<tags_peoples.length; i++) {
peoples.push({"label": tags_peoples[i].childNodes[1].textContent})
}
var subjects = [];
var tags_subjects = $("#s2id_subjects .select2-choices .select2-search-choice");
for (i=0; i<tags_subjects.length;i++) {
subjects.push({"label": tags_subjects[i].childNodes[1].textContent})
}
var places = [];
var tags_places = $("#s2id_places .select2-choices .select2-search-choice");
for (i=0; i<tags_places.length; i++) {
places.push({"label": tags_places[i].childNodes[1].textContent})
}
var begin = $(".daterangepicker_start_input")[0].childNodes[1].value;
var end = $(".daterangepicker_end_input")[0].childNodes[1].value;
var data = {
'content': $('#title').val(),
'people': peoples,
'subjects': subjects,
'begin_date': begin,
'end_date': end,
'places': places
}
$.ajax({
type: "POST",
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization", auth);
xhr.setRequestHeader("Content-Type","application/json");
xhr.setRequestHeader("Accept","application/json");
},
url: "https://my_site_url/api/v3/data/",
dataType: "json",
data: JSON.stringify(data),
contentType: "application/json",
success: function(data) {
$('#loading_image').hide();
window.location.href = 'saved.html';
setTimeout(function(){
window.close();
}, 2000);
},
error: function(data) {
$('#div1').text("Error on saving the data");
$('#loading_image').hide();
},
complete: function() {
submit.removeAttr('disabled').text('Save');
}
});
return false;
});
});
I am using this to close the extension
setTimeout(function(){window.close();}, 3000);
But this doesn't work. Should I write any EventListener to close the extension automatically?
Appreciated the answers
Consider this snippet from your code:
window.location.href = 'saved.html';
setTimeout(function(){
window.close();
}, 2000);
This will not work. As soon as you change location, the page starts to navigate away, eventually wiping the window state and all timeouts set when the new page loads.
You need to set the timeout from saved.html for this to work.

How could I trigger func when another has been completed?

I am using JQuery to collect latest tweets using Twitter API, but I am having some issues when calling two functions.
$(document).ready(function(){
JQTWEET.loadTweets();
});
This, is working ok, but then I want to call this function:
showHideTweets: function() {
alert("hola");
var ojeto = $(JQTWEET.appendTo).find(".item").first();
$(JQTWEET.appendTo).find(".item").first().css("display", "block");
},
Both functions are inside: jqtweet.js ...
loadTweets: function() {
var request;
// different JSON request {hash|user}
if (JQTWEET.search) {
request = {
q: JQTWEET.search,
count: JQTWEET.numTweets,
api: 'search_tweets'
}
} else {
request = {
q: JQTWEET.user,
count: JQTWEET.numTweets,
api: 'statuses_userTimeline'
}
}
$.ajax({
url: 'tweets.php',
type: 'POST',
dataType: 'json',
data: request,
success: function(data, textStatus, xhr) {
if (data.httpstatus == 200) {
if (JQTWEET.search) data = data.statuses;
var text, name, img;
try {
// append tweets into page
for (var i = 0; i < JQTWEET.numTweets; i++) {
img = '';
url = 'http://twitter.com/' + data[i].user.screen_name + '/status/' + data[i].id_str;
try {
if (data[i].entities['media']) {
img = '<img src="' + data[i].entities['media'][0].media_url + '" />';
}
} catch (e) {
//no media
}
var textoMostrar = JQTWEET.template.replace('{TEXT}', JQTWEET.ify.clean(data[i].text) ).replace('{USER}', data[i].user.screen_name).replace('{IMG}', img).replace('{URL}', url );
/*.replace('{AGO}', JQTWEET.timeAgo(data[i].created_at) ) */
//alert(JQTWEET.timeAgo(data[i].created_at));
$(JQTWEET.appendTo).append( JQTWEET.template.replace('{TEXT}', JQTWEET.ify.clean(data[i].text) )
.replace('{USER}', data[i].user.screen_name)
.replace('{NAME}', data[i].user.name)
.replace('{IMG}', img)
.replace('{PROFIMG}', data[i].user.profile_image_url)
/*.replace('{AGO}', JQTWEET.timeAgo(data[i].created_at) )*/
.replace('{URL}', url )
);
if ( (JQTWEET.numTweets - 1) == i) {
$(JQTWEET.appendTo).find(".item").last().addClass("last");
}
}
} catch (e) {
//item is less than item count
}
if (JQTWEET.useGridalicious) {
//run grid-a-licious
$(JQTWEET.appendTo).gridalicious({
gutter: 13,
width: 200,
animate: true
});
}
} else alert('no data returned');
}
});
callback();
},
showHideTweets: function() {
alert("hola");
var ojeto = $(JQTWEET.appendTo).find(".item").first();
$(JQTWEET.appendTo).find(".item").first().css("display", "block");
},
The problem is that if a call functions like this:
$(document).ready(function(){
JQTWEET.loadTweets();
JQTWEET.showHideTweets();
});
Second function executes before tweets has been loaded, so it have nothing to search in, because I can see the alert("hola") working, but Ojeto is 0.
I was trying to create some kind of callback inside loadTweets(); but I could not.
The callback isn't a bad idea.
change loadTweets to look like this:
loadTweets: function(callback) {
And call it here:
$.ajax({
...
success: function(data, textStatus, xhr) {
...
if (callback) callback();
}
});
And then in your DOM ready callback:
$(document).ready(function(){
JQTWEET.loadTweets(JQTWEET.showHideTweets);
});
Your other option (which I actually prefer, in general) is to use a deferred object:
loadTweets: function(callback) {
var def = $.Deferred();
...
$.ajax({
...
success: function(data, textStatus, xhr) {
...
def.resolve();
}
});
return def.promise();
}
...
$(document).ready(function(){
JQTWEET.loadTweets().done(JQTWEET.showHideTweets);
});
Try jQuery methods chaining:
$(document).ready(function(){
JQTWEET.loadTweets().showHideTweets();
});

Categories

Resources