traversing in jquery DOM failed? - javascript

I want to remove the inputs when I click the button. Below is my DOM
I tried but didn't work.
$('#changePassword').click(function(){
$(this).find('.modal-body .inputWrap input').remove();
});
I also tried $(this).find('.modal-body .inputWrap input').remove();

The .modal-body element is not an descendant of the #changePassword element, so using $(this).find(...) will not return any element.
Instead model-body is a ancestor of the button, so you can use .closest() to find it then use .find() on that element to find the target input elements
$('#changePassword').click(function () {
$(this).closest('.modal-body').find('.inputWrap input').remove();
});

Inside $('#changePassword').click, this refers to #changePassword, which is a sibling of the .inputWrap you're searching for. You need to navigate sideways in the DOM, not down.
$('#changePassword').click(function () {
$(this).prev('.inputWrap').find('input').remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
<div class="inputWrap">
<input type="text" value="where">
<input type="text" value="who">
</div>
<button id="changePassword">Click!</a>
</div>

Related

getting the value of the button clicked in a group of buttons

html
<div id="group1">
<button>buttonA</button>
<button>buttonB</button>
</div>
javascript
$('#group1').on('click', function(event) {
// get ONLY the value of the button cilcked
});
Is something like this possible without attaching an event to every button in the group?
Add a target selector to the on() and use this or event.currentTarget within the handler function to access the matching element the event occurs on
$('#group1').on('click', 'button', function(event) {
console.log($(this).text())
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="group1">
<button>buttonA</button>
<button>buttonB</button>
</div>

How do I make DOM/event listeners aware of newly appended nodes?

TL;DR:
I use $(..).append(node), but newly added nodes are not considered for inclusion despite them (supposedly) matching jQuery selectors.
Question
I have some code below that uses checkboxes but emulates radio button behavior. In other words, only one checkbox can (validly) be selected at any time. No more than one should be selected.
If you run the example below and click on the first 3 checkboxes, they will behave like radio buttons. Only one will be selected, no matter how many you click.
However, if you Add Point, newly added points will not be considered for the JS even though in theory it should grab them too...
Specifically: You can select the newly added checkbox, and it will be selected in addition to one already selected previously. That is incorrect as only 1 should be selected at any time and all others should be unselected.
What is happening and how can I have newly added nodes be included into jQuery selectors?
$(function() {
//check first box
$("input.duty:first").prop("checked", true);
//clicking unchecked box should check that box
//unchecks all others
$(".duty").on('click', function(event) {
$("input.duty").prop("checked", false);
$(this).prop("checked", true);
});
$("#addCasePoint").on("click", function() {
var newRowIndex = $('#newRowIndex').text();
var template = $('#casePointTemplate').data('template');
template = template.replace(/__index__/g, newRowIndex);
$('#casePointsFieldset').append(template);
$('#newRowIndex').text(++newRowIndex);
return false;
});
//deletes case point
$("#selection").on("click", ".removeCase", function() {
var caseCount = $('#selection .casePointFieldset').length
if (caseCount === 1) return false; //keep at least one row
$(this).closest("fieldset").remove();
return false;
});
});
.casePointFieldset {
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="selection">
<fieldset id="casePointsFieldset">
<legend>Case Points</legend>
<div id="pointFieldset">
<fieldset class="casePointFieldset">
<div>
<label><span>Duty:</span> <input name="point[1]" class="duty" value="1" type="checkbox"></label>
</div>
<button class="removeCase">Remove</button>
</fieldset>
<fieldset class="casePointFieldset">
<div>
<label><span>Duty:</span> <input name="point[1]" class="duty" value="1" type="checkbox"></label>
</div>
<button class="removeCase">Remove</button>
</fieldset>
<fieldset class="casePointFieldset">
<div>
<label><span>Duty:</span> <input name="point[1]" class="duty" value="1" type="checkbox"></label>
</div>
<button class="removeCase">Remove</button>
</fieldset>
</div>
<!-- include template -->
<span id="casePointTemplate" data-template="<fieldset class="casePointFieldset"><div><label><span>Duty:</span> <input name="point[__index__]" class="duty" value="1" type="checkbox"></label></div><button class="removeCase">Remove</button></fieldset>">
</span>
</fieldset>
<button id="addCasePoint">Add Point</button>
</form>
The problem is how you're binding to them. The .click function (or .on('click')) basically works like this:
Find all of the currently existing elements which match a selector ($('.your.selector.here'))
Attach an event handler to each of those elements
Notice how I mentioned it binds to ones which already exist? That means it won't bind to newly created ones automatically. However, you can use .on to bind to the parent of those elements then listen for events on a selector. I'll show you what I mean:
$('#addItem').click(function() {
$('.container').append('<button class="item">Item</button>');
});
// Notice that I'm binding to the parent
// then specifying which events from it's children
// I want to listen to (click events from .item elements)
$('.container').on('click', '.item', function() {
console.log("I'm an item");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<button class="item">Item</button>
</div>
<button id="addItem">Add New Item</button>
If you change your on('click' to work like that then you'll have no problems.
Easiest way will be, attaching the event to the document. In the past this was done with the live() method.
$(document).on('click', '.duty', function(event) {
$("input.duty").prop("checked", false);
$(this).prop("checked", true);
});

jQuery toggleClass only toggles once

I have a div which i am trying to toggle its class from one to another. I am able to toggle it only once but it will not return to the original class. I looked around for possible answers and looked into the propogation function, however i am unsure this is the correct use?
<body>
<div id="wrapBreather">
<div id="counter" class="cInact">
<!--<canvas id="timerAnimation"></canvas>-->
</div>
</div>
<br />
<button id="startStopCount" class="HomeButton" >Start</button>
<script>
$(startStopCount).click(function(e){
e.stopPropagation();
$('.cInact').toggleClass('cDown cInact');
});
$('html').click(function () {
$('#counter').removeClass('cDown');
});
</script>
</body>
You are getting the element via $('.cInact'). However, when you toggle the class .cInact, you can no longer get that element by $('.cInact') (it doesn't have that class anymore).
You can either do a selection with $('#counter') (getting the ID instead of the class, because you aren't toggling the ID) or assign the element reference to a variable:
var myAwesomeCounter = $('.cInact');
// Then use
myAwesomeCounter.toggleClass('cDown cInact');
Well, you're selecting the class 'cInact' and then toggling it's class.
i.e- removing it.
Wen you're trying to select the element again with the same selector: classname == cInact it's no longer true for that element. so you select nothing, and nothing happens.
To fix this, try using a different selector- e.g- id, like so-
$('#counter').toggleClass('cDown cInact');
The selector $(startStopCount) is wrong. It should be $("#startStopCount")
$('#startStopCount').click(function(e){
e.stopPropagation();
$('.cInact').toggleClass('cDown');
});
$('html').click(function () {
$('#counter').removeClass('cDown');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="wrapBreather">
<div id="counter" class="cInact">
<!--<canvas id="timerAnimation"></canvas>-->
</div>
</div>
<br />
<button id="startStopCount" class="HomeButton" >Start</button>
</body>
$('#startStopCount').click(function(e){
e.stopPropagation();
$('#counter').toggleClass('cDown cInact');
});
$('html').click(function () {
$('#counter').removeClass('cDown');
});
Better perhaps:
$('#startStopCount').click(function(e){
e.stopPropagation();
$('#counter').toggleClass('cDown cInact');
});
$('body').click(function () {
$('#counter').removeClass('cDown');
});

How could i target a div and it's child to handle a click?

I have a <div class="stock"></div>wrapped around :
<div class="stockAdd"></div>
<div class="stockRemove"></div>
<div class="stockInput"></div>
I want to prevent a click inside my .stock to trigger a function. For now i have the following :
if ($(event.target).is('.stockInput') || $(event.target).is('.stockAdd') || $(event.target).is('.stockRemove')) {
console.log("Ajout stock");
return
}
Isn't there a better way to select thos three divs ? The $(event.target).is('.stock') don't get the job done when i click my nested divs.
Thanks
If I understand you correctly, you want to catch click events on .stockAdd, .stockRemove, and .stockInput, but not on other elements within .stock itself, is that correct?
If so, a delegated event can take care of that without any need to manually check the event target:
$('.stock').on('click', '.stockAdd, .stockRemove, .stockInput', function() {
alert("Clicked");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="stock">
<div class="stockAdd">stockAdd</div>
<div class="stockRemove">stockRemove</div>
<div class="stockInput">stockInput</div>
<div>No event</div>
</div>
I would strongly recommend against depending on event.target here; it's too fragile. Any HTML tags nested inside your desired targets would break things:
$('.stock').on('click', function(event) {
if (event.target.className=="stockAll") {
alert("clicked");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="stock">
<div class="stockAll">
This <b> will not work if someone clicks in the bold area</b> but works outside
</div>
</div>
You can add a separate class to all of them like .stock-inner and then grab them all with $('.stock-inner') or you can use a $("div[class^='stock-inner']) - this will grab the parent .stock div...
Also, to reject a click event within the handler you're gunna want to use e.preventDefault() where e is the event object.
the reason it doesn't work well on nested divs is they pass the conditional if in your example, to make it stricter you could add div to selector:
if ($(event.target).is('div.stockInput') || $(event.target).is('div.stockAdd') || $(event.target).is('div.stockRemove'))
You can attach the event on .stock and then filter using the event.target.
HTML
<div class="stock" style="border: 10px solid #000;">
<div class="stockAdd">Add</div>
<div class="stockRemove">Remove</div>
<div class="stockInput">Input</div>
</div>
JavaScript
$('.stock').on('click', function(e) {
if( e.target.className !== 'stock' ) {
console.log(e.target.className);
}
});
jsfiddle

jQuery - How do you select a parent based on the attribute of a child?

How do you select a parent based on the attribute of a child?
I want to select a div:
that has a child with the radio:checked
<div> <input id="1" type="radio"/> </div>
<div> <input id="2" type="radio"/> </div>
for example.
$('div radio:checked').click(function(){
$(*** div parent based on radio:checked ***).css({'background':'#F00'});
});
closest()
$('div radio:checked').click(function(){
$(this).closest('div').css({'background':'#F00'});
});
if you want the nearest 'parent' div, even if it is several levels up.
parent()
$('div radio:checked').click(function(){
$(this).parent('div').css({'background':'#F00'});
});
if you want the direct parent
Interestingly, you can do a sort of reverse lookup selector with :has like
$('div:has(radio:checked)').click(function(){
$(this).css({'background':'#F00'});
});
try:
$('div radio:checked').click(function(){
$(this).parent().css({'background':'#F00'});
});
UPDATE:
the 'div radio:checked' do not work in your code, you can use:
$('div input[type=radio]').click(function () {
$(this).parent().css({'background': '#F00'});
});

Categories

Resources