$("input").on("keypress",function(e){
if(e.which===13){
$("ul").last().append("<li>"+$(this).val()+"</li>");
}
$("li").on("click",function(){
$(this).toggleClass("striked");
});
$("li").on("mouseenter",function(){
$(this).css("color","green");
});
});
$("li").on("click",function(){
$(this).toggleClass("striked");
});
$("li").on("mouseenter",function(){
$(this).css("color","green");
});
$("#slide").on("click",function(){
$("input").slideToggle();
});
Here, I have used the onClick event on<li> to apply the striked class two times just to make it work for both dynamic and non-dynamic elements on the page. But the code is replicated and seems long. Is there any way to shorten so that I can write it once and it gets activated for both types of elements?
Use event delegation instead, on the ul, so you only have to set up listeners once, rather than setting up multiple listeners for every element on load and on each .append. Also, save the ul and the input jQuery-wrapped elements in a variable once rather than selecting them and wrapping them with jQuery each time they're used:
const $ul = $("ul");
const $input = $("input");
$input.on("keypress", function(e) {
if (e.which === 13) {
$ul.last().append("<li>" + $(this).val() + "</li>");
}
});
$ul.on("click", 'li', function() {
$(this).toggleClass("striked");
});
$ul.on("mouseenter", 'li', function() {
$(this).css("color", "green");
});
$("#slide").on("click", function() {
$input.slideToggle();
});
A rather generic approach would be to capture the click event and check if it is from ul
document.body.onclick = function(e){
e = e || event;
var from = findParent('ul',e.target || e.srcElement);
if (from){
/* it's a link, actions here */
}
}
//find first parent with tagName [tagname]
function findParent(tagname,el){
while (el){
if ((el.nodeName || el.tagName).toLowerCase()===tagname.toLowerCase()){
return el;
}
el = el.parentNode;
}
return null;
}
now you can change the tagName passed to the findParent function and do accordingly
Read Here
You can try using the jquery all selector $('*'). For more information on this see
https://api.jquery.com/all-selector/.
Or you can add a specific class to every element you want to have an onClick action.
Related
I have the following code:
$("#content h1").on("click", function(){
var f = $(this);
var clicked_id = f.data("id");
var children = _.filter(data, function(key){
var id = key.id.split("-")
id.pop()
id = id.join("-")
return clicked_id == id;
});
if (children.length != 0) {
$("#content").html("");
_.each(children, function(obj){
$("#content").append("<h1 data-id='"+ obj.id +"'>"+ obj.txt +"</h1>")
});
}
});
So basicly Im binding a .on "click" event to h1. On the click I clean the element containing the H1 then I add a new H1 element. Now the click does not register anymore. How should I actually be doing this so I can keep clicking?
Use on like so (event delegation):
$("#content").on("click", "h1", function() {
Now, each time you click #content, it'll check for an h1 and run the event. Your previous code only bound the handler to the h1 at runtime.
Maybe you could bind this way?
$(document).on("click", "#content h1", function(){
...
});
I have some dynamically generated elements with the class my-class on which I want to bind some events. I have the below code which works properly.
$(document).on("event1", ".my-class", function () {
alert("Event 1");
});
$(document).on("event2", ".my-class", function () {
alert("Event 2");
});
I want to refactor it so that there can be a single call to on for the category. Something like this
$(document).on(".my-class", {
"event1": function() {alert("Event1")},
"event2": function() {alert("Event2")}
});
Is this possible in jquery?
There might be a better way, but I've used this before and it worked for me:
Demo Fiddle
I wouldn't delegate off the document, instead I'd use the closest parent container.
JS:
$('body').on('click mouseenter', 'div', function(e) {
if (e.type === 'click') {
$('div').html('clicked');
}
else { //you'd need an else if here if you had more than two event types
$('div').html('mouse enter');
}
});
I'm writing a simple jQuery plugin that will dynamically place a div under a text box whenever it has focus. I've been able to get the position just about right in all the browsers.
I have to attach two event handlers as well on the focus and blur events of the textbox. And it works okay, but the problem is that the div that has been placed under the textbox closes even when we click on it. Now it makes sense why it would so happen, it's because the textbox loses focus, but is there a way I can stop it from happening?
I tried attaching this to the blur event handler -
if($(mainElem).is(":focus")) return;
where mainElem is the div that is shown below the textbox.
Here is a jsFiddle to illustrate the problem.
You are not going to be able to use the blur event if you want to place "clickable" elements in the div that shows. One way to solve this is to bind your event listener to a more global element like the document and then filter out the targets.
Here is a code sample:
$(document).on('click', function (e) {
var targetEl = e.target,
parent = $(e.target).parents()[0];
if (relElem[0] === targetEl || self[0] === targetEl || self[0] === parent) {
$(mainElem).show();
} else {
$(mainElem).hide();
}
});
Here is an update to your fiddle: http://jsfiddle.net/9YHKW/6/
This is a fiddle that I threw together for a project a while back: http://jsfiddle.net/MYcZx/4/
While it is not based off of your fiddle (and I do apologize) I believe that the functionality is much the same as what you're looking for. My example does not include input fields, but rather spans that hold the values. And while I'm not managing focus/blur, you could add a tabIndex attribute to the spans and then add a trigger on focus that would open the menu.
var $sub = $('.subscription');
$sub
.on('click', '.remove', function() {
$(this).parent().remove();
})
.on('click', 'li', function(e) {
var $this = $(this),
$parent = $this.parent(),
$options = $parent.children('li'),
$value = $parent.siblings('.value'),
isMulti = $parent.hasClass('multi'),
values = [];
if(!isMulti) {
$options.removeClass('active');
}
$this.toggleClass('active');
$options.filter('.active').each(function() {
values.push($(this).text());
});
$value.text(values.join(', ') || 'select');
$value[(values.length ? 'add' : 'remove') + 'Class']('set');
});
var $clone = $sub.clone(true);
$('.new')
.on('click', function() {
$(this).before($clone.clone(true));
});
Is it possible to have an alert pop up when any element on the page is clicked that tells you the tag name (or id or whatever other information) about that element?
I basically want to set up the following for every element:
$('#wrapper').click(function() {
alert($(this).prop('tagName'));
})
Except I don't want to write that code for every single element on the page as that would take forever and would be extremely impractical in every way.
Bind your listener on a global object with a selector.
$(document).on('click', '*', function() {
alert($(this).prop('tagName'));
});
should work.
document.body.addEventListener("click", function (e) {
e = e || window.event;
alert(e.toElement.getAttribute("id"));
});
How about this
$(document).on('click', '*', function() {
// Set clicked element's id to variable
var elementName = $(this).attr('id');
// Alert displaying id of clicked element
alert(elementName);
})
Here is an pure javascript method:
document.onclick = function(e) {
e = e || window.event;
var o = e.srcElement||e.target;
alert(o.id);
}
I am trying to figure out how to bind an event to dynamically created elements. I need the event to persist on the element even after it is destroyed and regenerated.
Obviously with jQuery's live function its easy, but what would they look like implemented with native Javascript?
Here's a simple example:
function live(eventType, elementId, cb) {
document.addEventListener(eventType, function (event) {
if (event.target.id === elementId) {
cb.call(event.target, event);
}
});
}
live("click", "test", function (event) {
alert(this.id);
});
The basic idea is that you want to attach an event handler to the document and let the event bubble up the DOM. Then, check the event.target property to see if it matches the desired criteria (in this case, just that the id of the element).
Edit:
#shabunc discovered a pretty big problem with my solution-- events on child elements won't be detected correctly. One way to fix this is to look at ancestor elements to see if any have the specified id:
function live (eventType, elementId, cb) {
document.addEventListener(eventType, function (event) {
var el = event.target
, found;
while (el && !(found = el.id === elementId)) {
el = el.parentElement;
}
if (found) {
cb.call(el, event);
}
});
}
In addition to Andrew's post and Binyamin's comment, maybe this is an option:
With this you can use 'nav .item a' as the selector.
Based on Andrew's code.
function live (eventType, elementQuerySelector, cb) {
document.addEventListener(eventType, function (event) {
var qs = document.querySelectorAll(elementQuerySelector);
if (qs) {
var el = event.target, index = -1;
while (el && ((index = Array.prototype.indexOf.call(qs, el)) === -1)) {
el = el.parentElement;
}
if (index > -1) {
cb.call(el, event);
}
}
});
}
live('click', 'nav .aap a', function(event) { console.log(event); alert('clicked'); });
The other solutions are a little overcomplicated...
document.addEventListener('click', e => {
if (e.target.closest('.element')) {
// .element has been clicked
}
}
There is a polyfill in case you need to support Internet Explorer or old browsers.
An alternative to binding an event to dynamically to a specific element could be a global event listener. So, each time you update the DOM with another new element event on that element will also the "catches". An example:
var mybuttonlist = document.getElementById('mybuttonlist');
mybuttonlist.addEventListener('click', e=>{
if(e.target.nodeName == 'BUTTON'){
switch(e.target.name){
case 'createnewbutton':
mybuttonlist.innerHTML += '<li><button name="createnewbutton">Create new button</button></li>';
break;
}
}
}, false);
ul {
list-style: none;
padding: 0;
margin: 0;
}
<ul id="mybuttonlist">
<li><button name="createnewbutton">Create new button</button></li>
</ul>
In this example I have an event listener on the <ul> for click events. So, an event happens for all child elements. From the simple event handler I created, you can see that it is easy to add more logic, more buttons (with different or repeating names), anchors etc.
Going all in, you could add the eventlistener to document instead of the list element, catching all click events on the page and then handle the click events in the event handler.