user3142695
user3142695

Reputation: 17342

Multiple elements on mouseover event instead of single element

JSFiddle: http://jsfiddle.net/357nf0ht/4/

If you are hovering one of the .item, a menu will appear. Hovering the "X" will show you a button. I expect, that hovering the button will create a single temporary item, which belongs to the first selected .item. But instead of that, there are multiple temporary items, if you have hovered more then one .item at the beginning. It seems, that this remembers also the events in the past.

I don't understand this behavior.

$(document).on('mouseenter', '.item', function (event) {
    var item = $(this);
    $('#item_add').css({
        "left": '5.5em',
        "top": item.offset().top - 15
    }).show();

    $('#item_add').hover(function () {
        var menue = $(this);
        menue.animate({
            "width": '7em',
            "left": '0.5em'
        }, 200, function () {
            $(this).find(".body").stop().slideDown(200);
        });
    }, function () {
        var menue = $(this);
        menue.find(".body").stop().slideUp(200, function () {
            menue.animate({
                "width": '2em',
                "left": '5.5em'
            }, 200);
        });
    });

    $('#item_element_new').hover(function () {
        item.after('<div id="item_new"></div>');
    }, function () {
        $('#item_new').remove();
    });
});

Upvotes: 0

Views: 4022

Answers (2)

adricadar
adricadar

Reputation: 10219

This is happening because every time you trigger mouseenter on .item you attach a new event to button.

Quick Solution: You have to remove previous events before attaching a new one, you can do this with .unbind(), here is a working example

$('#item_element_new').unbind();
$('#item_element_new').hover(function () {

$(document).on('mouseenter', '.item', function (event) {
    var item = $(this);
    $('#item_add').css({
        "left": '5.5em',
        "top": item.offset().top - 15
    }).show();

    $('#item_add').hover(function () {
        var menue = $(this);
        menue.animate({
            "width": '7em',
            "left": '0.5em'
        }, 200, function () {
            $(this).find(".body").stop().slideDown(200);
        });
    }, function () {
        var menue = $(this);
        menue.find(".body").stop().slideUp(200, function () {
            menue.animate({
                "width": '2em',
                "left": '5.5em'
            }, 200);
        });
    });
    $('#item_element_new').unbind();
    $('#item_element_new').hover(function () {
        item.after('<div id="item_new"></div>');
    }, function () {
        $('#item_new').remove();
    });

});
.item {
	border: 1px solid #e2e2e2; 
	margin: 6px;
	padding: 0px 10px 0px 10px;
	position: relative; 
    height: 40px;
	}
.wrap {
    margin-left: 8em;
}
#item_new {
    border: 1px dashed #C0C0C0 !important;
    background: none repeat scroll 0% 0% #F7F7F7;
    display: block;
    height: 2.2em;
    margin: 6px;
    padding: 0px 10px;
    position: relative;
}
#item_add {
    display: none;
    position: absolute;
    width: 2em;
    border: 1px solid #ddd;
    background-color: #f7f7f7;
    color: #aaa;
    padding: 0px 6px;
}
#item_add .body {
    display: none;
}
#item_add .arrow {
    width: 0px;
    height: 0px;
    -webkit-transform:rotate(360deg);
    border-style: solid;
    border-width: 5px 0 5px 7px;
    border-color: transparent transparent transparent #f7f7f7;
    top: 5px;
    right: -7px;
    position: absolute;
}
#item_add button {
    background: none repeat scroll 0px center #fff;
    padding: 0.2em 2em;
    margin: 3px .2em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="wrap">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
</div>
<div id="item_add">
    <header>X</header>
    <div class="body">
        <button id="item_element_new">Example</button>
    </div>
    <div class="arrow"></div>
</div>


Soulution 2: As @Regent pointed out your code have some problems, you can solve a part of them:

  1. Moving event binding outside mouseenter event handler

  2. Caching jQuery objects

  3. Not using .unbind() anymore

var $itemAdd = $('#item_add');
var $menuBody = $itemAdd.find(".body")
var $item = $('.item');

$itemAdd.hover(function () {
    $itemAdd.animate({
        "width": '7em',
        "left": '0.5em'
    }, 200, function () {
        $menuBody.stop().slideDown(200);
    });
}, function () {
    $menuBody.stop().slideUp(200, function () {
        $itemAdd.animate({
            "width": '2em',
            "left": '5.5em'
        }, 200);
    });
});

$('#item_element_new').hover(function () {
    $('.item-hovered').after('<div id="item_new"></div>');
}, function () {
    $('#item_new').remove();
});
   
$item.mouseenter(function (event) {
    var $currentItem = $(this);
     $currentItem.addClass('item-hovered');
     $currentItem.siblings().removeClass('item-hovered');
    
    $itemAdd.css({
        "left": '5.5em',
        "top":  $currentItem.offset().top - 15
    }).show(); 
});
.item {
	border: 1px solid #e2e2e2; 
	margin: 6px;
	padding: 0px 10px 0px 10px;
	position: relative; 
    height: 40px;
	}
.wrap {
    margin-left: 8em;
}
#item_new {
    border: 1px dashed #C0C0C0 !important;
    background: none repeat scroll 0% 0% #F7F7F7;
    display: block;
    height: 2.2em;
    margin: 6px;
    padding: 0px 10px;
    position: relative;
}
#item_add {
    display: none;
    position: absolute;
    width: 2em;
    border: 1px solid #ddd;
    background-color: #f7f7f7;
    color: #aaa;
    padding: 0px 6px;
}
#item_add .body {
    display: none;
}
#item_add .arrow {
    width: 0px;
    height: 0px;
    -webkit-transform:rotate(360deg);
    border-style: solid;
    border-width: 5px 0 5px 7px;
    border-color: transparent transparent transparent #f7f7f7;
    top: 5px;
    right: -7px;
    position: absolute;
}
#item_add button {
    background: none repeat scroll 0px center #fff;
    padding: 0.2em 2em;
    margin: 3px .2em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="wrap">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
</div>
<div id="item_add">
    <header>X</header>
    <div class="body">
        <button id="item_element_new">Example</button>
    </div>
    <div class="arrow"></div>
</div>

Upvotes: 3

c4605
c4605

Reputation: 185

The easiest fix, reason is what @erik-philips said:

$(document).on('mouseenter', '.item', function (event) {
    var item = $(this);
    $('#item_add').css({
        "left": '5.5em',
        "top": item.offset().top - 15
    }).show();
    $('#item_element_new').data('hovering_item', item);
});

$('#item_add').hover(function () {
    var menue = $(this);
    menue.animate({
        "width": '7em',
        "left": '0.5em'
    }, 200, function () {
        menue.find(".body").stop().slideDown(200);
    });
}, function () {
    var menue = $(this);
    menue.find(".body").stop().slideUp(200, function () {
        menue.animate({
            "width": '2em',
            "left": '5.5em'
        }, 200);
    });
});

$('#item_element_new').hover(function () {
    var item = $('#item_element_new').data('hovering_item');
    item.after('<div id="item_new"></div>');
}, function () {
    var item = $('#item_element_new').data('hovering_item');
    $('#item_new').remove();
});
.item {
	border: 1px solid #e2e2e2; 
	margin: 6px;
	padding: 0px 10px 0px 10px;
	position: relative; 
    height: 40px;
	}
.wrap {
    margin-left: 8em;
}
#item_new {
    border: 1px dashed #C0C0C0 !important;
    background: none repeat scroll 0% 0% #F7F7F7;
    display: block;
    height: 2.2em;
    margin: 6px;
    padding: 0px 10px;
    position: relative;
}
#item_add {
    display: none;
    position: absolute;
    width: 2em;
    border: 1px solid #ddd;
    background-color: #f7f7f7;
    color: #aaa;
    padding: 0px 6px;
}
#item_add .body {
    display: none;
}
#item_add .arrow {
    width: 0px;
    height: 0px;
    -webkit-transform:rotate(360deg);
    border-style: solid;
    border-width: 5px 0 5px 7px;
    border-color: transparent transparent transparent #f7f7f7;
    top: 5px;
    right: -7px;
    position: absolute;
}
#item_add button {
    background: none repeat scroll 0px center #fff;
    padding: 0.2em 2em;
    margin: 3px .2em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="wrap">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
</div>
<div id="item_add">
    <header>X</header>
    <div class="body">
        <button id="item_element_new">Example</button>
    </div>
    <div class="arrow"></div>
</div>

Upvotes: 2

Related Questions