Search code examples
jqueryhtmlformsfocusexpand

form expand/reduce handling with jquery


I have a comment form with a textarea, input text and input radio. first, you'll see the textarea. if you click in it, the whole form expand. When you click outside the form and the fields have no values, the form should reduce to the textarea again. This works as well.

The problem is, when you switch from field to field inside the form, the form reduces and expand, and again and again. The if ($this.not(":focus")) will not help out.
Any ideas?

HTML

<div id="commentBox">
    <form action="...">
        <label for="comment">Write a comment...</label>
        <textarea id="comment"></textarea>

        <div class="expandBox" style="display: none">
            <label for="title">Title</label>
            <input type="text" id="title" />
            <br />
            <label for="email">E-Mail *</label>
            <input type="text" id="email" />
            <br />
            <label for="name">Newsletter</label>
            <input type="radio" id="yes" name="newsletter" /><label for="yes">ja</label>
            <input type="radio" id="no" name="newsletter" /><label for="no">nein</label>
            <br />
            <label for="name">Name *</label>
            <input type="text" id="name" />
            <br />
            <input type="submit" value="senden" />
        </div>

    </form>
</div>

jQuery snippet (in domready off course)

$("#commentBox").find("input,textarea").each(function() {
    var $this = $(this);
    var $expandBox = $this.parents("#commentBox").find(".expandBox");

    $this.focus(function() { 
            $expandBox.slideDown(250);
    });

    $this.blur(function() {
            if ($this.val() === "" && $this.not(":focus")) {
                    $expandBox.slideUp(250);
            }
    });
});

Solution

  • The problem is that when you switch between inputs/textareas, focus() is triggered on the new focused element, and blur() on the last one.

    $expandBox is thus asked to slideUp() AND slideDown().

    To fix this problem, you have to tell these animations to stop previous animations when they're called. That way, slideUp() will be called, and immediately stopped by slideDown().

    Use stop() for that.

    $("#commentBox").find("input,textarea").each(function() {
        var $this = $(this);
        var $expandBox = $this.parents("#commentBox").find(".expandBox");
    
        $this.focus(function() { 
                $expandBox.stop().slideDown(250);
        });
    
        $this.blur(function() {
                if ($this.val() === "" && $this.not(":focus")) {
                        $expandBox.stop().slideUp(250);
                }
        });
    });