有没有更好的方法来包含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个回答

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>
douyong7199
douyong7199 代码本身工作正常。 当它通过xmlhttprequest时它停止工作。
接近 6 年之前 回复
douqiang5163
douqiang5163 不知道该告诉你什么,这种技术有效,只需要正确应用它。
接近 6 年之前 回复
dongxixian7803
dongxixian7803 谢谢TJ。 不幸的是,它仍然没有用。 为了测试它,我在一个浏览器选项卡中打开了注册表单,在另一个选项卡中打开了update-email-form。 在我的jquery.js文件中,我包含了您提供的代码示例(当然,使用正确的#ids和标签进行了修改)。 当我运行代码时,它在注册表单中工作,但不在update-email-form中工作。
接近 6 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐