How do i prevent the parent click event from firing if the child div is clicked?
http://jsfiddle.net/2GEKu/
var p = document.getElementById('parent');
var c = document.getElementById('child');
p.onclick = function () {
alert('parent click');
}
c.onclick = function () {
alert('child click');
}
Invoke the .stopPropagation() method of the event object in the child's handler.
var p = document.getElementById('parent');
var c = document.getElementById('child');
p.onclick = function () {
alert('parent click');
}
c.onclick = function (event) {
event.stopPropagation();
alert('child click');
}
To make it compatible with IE8 and lower, do this:
c.onclick = function (event) {
if (event)
event.stopPropagation();
else
window.event.cancelBubble = true;
alert('child click');
}
Related
I have a modal object that has various functions as its properties, but when I click to open a modal I'm getting the error this.openModal is not a function. I've tried debugging but it just falls over as soon as it hits the function I want it to run. I suspect it might be an issue with the 'this' binding, but I'm not sure where the problem is. All my JS is below, one function kind of chains onto another so it's easier to see the whole object.
var modal = function () {
// Modal Close Listeners
this.closeModalListen = function(button) {
var modalFooter = button.parentElement;
var modalContent = modalFooter.parentElement;
var modalElement = modalContent.parentElement;
var backdrop = document.getElementById("modal-backdrop");
this.closeModal(modalElement, backdrop);
}
// Open Modal
this.openModal = function(button) {
var button = button;
var modal = button.getAttribute("data-modal");
var modalElement = document.getElementById(modal);
var backdrop = document.createElement('div');
backdrop.id="modal-backdrop";
backdrop.classList.add("modal-backdrop");
document.body.appendChild(backdrop);
var backdrop = document.getElementById("modal-backdrop");
backdrop.className += " modal-open";
modalElement.className += " modal-open";
}
// Close Modal
this.closeModal = function(modalElement, backdrop) {
modalElement.className = modalElement.className.replace(/\bmodal-open\b/, '');
backdrop.className = backdrop.className.replace(/\bmodal-open\b/, '');
}
// Initialise Function
this.init = function () {
// Create Events for creating the modals
if (document.addEventListener) {
document.addEventListener("click", this.handleClick, false);
}
else if (document.attachEvent) {
document.attachEvent("onclick", this.handleClick);
}
}
// Handle Button Click
this.handleClick = function(event) {
var thisModal = this;
event = event || window.event;
event.target = event.target || event.srcElement;
var element = event.target;
while (element) {
if (element.nodeName === "BUTTON" && /akela/.test(element.className)) {
thisModal.openModal(element);
break;
} else if (element.nodeName === "BUTTON" && /close/.test(element.className)) {
thisModal.closeModalListen(element);
break;
} else if (element.nodeName === "DIV" && /close/.test(element.className)) {
thisModal.closeModalListen(element);
break;
}
element = element.parentNode;
}
}
}
// Initalise Modal Engine
var akelaModel = new modal();
akelaModel.init();
I'm looking to fix this with pure js and no jquery.
You need to bind the function to the object before giving it as a event listener:
document.addEventListener("click", this.handleClick.bind(this), false);
document.attachEvent("onclick", this.handleClick.bind(this));
Otherwise it becomes detached from its original object and doesn't have the expected this.
As an alternative to using bind, you can move:
var thisModal = this;
from the handleClick method to the constructor.
Also, it's convention to give constructors names starting with a capital letter so it's easier to see that they're constructors.
var Modal = function () {
var thisModal = this;
// Open Modal
this.openModal = function(button) {
console.log('openModal called on ' + button.tagName);
}
// Initialise Function
this.init = function () {
// Create Events for creating the modals
if (document.addEventListener) {
document.addEventListener("click", this.handleClick, false);
}
}
// Handle Button Click
this.handleClick = function(event) {
thisModal.openModal(event.target);
}
}
// Initalise Modal Engine
var akelaModel = new Modal();
akelaModel.init();
<div>Click <span>anywhere</span></div>
I want to do mouseleave only once after focus triggered. How?
I try several options like off,preventDefault,stopPropagation, return false; but none have worked.
Thank you in advance.
addEvent(date, 'focus', function () {
console.log("focuz" + this.innerHTML);
document.designMode = 'on';
addEvent(swap_date, 'mouseleave', function (e) {
console.log("mouseleave" + this.innerHTML);
//document.designMode = 'on';
$(this).off(e);
e.preventDefault();
e.stopPropagation();
return false;
});
});
fixed in mouseenter event to trigger the check with stop var.
Once mouseleave happends, the stop is on.
addEvent(swap_date, 'mouseenter', function () {
stop = false;
});
addEvent(swap_date, 'focus', function () {
document.designMode = 'on';
if (this.innerHTML != "") {
$(document).ready(function () {
$('.swapDate').bind('mouseleave', function (event) {
if (!stop && this.innerHTML != "")
checkDate(this.innerHTML);
stop = true;
$('.swapDate').unbind('mouseleave');
});
});
}
});
I have a function that is working and looks like this:
var $$ = function(selector, context) {
context = context || document;
var elements = context.querySelectorAll(selector);
return Array.prototype.slice.call(elements);
}
// My function
var myFunction = function() {
$$( '.my-selector' ).forEach( function( element ) {
element.addEventListener('click', function(e){
console.log('Do something');
});
});
}
I would prefer it looks more like jQuery:
// My function
var myFunction = function() {
$('.my-selector').click(function(e) {
console.log('Do something');
});
}
I can't figure out how to do that. Any ideas?
(I want my code to be independent of frameworks so I don't want jQuery)
Solution1: with your own wrapper: Fiddler link
var $$ = function(selector, context) {
context = context || document;
var elements = context.querySelectorAll(selector);
var wrapper = function(elem){
var element = elem;
this.click = function(cb){
element.forEach(function(el){
el.addEventListener('click', function(e){
cb.apply(element,[e]);
});
});
};
};
return new wrapper(Array.prototype.slice.call(elements));
}
$$("#test").click(function(e){
console.log("Do something:"+e.type);
});
Solution 2 directly binding to native element: Fiddler link
var $$ = function(selector, context) {
context = context || document;
var elements = Array.prototype.slice.call(context.querySelectorAll(selector));
elements.click = function(cb){
elements.forEach(function(el){
el.addEventListener('click', function(e){
cb.apply(elements,[e]);
});
});
};
return elements;
}
$$("#test").click(function(e){
console.log("Do something:"+e.type);
});
Please check it. Here is the Fiddle: http://jsfiddle.net/4467yz37/
When I do click in the Link it works good (Show and Hide). The only problem existing it's when I want to hide the Items section doing click outside the Link and the Items (that is in the Body except in the Items section).
Here is the JavaScript code:
(function(document) {
var alterNav = function() {
var item = document.querySelector('.items');
var link = document.querySelector('.clickme');
var theClass = 'display';
var itemIsOpened = false;
if (link) {
link.addEventListener('click', function (event) {
event.preventDefault();
if (!itemIsOpened) {
itemIsOpened = true;
addClass(item, theClass);
} else {
itemIsOpened = false;
removeClass(item, theClass);
}
});
}
};
var addClass = function (element, className) {
if (!element) {
return;
}
element.className = element.className.replace(/\s+$/gi, '') + ' ' + className;
};
var removeClass = function(element, className) {
if (!element) {
return;
}
element.className = element.className.replace(className, '');
};
alterNav();
})(document);
I try to solve it creating another variable with the tag Html or Body and alter the JS code, but it still don't working good: http://jsfiddle.net/g1d321rv/2/
var link = document.querySelector('body');
I manipulated your code a bit. Do you use jquery? I assumend that you are not using jquery.Here jsfiddle :
http://jsfiddle.net/9fpf07mt/
window.onclick = function (e) {
console.log(e);
if (!itemIsOpened) {
if (e.target == link) {
itemIsOpened = true;
addClass(item, theClass);
}
} else {
if (!isChild(e.target, item)) {
itemIsOpened = false;
removeClass(item, theClass);
}
}
};
edit for last request:
link.addEventListener('click', function (event) {
event.preventDefault();
});
Im trying to use hover with .on(), but all bits of code and answers i find do not work.
I need to use .on because its Ajax content.
A few ive tried:
$(document).on('mouseenter', '[rel=popup]', function() {
mouseMove = true;
width = 415;
$('#tool-tip').show();
var type = $(this).attr('data-type'),
id = $(this).attr('data-skillid');
console.log("TT-open");
ttAjax(type, id);
}).on('mouseleave', '[rel=popup]', function() {
mouseMove = false;
console.log("TT-close");
$('#tool-tip').hide();
$('#tt-cont').html("");
$('#tt-ajax').show();
});
$('[rel=popup]').on('hover',function(e) {
if(e.type == "mouseenter") {
mouseMove = true;
width = 415;
$('#tool-tip').show();
var type = $(this).attr('data-type'),
id = $(this).attr('data-skillid');
console.log("TT-open");
ttAjax(type, id);
}
else if (e.type == "mouseleave") {
mouseMove = false;
console.log("TT-close");
$('#tool-tip').hide();
$('#tt-cont').html("");
$('#tt-ajax').show();
}
});
$('[rel=popup]').on("hover", function(e) {
if (e.type === "mouseenter") { console.log("enter"); }
else if (e.type === "mouseleave") { console.log("leave"); }
});
$(document).on({
mouseenter: function () {
console.log("on");
},
mouseleave: function () {
console.log("off");
}
}, "[rel=popup]"); //pass the element as an argument to .on
The original non .on:
$('[rel=popup]').hover(function(){
mouseMove = true;
width = 415;
$('#tool-tip').show();
var type = $(this).attr('data-type'),
id = $(this).attr('data-skillid');
console.log("TT-open");
ttAjax(type, id);
},function () {
mouseMove = false;
console.log("TT-close");
$('#tool-tip').hide();
$('#tt-cont').html("");
$('#tt-ajax').show();
})
All the .on return "TypeError: $(...).on is not a function". I am using version 1.9.1.
The events you're looking for may be
$("#id").mouseover(function(){});
or
$("#id").mouseout(function(){});
There was an answer with:
$(document).on({
mouseenter: function () {
console.log("on");
},
mouseleave: function () {
console.log("off");
}
},"[rel=popup]");
This worked, and for some reason I have JQ 1.4 in a 1.9.1 named file that was causing the problem.