1

我在多页表单中使用 jQuery mobile。当用户单击标记为Next Page的按钮时,我想运行 AJAX 请求。根据 AJAX 请求的结果,我想阻止用户访问下一页。

我相信我遇到的问题是我的 AJAX 请求比下一页事件需要更长的时间来回复。因此,它让用户进入下一页而不让 AJAX 请求完成。

至少我认为这就是正在发生的事情。有没有人遇到过这个问题或知道这个问题的解决方案?

HTML:

<div id="page1" data-role="page">
    <div data-role="header" data-position="fixed" data-theme="d">
        <a href="#page2" data-role="button" id="btnPage2" class="ui-btn-right" data-icon="arrow-r">Next Page</a>
    </div>
    <div role="main" class="ui-content">
        <label for="testVal">Test Val:</label>
        <input type="text" id="testVal" name="testVal"/>
    </div>
</div>
<div id="page2" data-role="page">
    <div role="main" class="ui-content">

    </div>
</div> 

jQuery:

$('#btnPage2').click(function(){
    var isValid = '';
    var aValue = $('#testVal').val();
    $.ajax({
        type: "POST",
        url: "php-file.php",
        data: {"something":aValue },
        success: function(data){
            var json = $.parseJSON(data);
            if(json.hasOwnProperty('error')){
                console.log("the user is not allowed on page 2");
                isValid = false;
            }else{
                isValid = true;
            }
        }
    });
    if(!isValid){
        alert('sorry you can not enter page 2');
        return false;
    }
});

在上面的代码示例中,当我单击“下一页”按钮(即#btnPage2)时,它允许我访问第 2 页,即使当我检查控制台日志并且我看到“第 2 页上不允许该用户”时也是如此。

更新:

我尝试将代码调整为以下。它有点工作,但只有在不允许用户访问 page2 时。 e.preventDefault正在让 ajax 完成,但是,我想不出一种强制更改 page2 的方法。如果允许用户访问 page2 行

$(":mobile-pagecontainer").pagecontainer("change", "#page2");

似乎是导致问题的原因......它只是创建了调用 pageChange 事件的无限循环。我认为这是强制将页面更改为 page2 的方法,但我认为我错了,我无法弄清楚如何强制它更改为 page2

$(document).bind('pagebeforechange', function(e, data) {
    var to = data.toPage,
        from = data.options.fromPage;

    if (typeof to === 'string') {
        var u = $.mobile.path.parseUrl(to);
        to = u.hash || '#' + u.pathname.substring(1);
        if (from) from = '#' + from.attr('id');

        if (from === '#page1' && to === '#page2') {
        e.preventDefault();
        var aValue = $('#testVal').val();
            $.ajax({
                type: "POST",
                url: "php-file.php",
                data: {"something":aValue },
                cache: false,
                success: function(data){
                    var json = $.parseJSON(data);
                    if(json.hasOwnProperty('canNotPass')){
                        alert('Sorry you can not view page 2');
                    }else{
                        ///  if json does not contain canNotPass then continue to page2 
                        $(":mobile-pagecontainer").pagecontainer("change", "#page2");
                    }
                },
                beforeSend: function() {
                    $.mobile.loading("show");
                },
                complete: function() {
                    $.mobile.loading("hide");
                }
            });   
        }            
    }
});

更新#2

我尝试实施@deblocker 修复,但我仍然遇到同样的问题。canNotPass当我在 ajax 设置为代码的情况下运行以下代码时,true似乎永远无法达到测试canNotPass. 因此,它永远不会被设置e.preventDefault,并且用户被允许访问 page2。

我认为该解决方案与设置延迟对象有关,该对象将允许 ajax 在页面更改发生之前完成。唯一的问题是我知道如何设置/使用延迟对象。

JSFiddle

4

2 回答 2

2

使用按钮而不是锚点:

<button id="btnPage2" class="ui-btn-right ui-icon-arrow-r">Next Page</a>

...并通过处理程序内的代码导航success

$(":mobile-pagecontainer").pagecontainer("change", "#page2");

顺便说一句,您还可以使用 ajax 中的其他一些处理程序:

$.ajax({
  type:...
  url:...
  data:...
  success: ...
  beforeSend: function() {
    $.mobile.loading("show");
  },
  complete: function() {
    $.mobile.loading("hide");
  },
  error: function (request,error) {
    alert('sorry you can not enter page 2');
});

更新:

按照 Omar 的建议,在pagecontainerbeforechange处理程序的第一部分中,您应该中断导航,因为您已经处于第 2 页的中途。因此,您不再需要在此处的事件中告诉pagecontainerto 切换到 page2 。pagecontainerbeforechange您应该简单地将您的 ajax 请求和您的 canNotPass标志保存在$('#btnPage2').click().

演示:

$(document).on("pagecontainerbeforechange", function(e, ui) {
  var from = "#" + $(":mobile-pagecontainer").pagecontainer("getActivePage").prop("id");
  var to = ui.toPage;	
  if (typeof ui.toPage == "string") {
    var u = $.mobile.path.parseUrl(to);
    to = u.hash || "#" + u.pathname.substring(1);
    if (from === "#page-one" && to === "#page-two") {
      var canNotPass = !$("#canPass").prop("checked");
      if(canNotPass) {
        e.preventDefault();
        $.mobile.activePage.find('.ui-btn-active').removeClass('ui-btn-active').blur();
      }
    }
  }
});
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
  <link rel="stylesheet" href="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.css">
  <script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
  <script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.js"></script>
</head>
<body>
  <div data-role="page" id="page-one">
    <div data-theme="a" data-role="header" data-position="fixed">
      <h1>First Page</h1>
      <a href="#page-two" class="ui-btn-left">Next</a>
    </div>
    <div data-role="content">
      <label for="canPass">Can Navigate to Page 2 ?</label>
      <input data-role="flipswitch" name="canPass" id="canPass" data-on-text="Yes" data-off-text="No" type="checkbox">
    </div>
    <div data-theme="a" data-role="footer" data-position="fixed">
      <h1>Footer</h1>
    </div>
  </div>
  <div data-role="page" id="page-two">
    <div data-theme="a" data-role="header" data-position="fixed">
      <h1>Second Page</h1>
      <a href="#page-one" class="ui-btn-left">Back</a>
    </div>
    <div data-role="content">
    </div>
    <div data-theme="a" data-role="footer" data-position="fixed">
      <h1>Footer</h1>
    </div>
  </div>
</body>
</html>

EDIT2:(来源:Omar)-这是如何将直接导航捕获到“受保护”页面

$(document).on("pagecontainerbeforechange", function(e, ui) {
  /* in case user enter foo.com/#page2 directly */
  if (typeof ui.toPage === "object" && ui.absUrl === undefined && ui.toPage[0].id == "page2") {
    /* make ajax call */
    var ajaxCall = true;
    if (ajaxCall) {
      $.noop
    } else {
      ui.toPage = "#noAccessPage"
    }
  }

  /* internal navigation from page1 to page2 */
  if (typeof ui.toPage === "string" && ui.absUrl !== undefined && $.mobile.path.parseUrl(ui.absUrl).hash == "#page2") {
    /* make ajax call */
    var ajaxCall = true;
    if (ajaxCall) {
      $.noop
    } else {
      ui.toPage = "#noAccessPage"
    }
  }
});
于 2017-04-29T17:16:55.520 回答
0

感谢Omardeblocker在这个问题上花费了这么多时间。不幸的是,我无法在不干扰其他页面交互的情况下实施您的建议。下面列出了我想出的唯一可行的解​​决方案。不幸的是,该解决方案不使用处理页面更改事件的内置散列函数。我只是使用一个普通按钮并为其分配点击侦听器。有点笨拙,但它似乎是在我的情况下它可以工作的唯一方法。

<button id="btnNewPage">Go To Page 2</button>

$(document).ready(function(){
    $("#btnPageNew").click(function(){
        var testVal = $('#testVal').val();
        var canNotPass = promiseTest(testVal);
            canNotPass.done(function(data){
                var json = $.parseJSON(data);
                    console.log(json);
                    if(json.hasOwnProperty('error')){
                        // user can not access the next page
                        console.log('can not pass');
                        $.mobile.activePage.find('.ui-btn-active').removeClass('ui-btn-active').blur();
                    }else{
                        // allow user to access the next page
                        $(":mobile-pagecontainer").pagecontainer("change", "#page2");
                    }
            });


    });
});

function promiseTest(aValue){
    return $.ajax({
                type: "POST",
                url: "php-file.php",
                data: {"something":aValue  },
                cache: false
            });
}
于 2017-05-08T12:14:41.210 回答