2014-01-31 33 views
0

我正在嘗試在窗體中提交2個請求。AJAX POST請求取消,因爲頁面導航

使用外部腳本將請求發送到外部數據庫。

另一請求然而是存儲在localStorage的表單字段和帖子的JSON的PHP文件,然後將數據保存到當前服務器上的文本文件(其中形式託管)

一個AJAX POST請求

問題是,在提交時AJAX POST請求被取消,因爲第一個操作(向外部數據庫發送數據的外部腳本)導航離開當前頁面,併爲您提交提交的成功/失敗狀態。

我知道這是因爲有一個表單驗證(不停止AJAX請求),並且如果電子郵件中存在驗證錯誤,表單不會導航到另一個頁面,但AJAX POST請求是成功和JSON數據正確傳遞到服務器上的文本文件。

以下是HTML/JS和PHP代碼:

HTML/JS:

<!DOCTYPE html> 
<html> 
<head> 

<link rel="stylesheet" type="text/css" href="eloqua.css"> 
<script src="http://code.jquery.com/jquery-1.9.0.js"></script> 
<script type="text/javascript"> 
$(document).ready(function(){ 
    localStorage.clear(); 

    $("form").on("submit", function() { 
     if(window.localStorage!==undefined) { 
      var fields = $(this).serialize(); 

      localStorage.setItem("eloqua-fields", JSON.stringify(fields)); 

      $.ajax({ 
       type: "POST", 
       url: "backend.php",   
       data: fields 
      }); 
     } else { 
      alert("Storage Failed. Try refreshing"); 
     } 
    }); 
}); 
</script> 

<script type="text/javascript"> 
function validateForm() 
{ 

var a=document.forms["EloquaForm"]["C_FirstName"].value; 
if (a==null || a=="") 
    { 
    alert("First name must be filled out"); 
    return false; 
    } 

var b=document.forms["EloquaForm"]["C_LastName"].value; 
if (b==null || b=="") 
    { 
    alert("Last name must be filled out"); 
    return false; 
    } 

var y=document.forms["EloquaForm"]["C_EmailAddress"].value; 
var atpos=y.indexOf("@"); 
var dotpos=y.lastIndexOf("."); 
if (atpos<1 || dotpos<atpos+2 || dotpos+2>=y.length) 
    { 
    alert("Not a valid e-mail address"); 
    return false; 
    } 
} 
</script> 
</head> 

<body> 
<p><img src="red-asterix.jpeg"> indicates a required field</p> 

<div class="form-container" style="width: 625px"> 
<form class="form-eloqua" name="EloquaForm" action="http://s33.t.eloqua.com/e/f2" onsubmit="return validateForm();" method="post"> 
<span class="form-eloqua-label"><span>First Name</span></span><input id="firstname" type="text" name="C_FirstName" /> 
<span class="form-eloqua-label"><span>Last Name</span></span><input id="lastname" type="text" name="C_LastName" /> 
<span class="form-eloqua-label"><span>Email Address</span></span><input id="email" type="text" name="C_EmailAddress" /> 
<span class="form-eloqua-label">Title</span><input id="title" type="text" name="C_Title" /> 
<span class="form-eloqua-label">Company</span><input id="company" type="text" name="C_Company" /> 
<span class="form-eloqua-label">ZIP or Postal Code</span><input id="postcode" type="text" name="zipOrPostalCode" /> 
<span class="form-eloqua-label">Country</span><select id="country" name="country"> 
<option value="">Please select ...</option> 
<option value="AF">Afghanistan</option> 
<option value="AL">Albania</option> 
<option value="DZ">Algeria</option> 
<option value="AS">American Samoa</option> 
<option value="AD">Andorra</option> 
<option value="AG">Angola</option> 
<option value="AI">Anguilla</option> 
<option value="AG">Antigua &amp; Barbuda</option> 
<option value="AR">Argentina</option> 
<option value="AA">Armenia</option> 
<option value="AW">Aruba</option> 
<option value="AU">Australia</option> 
<option value="AT">Austria</option> 
<option value="AZ">Azerbaijan</option> 
<option value="BS">Bahamas</option> 
<option value="BH">Bahrain</option> 
<option value="BD">Bangladesh</option> 
<option value="BB">Barbados</option> 
<option value="BY">Belarus</option> 
<option value="BE">Belgium</option> 
<option value="BZ">Belize</option> 
<option value="BJ">Benin</option> 
<option value="BM">Bermuda</option> 
<option value="BT">Bhutan</option> 
<option value="BO">Bolivia</option> 
<option value="BL">Bonaire</option> 
<option value="BA">Bosnia &amp; Herzegovina</option> 
<option value="BW">Botswana</option> 
<option value="BR">Brazil</option> 
<option value="BC">British Indian Ocean Ter</option> 
<option value="BN">Brunei</option> 
<option value="BG">Bulgaria</option> 
<option value="BF">Burkina Faso</option> 
<option value="BI">Burundi</option> 
<option value="KH">Cambodia</option> 
<option value="CM">Cameroon</option> 
<option value="CA">Canada</option> 
<option value="IC">Canary Islands</option> 
<option value="CV">Cape Verde</option> 
<option value="KY">Cayman Islands</option> 
<option value="CF">Central African Republic</option> 
<option value="TD">Chad</option> 
<option value="CD">Channel Islands</option> 
<option value="CL">Chile</option> 
<option value="CN">China</option> 
<option value="CI">Christmas Island</option> 
<option value="CS">Cocos Island</option> 
<option value="CO">Colombia</option> 
<option value="CC">Comoros</option> 
<option value="CG">Congo</option> 
<option value="CK">Cook Islands</option> 
<option value="CR">Costa Rica</option> 
<option value="CT">Cote D'Ivoire</option> 
<option value="HR">Croatia</option> 
<option value="CU">Cuba</option> 
<option value="CB">Curacao</option> 
<option value="CY">Cyprus</option> 
<option value="CZ">Czech Republic</option> 
<option value="DK">Denmark</option> 
<option value="DJ">Djibouti</option> 
<option value="DM">Dominica</option> 
<option value="DO">Dominican Republic</option> 
</select> 
<div class="form-eloqua-separator"></div> 
<span class="form-eloqua-label">Annual Revenue Range</span><select name="C_Annual_Revenue1"> <option value="">Please select ...</option> <option value="0-100,000,000">0-100,000,000</option><option value="100,000,001-300,000,000">100,000,001-300,000,000</option><option value="300,000,001-500,000,000">300,000,001-500,000,000</option><option value="500,000,001-2,000,000,000">500,000,001-2,000,000,000</option><option value="2 Billion +">2 Billion +</option></select> 
<div class="submit-button"><input type="submit" id="submit" value="Submit" /></div> 
<div id="output"></div> 
<input type="hidden" name="elqoffer" value="GGB2BContentMktg" /> 
<input type="hidden" name="elqchannel" value="TheMarketer" /> 
<input type="hidden" name="elqbq" value="14Q2" /> 
<input type="hidden" name="elqbc" value="UK" /> 
<input type="hidden" name="elqFormName" value="2013-Syndication-1372365875136" /> 
<input type="hidden" name="elqSiteId" value="33" /> 
</form> 
</div> 
</body> 

</html> 

PHP:

<h1>Below is the data retrieved from SERVER</h1> 
<?php 
    date_default_timezone_set('America/Chicago'); // CDT 
    echo '<h2>Server Timezone : ' . date_default_timezone_get() . '</h2>'; 
    $current_date = date('d/m/Y == H:i:s '); 
    print "<h2>Server Time : " . $current_date . "</h2>"; 

    $file_content = array(); 
    if (file_exists('your_data.txt')){ 
     $file_content = (array)json_decode(file_get_contents('your_data.txt')); 
     unlink('your_data.txt'); 
    } 

    $file_content['users'][] = array('user'=>$_POST); 
     file_put_contents('your_data.txt',json_encode($file_content)); 
?> 

形式的LIVE VERSION:http://bhanuchawla.me/dev/redactive/marketerform/

,其中JSON數據發佈文字檔案:http://bhanuchawla.me/dev/redactive/marketerform/your_data.txt

注:如果您在提交表單得到投稿成功消息,這意味着在行動外部腳本成功,而不是跑AJAX。要測試數據是否通過AJAX提交,請查看your_data.txt文件(上面的URL)

如何確保在頁面導航之前完成AJAX POST?

回答

1

在您的ajax請求完成後,執行form.submit()。根據https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement.submit()它應該繞過你的事件處理程序,並得到你想要的結果。

var isSubmitted = false; 
$(document).ready(function(){ 
    localStorage.clear(); 

    $("form").on("submit", function(evt) { 
     if (!isSubmitted) { 
      evt.preventDefault(); 
      var $this = $(this); 
      if(window.localStorage!==undefined) { 
       var fields = $(this).serialize(); 

       // Not an async task so don't need promise. 
       localStorage.setItem("eloqua-fields", JSON.stringify(fields)); 

       $.ajax({ 
        type: "POST", 
        url: "backend.php",   
        data: fields 
       }).done(function() { 
        isSubmitted = true; 
        $this.submit(); 
       }); 
      } else { 
       alert("Storage Failed. Try refreshing"); 
      } 
      return false; 
     } else { 
      return true; 
     } 
    }); 
}); 

這是未經測試的,所以不知道它是否能正常工作。雖然,這是處理事情的相當複雜的方式。在我的腦海中,做一個AJAX請求+ POST表單提交感覺不對。我會堅持要做2個AJAX請求(包括表單提交)。

+0

無限循環隊友。繼續發佈到backend.php –

+0

好的,所以它不會繞過事件處理程序。這有點不好意思,但你可以做的是設置一個全局變量/標誌,以跟蹤是否Ajax事件完成,如果有,不要做preventDefault並返回false,而是返回true; – narak

+0

更新了答案 – narak

0

對您的PHP頁面同步調用,把 '異步:假' 在你的Ajax調用

$.ajax({ 
      type: "POST", 
      async:false; 
      url: "backend.php",   
      data: fields 
     }); 
+1

不是一個非常好的方法。有點擊敗了ajax的目的 – asprin

+0

不工作。這甚至停止通過AJAX發佈任何東西。 –

1

如果你改變了這個

$("form").on("submit", function() { 
    if(window.localStorage!==undefined) { 

$("form").on("submit", function(e) { 
    e.preventDefault(); 
    if(window.localStorage!==undefined) { 

這將阻止表單自然提交...

!更新:忘了把事件傳遞給函數!代碼已更新。

http://api.jquery.com/event.preventdefault/

+0

Uncaught ReferenceError:e is not defined –

+0

'function(e)'... – CBroe

+0

沒錯。這是有效的,但它不會在提交按鈕上運行外部腳本'action =「http://s33.t.eloqua.com/e/f2」'。 –

1

當我得到你的權利,你的問題是基於這樣的事實,要經過一個提交給做兩個完全不同的事情。你可以通過幾種方法來做到這一點。

變體之一:沒有Ajax,發佈數據,在backend.php中做任何你做的事情,然後使用curl to send post data到其他服務器。

變二:如果你想使用Ajax來做到這一點,你可以試試這樣說:

// this is your old anonymus function a bit modified... 
var ajaxSubmitHandler = function(e) { 
    e.preventDefault(); 
    if(window.localStorage!==undefined) { 
     var fields = $(this).serialize(); 
     localStorage.setItem("eloqua-fields", JSON.stringify(fields)); 
     $.ajax({ 
      type: "POST", 
      url: "backend.php", 
      data: fields, 
      // and when ajax is done ... remove the event handler 
      done : function() { 
       // deactivate submit handler.... 
       $("form").off("submit", ajaxSubmitHandler); 
       // and simply retrigger the submit 
       // this time it will only do the normal action 
       $("form").submit(); 
      } 
     }); 

    } else { 
     alert("Storage Failed. Try refreshing"); 
    } 
} 

// per default you use the handler with the nested ajax request 
$("form").on("submit", ajaxSubmitHandler); 
+0

不確定第二個變體是否有效。你可以在本地測試它與原始文件:https://www.dropbox.com/sh/mm1tdhr4fe6nstc/S4OT31LAiR 非常有責任 –

+0

不,我不會那樣做,這是你的項目不是我的,我給了anwser,執行它是你要做的,只需要你幾分鐘。 –

+0

對。我嘗試了它,並且做了與Marty的解決方案相同的事情。即AJAX工作正常,但提交操作腳本不起作用。 –

-1
$("form").on("submit", function() { 

    if(window.localStorage!==undefined) { 
     var fields = $(this).serialize(); 

 event.preventDefault(); 

 localStorage.setItem("eloqua-fields", JSON.stringify(fields)); 

     $.ajax({ 
      type: "POST", 
      url: "backend.php",   
      data: fields, 

  success: function(data) { 
      $('form').off('submit'); 
      $('form').submit(); 
      }, 
      error: function() { 
      $('form').off('submit'); 
      $('form').submit(); 
      } 

 }); 
    } else { 
     alert("Storage Failed. Try refreshing"); 
    } 
}); 

基本上,AJAX請求得到響應後,我允許的形式提交。使用$('form')是粗略的,但我希望你明白了。

+0

基本上這會導致無限循環,因爲每當你提交表單時,你都會記得提交。想法是正確的,但代碼錯誤,您必須在觸發新提交 –

+0

同意之前移除提交事件。添加jquery關閉。 – nightgaunt

+0

仍然是一個無限循環。 –

1

如果你想等到兩個ajax請求都完成,你可以使用jQuery的延期對象。這樣,只有當請求完成後,您纔可以重定向到其他頁面。以下是使用延遲對象的簡單示例代碼。

var fn1 = $.ajax("/url-1.php"); 
var fn2 = $.ajax("/url-2.php"); 

$.when(fn1, fn2).done(function(fn1, fn2) { 
    alert("all complete"); 
}); 
+0

感謝您回答Vivek,但是如果您看到我的代碼,那麼這是一個AJAX請求,另一個是提交操作。我應該怎麼做? –

+0

它也不工作。 :( –