duanpang5583 2014-12-07 09:27
浏览 44

有没有更好的方法来包含jquery事件处理程序与xmlhttprequest()

I've written the real-time form validation necessary for my Site. It's included in my javascript/jquery.js file and does things like:

//Let user know if they've left an invalid email in the field
 $signupEmail.on("blur", function() {
    var form = new SignupForm($signupEmail.val());
        if ( !form.isEmailEmpty() && !form.isEmailValid() ) {
            form.showEmailError("Invalid email");
        } else {
            form.isEmailRegistered();
            if (!form.emailError && form.isEmailValid()) {
                form.hideEmailError();
                form.showValidEmail();
            }
        }   
});

and:

 //Let user know when they've entered a valid email
$signupEmail.on("keyup", function() {
    var form = new SignupForm($signupEmail.val());
    var userEmail = form.userEmail();
     $.post("/sitename/scripts/checkEmailAvailability.php", {"userEmail": userEmail}, function (data) {
        if (form.isEmailValid() && !data) {
            form.showValidEmail();
        } else {
            form.hideEmailError();
        }
    });   

});

This and the rest of the code works flawlessly with my signup and contact forms.

I also have a directory called users/ with a sub-directory called account-settings/. Each page in the sub-directory contains a different form users can submit to update their account. For instance, there is an update-email.php, update-password.php, etc. These pages are loaded onto an account-settings.php page through an xmlhttprequest(). The problem I'm having is figuring out an efficient way of including the jquery real-time validation, which doesn't seem to work unless included in the xmlhttp.onreadystatechange function. As it is now, I have to include the jquery validation twice; One for the signup/contact forms and another for the account-settings forms. Please review the following code:

Site/users/account-settings/account-settings.php

//php includes
//session configurations
 <div id="user-settings">
        <ul>
            <li><a href="#update-email">Update Email</a></li>
            <li><a href="#update-password">Update Password</a></li>
            <li><a href="#update-photo">Update Photo</a></li>
            <li><a href="#manage-friends">Manage Friends</a></li>
        </ul>
    </div>
    <div id="user-settings-forms">

    </div>

//php include footer


Site/javascript/jquery.js

//Show User Profile's Settings Forms
$("#user-settings li").on('click', function() {
    var data = $(this).find('a').attr('href');
    var xmlhttp = new XMLHttpRequest();

    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
            document.getElementById("user-settings-forms").innerHTML = xmlhttp.responseText;
            // I'm currently duplicating all of the real-time validation here
            // If I move the code anywhere else, it doesn't work
            // This makes for a lot of redundancy
            // I also don't know how this affects the xmlhttprequest
        }
    }

    if (data === '#update-email') {
        xmlhttp.open('POST', 'update-email.php');
    } else if (data === '#update-password') {
        xmlhttp.open('POST', 'update-password.php');
    } else if (data === '#update-photo') {
        xmlhttp.open('POST', 'update-photo.php');
    } else if (data === '#manage-friends') {
        xmlhttp.open('POST', 'manage-friends.php');
    }

    xmlhttp.send();

});

Things I've tried so far:
1. Including the necessary jquery code on the update-email.php, update-password.php pages. I thought: well, if I include the code directly on the page that would be using it, it should always work regardless of whether the page is passed through an xmlhttprequest or not. But, I was wrong. It doesn't work.

2. Remove require("templates/header") from the update-email.php, update-password.php pages. This template includes, among other things, all the links to my css and js files. I thought: maybe there is a collision of the templates happening when the page is sent through the xmlhttprequest function. It only seemed half logical since the css was still rendering without a problem but, it was worth a shot.

3. Including the javascript file asynchronously, the same way I would a Google map. I thought: since the xmlhttprequest happens asynchronously, adding the script asynchronously may be necessary. But, that didn't work either.

So, is there a more efficient way of including the jquery events handlers that belong with the page passed through an xmlhttprequest object? If this is the only way, how does it affect the xmlhttprequest? Slow it down? No change at all? Will adding too much code cause a problem with the script in any way? Thank you. I really appreciate any help you can give.

  • 写回答

1条回答

  • douqin2108 2014-12-07 09:35
    关注

    The issue is that by assigning to innerHTML on the form, you're destroying the elements you have the handlers attached to, and replacing them with new elements you don't have handlers attached to.

    This is a good use case for event delegation: You hook the event on the form, not the element, but tell jQuery to only notify you of the event when it passes through a given element during the bubbling phase. So suppose your $signupEmail field has name="user-email" or some such (you haven't shown it, so I'm just picking something as an example). To handle blur on it:

    $("#user-settings-forms").on("blur", "input[name=user-email]", function() {
        /// Your validation logic here, this will refer to the user-email field
    });
    

    jQuery makes events like blur and focus bubble even on browsers where they don't natively.

    More about event delegation in the .on documentation.

    The above hooks up specifically the user-settings-forms element, but you could use a common class on both forms to avoid making it specific like that, so you can include your validation script on both pages without modification.

    Here's an example using a .user-form-validate class:

    $(".user-form-validate").on("blur keyup", "input[name=user-email]", function(e) {
      var $this = $(this),
          $validation = $this.closest("label").next(".validation-error");
      if (!$.trim($this.val())) {
        if (e.type === "blur" || e.type === "focusout") {
         $validation.text("Please fill in an email address").fadeIn();
        }
      } else {
        $validation.fadeOut();
      }
    });
    .validation-error {
      color: #a00;
    }
    <form class="user-form-validate">
      <label>Email address:
        <input type="text" name="user-email">
      </label>
      <p class="validation-error" style="display: none"></p>
      <div>
        <input type="button" value="Fake Send Button">
      </div>
    </form>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

    </div>
    
    评论

报告相同问题?

悬赏问题

  • ¥15 如何用stata画出文献中常见的安慰剂检验图
  • ¥15 c语言链表结构体数据插入
  • ¥40 使用MATLAB解答线性代数问题
  • ¥15 COCOS的问题COCOS的问题
  • ¥15 FPGA-SRIO初始化失败
  • ¥15 MapReduce实现倒排索引失败
  • ¥15 ZABBIX6.0L连接数据库报错,如何解决?(操作系统-centos)
  • ¥15 找一位技术过硬的游戏pj程序员
  • ¥15 matlab生成电测深三层曲线模型代码
  • ¥50 随机森林与房贷信用风险模型