Ajax file upload form works in firefox but not safari - javascript

I've written the following code to upload a file from a web browser. It works in Firefox but not Safari, are there any obvious reasons why this might be the case.
// when the file field is changed I get its data and the "salonId" variable
$("#btnFrontUpload").change(function (e){
frontPic = e.target.files[0]
displayPicAsBackground(frontPic, "btnFrontUploadShow")
frontPicName = frontPic.name
salonId=$("#salonId").val();
});
fd = new FormData()
$("#btnNextPhotos").click(function(){
$('#mdlPhotos').modal('hide')
resizeAndPopulateVariables()
doAjaxRequest()
});
});
function updateMilliTime(){
milliTime = (new Date).getTime()
}
function displayPicAsBackground(file, btn){
// here I display the uploaded file (which is a picture) on the screen
// it works on most browsers including mobile safari, but not the "desktop" safari
$.canvasResize(file,
{
width: 160,
height: 0,
crop: false,
quality: 100,
callback: function (data)
{
$('#'+btn).css("background", "url("+data+")")
}
});
}
function resizeAndPopulateVariables(){
// I resize the image and create a file variable for upload
$.canvasResize(frontPic,
{
width: 400,
height: 0,
crop: false,
quality: 100,
callback: function (data)
{ // Add file data
var frontPicForUpload = $.canvasResize('dataURLtoBlob', data)
fd.append("frontPic", frontPicForUpload)
fd.append("frontPicName", frontPicName)
fd.append("salonId", salonId)
}
});
}
function doAjaxRequest(){
// send the ajax request
$.ajax(
{
url: '/create/picture',
type: 'POST',
data: fd, //fd is a global variable
dataType: 'json',
contentType: false,
processData: false,
beforeSend: function (xhr)
{
xhr.setRequestHeader("pragma", "no-cache");
}
}
).done(function (response){
window.location.reload()
});

I don't really know your issue here maybe is your Ajax cal, so why not use a plugin Ajax . I know this sounds depressive.
here is a sample is so easy:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js"></script>
<script src="http://malsup.github.com/jquery.form.js"></script>
<script>
// wait for the DOM to be loaded
$(document).ready(function() {
// bind 'myForm' and provide a simple callback function
$('#myForm').ajaxForm(function() {
alert("Thank you for your comment!");
});
});
</script>
</head>

There are many syntax errors in your code. I'm not sure how it runs in Firefox. Run your code through a Javascript code checker, like JSLint. The obvious one is that you don't have semicolons (;) at the ends of your lines. Add them.
The biggest one though is this segment:
$("#btnNextPhotos").click(function(){
$('#mdlPhotos').modal('hide');
resizeAndPopulateVariables();
doAjaxRequest();
}); // <--- what is this closing?
});
It looks like you meant to call .modal() with a callback function because you have a closing )} after doAjaxRequest(). I'm not familiar with the .modal() function, but it either needs to have a callback, perhaps like this:
$("#btnNextPhotos").click(function(){
$('#mdlPhotos').modal('hide', function () {
resizeAndPopulateVariables();
doAjaxRequest();
});
});
Or you need to remove the extra closing operators:
$("#btnNextPhotos").click(function(){
$('#mdlPhotos').modal('hide');
resizeAndPopulateVariables();
doAjaxRequest();
});

Related

What is the proper way of doing long polling using jQuery and AJAX

I have a project which involves live notification. So I stumbled upon using socket io but I didn't have enough time to learn it yet. So I tried doing it with AJAX and jQuery. Below is my code structure and I was wondering if this is gonna work with no drawbacks?
setInterval(function(){
if( !element.hasClass('processing') ){
element.addClass('processing');
$.ajax({
type: 'post',
dataType: 'json',
url: ajaxurl,
data: {},
success: function( response ){
/* Success! */
element.removeClass('processing');
}
});
}
}, 2500);
Some Extra Info
The way you described will work. From Experience I would just like to point out some things.
I usually do a recursive function, allows you to wait your interval between ajax calls and not a fixed rate. //OPTIONAL BUT DOES GIVE THE SERVER SOME BREATHING ROOM.
Use window.setTimeout() with an isActive flag. //ALLOWS YOU TO STOP POLLING FOR WHATEVER REASON, AND BECAUSE FUNCTION IS RECURSIVE START UP AGAIN IF NEED BE
For Sake of being thorough, I found it is always a good idea to handle the error case of the $.ajax() post. You could perhaps display some message telling the user he is no longer connected to the internet etc.
Some Sample Code:
var isActive = true;
$().ready(function () {
//EITHER USE A GLOBAL VAR OR PLACE VAR IN HIDDEN FIELD
//IF FOR WHATEVER REASON YOU WANT TO STOP POLLING
pollServer();
});
function pollServer()
{
if (isActive)
{
window.setTimeout(function () {
$.ajax({
url: "...",
type: "POST",
success: function (result) {
//SUCCESS LOGIC
pollServer();
},
error: function () {
//ERROR HANDLING
pollServer();
}});
}, 2500);
}
}
NOTE
This is just some things I picked up using the exact method you are using, It seems that Web Sockets could be the better option and I will be diving into that in the near future.
Please refer :
Jquery : Ajax : How can I show loading dialog before start and close after close?
I hope this could help you
$("div.add_post a").click(function(){
var dlg = loadingDialog({modal : true, minHeight : 80, show : true});
dlg.dialog("show");
$.ajax({
url : "/add.php",
complete : function (){
dlg.dialog("hide");
}
});
return false;
});
//--Loading dialog
function loadingDialog(dOpts, text = "пожалуйста подождите, идет загрузка...")
{
var dlg = $("<div><img src='/theme/style/imgs/busy.gif' alt='загрузка'/> "+text+"<div>").dialog(dOpts);
$(".ui-dialog-titlebar").hide();
return dialog;
}

Javascript Function scope / accessibility

I'm no javascript expert and I'm trying to find out how I can ensure my functions are available for all my pages.
My setup:
index.php > my main page where I load my javascript functions
sl.php > a back end script sending html back
$(document).ready(
function ButtonManager()
{
$( "button" ).click(function()
{
$.ajax
({
type: 'POST',
url: 'php/sl.php',
data: 'test=1',
cache: false,
async: false,
dataType: 'html',
success: function(result)
{ $('#mydiv').html(result);
}
});
}
});
</pre>
In my index.php, I have a button that triggers this function and it works fine. Basically it retrieves some html containing other buttons using the same function as the one described above. The problem is that the function declared in index.php does not seem to be known by the html I get back from sl.php
Is there a way to make my ButtonManager function available for the html code that comes back from the server ? The html I get back from the server is inserted in the page where the function is declared.
UPDATE 29/07 :
Here is an example of the buttons I use
TEST
I have such a button in index.php and when I click on it, it posts test=1 to sl.php
In return I get some content that I insert into #mydiv. The process works fine except that buttons included in the sl.php output do not react at all when I click on them.
TJ Crowder:
I have tried your solution (the one without the ready tag) but now even the buttons in index.php don't react any more.
Here is a simplified version to clear any interferences with something else.
var MyApp;
MyApp = MyApp || {};
(function() {
MyApp.ButtonManager = ButtonManager;
function ButtonManager() {
$("button").click(function() {
alert ('oo');
});
}
})();
In the end, the only thing I would like to do is have one location to manage all buttons with sometimes buttons being used in index.php sometimes elsewhere.
Thanks!
Laurent
The code in the question has syntax errors. I'm going to guess your code actually looks like this:
$(document).ready(function() {
function ButtonManager() {
$("button").click(function() {
$.ajax({
type: 'POST',
url: 'php/sl.php',
data: 'test=1',
cache: false,
async: false,
dataType: 'html',
success: function(result) {
$('#mydiv').html(result);
}
});
});
}
});
If so, your ButtonManager function is only accessible within the anonymous function you've passed to ready; it's not accessible outside it.
You can make it a global, but the global namespace is already really crowded, so I'd only create one more global, MyApp or something, and make your functions properties on that object:
// Declare it -- this is a no-op if it's already been declared by another script
var MyApp;
// Use it if it's already initialized by another script, or initialize it if not
MyApp = MyApp || {};
// Your original code
$(document).ready(function() {
// Make ButtonManager a property of MyApp
MyApp.ButtonManager = ButtonManager;
function ButtonManager() {
$("button").click(function() {
$.ajax({
type: 'POST',
url: 'php/sl.php',
data: 'test=1',
cache: false,
async: false,
dataType: 'html',
success: function(result) {
$('#mydiv').html(result);
}
});
});
}
});
Using it:
var mgr = MyApp.ButtonManager();
There, I've left your ButtonManager inside the ready callback on the theory that you have other code in that callback that needs to wait for ready, but just creating the ButtonManager function doesn't need to wait for ready. If you don't have code that needs to wait for ready, you can do this:
// Declare it -- this is a no-op if it's already been declared by another script
var MyApp;
// Use it if it's already initialized by another script, or initialize it if not
MyApp = MyApp || {};
// Use a scoping function to avoid creating more globals
(function() {
// Make ButtonManager a property of MyApp
MyApp.ButtonManager = ButtonManager;
function ButtonManager() {
$("button").click(function() {
$.ajax({
type: 'POST',
url: 'php/sl.php',
data: 'test=1',
cache: false,
async: false,
dataType: 'html',
success: function(result) {
$('#mydiv').html(result);
}
});
});
}
})();
Side note: The overwhelming convention in JavaScript is that function names start with a lowercase letter unless the function is meant to be called via the new operator. So in this case, buttonManager rather than ButtonManager.
I think I have found the solution, TJ Crowder put me on the right track.
In my main page, I have isolated my function to make it global:
<pre>
function ButtonManager()
{ same ajax call }
in my server side output I have added:
<script>
var mgr = ButtonManager();
</script>
</pre>
When I now click on one of the button coming from the server, the function is correctly executed!
Thanks!

Why is ajaxStop() not firing in Internet Explorer?

this is my first time using ajax. and i don't have an idea where the ajaxStop takes place. I am using the ajaxStart to show a loading image and need the ajaxStop to hide the loading image. Please help.
I have this code to call a popup from "PageOne"
function ShowFixSteps(path, title){
var winHeight = parseInt(jQuery(window).height() - 100);
var winWidth = parseInt(jQuery(window).width() - 600);
jQuery.ajax({
url: path,
success: function(data) {
jQuery("#divPopup").load(path).dialog({
modal: true,
width: winWidth,
height: winHeight,
title: title,
position: "center"
});
}
});
jQuery("#divPopup").bind("dialogbeforeclose", function(){
jQuery("#divPopup").empty('');
});
}
And on my Master page, I have this code to check the start and stop of ajax call:
$(document).ajaxStart(function() {
alert('start');
});
$(document).ajaxStop(function() {
alert('stop');
});
$(document).ajaxError(function() {
alert('error');
});
It alerts the START but not the STOP: no ERROR also.
NOTE: START and STOP alerts are working on Chrome but not IE.
ajaxStop is triggered after all current AJAX requests have completed.
You can read more about ajaxStop using the jQuery API documentation.
You can use .ajaxStop() in the following manner:
$(document).ajaxStop(function() {
$('#loading-spinner').hide();
});
Or you could add :complete callback to your AJAX function, like so:
jQuery.ajax({
url: path,
success: function(data) {
jQuery("#divPopup").load(path).dialog({
modal: true,
width: winWidth,
height: winHeight,
title: title,
position: "center"
});
},
complete: function() {
// do something here when ajax stops
// like hiding the spinner or calling another function
}
});
And as you mentioned how to stop an AJAX request in one of your comments, here's how:
var ajax1 = $.ajax({
type: "POST",
url: "some.php",
...
});
ajax1.abort()
You could check if a specific AJAX request is running before aborting by doing this:
if (ajax1) {
ajax1.abort();
}
Or you could check to see if any ajax requests are running before aborting by doing something like this:
var ajax_inprocess = false;
$(document).ajaxStart(function() {
ajax_inprocess = true;
});
$(document).ajaxStop(function() {
ajax_inprocess = false;
});
if (ajax_inprocess == true) {
request.abort();
}
Beware using .abort() though, as it only stops the client-side code from listening for a response, it wont actually stop the server from working. There are actually a few major caveats using this, so make sure you read about it first.
UPDATED ANSWER FOR UPDATED QUESTION
For IE problem, try using:
$(document).ajaxComplete(function() {
// do something
})
Instead of ajaxStop(). ajaxComplete() will fire each time an AJAX request finishes, rather than when ALL requests have finished using ajaxStop(). Maybe it will help, maybe not.

jQuery plugin bsmSelect doesn't update its values when it is called again and its select options have changed

I'm using bsmSelect jQuery plugin. Basically, what it does is changing the way a select-multiple is rendered to make easier to pick up the options. It hides the select element and shows a list instead.
So, first of all I'm applying the plugin function to my select-multiple element:
$(document).ready(function() {
...
$('#my_select_multiple').bsmSelect({
plugins: [$.bsmSelect.plugins.sortable()],
title: 'Add',
removeLabel: 'Remove'
});
...
});
On the other way, I have another select element (this one is simple) which has an ajax request bind to its change event. This ajax request get new #my_select_multiple options depending on the select simple value. Ajax response is the new HTML for #my_select_multiple options. So I have:
function getNewOptions(val) {
var r = $.ajax({
type: 'GET',
url: /*My URL*/
}).responseText;
return r;
}
...
$(document).ready(function() {
...
$('#my_select_simple').change() {
$('#my_select_multiple').html(getNewOptions($(this).val()));
}
...
});
AJAX is working as expected. New options are got correctly and they are inserted into #my_select_multiple (which is hidden by bsmSelect plugin, but I can check it with Firebug). But bsmSelect didn't realize new changes and doesn't get updated.
So, I think what I want is to reapply $('#my_select_multiple').bsmSelect(); with its new options.
I've been looking around a little bit and here is what I have tried.
1. I've tried to call again the funcion with the success and complete (one at time) of the AJAX request. Didn't work:
function getNewOptions(val) {
var r = $.ajax({
type: 'GET',
url: /*My URL*/,
success: function() { $('#my_select_multiple').bsmSelect(); }
}).responseText;
return r;
}
2. I've tried to bind the function with the on jQuery function. Didn't work:
$('#my_select_simple').on('change', function() {
$('#my_select_multiple').bsmSelect();
});
3. I've tried 1 and 2 removing previosly the HTML generated by bsmSelect. Didn't work.
Thank you very much.
UPDATE: The exact code
First I have a global.js file which apply bsmSelect plugin to some select multiples (.quizzes):
$('.quizzes').bsmSelect({
plugins: [$.bsmSelect.plugins.sortable()],
title: 'Add',
removeLabel: 'Remove'
});
And then, in the php file I define the updateQuizzes function and bind it to the select simple (project_id) change event:
<script type="text/javascript">
function updateQuizzes(project_id) {
var r = $.ajax({
type: 'GET',
url: '<?php echo url_for('event/updateQuizzes')?>'+'<?php echo ($form->getObject()->isNew()?'':'?id='.$form->getObject()->getId()).($form->getObject()->isNew()?'?project_id=':'&project_id=')?>'+project_id,
success: function() { $('.quizzes').bsmSelect({
plugins: [$.bsmSelect.plugins.sortable()],
title: 'Add',
removeLabel: 'Remove'
}); }
}).responseText;
return r;
}
$('#project_id').change(function(){
$('.quizzes').html(updateQuizzes($(this).val()));
});
</script>
As I told, the AJAX request works without problems, but not the calling bsmSelect the second time...
Not sure if this is what the problem is, but you could try
$('#my_select_simple').change() {
$('#my_select_multiple').html(getNewOptions($(this).val())).trigger('change');
}
This triggers a change event on select_multiple, and might fire bsmSelect. I'm not sure what the problem here is exactly, but that's the best I can come up with.
I think you want to set your HTML in the success of the Ajax call, something like:
function loadNewOptions(val) {
$.ajax({
type: 'GET',
url: /*My URL*/,
success: function(data) {
$('#my_select_multiple').html(data).bsmSelect();
}
});
}
And then calling like:
$('#my_select_simple').change() {
loadNewOptions($(this).val());
}
$(document).ready(function() {
$('#my_select_simple').change() {
$('#my_select_multiple').load("your Url", function(){
$('#my_select_multiple').bsmSelect();
});
}
});
something like this should work.
.load will put whatever your url returns into #my_select_multiple
the first parameter is the url to load, and the 2nd is a function to call when it is done. which is where you need to set up your fancy selector.
Ok, I opened a ticket and bsmSelect developer has answered me in minutes. Great!
To let bsmSelect know about its select changes, you have to trigger a change event on the select. There is no need to call bsmSelect again.
So it can be that way:
function loadNewOptions(val) {
var r = $.ajax({
type: 'GET',
url: /*My URL*/,
success: function(data) {
$('#my_select_multiple').html(data).trigger('change');
}
}).responseText;
return r;
}
$('#my_select_simple').change(function() {
loadNewOptions($(this).val());
});

jQuery.ajax not working in IE7/8

Something in my script is breaking IE.
I'm looking on a collection of links with a class, and hijacking the URL's.
Clicking a link will animate the height and reveal a message. It also
does an ajax request to mark the message as read.
However, in IE it simply goes to the URL instead of staying on the page and processing the http request.
$('.message .subject .subject_link').click(function(e) {
toggle_message(e)
return false;
});
function toggle_message(m) {
var link = m.target;
var parent = $(link).parent().parent();
console.log(link.href);
$.ajaxSetup({
url: link.href,
dataType: 'json',
timeout: 63000,
type: 'GET',
cache: false
});
if($(parent).hasClass('unread')) {
$(parent).addClass('read').removeClass('unread');
$.ajax({
complete: function(r, textStatus) {
console.log(r.responseText)
}
});
}
if($(parent).find('.body_wrapper').hasClass('collapsed')) {
$(parent).find('.body_wrapper').addClass('expanded').removeClass('collapsed');
$(parent).find('.body_wrapper').animate({
height: 'toggle'
})
} else {
$(parent).find('.body_wrapper').addClass('collapsed').removeClass('expanded');
$(parent).find('.body_wrapper').animate({
height: 'toggle'
})
}
}
any ideas what's causing this issue?
http://support.cooper.krd-design.net/
tester: 12345 if you want to review the page
Thanks
Rich
Adding
e.preventDefault();
before toggle_message in the first function should work, although return false should as well.
I don't have access to IE right now but I think you could try preventing the default click event to fire in your click()-function like so:
$('.message .subject .subject_link').click(function(e) {
toggle_message(e)
e.preventDefault();
});
More on .preventDefault() here: http://api.jquery.com/event.preventDefault/

Categories