I used jQuery to set hover callbacks for elements on my page. I'm now writing a module which needs to temporarily set new hover behaviour for some elements. The new module has no access to the original code for the hover functions.
I want to store the old hover functions before I set new ones so I can restore them when finished with the temporary hover behaviour.
I think these can be stored using the jQuery.data() function:
//save old hover behavior (somehow)
$('#foo').data('oldhoverin',???)
$('#foo').data('oldhoverout',???);
//set new hover behavior
$('#foo').hover(newhoverin,newhoverout);
Do stuff with new hover behaviour...
//restore old hover behaviour
$('#foo').hover($('#foo').data('oldhoverin'),$('#foo').data('oldhoverout'));
But how do I get the currently registered hover functions from jQuery?
Shadow2531, I am trying to do this without modifying the code which originally registered the callbacks. Your suggestion would work fine otherwise. Thanks for the suggestion, and for helping clarify what I'm searching for. Maybe I have to go into the source of jquery and figure out how these callbacks are stored internally. Maybe I should change the question to "Is it possible to do this without modifying jquery?"
Calling an event bind method (such as hover) does not delete old event handlers, only adds your new events, so your idea of 'restoring' the old event functions wouldn't work, as it wouldn't delete your events.
You can add your own events, and then remove them without affecting any other events then use Event namespacing: http://docs.jquery.com/Events_(Guide)#Namespacing_events
Not sure if this will work, but you can try this:
function setHover(obj, mouseenter, mouseleave) {
obj.data("_mouseenter", mouseenter);
obj.data("_mouseleave", mouseleave);
obj.hover(obj.data("_mouseenter"), obj.data("_mouseleave"));
}
function removeHover(obj) {
obj.unbind("mouseenter", obj.data("_mouseenter"));
obj.unbind("mouseleave", obj.data("_mouseleave"));
obj.data("_mouseenter", undefined);
obj.data("_mouseleave", undefined);
}
$(document).ready(function() {
var test = $("#test");
setHover(test, function(e) {
alert("original " + e.type);
}, function(e) {
alert("original " + e.type);
});
var saved_mouseenter = test.data("_mouseenter");
var saved_mouseleave = test.data("_mouseleave");
removeHover(test);
setHover(test, function() {
alert("zip");
}, function() {
alert('zam');
});
removeHover(test);
setHover(test, saved_mouseenter, saved_mouseleave);
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Jquery - Get, change and restore hover handlers</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<p><a id="test" href="">test</a></p>
</body>
</html>
If not, maybe it'll give you some ideas.
I'm not sure if this is what you mean, but you can bind custom events and then trigger them.
http://docs.jquery.com/Events/bind
So add your hover event, script the functionality you need for that hover, then trigger your custom event.
Maybe it would be easier to just hide the old element and create a clone with your event handlers attached? Then just swap back in the old element when you're done..
Related
I have one problem about mouseover and mouseleave function.
In this DEMO page you can see there is a picture. When you hover over muse then you can see the hovercard. The hovercard inside have click to follow link. But you can not click that link because when you mouseleave on that link the hovercard to be closed. How can I solve this problem. Is anyone can help me ?
The Jquery code is here:
$(document).ready(function(){
function showProfileTooltip(e, id){
e.append($('.p-tooltip').css({
'top':'20',
'left':'80'
}).show());
//send id & get info from go_card.php
$.ajax({
url: 'go_card.php?uid='+id,
beforeSend: function(){
$('.p-tooltip').html('Yükleniyor..');
},
success: function(html){
$('.p-tooltip').html(html);
}
});
}
function hideProfileTooltip(){
$('.p-tooltip').hide();
}
$('.summary a').mouseover(function(e){
var id = $(this).attr('data-id');
showProfileTooltip($(this), id);
});
$('.summary').mouseleave(function(){
hideProfileTooltip();
});
});
and HTML code:
<div class="paylasilan-alani">
<div class="paylasan-profil-fotosu profile">
<div class="summary" id="summary1" data-id="7"><img src="http://www.designbolts.com/wp-content/uploads/2013/11/Frozen-Movie-poster-payoff-Wallpaper-HD1.jpg" width="64" height="64"/></div>
</div>
<div class="paylasilan">Some text here.</div>
</div>
The issue is the .mouseover() function which is triggering the ajax call over and over.
per the documentation for .mouseover():
This event type can cause many headaches due to event bubbling. For instance, when the mouse pointer moves over the Inner element in this example, a mouseover event will be sent to that, then trickle up to Outer. This can trigger our bound mouseover handler at inopportune times. See the discussion for .mouseenter() for a useful alternative.
instead switch to .hover(). You can use a callback to handle the mouseleave() functionality too:
$('.summary a').hover(function(e){
var id = $(this).attr('data-id');
showProfileTooltip($(this), id);
}, function(){
hideProfileTooltip();
});
Also the plugin you are using which is adding inline styles to .summary and the class scroll-to-fixed-fixed is setting .summary to z-index:0. The z-index property is inherited by it's children and this is causing your pop up to sit behind other elements. I would either look through the plugin's JS file and remove this or override it in your CSS by adding:
.summary{
z-index: 1 !important;
}
JSBIN
function hideProfileTooltip(){
$('.p-tooltip').hide();
}
$('.summary a').mouseover(function(e){
var id = $(this).attr('data-id');
showProfileTooltip($(this), id);
});
$('.summary').mouseleave(function(){
hideProfileTooltip();
});
This is your issue code. To achieve your purpose. The key is the.p-tooltip doesn't disapper when trigger the function ummary.mouseleave if your cursor move to the .p-tooltip,but when your cursor move to other place. The .p-tooltip should be disappear.
So I create a JSBIN to simulate your issue. The jsbin simply simulates your problem. It's just a way with a HTML structure to fixed your issue. I believe there is another way to resolve it. But use this structure is a brief way to make it. So, I advise you should repaint your HTML, specially pay more attention the parent & child relation.
That's all.
You need to specify the mouseleave function inside the mouse enter function. This way, after focusing on the element, it hides if the user leaves the element.
There are a couple of questions that seem to ask this question, but no one accepted answers and nothing has worked for me.
I have a 'group' button that when it's clicked, will dynamically create a 'group' div (I then append some pre-selected 'child' divs within it)
However I need the new 'group' div to be draggable.
I can set the draggable attribute dynamically, no problem.
But being draggable is not much good without the ondragstart() event, and no matter what I've tried, I can't get this assigned.
I am using jQuery which may have a bearing.
The latest iteration of my code is (this appears in an init() function that is called from body.onload):
var group=$(document.createElement('div'));
group.attr({id: 'group'+grpcount});
group.attr({draggable: "true"});
group.addClass('group');
group.html("<span class='group'>Group"+grpcount+"</span>");
$('#boundary').append(group);
document.getElementById('group'+grpcount).addEventListener("startdrag",drag);
But I have also tried various combinations of jQuery .bind:
group.bind("dragstart", drag(ev));
group.bind("dragstart", function(ev){drag(ev);});
All to no avail.
I have a drag function already defined (and I've tried putting it before and after the code above):
function drag(ev) {
ev.dataTransfer.setData("Text",ev.target.id+":"+ev.pageX+":"+ev.pageY);
}
I hope there is something glaringly obvious that I just can't see.
Can somebody solve this?
You'll be better to take a look at Jquery UI draggable here
and if you dont know yet, you can call multiple jquery finctions in a chain, so your code looks more readable like below:
var group=$('div').attr('id', 'group'+grpcount)
.addClass('group')
.html("<span class='group'>Group"+grpcount+"</span>");
$('#boundary').append(group);
and instead of
document.getElementById('group'+grpcount).addEventListener("startdrag",drag);
use this
group.draggable({
start:function(event, ui){
//this is where dragging starts when you push mousedown and move mouse
},
drag:function(event, ui){
//this function will be called after drag started each time you move your mouse
}
stop:function(event, ui){
//this is where you release mouse button
}
})
this jquery draggable widget with droppable widget will ease your life if you really want to implement complex drag-and-drop functionality
I made this:
function drag(ev) { alert('Hi'); }
var grpcount = 21;
var group=$(document.createElement('div'));
group.attr({id: 'group'+grpcount});
group.attr({draggable: "true"});
group.addClass('group');
group.html("<span class='group'>Group"+grpcount+"</span>");
group.bind("dragstart", function(ev){drag(ev);});
$('#boundary').append(group);
See the working fiddle here: http://jsfiddle.net/nxcSz/
I'm using the excellent jQuery knob plugin. However, I need to dynamically enable/disable the element depending on user input. There is support for having a disabled state on page load which have the effect that no mouse (or touch) events are bound to the canvas element. Does anyone know how to resolve this issue, that is, how to (after page load) bind and unbind these mouse event listeners?
Ideally I would like to do something like this (on a disabled knob)
$('.button').click(function() {
$('.knob').enable();
});
Edit:
I ended up rewriting the source which binds/unbinds the mouse and touch events. The solution is not perfect so I leave the question open if someone perhaps have a better (cleaner) solution.
html
<input class="knobSlider" data-readOnly="true">
<button id="testBtn">clickHere</button>
script
in doc ready,
$(".knobSlider").knob();
$("#testBtn").click(function(){
$(".knobSlider").siblings("canvas").remove();
if($(".knobSlider").attr("data-readOnly")=='true'){
$(".knobSlider").unwrap().removeAttr("data-readOnly readonly").data("kontroled","").data("readonly",false).knob();
}
else{
$(".knobSlider").unwrap().attr("data-readOnly",true).data("kontroled","").data("readonly",true).knob();
}
});
For reference you can use my jsfiddle link > http://jsfiddle.net/EG4QM/ (check this in firefox, because of some external resource load problem in chrome)
If someone doesn't like how the accepted answer destroys and recreates the internal canvas element, then checkout my approach:
https://jsfiddle.net/604kj5g5/1/
Essentially, check the draw() implementation (I also recommend listening on value changes in the draw method instead of the change and release, which work for and click and mousewheel events respectively, which imo is inconvenient).
var $input = $("input");
var knobEnabled = true;
var knobPreviousValue = $input.val();
$input.knob({
draw: function () {
if (knobPreviousValue === $input.val()) {
return;
}
if (!knobEnabled) {
$input.val(knobPreviousValue).trigger("change");
return;
}
knobPreviousValue = $input.val();
console.log($input.val());
},
});
Try this to disable the control.
I'm still trying to find a way to enable it back
$("#btnDisable").click(function(){
$("#knob").off().prev().off();
});
I have a slideshow that i replace an unordered list within the slide show, the images change but any effects are not inherited. this is the script that introduces a new DOM:
jQuery("#kwick1").click(function () {
jQuery('#photography').load('/design.html #photography');
});
jQuery("#kwick2").click(function () {
jQuery('#photography').load('/design.html #design');
});
how do i get the jQuery slideshow to inherit this new list of images??
i both these functions and the slide show function in the same file.
I have a
jQuery(document).ready(function() {
that loads the slideshow script.
You have to let us know what slideshow plugin you are using. Regardless, you probably just need to destroy your old slideshow instance and restart it. Something like:
//start slideshow on
var slideshow = $('#slideshow').cycle();
slideshow.start();
$('#button').click( function() {
//depending on plugin api maybe stop, add and start again
slideshow.stop();
slideshow.addImages();
slideshow.start();
//or perhaps just destroy old slideshow and restart
slideshpw = $('#slideshow').cycle();
});
To attach events to newly added elements you should use live() or delegate();
jQuery('.yourselector').live('click', function(){
//do something on click
});
Instead of attaching events to each of elements, you should learn how to use event delegation. That way you can attach single event listener on some container ( or even document ) and catch the events as they bubble up.
Additionally it will make your code look much cleaner and easier to understand.
http://lab.distilldesign.com/event-delegation/
http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-javascript-event-delegation-in-4-minutes/
http://www.sitepoint.com/javascript-event-delegation-is-easier-than-you-think/
P.S. , if you put your code at the bottom of the HTML ( before </body> ) then, when it triggers , it will already be an "onDomReady" event.
I have a timed event I want to behave differently accordingly to what HTML element the mouse pointer is on.
Is there a way, assuming I have the HTML element, to know if the mouse pointer is currently on top of it.
I am well aware of the onmouseover/onmouseout events and how to use them.
I am using JQuery.
I am obviously looking for some kind of flag, as I need to check a state and not handle an event.
again, I know how to implement this with events.
I'm not aware of any built-in way to ping an element for the status of mouse hovering.
However, you can create one by updating a flag at mouseenter and mouseleave -- which is where Brian Driscoll's suggestion of .hover comes in:
jQuery.fn.tracking = function () {
this.data('hovering', false);
this.hover(function () {
$(this).data('hovering', true);
}, function () {
$(this).data('hovering', false);
});
return this;
};
jQuery.fn.hovering = function () {
return this.data('hovering');
}
You'll need to initialize tracking for each element you care about:
$('#elem1,#elem2').tracking();
But then you can get the status of any of them:
if ($('#elem1').hovering()) {
// ...
} else if ($('#elem2').hovering()) {
// ...
}
Demo: http://jsbin.com/amaxu3/edit
Have you looked into jQuery.hover()? http://api.jquery.com/hover/
You need to give name to html andme and on mouseover you need to check document.getelementsbyName. Then check what your are getting as output. Now you can take decision is it html control or asp.net.
When you use collObjects = object.getElementsByName("htmlcontrol") then compare id of both.
1 morething why you needed to check this in javascript. there may be some other solution for that. Just share with us.
You might have some luck with document.elementFromPoint, although I believe there are some inconsistencies in older browser implementations (http://www.quirksmode.org/dom/w3c_cssom.html#documentview).
$('#elem').mousemove(function(e){
if (this == document.elementFromPoint(e.clientX, e.clientY)) {
// Do stuff
}
});
Or outside of a handler
if ($('#elem').get(0) == document.elementFromPoint(x, y)) {
// Do stuff
}
Aside from that, the only other option that comes to mind is using event handlers to keep track of which element the mouse is over.