Adding click event handlers recursively - javascript

I have an element #standardBox
#standardBox.click --> replaces itself with #newBox
#newBox.click --> replaces itself with #standardBox
But this latest #standardBox has no click event listener. I want it to have an on click event listener and its subsequently created elements too. This is getting into a recursive loop, which I don't know how to address.
I'm using this for header with standard contents, which gets replaced by something intermediate/new contents, which again is to get back to standard contents ...
Thanks.
HTML
<div id="container">
<div id="standardBox"></div>
</div>
CSS
html, body {
margin: 0;
padding: 0;
height: 100%;
}
#container {
position: relative;
height: 5em;
width: 5em;
background: #C5CAE9;
}
#standardBox {
position: absolute;
top: 20%;
right: 20%;
bottom: 20%;
left: 20%;
background: #ffffff;
cursor: pointer;
}
#newBox {
height: 3em;
width: 3em;
background: #000000;
cursor: pointer;
}
JAVASCRIPT
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
$('#standardBox').click(function(){
$('#container').html('<div id="newBox"></div>');
// register event handler for new element created
$('#newBox').click(function(){
$('#container').html('<div id="standardBox"></div>');
// but this #standardBox has no click event listener
});
});
http://codepen.io/anon/pen/YPLKLq

Attach the handler to the body instead like this:
$("body").on("click", "#standardBox", function(){
$('#container').html('<div id="newBox"></div>');
})
.on("click", "#newBox", function(){
$('#container').html('<div id="standardBox"></div>');
});
This causes the body to listen for events that come from #standardBox and #newBox. Note that the this variable is still set to either the #standardBox or the #newBox element.

use below code. dynamically created element dose not fire event using 'click' function. you need to Attach the handler to the document( body )
$(document).on('click','#standardBox',function(){
$('#container').html('<div id="newBox"></div>');
// register event handler for new element created
});
$(document).on('click','#newBox',function(){
$('#container').html('<div id="standardBox"></div>');
// but this #standardBox has no click event listener
});

Why you are writing such complex code to do it. As there can be a very simple code.
Lets say this your html.
<div id="container">
<div id="standardBox"></div>
</div>
Now, to change the inner container.
$(function(){
$('#container div').click(function(){
$(this).attr("id")=="standardBox"?$(this).attr("id","newBox"):$(this).attr("id","standardBox");
});
});

Related

Add event listener to ::after with javascript [duplicate]

I have a div element with a CSS pseudo-element ::before used as a close button (instead of using an actual button). How do I apply an event listener to only the pseudo-element?
HTML
<div id="box"></div>
CSS
#box:before
{
background-image: url(close.png);
content: '';
display: block;
height: 20px;
position: absolute;
top: -10px;
right: -10px;
width: 20px;
}
#box
{
height: 100px;
width: 100px;
}
Was looking for a solution and found this thread. Now want to share my workaround:
CSS
element { pointer-events: none; }
element::after { pointer-events: all; }
JS
element.addEventListener('click', function() { ... });
This works if you don't need any pointer events on element. Check it in action.
No. The pseudo-element does not exist in the DOM so it has no HTMLElementNode object representing it.
There is no :before and :after selector in jQuery. However as an alternative, you can check the location of the click event and check if it is on your pseudo-element:
(I haven't tested this)
style:
#mything {
width: 100px;
height: 100px;
position: relative;
background: blue;
}
#mything:after {
content: "x";
font-size: 10px;
position: absolute;
top: 0;
right: 0;
background: red;
width: 10px;
height: 10px;
}
javascript:
$('#mything').click(function(e) {
if (e.clientX > $(this).offset().left + 90 &&
e.clientY < $(this).offset().top + 10) {
// do something
}
});
html:
<div id="mything">Foo</div>
If the position and dimensions of the generated content are known, you can add a click handler on the element itself and check the relative mouse position before handling it.
This is perverse, but possible.
Generally speaking no as indicated by others. But in case your tag with pseudo-element is empty, such as glyphicon in bootstrap.
You can wrap a div or span or whatever tag suitable in your case. Glyphicons in bootstrap uses :before but on the page you can see that it has hover event caught.
Example:
<span>
<span class="glyphicon glyphicon-asterisk" aria-hidden="true"></span>
</span>
Suppose you want to add event to the above glyphicon, you can use jquery parent selector
$('glyphicon').parent('span').click(function() {
// awesome things
});
Just a small trick in case your tag is empty.

JQmodal with on focus not working

I am loading a JQmodal with an ajax call with some basic input elements like a, input, label and button. I need to add a custom class for the elements on focus after immediately opening the modal
Note: Please use tab key to focus each elements
HTML
<p>HTML Images is a link to a page on this website.</p>
<p>W3C is a link to a website on the World Wide Web.</p>
view
...
<div class="jqmWindow" id="dialog">
</div>
CSS:
.jqmWindow {
display: none;
position: fixed;
top: 17%;
left: 50%;
margin-left: -300px;
width: 600px;
background-color: #EEE;
color: #333;
border: 1px solid black;
padding: 12px;
}
.jqmOverlay { background-color: #000; }
/* Fixed posistioning emulation for IE6
Star selector used to hide definition from browsers other than IE6
For valid CSS, use a conditional include instead */
* html .jqmWindow {
position: absolute;
top: expression((document.documentElement.scrollTop || document.body.scrollTop) + Math.round(17 * (document.documentElement.offsetHeight || document.body.clientHeight) / 100) + 'px');
}
*.focused
{
outline-width: 2px ;
outline-color: #282828;
outline-style: dotted;
}
Java Script
$(document).ready(function() {
$('#dialog').jqm({ajax: 'https://raw.githubusercontent.com/jothikannan89/jqModal/ed840123588cf99ebe061e749e9774e64387ba7f/examples/ajax_tab.html'});
});
$("a,input,button,select,textarea,.jqmClose").on('focus',
function(event) {
event.preventDefault();
$(this).addClass('focused');
});
$("a,input,button,select,textarea,.jqmClose").on('blur',
function(event) {
event.preventDefault() ;
$(this).removeClass('focused');
});
What I am getting is weird, focus class is adding for the parent page element but doesn't add to the elements loaded through ajax to the Modal but default focus is working
Fiddle example: Fiddle
When you do:
$("a,input,button,select,textarea,.jqmClose").on('focus',
function(event) {
event.preventDefault();
$(this).addClass('focused');
});
your dynamic content is not loaded in the DOM yet (that's why you have the expected behavior on the main page, but not in the modal content). You must wait for the return of your ajax request to attach event handlers.
I don't know how JQM works, but it must give you a promise or a way to pass some callbacks.
EDIT:
From the JQM documentation, there is an onload callback:
onLoad (callback) Called right after ajax content is loaded.
// onLoad : assign Mike Alsup's most excellent ajaxForm plugin to the returned form element(s).
var myLoad = function(hash){ $('form',hash.w).ajaxForm(); };
$('#dialog').jqm({onLoad:myLoad});
Use it to attach your handlers in the onLoad function and it will do the trick.

Using addClass to show an interval

I'm attempting to show an interval within a bar. Initially I was using the jQuery plugin for range, but it did not work like I wanted.
I have several different bulleted pointed within my bar. Whenever someone clicks within or near the point (in the class sliderInterval) I want the class rangeSection to be added to that area, basically showing that certain interval active. However, the rangeSection doesn't even show up, nor I am certain I am doing this correctly.
In addition, since I am doing this with intervals. I want to be able to give those intervals values, so that when one is selected I can display that value.
This is what I am trying to get it to look like:
I added a snippet to show what I have done so far. Any advise?
$(function interval() {
$(".slideInterval").click(function() {
$(this).addClass(".rangeSection");
});
});
#sliderBar {
border-radius: 15px;
width: 90%;
height: auto;
margin: 25px 10%;
background: blue;
}
.rangeSection {
width: 100px;
height: 100%;
color: purple;
position: absolute;
z-index: 1;
}
.intervalCircle {
border-radius: 50%;
height: 15px;
width: 15px;
background: red;
z-index: 1;
position: absolute;
}
.sliderInterval {
display: inline-block;
padding: 10px 8%;
}
.sliderInterval:first-child {
padding-left: 0;
}
.intervalCircle:first-child {
padding-left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="sliderBar">
<div class="rangeSection"></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle" ></span></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle" ></span></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle"></span></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle"></span></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle"></span></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle"></span></div>
</div>
try this one.
You can use the .ready(); function of the jQuery library and set the .click() listener on all the .sliderInterval elements. I added the active class as well.
try it here:
https://jsfiddle.net/8cxLLts1/
$(document).ready(function(){
$(".sliderInterval").click(function() {
$(this).addClass("active");
});
});
EDIT: actually, if you use toggleClass() instead of addClass(), you'll be able to turn on and off a specific section
Using onclick in your html attribute and then binding a click event also in js could be considered redundant and unnecessary. Try removing the onclick attribute from your html and then adjust your js like so:
$(document).ready(function(){
})
.on('click', '.sliderInterval', function(){
$(this).addClass(".rangeSection");
});
Bind it to the document itself and this will help with your event delegation naturally. Also, take care to double check your class names - your js is missing the 'r' in '.sliderInterval'.

jquery does not detect click on child element

I have created a div element which is supposed to be a contact list. It should contain other divs in it.
What I'm trying to do, is attach a click handler on each list item (on each inner div).
But the click handler is never triggered.
$(".contact").on("click", function() {
alert("clicked");
});
.contacts {
position: absolute;
top: 10px;
left: 300px;
width: 100px;
height: 250px;
border-color: black;
border-style: solid;
z-index: 1;
overflow: scroll;
}
.contact {
position: relative;
width: 80%;
height: 20%;
border-style: solid;
border-color: red;
z-index: 100;
}
<div id="contactList" class="contacts">
<div id="1" class="contact">one</div>
<div id="2" class="contact">two</div>
<div id="3" class="contact">three</div>
</div>
If I attach a click handler for the parent DOM object, it gets triggered. Am I missing something here?
EDIT:
silly of me, i forgot to mention that children are added this way:
$(".contacts").append($("<div id='"+id+"' class=contact >"+d[contact].name+"</div>"));
where "d" and "id" variables come from a successful server call.
you have
$(".contact").on("click",function(){
instead of
$(".contacts").on("click",function(){
do you have this on trigger in the document is loaded event?
it won't work otherwise
$(function(){
$(".contact").on("click",function(){
alert("clicked");
});
});
Edit:
Since the OP forgot to mention something critical, here is my answer to that.
There are no ' around the classname. This should work:
$(".contacts").append($("<div id='"+id+"' class='contact' >"+d[contact].name+"</div>"));
Edit 2
You could also use the children() method:
$(function(){
$(".contacts").children("div").on("click",function(){
alert("clicked");
});
});
A slightly better way of putting this event on is in a document ready function that gets loaded with the page combined with using the .click jquery function. This is short hand for .on("click", FUNCTION).
Example:
$(document).ready(function(){
$(".contact").click(function(){
alert("clicked");
});
});

Is this possible to force execution of .click() for all elements, even those that are underneath?

Consider this code:
HTML:
<div class='a'>a</div>
<div class='b'>b</div>
<div id='log'></div>
CSS:
.a, .b {
width: 100px;
height: 100px;
border: 1px solid black;
position: absolute;
text-align: right;
}
.a {
left: 100px;
top: 100px;
}
.b {
left: 150px;
top: 150px;
}
JS:
$('*').click(function(e) {
log(this.nodeName + ' ' + this.className);
});
function log(s) {
$('#log').append(s + '<br />');
}
If the intersection is clicked, .click() for .a is not called.
Is there any built-in method to force the execution of click() for all elements, and not only the top one and its parents, or I must implement this myself ?
I think that the behavior you are observing is correct. When clicking the topmost element the one beneath won't get a click event despite it looks it is in the "clicked" area. As a workaround you can manually trigger it's click event:
$('.a').click().
Calling click without arguments is equivalent to trigger('click') which raises the specified event. You can find more info in the trigger help topic.

Categories