Why document selector doesn't work for mouseenter event? - javascript

Here is my code:
$.fn.right = function() {
return $(document).width() - (this.offset().left + this.outerWidth());
}
$(document).ready(function(){
$('a').bind('mouseenter', function() {
var self = $(this);
this.iid = setTimeout(function() {
var tag_name = self.text(),
top = self.position().top + self.outerHeight(true),
right = self.right();
$('body').append("<div class='tag_info'>Some explanations about "+tag_name+"</div>");
$(".tag_info").css({top: top + "px", right: right + "px"}).fadeIn(200);
}, 525);
}).bind('mouseleave', function(){
if(this.iid){
clearTimeout(this.iid)
$('.tag_info').remove();
}
});
});
body{
padding: 20px;
direction: rtl;
}
a {
color: #3e6d8e !important;
background-color: #E1ECF4;
padding: 2px 5px;
}
.tag_info{
position: absolute;
width: 130px;
height: 100px;
display:none;
background-color: black;
color: white;
padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a>long-length-tag</a>
<a>tag</a>
It works fine. But in reality, the content (those tags) will be created later. I mean they will be created as an ajax response. So $('a') doesn't select them.
Now I'v written it like $(document).bind('mouseenter', 'a', function(){ ... }) to make that working even for the DOM which is created after page loading.
But as you see in this fiddle, it doesn't work. Does anybody know what's the problem and how can I fix it?

You need to bind the event with .on(). This works for future elements as well.
$(document).on('mouseenter', 'a', function(){ ... });
And, as #Gregg has answered, .bind() has been replaced by .on(). That's the actual cause why your fiddle doesn't work.

The on() function has replaced bind() since jQuery 1.7. If you read the documentation, you'll note that live() was actually used for delegate events like what you're trying to achieve while the bind() method was not; binding events to elements that will be added to the DOM later. The on() function can do this. Either from the document itself or from a direct descendent.

When anchor tag are being created in response of your AJAX call, put id in it like this:
$('body').append("<div class='tag_info' id='myTag'>Some explanations about "+tag_name+"</div>");
and then you can bind event mouseenter or mouseleave like this:
$('#myTag').bind('mouseenter', function(){
alert('Mouse Enter in your Anchor Tag');
}).bind('mouseleave', function(){
alert('Mouse leave');
});

Related

Shorthand to get jquery object from event?

Is there a way to get a jquery object back from an event to reduce the amount of $(e.target) that has to be done?
For example:
$(document).on('click',"div", function(e){
$(e.target).css('color', 'red');
}
});
could be written as
$(document).on('click',"div", function(e){
e.JQUERY_target.css('color', 'red');
}
});
Is there a way to get a jquery object from the event without having to convert it?
Is there a way to get a jquery object back from an event to reduce the
amount of $(e.target) that has to be done?
Yes. Do not use jQuery for the task. jQuery is not necessary at all for the specific requirement
$(document).on("click", "div", function(e){
e.target.style.color = "red";
});
No, events give you only DOM objects. If you want to use jQuery, $() them.
You can harness the awesome power of this!
$(document).on('click', 'div', function(){
$(this).css('color', 'red');
});
Where $(this) is the current object you are running code on. In this case, you're saying that whenever a div that is a child of document is clicked on, you want to run the given code on it. Thus, this is the div that was clicked on.
You can use $(this) if you want to use jQuery methods. Or e.target if you want to use vanilla JS methods.
Using $(this) with jQuery methods:
$(document).on('click', "div", function(e) {
$(this).css('color', 'red');
});
div {
width: 100px;
height: 100px;
background-color: gray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Click Me</div>
Using e.target with vanilla JS methods:
$(document).on('click', "div", function(e) {
e.target.style.color = 'red';
});
div {
width: 100px;
height: 100px;
background-color: gray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Click Me</div>

jQuery script not working on html appended from another page

I've already referred to these answers but that doesn't solve:
jQuery on button click not working after append
Jquery click event not working after append method
I want to load the html for click button on page load like this:(this shows the html with css correctly, but the script is not working)
$.get( "/plugins/system/conversekit/conver/test.php", function( data ) {
$('body').append(data);
}, "html" );
But if I load the html i n this way the script works:
$('body').append('<div id="ckit" class="layout-compact is-hiddenx"\
data-ckit-compact style=""><a href="javascript:void(0);"\
class="btn-toggle-ckit" data-ckit-toggle-on><i class="fa fa-comment-o">\
</i></a></div><div id="ckit" class="layout-full is-hidden disable-scrolling" data-ckit-full>\
<iframe src="/plugins/system/conver/conver/full-view-contact.php" data-ckit-iframe id="ckit-full-view" \
name="ckit-full-view" scrolling="no" frameborder="0"allowtransparency="true" \
style="position: absolute; top: 0px; right: 0px; bottom: 0px; left: 0px; width: 100%; height: 100%; border: 0px; padding: 0px; \
margin: 0px; float: none; background: none;"></iframe></div>');
SCRIPT:
var toggleCkitOn = $('[data-ckit-toggle-on]');
toggleCkitOn.on('click', function(e) {
$(ckitFull).removeClass("is-hidden");
$(ckitCompact).addClass("is-hidden");
$('body').addClass("disable-scrolling");
$("html").css({"height": "100%", "overflow": "hidden"});
$("body").css({"position": "relative"});
e.preventDefault();
});
HTML
<div id="ckit" class="layout-compact is-hiddenx" data-ckit-compact style="">
</i>
</div>
<div id="ckit" class="layout-full is-hidden disable-scrolling" data-ckit-full>
<iframe src="conver/full-view-contact.php" data-ckit-iframe id="ckit-full-view" name="ckit-full-view" scrolling="no" frameborder="0" allowtransparency="true" style="position: absolute; top: 0px; right: 0px; bottom: 0px; left: 0px; width: 100%; height: 100%; border: 0px; padding: 0px; margin: 0px; float: none; background: none;"></iframe>
</div>
I tried to avoid the delegation but doesn't help,
$('body').on('click',toggleCkitOn, function(e) {...});
Tried with other promises to check if ajax functions correctly, and I get all the below get executed without error:
1) success
2) second success
3) finished
var jqxhr = $.get( "/plugins/system/conversekit/conversekit/test.php", function() {
alert( "success" );
})
.done(function() {
alert( "second success" );
})
.fail(function() {
alert( "error" );
})
.always(function() {
alert( "finished" );
});
Working answer (but i want the variables to be global scope, declaring them outside this function makes the click the doesn't work):
$("body").on("click", ".btn-toggle-ckit", function(e) {
var toggleCkitOn = $('[data-ckit-toggle-on]');
var ckitFull = $('[data-ckit-full]');
var ckitCompact = $('[data-ckit-compact]');
var ckitIframe = $('[data-ckit-iframe]');
$(ckitFull).removeClass("is-hidden");
$(ckitCompact).addClass("is-hidden");
$('body').addClass("disable-scrolling");
$("html").css({"height": "100%", "overflow": "hidden"});
$("body").css({"position": "relative"});
e.preventDefault();
} );
function ckitDelegate() {
var toggleCkitOn = $('[data-ckit-toggle-on]');
toggleCkitOn.on('click', function(e) {
$(ckitFull).removeClass("is-hidden");
$(ckitCompact).addClass("is-hidden");
$('body').addClass("disable-scrolling");
$("html").css({"height": "100%", "overflow": "hidden"});
$("body").css({"position": "relative"});
e.preventDefault();
});
};
$.get("/plugins/system/conversekit/conver/test.php", function( data ) {
$('body').append(data);
ckitDelegate();
}, "html").fail(function() {
alert( "error" );
});
This my last opinion, i will give-up if it not working too:
$.get("/plugins/system/conversekit/conver/test.php", function( data ) {
$('body').append(data);
setTimeout(function(){ ckitDelegate(); }, 500);
}, "html");
please try this. Add click event in one function and call that function on DOM load and after the append operation. Like this:
function Init(){
toggleCkitOn.on('click', function(e) {});
}
$(document).ready(function(){
Init();
});
$.get( "/plugins/system/conversekit/conver/test.php", function( data ) {
$('body').append(data);
Init();
}, "html" );
Just make sure you have defined the Init() before calling them
Your issue was that the iframe was hiding $('[data-ckit-toggle-on]') and therefore preventing any click events - i.e. the click events weren't firing because you were clicking the iframe, not the a href.
If you remove the iframe (temporarily - solve one issue at a time), then try again, it should at least fire the click event.
Right click on your $('[data-ckit-toggle-on]') element in the DOM then click "Inspect element" to see if it is visible or not.
EDIT
Try this:
$.get("plugins/system/conversekit/conver/test.php",
function(data) { $('body').append(data); },
"html").then(function(data) {
var toggleCkitOn = $('[data-ckit-toggle-on]');
var ckitFull = $('[data-ckit-full]');
var ckitCompact = $('[data-ckit-compact]');
var ckitIframe = $('[data-ckit-iframe]');
$("body").on("click", ".btn-toggle-ckit", function(e) {
alert("hi");
$(ckitFull).removeClass("is-hidden");
$(ckitCompact).addClass("is-hidden");
$('body').addClass("disable-scrolling");
$("html").css({"height": "100%", "overflow": "hidden"});
$("body").css({"position": "relative"});
e.preventDefault();
});
});
If you're still having trouble clicking the a href, try adding a css margin-top to the iframe to where it isn't covering the a href. Let me know.
If your html create dynamic that time you should bind click method.
Write this code after appending your html.
Example :-
$('#buttonOuter').append('<input type="button" id="myid"/>');
$("#myid").unbind();
if($("#myid").length > 0 && $._data( $("#myid")[0], "events" )==undefined){
$('#myid').bind('click',function(){
// write your code
});
}
I think it's working for you

Document ready button.click only works in console

I have a button<button id="stbutton"></button> and I can enter into the Chrome Dev Console $('#stbutton').click(); and it works. Sounds easy enough, however:
$(document).ready(function () {
$("#stbutton").click();
});
Doesn't work. Also tried waiting for the parent div to load, no dice,
$('#panel').ready(function () {
$("#stbutton").click();
});
As for this page, I know it works in console. And jquery is definitely being loaded before it hits this line of code.
As #charlietfl pointed out, you're probably triggering the event before attaching the click listener to the element.
$(document).ready(function(){
$("#stbutton").click(); //This doesn't work
$("#stbutton").on("click", function(){
alert("clicked");
});
$("#stbutton").click(); //trigger event after listening to it.
});
#stbutton {
background: #000;
width: 100px;
height: 100px;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="stbutton"></div>
$(window).load(function () {
$('#stbutton').click();
})
I found the magic that is window.load!

jquery and hammer.js ghost click when panning

I'm using jQuery 191 and Hammer JS 204. I have the following example scenario
<div> class="myDiv">
<div class="content">
<img>
</div>
</div>
Example JS
$('.myDiv').hammer({}).bind("pan", function(h) {
h.gesture.srcEvent.preventDefault();
});
$('.content img').on('click', function(){
console.log('i was clicked');
});
When I click on the image to start panning myDiv, Right after panend, the myDiv img click event gets fired.
I've tried to stopPropagation and stopImmediatePropagation but still couldn't get it to stop firing the click after i finish panning.
var hammering = false;
$('.myDiv').hammer({}).bind("pan", function(h) {
h.gesture.srcEvent.preventDefault();
}).bind("panstart", function(h) {
hammering = true;
}).bind("panend", function(h) {
setTimeout(function(){
hammering = false;
}, 300);
});
$('.content img').on('click', function(){
if(hammering) return false;
console.log('i was clicked');
});
Another way to avoid this ghost click is to create a pseudo class over the hammer target.
for example you can add class and the style something like
`.block:after {
content: " ";
background: transparent;
top: 0;
left: 0;
width: 250px;
height: 100%;
z-index: 2;
display: block;
position: absolute;
}`
when panstart and remove it when panend.
hope this trick will help others.
I find out a easy way could prevent click event while hammer.js panning:
disable div pointer-events while pan start, then enable it while pan end.
...
myPanGesture.on("panstart", function(ev) {
$(".tab-pane.active").css({'pointer-events':'none'});
});
...
myPanGesture.on("panend", function(ev) {
$(".tab-pane.active").css({'pointer-events':'auto'});
});
...

jQuery show hide sliding panel from left side

I want a panel to slide from left edge of browser when clicking a button and hide the panel when clicking the same button (toggle).
Html
<div class="panel">
</div>
»
CSS
.panel {
width:300px;
float:left;
height:550px;
background:#d9dada;
position:relative;
left:-300px;
}
.slider-arrow {
padding:5px;
width:10px;
float:left;
background:#d9dada;
font:400 12px Arial, Helvetica, sans-serif;
color:#000;
text-decoration:none;
position:relative;
left:-300px;
}
jquery
$(function(){
$('.slider-arrow.show').click(function(){
$( ".slider-arrow, .panel" ).animate({
left: "+=300"
}, 700, function() {
// Animation complete.
});
$(this).html('«').removeClass('show').addClass('hide');
});
$('.slider-arrow.hide').click(function(){
$( ".slider-arrow, .panel" ).animate({
left: "-=300"
}, 700, function() {
// Animation complete.
});
$(this).html('»').removeClass('hide').addClass('show');
});
});
It is showing the panel but not hiding the panel. Any problem with the selectors used?
http://jsfiddle.net/Paramasivan/eHded/1/
As others have said with jQuery once the document is initialized its only looking for elements that initially existed. For that reason your .show function was being run every time.
Instead of looking for a click event on .slider-arrow.show you can just look at .slider-arrow and then check for the classes once it has been clicked like in this example.
$(function(){
$('.slider-arrow').click(function(){
if($(this).hasClass('show')){
$( ".slider-arrow, .panel" ).animate({
left: "+=300"
}, 700, function() {
// Animation complete.
});
$(this).html('«').removeClass('show').addClass('hide');
}
else {
$( ".slider-arrow, .panel" ).animate({
left: "-=300"
}, 700, function() {
// Animation complete.
});
$(this).html('»').removeClass('hide').addClass('show');
}
});
});
http://jsfiddle.net/eHded/4/
Since you are using jQuery to manipulate the "show" and "hide" after the DOM has loaded, jQuery doesn't know those elements exist.
Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call...
I suggest using jQuery's on() in order to delegate events and select dynamically generated classes, like so:
$(document).on('click','.slider-arrow.show',function(){
....
});
$(document).on('click','.slider-arrow.hide',function(){
....
});
http://jsfiddle.net/eHded/2/
I think you can manage the action choosing from the active anchor class like this:
$(function(){
$('.slider-arrow').click(function(){
var anchor = this;
var removeClass = "show";
var addClass = "hide";
var diff = "+=300";
var arrows = "«";
if($(anchor).hasClass("hide")){
diff = "-=300";
removeClass = "hide";
addClass="show";
arrows = '»';
}
$( ".slider-arrow, .panel" ).animate({
left: diff
}, 700, function() {
// Animation complete.
$(anchor).html(arrows).removeClass(removeClass).addClass(addClass);
});
});
});
So you've got only one animation function.
Here is the updated fiddle: http://jsfiddle.net/eHded/5/
You should try using .slideToggle(), put inside a .click(function(){/*in here*/}).
When you write $('.slider-arrow.hide').click(func....., that binds the click event at the time that code is first ran (probably when the document is ready). If you change the DOM later on (ie. add the .hide class) you need to re-bind the click event.
You need to use jQuery's .on() method instead (http://api.jquery.com/on/).
$(document).on('click', '.slider-arrow.show', function() { /*.......*/ });
$(document).on('click', '.slider-arrow.hide', function() { /*.......*/ });
A better alternative altogether however would be to use CSS3 transitions and jQuery's .toggleClass()
.panel {
left: -300px;
transition: left 1s;
/* other styles... */
}
.panel.expand {
left: 0;
}
$('.slider-arrow').click(function() {
$('.panel').toggleClass('expand');
}
For this task I use SlideReveal jQuery plugin.
After you include the library the setup is as easy as:
<div id='slider'>Hello World!!</div>
<button id='trigger'>Trigger</button>
<script>
$('#slider').slideReveal({
trigger: $("#trigger")
});
</script>
Please refer to documentation for more details and live samples.

Categories

Resources