mouseover action run just once (how to) - javascript

I would like to load data(via ajax) in a tooltip when the mouse is over a specific area. The problem is that the ajax call is made as long as my mouse is on that area. Is there any way, that I could make onmouseover (ajax call) efect happen just once? Here is the code:
$.post('calendar/event-details', {'eventId' :event.id},
function (data){
this.top = (ui.clientY + 15); this.left = (ui.clientX - 230);
$('body').append( '<div id="vtip">' + data + '</div>' );
$('div#vtip').css("top", this.top+"px").css("left", this.left+"px").fadeIn("slow");
$('div#vtip').css("position","absolute");
$('div#vtip').css("z-index", "+99");
})

With .one:
$('element').one('mouseover', function() { /* ajax */ });
.one will detach the handler as soon as it is executed. As a result, it won't execute any more times.

You may want to hook your function to the onMouseEnter event instead of the onMouseOver event, along with a function hooked to the onMouseLeave event that hides the tooltip:
$('element').mouseenter(function() {
/* Make request, show tooltip */
});
$('element').mouseleave(function() {
/* Hide tooltip */
});
Note that the pure JS versions of these events are IE only, jQuery simulates the behaviour for other browsers

Use modern JS!
node.addEventListener("mouseover", function() {
// Load data here
}, {once : true});
Documentation, CanIUse

I know it's been a long time since this has been a topic but for anyone looking for an easy alternative:
Set a static variable and check the last id used.
If the last id is the current id, do nothing; quick example below
var LastId = null;
function Hover(Id){
if(Id!= LastId){
LastId = Id;
$(Id).hide('fast');
}else{
//Do nothing; this will keep the function from recalling
}
}

I guess you need to use onmouseenter instead of onmouseover
please read the docs here

Related

why does my button disappear when I add the toggle event in jquery?

I want to toggle text between bold and normal I made this code for it, but when I open my page the bold button disappears?
$("#bold").toggle(function() {
$('.focus').css("font-weight", $(this).val());
}, function() {
$('.focus').css("font-weight", "normal");
});
Is there something wrong with my code?
Please help, thanks in advance.
Assuming you're using jQuery 1.9 or later the problem is that the .toggle() event handling method was removed from the library. So what you're actually calling is the .toggle() function that hides/shows elements. (In earlier versions of jQuery both functions existed and jQuery figured out which one you meant based on the arguments passed in.)
You can implement your own toggle easily enough with a standard .click() handler:
$("#bold").click(function() {
var f = !$(this).data("toggleFlag");
if (f) {
$('.focus').css("font-weight", $(this).val());
} else {
$('.focus').css("font-weight", "normal");
}
$(this).data("toggleFlag", f);
});
This uses the .data() method to keep track of a boolean flag to indicate which code to execute. The very first time the click handler is called the flag will be returned as undefined because it hasn't previously been set, but we just convert that to a boolean with ! (assuming you want to execute the if and not the else case on the first click).
It disappears because that version of toggle is deprecated and removed, and in newer versions of jQuery all it does is toggle visibility.
You could do something like this instead :
var state = true;
$("#bold").on('click', function() {
$('.focus').css("font-weight", state ? this.value : 'normal');
state = !state;
});
FIDDLE
The only solution I fount to the disappearing element after click... is Callback function after the toggle effect finished.
here a link that explain the Callback function.
and here is my code:
jQuery('.menu li.item-487').click(function(){
jQuery('#main-menu .moduletable .menu li').toggle("slow",function(){jQuery('.menu li.item-487').css('display' , 'block');});
});

Event For DOM Object Creation

How would one fire an event that fires every time a div is created?
I was thinking something along the lines of this, but clearly not.
$("#content").on("create", "div.block", function () {
$(this).css({"background-color":"#FF0000"});
});
I have discovered MutationObserver (https://stackoverflow.com/a/11546242/165737), however as seen in the comments this does not work in IE.
you could use a mutation event (DOMNodeInserted)... however IE might not fully capable of dealing with that.
http://jsfiddle.net/kasperfish/AAd8f/
$(function() {
$('#btn').click(function(){
$('body').append('<div style="width:30px;height:30px;border:1px solid black"></div>');
});
$(document).on('DOMNodeInserted', function(e) {
$(e.target).addClass('blue');
});
});
I like to note that it is better to use callback events instead of listening to the DOM. You'll need to write a callback after a div is inserted in the DOM. I don't think there is an other (non-hacky) way to accomplish this.
You may try something like this instead of MutationObserver to get notified when ever a div.block has been added to the div#content
$(function(){
var c = $('#content'), l = c.find('.block').length;
setInterval(function(){
var lOld = l;
if(c.find('.block').length > lOld) {
l = c.find('.block').length;
c.find('.block').css({"background-color":"#FF0000"});
}
}, 100);
});
An example and here is another example with multiple Background color effect.

jQuery: Can't cache onclick handler?

I've got a step-by-step wizard kind of flow where after each step the information that the user entered for that step collapses down into a brief summary view, and a "Go back" link appears next to it, allowing the user to jump back to that step in the flow if they decide they want to change something.
The problem is, I don't want the "Go Back" links to be clickable while the wizard is animating. To accomplish this I am using a trick that I have used many times before; caching the onclick handler to a different property when I want it to be disabled, and then restoring it when I want it to become clickable again. This is the first time I have tried doing this with jQuery, and for some reason it is not working. My disabling code is:
jQuery.each($("a.goBackLink"), function() {
this._oldOnclick = this.onclick;
this.onclick = function() {alert("disabled!!!");};
$(this).css("color", "lightGray ! important");
});
...and my enabling code is:
jQuery.each($("a.goBackLink"), function() {
this.onclick = this._oldOnclick;
$(this).css("color", "#0000CC ! important");
});
I'm not sure why it's not working (these are good, old-fashioned onclick handlers defined using the onclick attribute on the corresponding link tags). After disabling the links I always get the "disabled!!!" message when clicking them, even after I run the code that should re-enable them. Any ideas?
One other minor issue with this code is that the css() call to change the link color also doesn't appear to be working.
I wouldn't bother swapping around your click handlers. Instead, try adding a conditional check inside of the click handler to see if some target element is currently animating.
if ($('#someElement:animated').length == 0)
{
// nothing is animating, go ahead and do stuff
}
You could probably make this a bit more concise but it should give you an idea... Havent tested it so watch your console for typeos :-)
function initBack(sel){
var s = sel||'a.goBackLink';
jQuery(s).each(function(){
var click = function(e){
// implementation for click
}
$(this).data('handler.click', click);
});
}
function enableBack(sel){
var s = sel||'a.goBackLink';
jQuery(this).each(function(){
var $this = jQuery(this);
if(typeof $this.data('handler.click') == 'function'){
$this.bind('goBack.click', $this.data('handler.click'));
$this.css("color", "lightGray ! important");
}
});
}
function disableBack(sel){
var s = sel||'a.goBackLink';
jQuery(s).each(function(){
var $this = jQuery(this);
$this.unbind('goBack.click');
$this.css("color", "#0000CC ! important");
});
}
jQuery(document).ready(function(){
initBack();
jQuery('#triggerElement').click(function(){
disableBack();
jQuery('#animatedElement').animate({/* ... */ }, function(){
enableBack();
});
});
});

Add click event to Div and go to first link found

I think I've been too much time looking at this function and just got stuck trying to figure out the nice clean way to do it.
It's a jQuery function that adds a click event to any div that has a click CSS class. When that div.click is clicked it redirects the user to the first link found in it.
function clickabledivs() {
$('.click').each(
function (intIndex) {
$(this).bind("click", function(){
window.location = $( "#"+$(this).attr('id')+" a:first-child" ).attr('href');
});
}
);
}
The code simply works although I'm pretty sure there is a fairly better way to accomplish it, specially the selector I am using: $( "#"+$(this).attr('id')+" a:first-child" ). Everything looks long and slow. Any ideas?
Please let me know if you need more details.
PS: I've found some really nice jQuery benchmarking reference from Project2k.de here:
http://blog.projekt2k.de/2010/01/benchmarking-jquery-1-4/
Depending on how many of these div.click elements you have, you may want to use event delegation to handle these clicks. This means using a single event handler for all divs that have the click class. Then, inside that event handler, your callback acts based on which div.click the event originated from. Like this:
$('#div-click-parent').click(function (event)
{
var $target = $(event.target); // the element that fired the original click event
if ($target.is('div.click'))
{
window.location.href = $target.find('a').attr('href');
}
});
Fewer event handlers means better scaling - more div.click elements won't slow down your event handling.
optimized delegation with jQuery 1.7+
$('#div-click-parent').on('click', 'div.click', function () {
window.location.href = $(this).find('a').attr('href');
});
Instead of binding all the clicks on load, why not bind them on click? Should be much more optimal.
$(document).ready(function() {
$('.click').click(function() {
window.location = $(this).children('a:first').attr('href');
return false;
});
});
I would probably do something like;
$('.click').click(function(e){
window.location.href = $(this).find('a').attr('href');
});

preventing effects to be applied to the same object twice when adding objects with ajax

I'm having a little issue with an application I'm making. I have a page where the user edits a document via dragging modules into the page or "canvas" area.
http://thinktankdesign.ca/temp_img.jpg
When the page is loaded, javascript haves the modules collapsible (like above). However after the user drags in a new module the effect is applied again some new modules can collapse as well. here is the problem. each time a module loads the same effect gets applied to the modules that already can collapse. It ends up breaking their animations.
heres the code that gets executed on page load.
//make colapsible
$("h1.handle").click(function() {
var object = $(this);
v$(this).next().toggle("fast", colapsible_class(object));
vreturn false;
}).addClass("open");
and heres the code that gets executed in the creation of a module via ajax
function get_module(id){
var template = $('input[name=template]').val();
$.post(window.location.href, { template: template, module: id, mode: 'create' },
function(data){
$(data).insertBefore(".target_wrapper");
//enable deletion of module
$(".js_no_modules").slideUp("slow");
$(enable_module_deletion());
//show delete button
$("button[name=delete]").show();
//make colapsible
$("h1.handle").click(function() {
var object = $(this);
$(this).next().toggle("fast", colapsible_class(object));
return false;
}).addClass("open");
}
);
}
I need a solid way of preventing the toggle effect to be applied to the same module twice
Use jQuery 1.3 live events instead.
//make colapsible
$("h1.handle").live("click", function() {
var object = $(this);
v$(this).next().toggle("fast", colapsible_class(object));
vreturn false;
}).addClass("open");
and then eliminate the click declaration in the second block of code, changing it to $("h1.handle").addClass("open");
Live events bind all current and future matching elements with an event.
In your Ajax success handler try the following:
//make collapsible
$("h1.handle:not(.open)").click(function() {
var object = $(this);
$(this).next().toggle("fast", colapsible_class(object));
return false;
}).addClass("open");
The best way to solve your problem is, instead of using $("h1.handle") on the AJAX callback, go for $(data).find("h1.handle"). Something like,
var x = $(data);
x.insertBefore(...);
/* your other code */
x.find('h1.handle').click(...).addClass(...);
Like that, only the newly added items will have the event bounded. The already present ones will not be touched.
If we want to answer your question instead of just solving your problem, then we have several alternatives, such as:
store, in your objects, that the onclick event handler has been set so that you don't set it twice
always bind the onclick event, but always unbind it first
use jQuery's live events and the addClass open only on the newly created items.
IMO, the first one is the easiest. You can accomplish it by using jQuery's data(). Then you could do something like:
$("h1.handle").each(function() {
var me = $(this);
// if already has click handler, don't do anything
if (me.data('click_set') != null) { return true; }
// otherwise, store the data and bind the click event
me.data('click_set', true).click(function() {
/* the code you already have on the click handler */
}).addClass('open');
}
The second alternative involves storing the function that you pass inline to the click event binder in a variable, and then using jQuery's unbind to disable it.

Categories