Reputation: 39028
I'm having a strange problem in my Angular app.
In the sidebar I have some tags with code to show a hover and hide a hover. It requires the user sit over the tag for 2 secs before the hover is shown, if the user leaves before 2 secs, the $timeout.cancel
will wire in the mouseleave
function and kill it. So it works great.
However in another directive this does not happen, I basically/90% have the exact same code, however the $timeout.cancel
is completely ignored, so as soon as you hover over a tag in this other directive, after 2 secs the hover will fire no matter what.
Working code (tagsPanel Directive)
function hoverTag(tag) {
vs.hoverTimeout = $timeout(function() {
ApiFactory.getTagDataSilm(tag.term_id).then(function(data) {
console.log('getTagDataSilm: ', data.data.ticker_tag);
tag.tickers = data.data.ticker_tag.tickers;
tag.tagsHoverDisplay = true;
});
}, 2000);
}
function leaveTag(tag) {
$timeout.cancel(vs.hoverTimeout);
tag.tagsHoverDisplay = false;
}
Working markup
<li ng-repeat="t in tags" ng-class="{'selected': t.selected}">
<div class="tag-container-container">
<div class="tag-container"
ng-class="{'width-auto': widthAuto}"
ng-mouseleave="leaveTag(t)">
<div class="tag"
ng-click="selectTag(t)"
ng-mouseover="hoverTag(t)"
ng-class="{'positive': t.direction == 'positive',
'negative': t.direction == 'negative',
'' : t.direction == 'stagnant'}">
{{t.term}}
</div>
<tags-hover tag="t"></tags-hover>
</div>
</div>
</li>
NOT working code (viewHeader Directive)
function hoverViewTag(ticker, tag) {
console.log('hoverViewTag ', tag);
vs.hoverViewTimeout = $timeout(function() {
ApiFactory.getTagData(ticker, tag.term_id).then(function(data) {
var timeSpan = TimeSpanFactory.getTimeSpan();
var period = createSortString(timeSpan.when);
var singleTagArray = [];
singleTagArray.push(data.data.ticker_tag);
var tagDetails = TagFactory.renderDirections(singleTagArray, null, period);
tag.tagsHoverDisplay = true;
tag.favorite = tagDetails[0].favorite;
tag.quantity = tagDetails[0].quantity;
tag.tickers = tagDetails[0].tickers;
tag.tweet_percentage = tagDetails[0].tweet_percentage;
tag.momentum_twitter_preview = tagDetails[0].momentum_twitter_preview;
});
}, 2000);
}
function leaveViewTag(tag) {
// Cancel damn it!
$timeout.cancel(vs.hoverViewTimeout);
tag.tagsHoverDisplay = false;
}
NOT working markup (timeout will fire despite mouseleave function)
<ul class="view-tags-ul" ng-repeat="obj in vh.viewTickerTags">
<li ng-repeat="t in obj.tags track by $index">
<div class="tag-container"
ng-mouseleave="vh.leaveViewTag(t)">
<div class="tag"
ng-click="vh.removeTag(obj.ticker, t)"
ng-mouseover="vh.hoverViewTag(obj.ticker, t)"
ng-class="{'positive': t.direction == 'positive',
'negative': t.direction == 'negative',
'' : t.direction == 'stagnant'}">{{t.term}}
<div class="close-x-sml"></div>
</div>
<tags-hover tag="t"></tags-hover>
</div>
</li>
</ul>
Extras
This is what tags
looks like in the tagsPanel scope:
This is what the vh.viewTickerTags
object looks like:
CSS for .tag
.tag {
text-align: left;
border: 1px solid $gray_light;
background: $gray_bg;
&:hover {
-webkit-transition : border 2000ms ease-out;
-moz-transition : border 2000ms ease-out;
-o-transition : border 2000ms ease-out;
border: 1px solid $gray4 !important;
background: #fff !important;
}
&.positive,
&.negative { border: 1px solid $gray2; }
&.positive:after {
position: absolute;
top: -10px;
right: 0;
@include triangle(left, 10px, $green);
}
&.negative:after {
position: absolute;
right: -10px;
bottom: 0;
@include triangle(up, 10px, $red);
}
&.blue1 { @include colored-tag($blue1) }
&.blue2 { @include colored-tag($blue2) }
&.blue3 { @include colored-tag($blue3) }
}
li.selected {
.tag {
font-family: 'robotoregular';
border: 1px solid $gray4;
}
}
CSS for .tag
inside of the viewHeader
scope
.viewing-tags {
margin-left: 20px;
span {
float: left;
position: relative;
top: 2px;
font-style: Condensed;
font-weight: 700;
font-size: em(10);
text-transform: uppercase;
}
.ticker { margin-right: 0; }
.tags-hover-container {
.ticker { margin-right: 5px; }
}
.tag { margin-right: 0; padding-right: 0px; }
.tag { padding-bottom: 6px; }
.tag {
max-width: auto !important;
width: auto !important;
border: 1px solid $gray4 !important;
background: none !important;
}
}
Upvotes: 1
Views: 58
Reputation: 95017
In your second (non-working) example, the div has children, and since you're using mouseover, the event handler will run each time you hover over a child of that div.
To fix this, simply replace ng-mouseover
with ng-mouseenter
, which differs from mouseover in that it will trigger when you enter the div, but not when you hover over one of it's children. It's the opposite of mouseleave. The opposite of mouseover is mouseout.
Upvotes: 1