Phonegap MobileJQuery AJAX Posts Twice while debugging - jquery-mobile

Hope there is some out there that can help!,
While debugging a WCF service that a phonegap application connects to it seems to post twice.
When the application runs normally no Break points etc it all works fine and i only receive 1.
It appears to me that ajax reposts itself if no response is returned from the server after a few seconds.
I will need to confirm this threw wireshark but just wanted to know if anyone else has come accross this before.
$.ajax({
type: "POST",
url: ServicePATH ,
data: JSON.stringify({ objs: arrayobj, parm2: var2, parm3: var3, parm4: 1 }),
contentType: "application/json",
dataType: "json",
success: function (data, textStatus, jqXHR) {
CallonSuccess(data);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
console.log('error ' + textStatus);
console.log('XMLHttpRequest ' + XMLHttpRequest);
var str = '';
for (prop in XMLHttpRequest) {
str += "prop " + prop + " value :" + XMLHttpRequest[prop] + "\n"; //Concate prop and its value from object
}
console.log(str);
console.log('errorThrown ' + errorThrown);
console.log('passing ' + JSON.stringify({ objs: arrayobj, parm2: var2, parm3: var3, parm4: 1 }));
}
}).done(function () { console.log('Finished ajax'); });
Thanks Lmac

Perhaps no solution (see update below) for you but the same behaviour here.
Without the jquery Mobile framework everything works okay, with the framework embedded it fetches my json file a second time. In Chrome's Console you can see it under Network: GET status 200 and GET status 304 (not modified).
I have the option to throw out jQuery Mobile and I surely will. But would be also interested in knowing what's happening there.
UPDATE:
I had the xmlhttprequest within the $(document).ready(function() { }); It seems as if both jQuery and jQuery Mobile react to that.
If I put the script at the end of the site and make my xmlhttprequest outside the ready-method it fetches my json file only once.

Related

Angular $http.get and variable use

Ok, so still new to Angular, using 1.3.1, and here's my problem:
console.log('CompanyID: ' + $scope.companyID);
$http.get('/api/List/GetGangTemplates', { params: { id:$scope.companyID }})
.success(function (data, status, headers, config) {
console.log('CompanyID SUCCESS: ' + $scope.companyID);
$scope.templates.data = data;
})
first console.log -> 'CompanyID: undefined'
second console.log (in success) -> 'CompanyID SUCCESS: 1' // this is what it should be!
Looking at my Scope via batarang shows companyID: 1.
I should note that this is a MVC / Angular hybrid. My Razor page has the following:
#Html.HiddenFor(Function(model) model.CompanyID, New With {.ng_init = "companyID=" & Model.CompanyID})
What am I missing? I want to use a hidden field on my Razor page to pass an ID to Angular to do my AJAX call....

Loading failed error

I am getting Loading failed error when searching for something in a select2 box using ajax. My code is as follows:
$("#drugSearch").select2({
placeholder: "Search for a drug by drug id or name",
minimumInputLength: 3,
ajax: {
url: "#Url.Action("SearchDrug", "Drug")",
dataType: 'jsonp',
quietMillis: 100,
data: function (term, page) {
return {
query: term
};
},
results: function (data, page) {
debugger;
return {
results: data.drugs
};
}
},
formatResult: drugResult,
formatSelection: drugSelection,
escapeMarkup: function (m) { return m; }
});
function drugResult(drug) {
debugger;
return drug.Name + " (" + drug.DrugBankRef + ")";
}
function drugSelection(drug) {
debugger;
return drug.Name + " (" + drug.DrugBankRef + ")";
}
The breakpoints are also not hitting the above debugger; lines
My JSON is returned as:
{ drugs: {[...]} }
It also has the properties Name and DrugBankRef and I have confirmed a valid JSON is returned from the URL after searching.
What am I doing wrong here? Anything else you need to trace the issue?
I was using JSONP instead of JSON, changing the data type to JSON fixed the issue.
It is not an error. There is a real difference between JSON and JSONP. In JSONP, your JS will send in a supplementary parameter, named callback, that contains the name of expeted enclosing function name.
Select2 supports the two modes :
JSON, which expects { drugs: {[...]} } as data
JSONP, which provide a callbackName and expects callbackName({ drugs: {[...]} }); as data
Both works, and are correct, differents, way of processing.
Feel free to read http://en.wikipedia.org/wiki/JSONP

jQuery.ajax reloads page instead of performing ajax request in Safari on iOS

I have a function being called on a page on a local apache instance (/test) which calls a subpage (/test/info) with jQuery.ajax and correctly makes an AJAX call and dynamically loads the content from the response on my desktop in FF, Safari, Chrome, but in the iOS emulator, no call is made and the page is refreshed.
window.getInfo = function ( event ) {
console.log('1) prior to $.ajax');
$.ajax({
url: 'http://localhost/test/info',
dataType: 'html',
beforeSend: function(xhr) {
console.log('2) beforeSend');
},
success: function(data, textStatus) {
console.log('3) success');
if ( textStatus == 'success' ) {
// doing stuff with data
}
}
}).always( function() { console.log('4) always'); });
};
From the desktop browsers all of the logs are printed and my apache server reports a request at /test, but on Safari in the iOS emulator, only the '1) prior to $.ajax' and '2) beforeSend' logs are printed and the next request made to apache is for /test.
Does anyone have any idea what is happening here, and how to make iOS behave itself?
UPDATE: When I add the async: false attribute to the ajax call, all the logs are printed, and the request is made, so that basically fixed the issue; however the page still reloads which I believe is a different issue related to event propagation on iOS.
All that is needed to make this work is a return false; from the handler function. See event.preventDefault() vs. return false for a more complete explanation, but basically "return false from within a jQuery event handler is effectively the same as calling both e.preventDefault and e.stopPropagation on the passed jQuery.Event object."
So a fully functional version of the above code is:
getInfo = function() {
$.ajax({
url: '/test/info',
dataType: 'html',
success: function(data, textStatus) {
if ( textStatus == 'success' ) {
// doing stuff with data
}
}
});
return false;
};
// The order of vv that string may be important
$(document).on('click touchend', '.getInfo', getInfo );

XMLHttpRequest different in IE8 vs. FireFox/Chrome

I'm having a problem similar to jQuery $.ajax Not Working in IE8 but it works on FireFox & Chrome, but with a different use case.
I'm using the jQuery Form plug-in to handle a file upload to an ASP.NET MVC controller, which sends the file off for parsing and processing. If an Exception is thrown, it should alert the user to the issue.
//client side code
//make an ajax call, sending the contents of the file
$("#ajaxUploadForm").ajaxSubmit({
dataType: 'json',
url: '/plan/Something/ExcelImport',
iframe: true,
beforeSend: function () {
$(".ui-dialog-buttonpane").find("#my_progress").fadeIn();
},
success: function (data, textStatus) {
output = "<center><span class='flash'>" + data.message + "</span></center>";
$("#flash_message").html(output).fadeIn('slow');
setTimeout(function () { $("#flash_message").fadeOut() }, 5000);
cleanup();
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("XMLHttpRequest is " + XMLHttpRequest);
var contents = "";
for (prop in XMLHttpRequest) {
contents += "\na property is " + prop + " it's value is " + XMLHttpRequest[prop];
}
alert("the contents are " + contents);
alert("textStatus is " + textStatus);
alert("errorThrown is " + errorThrown);
//comes back in an HTML envelope. This should be parsed with regex, but I can't get it to work. Dirty hack
response = XMLHttpRequest.responseText.substring(XMLHttpRequest.responseText.indexOf("<body>"));
response = response.replace("<body>", "");
response = response.replace("</body>", "");
alert("There was a problem with the upload.\r\n" + response);
},
complete: function (XMLHttpRequest, textStatus) {
$(".ui-dialog-buttonpane").find("#my_progress").remove();
something_import.dialog('close');
something_import.dialog('destroy');
}
});
//server side code
public FileUploadJsonResult ExcelImport()
{
FileUploadJsonResult result = new FileUploadJsonResult();
HttpPostedFileBase hpf = Request.Files[0] as HttpPostedFileBase;
if (hpf.ContentLength == 0)
return new FileUploadJsonResult { Data = new { message = "File contained no data" } };
String fileName = Path.GetFileName(hpf.FileName);
String timeStampedFile = fileName.Insert(fileName.IndexOf('.'),"_"+DateTime.Now.ToFileTimeUtc());
string savedFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "tempo", timeStampedFile);
hpf.SaveAs(savedFileName);
try
{
result = ProcessFile(savedFileName, Request["Id"]) as FileUploadJsonResult;
}
catch (ArgumentException e)
{
this.Response.StatusCode = 500;
this.Response.StatusDescription = System.Net.HttpStatusCode.BadRequest.ToString();
Response.Write(e.Message);
result = Json(new { message = e.Message, stackTrace = e.StackTrace }) as FileUploadJsonResult;
}
return result;
}
This works perfectly in Chrome and Firefox. In IE, the XMLHttpRequest object coming back is different:
FF:
IE:
I've been Googling around for differences between the browser implementations of XMLHttpRequest, but haven't found anything that deals specifically with this case. Stymied.
The reason this is happening is because of the iframe fallback strategy that ajaxSubmit employs. I think since the response gets posted into the iframe IE tries to figure out how to dipslay it and decides that it wants to ask you to download the response instead of just putting it in the iframe.
I came across this same situation a while ago and found an article (that I can't find now) that offered a workaround.
If you surround your json response in a textarea nobody is going to complain(IE,FF,Chrome,probably Safari) and you'll get your response parsed correctly.
E.g. if you are returning
{Id: 1, Name: 'Me'}
just return:
<textarea>{Id: 1, Name: 'Me'}</textarea>
You see now IE thinks it's html so it inserts it into the hidden iframe. Your ajaxSubmit function still gets called and parses the json correctly and then everybody's happy. :)
If you're using ASP.NET MVC you could shamelessly copy this extension method :)
public static class ControllerExtensions
{
public static ActionResult JsonSafe(this IController controller, object obj)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
return new WriteResult(string.Format("<textarea>{0}</textarea>", serializer.Serialize(obj)));
}
}
The wikipedia article on XMLHttpRequest seems to give a good overview of the history behind the XMLHttpRequest. It seems Microsoft and Mozilla developed/adopted their own versions of the object and hence why you are probably seeing different properties.
Here is a link to Microsoft's implementation of the XMLHttpRequest interface members, which seem to match the properties in your alert.
Here is the a link to Mozilla's implementation of XMLHttpRequest.
So while we wait for the W3C to standardize the XMLHttpRequest you will continue to have different implementations across the browsers like you are seeing in this case.
For some added fun here is Apple's and Opera's specifications on XMLHttpRequest.

jQuery + Ajax + Loading Spinner Image = Too Fast!

I'm using jQuery in my ASP.NET MVC 2 page. It's a super simple post that gets a date in return. The process itself runs very quickly. I want to use a spinner image to show the user something is going on. All works fine in Firefox, testing locally. However, in IE 8, the spinner image doesn't display long enough; it just flickers. This might confuse the end user if they do not see an indication that the process is working/done. What would be the best way to fix this problem?
Thanks.
<img id="signedout<%: item.Id %>" src="/Content/Images/signed_out.png" alt="Signed Out" title="Signed Out" style="display:none" />
<div id="ajaxloader<%: item.Id %>" style="display:none;text-align:center"><img src="/Content/Images/ajax-loader.gif" alt="loading..." title="loading..." /></div>
<script type="text/javascript">
$(function () {
var id = "<%: item.Id %>";
$("#signout" + id).click(function () {
if (confirm("Are you sure you want to sign this visitor out?")) {
$(this).hide();
//$("#signout" + id).hide();
$("#ajaxloader" + id).show();
var url = '<%: Url.Action("signout") %>';
$.ajax({
type: "POST",
url: url,
data: "id=" + id,
success: function (result) {
$("#timeout" + id).append(result);
$("#ajaxloader" + id).hide();
$("#signedout" + id).show();
$("#row" + id).css("background", "#E8E8E8");
},
error: function () {
alert("There was an unexpected error. Please try again later.");
$("#ajaxloader" + id).hide();
$("#signout" + id).show();
}
});
}
});
});
</script>
It would probably be a better idea to give some other indication that the process has finished rather than misleadingly displaying the spinner when nothing is actually being processed. However you seem set on this.
This is based on amurra's answer and is designed to either hide the spinner once the process is loaded if and only if the timeout has already been returned. Therefore, if the AJAX request returns "too fast" it will wait for the timeout.
var timeoutComplete=false;
var requestComplete=false;
function HideLoadingSpinner() {
if(requestComplete) {
$("#ajaxloader" + id).hide();
} else {
timeoutComplete=true;
}
}
Meanwhile, inside the click handler...
setTimeout(HideLoadingSpinner, 2000);
$.ajax({type: "POST",
url: url,
data: "id=" + id,
success: function (result) {
$("#timeout" + id).append(result);
$("#signedout" + id).show();
$("#row" + id).css("background", "#E8E8E8");
if(timeoutComplete) {
$("#ajaxloader" + id).hide();
} else {
requestComplete=true;
}
},
error: function () {
alert("There was an unexpected error. Please try again later.");
$("#ajaxloader" + id).hide();
$("#signout" + id).show();
}
});
EDIT: I just removed the if(timeoutComplete) stuff from the error function, since there will be an alert before it anyway.
You could set a timeout in js and that would guarantee that the spinner wouldn't be hidden till after the timeout had expired:
function HideLoadingSpinner() {
$("#ajaxloader" + id).hide();
}
Then replace your ajax call with this one:
$.ajax({type: "POST",
url: url,
data: "id=" + id,
success: function (result) {
$("#timeout" + id).append(result);
setTimeout(HideLoadingSpinner, 2000);
$("#signedout" + id).show();
$("#row" + id).css("background", "#E8E8E8");
},
error: function () {
alert("There was an unexpected error. Please try again later.");
setTimeout(HideLoadingSpinner, 2000);
$("#signout" + id).show();
}
});
You could also move the other logic in the success callback into the HidingLoadingSpinner function if you get weird behavior due to the timer.
Can't you just show "Data loaded" message in bright background with fades off in few seconds after reload?
I've seen this before. Actually what you're seeing is IE taking a normal amount of time to run the request and FF taking longer than it should. You can set network.dns.ipv4OnlyDomains to localhost in about:config to dramatically speed up FF on localhost. Source.
In my own applications, I follow #Im0rtality's suggestion and have a notification that an ajax request is complete and show a spinner while it's happening. Many times I don't even see the spinner. I use a custom implementation of JBar for my notifications which is very professional looking.
As far as showing a spinner during AJAX calls, you include this in your master page to show a spinner during all JQuery AJAX calls:
$(function () {
$('.spinner')
.hide()
.ajaxStart(function () {
$(this).show();
})
.ajaxStop(function () {
$(this).hide();
});
});
Then you don't have to include showing and hiding the spinner w/ every call to $.ajax.

Resources