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 矩阵加法的规则是两个矩阵中对应位置的数的绝对值进行加和
  • ¥15 活动选择题。最多可以参加几个项目?
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型
  • ¥15 vs2019中数据导出问题
  • ¥20 云服务Linux系统TCP-MSS值修改?
  • ¥20 关于#单片机#的问题:项目:使用模拟iic与ov2640通讯环境:F407问题:读取的ID号总是0xff,自己调了调发现在读从机数据时,SDA线上并未有信号变化(语言-c语言)
  • ¥20 怎么在stm32门禁成品上增加查询记录功能
  • ¥15 Source insight编写代码后使用CCS5.2版本import之后,代码跳到注释行里面
  • ¥50 NT4.0系统 STOP:0X0000007B
  • ¥15 想问一下stata17中这段代码哪里有问题呀