I have a MooTools script (please dont ask why..) where elements are added a mouseenter event. In jQuery, I open/show those elements within a fancybox. When it pops up, the mouseenter event wont get fired in the first place since the cursor is already on an element eventually, depending where the user clicks to open the fancybox. But the jQuery mousemove event does fire on those.
I could just add a mousemove event in the MooTools file which triggers the mouseenter event, but for the sake of learning: how would I fire an elements event function (and make use of the this-reference)?
This didnt work for me.
MooTools:
$$('.foo').addEvents({
mouseenter: function(){
console.log('fired!'); // never does ):
// stuff happens here
}
});
jQuery:
$('#bar').fancybox({
onComplete: function() {
$('.foo').unbind('mousemove').mousemove(function() {
var el = this;
console.log('mousemoved');
$('.foo').unbind('mousemove');
// does not work:
(function($$) {
$$(this).fireEvent('mouseenter', $(this));
})(document.id);
// neither does this:
var event;
if (document.createEvent) {
event = document.createEvent("HTMLEvents");
event.initEvent("mousemove", true, true);
} else {
event = document.createEventObject();
event.eventType = "mousemove";
}
event.eventName = "mousemove";
event.memo = {};
if (document.createEvent) {
this.dispatchEvent(event);
}
else {
this.fireEvent("on" + event.eventType, event);
}
// whats the solution?
// something like: this.fireEvent('mouseenter', this); would be cool!
});
}
});
Just get to your jQuery Element and then call the fireEvent from the Element.prototype
// does not work:
(function($$) {
$$(this).fireEvent('mouseenter', $(this));
})(document.id);
to:
$(this)[0].fireEvent('mouseenter' /* optional event obj, { target: $(this)[0] } */);
// or as #Sergio suggests -
this.fireEvent('mouseenter'); // this == element anyway
Related
So I have a regular onclick event attached to a few buttons, each function that handles the onclick event does something different (so I can't reuse the same function for both events).
element1.onclick = function() {
if(this.classList.contains('disabled') {
return false;
}
// For example make an AJAX call
};
element2.onclick = function() {
if(this.classList.contains('disabled') {
return false;
}
// For example hide a div
};
I'm writing duplicate code for this 'disabled' class check, I want to eliminate this by hooking in some common onclick check then fire the regular onclick event if that check passes.
I know the below won't work but I think it will illustrate what I'm trying to do:
document.addEventListener('click', function() {
// 1. Do the disabled check here
// 2. If the check passes delegate the event to the proper element it was invoked on
// 3. Otherwise kill the event here
});
I'm not using any JavaScript library and I don't plan to, in case someone comes up with 'Just use jQuery' type answers.
EDIT: Had to pass boolean third argument to addEventListener as true and everything is fine.
Use event capturing, like so:
document.addEventListener('click', function(event) {
if (/* your disabled check here */) {
// Kill the event
event.preventDefault();
event.stopPropagation();
}
// Doing nothing in this method lets the event proceed as normal
},
true // Enable event capturing!
);
Sounds like you need to set the capture flag to true and then use .stopPropagation() on the event if a certain condition is met at the target, f.ex:
document.addEventListener('click', function(e) {
if ( condition ) {
e.stopPropagation();
// do soemthing else, the default onclick will never happen
}
}, true);
Here is a demo: http://jsfiddle.net/v9TEj/
You can create a generic function that receives a callback:
//check everything here
function handleOnclick(callback) {
if(this.classList.contains("disabled")) {
return false;
} else {
callback(); //callback here
}
}
//and now on every onclick, just pass the custom behavior
element1.onclick = function() {
handleOnClick(function() {
console.log('element1 onclick fire'); // For example hide a div
});
};
element2.onclick = function() {
handleOnClick(function() {
console.log('element2 onclick fire'); // For example ajax request
});
};
Edit
Based on your latest comment, let me know if this rewrite works for you... only one biding this time.
element1.customFunction = function() {
handleOnClick(function() {
console.log('element1 onclick fire'); // For example hide a div
});
};
element2.customFunction = function() {
handleOnClick(function() {
console.log('element2 onclick fire'); // For example ajax request
});
};
document.addEventListener('click', function() {
//1. grab the element
//2. check if it has the customFunction defined
//3. if it does, call it, the check will be done inside
};
I need to get the newly focussed element (if any) while executing an onBlur handler.
How can I do this?
I can think of some awful solutions, but nothing which doesn't involve setTimeout.
Reference it with:
document.activeElement
Unfortunately the new element isn't focused as the blur event happens, so this will report body. So you are gonna have to hack it with flags and focus event, or use setTimeout.
$("input").blur(function() {
setTimeout(function() {
console.log(document.activeElement);
}, 1);
});
Works fine.
Without setTimeout, you can use this:
http://jsfiddle.net/RKtdm/
(function() {
var blurred = false,
testIs = $([document.body, document, document.documentElement]);
//Don't customize this, especially "focusIN" should NOT be changed to "focus"
$(document).on("focusin", function() {
if (blurred) {
var elem = document.activeElement;
blurred = false;
if (!$(elem).is(testIs)) {
doSomethingWith(elem); //If we reached here, then we have what you need.
}
}
});
//This is customizable to an extent, set your selectors up here and set blurred = true in the function
$("input").blur(function() {
blurred = true;
});
})();
//Your custom handler
function doSomethingWith(elem) {
console.log(elem);
}
Why not using focusout event? https://developer.mozilla.org/en-US/docs/Web/Events/focusout
relatedTarget property will give you the element that is receiving the focus.
Here's a fiddle illustrating the problem. I am adding a jQuery one binding on the click of one element to the 'html' element. I am not expecting the 'one' event handler to fire until the next click, but it fires on the click that adds the binding. This seems to not be a problem if it is a more specific element that the 'one' event handler is added to, but it happens when I use 'html' or 'body' as the element, which is what I want to do.
This doesn't make sense to me, I'd think the first click would add the one for the next click and it wouldn't fire on the click on the link.
By the way, my actual problem could probably be solved in a better way, but I came across this and was curious why it didn't work as I expected.
Code:
html:
<div id='hello'>hello</div>
<a class="title" href="#">this example</a> is a test
js:
$(function() {
$('a.title').click(function() {
var htmlClickBind = function (e) {
console.log('clicked on html, e.target = ' + e.target);
console.log(e.target == '');
if (!$(e.target).is('a') ) {
console.log('cleared click event');
}
else {
$('html').one('click', htmlClickBind);
}
};
$('html').one('click', htmlClickBind);
});
});
The click event on the a.target element bubbles up to the html element, where your (just-added) handler sees it.
To prevent this, use event.stopPropgation in your a.target click handler (or return false, which does stopPropagation and preventDefault).
Updated code (see the comments): Live copy
$(function() {
// Accept the event arg ----v
$('a.title').click(function(e) {
// Stop propagation
e.stopPropagation();
var htmlClickBind = function (e) {
console.log('clicked on html, e.target = ' + e.target);
console.log(e.target == '');
if (!$(e.target).is('a') ) {
console.log('cleared click event');
}
else {
$('html').one('click', htmlClickBind);
}
};
$('html').one('click', htmlClickBind);
});
});
I want to show a menu after a click, drag, and release action.
How do I trigger that with jQuery?
Listen for a mousedown event on whatever should be clicked on.
Add a mousemove and mouseup event handler to the window
In the mouseup event handler call trigger('yourcustomeventhere') on whatever element you please. Also, remove the mouseup and mousemove event handlers from window
...?
profit.
jQuery is the library that will do this for you. I thought I explained the code well enough, but apparantly not:
$(anElement).mousedown(foodown);
function foodown(){
$(window).mousemove(foomove).mouseup(fooup);
//stuff
}
function foomove(){
//stuff
}
function fooup(){
$(someElement).trigger('yourcustomevent');
$(window).unbind('mousemove', foomove).unbind('mouseup', fooup);
}
/**
* Dragondrop jQuery plugin by zzzzBov
*/
(function ($) {
"use strict";
var $window;
function begin(e) {
var event;
$window.mousemove(drag).mouseup(end);
event = $.Event('beginDragon');
$(e.target).trigger(event);
if (event.isDefaultPrevented()) {
e.preventDefault();
}
}
function drag(e) {
var event;
event = $.Event('dragDragon');
$(e.target).trigger(event);
if (event.isDefaultPrevented()) {
e.preventDefault();
}
}
function end(e) {
var event;
event = $.Event('endDragon');
$(e.target).trigger(event);
$window.unbind('mousemove', drag).unbind('mouseup', end);
if (event.isDefaultPrevented()) {
e.preventDefault();
}
}
$.each('beginDragon dragDragon endDragon'.split(' '), function (i, name) {
$.fn[name] = function(data,fn) {
if (fn == null) {
fn = data;
data = null;
}
return arguments.length > 0 ?
this.bind(name, data, fn) :
this.trigger(name);
};
});
$window = $(window);
$window.mousedown(begin);
}(jQuery));
You could use the jQueryUI and let it do a lot for you. It also comes with a create UI (of course, because it's jQuery UI)
Take a look at this: http://jqueryui.com/demos/droppable/
edit:
Or take a look here: http://jqueryui.com/demos/draggable/
Take a close look to the events used here.
jQuery UI has a drag and drop implementation. If that doesn't do what you do, you'll have to roll your own implementation by tracking the mouseup and mousedown events on the element yourself. (And possibly mouseleave to detect if the mouse left the area you want to track the gesture in.)
I have an anchor tag on my page, I want an event attached to it, which will fire when the display of this element change.
How can I write this event, and catch whenever the display of this element changes?
This is my way of doing on onShow, as a jQuery plugin. It may or may not perform exactly what you are doing, however.
(function($){
$.fn.extend({
onShow: function(callback, unbind){
return this.each(function(){
var _this = this;
var bindopt = (unbind==undefined)?true:unbind;
if($.isFunction(callback)){
if($(_this).is(':hidden')){
var checkVis = function(){
if($(_this).is(':visible')){
callback.call(_this);
if(bindopt){
$('body').unbind('click keyup keydown', checkVis);
}
}
}
$('body').bind('click keyup keydown', checkVis);
}
else{
callback.call(_this);
}
}
});
}
});
})(jQuery);
You can call this inside the $(document).ready() function and use a callback to fire when the element is shown, as so.
$(document).ready(function(){
$('#myelement').onShow(function(){
alert('this element is now shown');
});
});
It works by binding a click, keyup, and keydown event to the body to check if the element is shown, because these events are most likely to cause an element to be shown and are very frequently performed by the user. This may not be extremely elegant but gets the job done. Also, once the element is shown, these events are unbinded from the body as to not keep firing and slowing down performance.
You can't get an onshow event directly in JavaScript. Do remember that the following methods are non-standard.
IN IE you can use
onpropertychange event
Fires after the property of an element
changes
and for Mozilla
you can use
watch
Watches for a property to be assigned
a value and runs a function when that
occurs.
You could also override jQuery's default show method:
var orgShow = $.fn.show;
$.fn.show = function()
{
$(this).trigger( 'myOnShowEvent' );
orgShow.apply( this, arguments );
return this;
}
Now just bind your code to the event:
$('#foo').bind( "myOnShowEvent", function()
{
console.log( "SHOWN!" )
});
The code from this link worked for me: http://viralpatel.net/blogs/jquery-trigger-custom-event-show-hide-element/
(function ($) {
$.each(['show', 'hide'], function (i, ev) {
var el = $.fn[ev];
$.fn[ev] = function () {
this.trigger(ev);
return el.apply(this, arguments);
};
});
})(jQuery);
$('#foo').on('show', function() {
console.log('#foo is now visible');
});
$('#foo').on('hide', function() {
console.log('#foo is hidden');
});
However the callback function gets called first and then the element is shown/hidden. So if you have some operation related to the same selector and it needs to be done after being shown or hidden, the temporary fix is to add a timeout for few milliseconds.