0

The beforeSubmit function in my jQuery Form plugin needs to check whether the selected file already exists on the server. Here's that relevant code:

$('#frmSermonUpload').ajaxForm({
    beforeSubmit: function() {
        // Reset errors and clear messages
        ClearForm(false);
        var formValid = true,
            fileExists = CheckFileExists();

        console.log('beforeSubmit fileExists: ' + fileExists);

        if (fileExists === 'true') {
            $('#uploadedFile').addClass('inputError');
            $('#fileErrorMsg').append('  A file with that name already exists on the server.');
            formValid = false;
        } else {
            if (!ValidateUploadForm()) {
                formValid = false;
            }
        }

        console.log('formValid: ' + formValid);

        if (!formValid) {
            return false;
        }

    },
    ...

Here's the CheckFileExists() function:

function CheckFileExists() {

    var fileName = $('#uploadedFile').val().replace(/C:\\fakepath\\/i, ''),
        dataString;

    dataString = 'checkFileExists=' + fileName;

    console.log('fileName: ' + fileName);
    console.log('dataString: ' + dataString);

    $.ajax({
        type: 'POST',
        url: '../scripts/sermonUpload.php',
        data: dataString,
        success: function(serverResult) {
            console.log('serverResult: ' + serverResult);

            if (serverResult === 'existsTrue') {
                return 'true';
            } else {
                return 'false';
            }

        },
        error: function(xhr, status, error) {
            alert('An error occurred while attempting to determine if the selected file exists. Please try again.);
        }
    });

    //console.log('Current value of returnResult: ' + returnResult);
    //return returnResult;
}

As you can see I'm using console output to check what's going on. In the CheckFileExists() function, fileName and dataString are being reported correctly. On the PHP side, I know that the POST data is getting there due to some logging I've got going on there.

Here's the PHP code that uses the POST data:

if (isset($_POST['checkFileExists']) && $_POST['checkFileExists'] !== '') {
    $log->lwrite('**Checking if file exists.**');

    $fileToCheck = $targetPath . $_POST['checkFileExists'];

    $log->lwrite('file_exists: ' . file_exists($fileToCheck));

    if (file_exists($fileToCheck)) {
        echo 'existsTrue';
    } else {
        echo 'existsFalse';
    }
}

What's happening is, in the console, the line console.log('beforeSubmit fileExists: ' + fileExists); is returning "undefined" (beforeSubmit fileExists: undefined).

Here's all of the console output for an upload where the file already exists, so the beforeSubmit should be stopped:

fileName: 042913sermon.mp3 dataString; checkFileExists=042913sermon.mp3 beforeSubmit fileExists: undefined formValid: true serverResult: existsTrue

It must be significant that the serverResult line is displaying after everything else. Does that have to do with how long the ajax call takes? If so, is there a way to delay the rest of the script until the ajax call is done executing?

UPDATE As aorlando pointed out, the order of the console output signified that I needed to add async: false to my $.ajax call. After doing so, the console output was correct, but the function CheckFileExists() is still getting reported as undefined in beforeSubmit.

marky
  • 4,878
  • 17
  • 59
  • 103

2 Answers2

1

You are using an AJAX async call. Your method CheckFileExists()n return a value before the ajax call complete. So the simplest solutions is to use:

 $.ajax({
        type: 'POST',
        url: '../scripts/sermonUpload.php',
        data: dataString,
        async: false ...

if you want to use async call (the default as you can see: http://api.jquery.com/jQuery.ajax/ you must call (for ex.) a postcall function in the success function of the ajax call:

success: function(serverResult) {
        console.log('serverResult: ' + serverResult);

        if (serverResult === 'existsTrue') {
            postFn('true');

        } else {
            postFn('false');
        }

    }, ...

Be carefull with the scope of the postFn

funcion postFn(_result){
    console.log(_result);
}

I hope to be clear. That's all folks!

aorlando
  • 668
  • 5
  • 21
  • Thanks, aorlando. I noticed the async issue as you were posting your answer. I'll update my question shortly to reflect the following: with `async = false` added, the console output is displaying in the correct order, but CheckFileExists() is being reported as undefined in beforeSubmit. – marky May 07 '13 at 15:58
1

Ok. Now the problem is the scope of return. If you use "async: false" you can return in this way (not so elegant)

var returnValue='';
$.ajax({
        type: 'POST',
        url: '../scripts/sermonUpload.php',
        data: dataString,
        async: false,
        success: function(serverResult) {
            console.log('serverResult: ' + serverResult);

            if (serverResult === 'existsTrue') {
               returnValue = 'true';

            } else {
                returnValue= 'false';
            }

        },
        error: function(xhr, status, error) {
            alert('An error occurred while attempting to determine if the selected file                           exists. Please try again.);
        }
    });
return returnValue;

You must declare a var returnValue out of the scope of the ajax call. Inside the ajax function you can modify the value of returnValue; This is a solution which use closure, a quite complex javascript feature. Further read something about scope of a variable in javascript: What is the scope of variables in JavaScript?

This is not a very nice solution; is better if you call a function inside "success" function of ajax call as my previous example.

That's all folks!

Community
  • 1
  • 1
aorlando
  • 668
  • 5
  • 21