select div on click with different ids javascript - javascript

I have div question and one for each answer:
<div id="question"></div>
<div id="a"></div>
<div id="b"></div>
<div id="c"></div>
<div id="d"></div>
<div id="e"></div>
when user click in one div I'd to 'select' it adding a css background.
So, I did:
var divA = document.getElementById('a');
divA.addEventListener('click', function () {
remove();
divA.classList.add("select");
},false);
var divB = document.getElementById('b');
divB.addEventListener('click', function () {
remove();
divB.classList.add("select");
},false);
... same thing to C, D and E.
I'd like to not repeat the code for each div select. any ideas how to avoid all this divA, divB, divC, divD, divE functions and add all in one?
my remove function:
function remove(){
document.getElementById('a').classList.remove("select");
document.getElementById('b').classList.remove("select");
document.getElementById('c').classList.remove("select");
document.getElementById('d').classList.remove("select");
document.getElementById('e').classList.remove("select");
}

You need to do the following steps:
Use a same class for each option. Like I user "answer" in below code.
Then use querySelectorAll() to select all the elements in an array.
Loop through array and add event listener to each item.
In the function passed to event listener. First unselect all the elements.
Then select the clicked element.
I have added a little styling from myself.
Note: You can also remove the id from the elements the code will still work.
const answers = document.querySelectorAll('.answer');
answers.forEach(elm => {
elm.addEventListener('click', e =>{
//removing all the previous selections
answers.forEach(x => x.classList.remove('select'))
//selecting the current one
e.target.classList.add('select');
})
})
.answer{
padding:15px;
font-size: 30px;
text-align: center;
background: lightgray;
border-bottom:1px solid black;
font-family: cursive;
}
.select{
background: rgb(245, 245, 245)
}
.answer:hover{
background: rgb(245, 245, 245);
cursor:pointer;
}
<div id="question"></div>
<div class="answer" id="a">A</div>
<div class="answer" id="b">B</div>
<div class="answer" id="c">C</div>
<div class="answer" id="d">D</div>
<div class="answer" id="e">E</div>

Related

How to get last child in a div parent?

I would like to get the last child in of a parent div.
Actually, I'm using this:
var els = '#first,#second,#third';
$(els).each(function () {
$(this).children().last().addClass('memo');
});
It works great for divs with only 1 child, but when the last div is inside a div inside another div, it doesn't work.
var els = '#first,#second,#third';
$(els).each(function() {
$(this).children().last().addClass('memo');
});
.memo {
background-color: red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="first">First text
<div>a</div>
</div>
<div id="second">Second text
<img>b
</div>
<div id="third">Third text
<div>Nested 1
<div>Nested 2
<img>c
</div>
</div>
</div>
How can I refer to the latest child?
Children are different from grandchildren/descendants. $.children only looks at immediate children.
For the behavior you want, you could find all descendants using * and use last() in this scenario, if you are looking for the last descendant in each of #first,#second,#third
It's also important to mention that this gets the last element child, not the last text node. jQuery is not able to deal with text nodes directly. Credits to #T.J. Crowder. See How do I select text nodes with jQuery?
$('#first,#second,#third').each(function () {
$(this).find('*').last().addClass('memo');
});
img.memo {
border: 3px solid red;
padding: 5 px;
}
div.memo {
border: 3px solid blue;
padding: 5 px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="first">
<div>a</div>
</div>
<div id="second">
<img>b
</div>
<div id="third">
<div>
<div>
<img>c
</div>
</div>
</div>
You need remove the .last()
$(els).each(function() {
$(this).children().addClass('memo');
});

Limit selectable divs in a parent div

I'd like to create a product feature selection page where the user needs to select 3 features out of 6. Now, I got to a point where I can limit the number of selectable elements so if 3 elements are selected, the user wont be able to select a 4th one.
I need to modify this so when the user is attempting to select the 4th element, the 1st element they selected becomes unselected and the 4th element becomes selected. I hope it makes sense.
$('div').click(function(e) {
var $et = $(e.target);
if ($et.hasClass('fill')) {
$et.removeClass('fill');
} else {
if ($('.fill').length < 2) {
$et.addClass('fill');
}
}
});
div {
border: 1px solid blue;
height: 25px;
margin-bottom: 5px;
}
.fill {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<div id="1">one</div>
<div id="2">two</div>
<div id="3">three</div>
<div id="4">four</div>
This fiddle shows where I'm at with my code: http://jsfiddle.net/MarKP/32/
This fiddle is not mine, but this is exactly what I have right now in my project.
I'm trying to get this done using jQuery or plain JavaScript.
Thank you in advance!
To achieve this you can maintain an array which holds the order in which the elements were clicked. Then, when the limit is hit, you can remove the class from the element which was selected first. Try this:
var selections = [];
var $div = $('div').click(function(e) {
selections.push(this.id);
if (selections.length > 3)
selections.shift(); // remove first item
setState();
});
function setState() {
$div.removeClass('fill');
$div.filter(`#${selections.join(',#')}`).addClass('fill');
}
div {
border: 1px solid blue;
height: 25px;
margin-bottom: 5px;
}
.fill {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="1">one</div>
<div id="2">two</div>
<div id="3">three</div>
<div id="4">four</div>
<div id="5">five</div>
<div id="6">six</div>
Finally, note that jQuery 1.4.4 is massively outdated; nearly 10 years in fact. You need to update it.

change style of closest class when input radio is selected - Javascript

I have to make a real simple task but I cannot figure it out.
I have some cards that the user can select with a radio button. I want to higlight the selected card when the user click on the relative input radio.
I don't understand how can I select the closest class of the selected radio.
My HTML looks like this:
<div class="box">
<div class="box-content">
<input type="radio" name="box-input">
<label>Label One</label>
</div>
</div>
<div class="box">
<div class="box-content">
<input type="radio" name="box-input">
<label>Some Two</label>
</div>
</div>
And so on...
<button onclick="submit()">Submit</button>
If I do like this:
let boxes = document.querySelectAll('input');
const submit = () => {
for (let i=0;i<boxes.length;i++) {
boxes[i].checked? this.closest('.box').classList.add('selected'): console.log('nothing is selected')
}
}
It says that this.closest is undefined, and it works only if the user click on the submit button.
What I want to do is just add a class to div .box when the radio input is selected, and remove it when change the state to unselected.
I'd like also to avoid the inline HTML "onclick" if possible.
Please pure javascript only
EDIT
With the suggestion of #somethinghere I added onchange="change(this)" to each input radio and I change my script in this way:
const change = el => {
el.checked?el.closest('.box').classList.add('selected'):el.closest('.box').classList.remove('selected')
;
It works, it adds the class selected when I click on a input radio. But if I click on another input, then the class selected is not removed.
Suggestions?
Added code to change the style of closest class when input radio is selected
var radioAll = document.querySelectorAll('input');
for(var i = 0; i < radioAll.length; i++)
{
radioAll[i].onclick = function()
{
//remove selected class from all box classs
var boxElems = document.querySelectorAll(".box");
[].forEach.call(boxElems, function(el) {
el.classList.remove("selected");
});
if(this.checked)
{
this.closest('.box').classList.add('selected');
}
};
}
.selected{
background-color: coral;
}
<div class="box">
<div class="box-content">
<input type="radio" name="box-input">
<label>Label One</label>
</div>
</div>
<div class="box">
<div class="box-content">
<input type="radio" name="box-input">
<label>Some Two</label>
</div>
</div>
And so on...
<button onclick="submit()">Submit</button>
While you've already accepted an answer, I thought I'd add an alternative approach:
// get a reference to the <button> element; here you only have the one <button>,
// so document.querySelector() will suffice (as it returns either the first
// Node that matches the supplied selector or null):
let submitButton = document.querySelector('button'),
inputs = document.querySelectorAll('input');
// here we use the same Arrow function syntax, which does not - by design - get
// its own 'this' reference:
const submit = () => {
// since we have the <input> elements already we use that, along with the
// NodeList.prototype.forEach() method:
inputs.forEach(
// here 'input' is a reference to the current <input> element of the
// NodeList of <input> elements over which we're iterating.
// we use Element.closest() to find the relevant '.box' element, and
// use the Element.classList API to toggle the 'hasSelected'
// class-name based on the supplied 'switch', the 'input.checked'; if
// 'input.checked' is true the class-name is added to the '.box', if
// 'input.checked' is false the class-name is removed (if the class-name
// is already present, or not-present, when it's added or removed no
// error is thrown and it presents no problem):
(input) => input.closest('.box').classList.toggle('hasSelected', input.checked)
)
}
// using the EventTarget.addEventListener() method, in place of the obtrusive
// 'onclick' in-line event-handling; here we bind the submit() function
// (note the deliberate lack of parentheses) as the event-handler for the
// 'click' event:
submitButton.addEventListener('click', submit);
*,
::before,
::after {
box-sizing: border-box;
margin: 0;
padding: 0;
font-size: 1rem;
line-height: 1.5;
}
body>div {
display: flex;
justify-content: space-between;
width: 50vw;
margin: 1em auto;
}
div.box {
display: grid;
grid-template-columns: 1fr 30px;
grid-gap: 0 10px;
border: 2px solid transparent;
padding: 0.5em;
border-radius: 1em;
}
div.box.hasSelected {
border-color: limegreen;
}
div.box.hasSelected::after {
display: contents;
content: '✓';
font-weight: bold;
color: limegreen;
}
<div>
<div class="box">
<div class="box-content">
<label><input type="radio" name="box-input">
Label One</label>
</div>
</div>
<div class="box">
<div class="box-content">
<label><input type="radio" name="box-input">
Some Two</label>
</div>
</div>
<button>Submit</button>
</div>
JS Fiddle demo.
References:
Arrow functions.
Document.querySelector().
Element.classList API.
Element.closest().
EventTarget.addEventListener().
NodeList.prototype.forEach().

jQuery :has selector filter trouble

I have some containers with ids="container1", "container2", "container3"...
They can have one of two types of tags inside: tables or canvas.
I want to hide one of them depending on the device orientation.
I have tried with this
$('[id^=container]:has(canvas)').hide();
or
$('[id^=container]:has(table)').hide();
but both hide all the containers, don't filtering their inside tags.
You can do
var x = $('[id^=container]').find("table").length;
// Will be 0 if no table inside it
if(x==0) { .. }
else { .. }
You can use classes on your containers instead of ids. Here's a JSFiddle demo.
For better performance in modern browsers, use $( "your-pure-css-selector" ).has( selector/DOMElement ) instead.
Source: https://api.jquery.com/has-selector/
Basically I made a 3 containers. One with a table, one with a canvas and one with nothing.
<div class="container green">
<table></table>
</div>
<div class="container blue">
<canvas></canvas>
</div>
<div class="container red"></div>
And a quick CSS to have the divs visible.
div.container{
display: inline-block;
height: 50px;
margin: 10px;
width: 50px;
}
div.green{
background-color: green;
}
div.blue{
background-color: blue;
}
div.red{
background-color: red;
}
And to complete it, a jQuery that executes when the document is ready.
$(document).ready(function(){
$('div.container').has('canvas').hide();
});
If you know the element by which you want to grab the container is not nested within additional tags, you can use the parentNode property of an HTML element to climb up the DOM tree and hide the parent.
document.querySelector("[id^=container] > table").parentNode.style.display= "none";
Example that demos the concept:
document.getElementById("input").addEventListener("change", function() {
document.getElementById("container1").style.display = "block";
document.getElementById("container2").style.display = "block";
document.querySelector("[id^=container] > " + this.value).parentNode.style.display = "none";
});
#container1 {
border: 1px solid red;
}
#container2 {
border: 1px solid blue;
}
<select id="input">
<options>
<option value="table">Hide the table</option>
<option value="canvas">Hide the canvas</option>
</options>
</select>
<div id="container1">Table
<table></table>
</div>
<div id="container2">Canvas
<canvas></canvas>
</div>
I didn't realized I had a global container with id= "container*".
What a silly mistake. Sorry for stealing your time, and thank you everyone!

Click event and for loop

HTML code:
<div class="test" id="inner1">
ONE
</div>
<div class="test" id="inner2">
TWO
</div>
<div class="test" id="inner3">
THREE
</div>
<div class="test1" id="outer1">
ONE
</div>
<div class="test1" id="outer2">
TWO
</div>
<div class="test1" id="outer3">
THREE
</div>
Javascript code:
<script type="text/javascript">
for (var i=1;i<=3;i++)
{
$("#inner"+i).click(function () {
$("#outer"+i).css("background-color","blue")
});
}
</script>
and the CSS:
.test{
width: 100px;
padding: 10px;
background-color: green;
margin-bottom:10px;
cursor:pointer;
}
.test1{
width: 100px;
padding: 10px;
background-color: red;
margin-bottom:10px;
}
What I want is to change background color of outer1 by clicking on inner1, change background color of outer2 by clicking on inner2 and change background color of outer3 by clicking on inner3. The above code does not work since it looks for outer4 (i=4) which does not exist when event click is triggered... Do you have any idea how to implement the above with some kind of loop?
Thank you
http://jsfiddle.net/Lpwmyspo/1/
When you iterate like that, the i inside the click function isn't evaluated until you actually click something, and at that time the loop has finished and the value of i is the last thing it was set to in the loop.
The real question is why you're using a loop to begin with when you can use the attribute-starts-with selector and this instead
$('[id^="inner"]').on('click', function () {
$('#outer' + this.id.slice(-1)).css("background-color","blue");
});
FIDDLE
How about?
$(".test").on("click", function() {
var which = this.id.replace(/^inner/, "outer");
$(".test1").css("background-color","transparent"); // in case you need to reset the background
$("#" + which).css("background-color","blue");
});
Demo#Fiddle
Do it in the following way:
<div class="test" id="inner1" onclick="abc(this)">
ONE
</div>
<div class="test" id="inner2" onclick="abc(this)">
TWO
</div>
<div class="test" id="inner3" onclick="abc(this)">
THREE
</div>
<div class="test1" id="outer1">
ONE
</div>
<div class="test1" id="outer2">
TWO
</div>
<div class="test1" id="outer3">
THREE
</div>
and the JavaScript part as follows:
<script type="text/javascript">
function abc(e){
var id = e.id;
var lastchar = id.substr(id.length -1);
document.getElementById("outer"+lastchar).style.backgroundColor='blue';
}
</script>

Categories