Make DIV take space of another DIV which is hidden - javascript

I am building a quiz that is going to generate a set of 10 questions of out a pool of 40.
My idea is to use a generated array of 10 numbers and hide them using JQuery. The JQuery would .hide() the questions that aren't needed and the would be displayed in the default format.
I need the divs of the questions that are selected to take up the spaces left by the hidden divs. Since the pool is massive, is there a practical way to do this?
Note: I don't have the JQuery done at the moment.
/* Quiz Styling */
.quiz-wrapper{
position: absolute;
top: 90%;
left: 50%;
transform: translate(-50%, -50%);
width: 50%;
}
.header{
margin-top: 50px;
height: 150px;
text-align: center;
background-color: red;
width: 100%;
}
.question{
margin-top: 10px;
}
ul{
margin-left: 10px;
list-style-type: none;
}
#qu1{
visibility: hidden;
}
<div class="header">
<h1> You have made it into the quiz!</h1>
<br>
<p>You are about to go through a series of 10 MCQs. <br>
At the end of the questions, you will obtain your marks!<br>
Good Luck and Have Fun! <br>
Once ready, press the button below!</p>
</div>
<div class="quiz-wrapper">
<button id="quiz_start" class="quiz_start">Click me to start!</button>
<div class="quiz">
<div class="question" id="qu1"><span class="qu_no"></span>A game where player fight in an arena-style environment is referred as __________?
<ul>
<li>
<input type="radio" id="one_a" name="gametype" value="one_a" required>
<label for="one_a">MMO</label>
</li>
<li>
<input type="radio" id="one_b" name="gametype" value="one_b" required>
<label for="one_b">RPG</label>
</li>
<li>
<input type="radio" id="one_c" name="gametype" value="one_c" required>
<label for="one_c">Open World</label>
</li>
<li>
<input type="radio" id="one_d" name="gametype" value="one_d" required>
<label for="one_d">FPS</label>
</li>
</ul>
</div>
<div class="question" id="qu2"><span class="qu_no"></span>What is the name of the most recent graphics card series released by nVidia?
<ul>
<li>
<input type="radio" id="two_a" name="gpucards" value="two_a" required>
<label for="two_a">RTX 3000 Series</label>
</li>
<li>
<input type="radio" id="two_b" name="gpucards" value="two_b" required>
<label for="two_b">Intel i5</label>
</li>
<li>
<input type="radio" id="two_c" name="gpucards" value="two_c" required>
<label for="two_c">Jolt Series</label>
</li>
<li>
<input type="radio" id="two_d" name="gpucards" value="two_d" required>
<label for="two_d">GTX 1000 Series</label>
</li>
</ul>
</div>

I think that if any element have been hidden by JQuery .hide(), the element has display: none style, so nothing in this element cannot be displayed.

Simply have a set size for the whole div.
The hidden questions will have display:none and will therefore not take up any space, you can give all questions something like height: 100%; and they will always fill out the big div, or if they also have a set size (as in set by pixels, or vh etc.) the questions will just keep appearing as in a list.
Not sure if this answers your question or if there is something else you are trying to do, do you mean that you always want the next question on top? In that case I would not have the questions as a part of the div from the beginning, but rather have them in an array in JavaScript and then use the jquery function .prepend() to add them as the first element to the div.

Related

How do I properly structure a dark mode toggle using Javascript?

I've been trying to have my toggle trigger a dark mode on and off using JavaScript but clearly I'm doing something wrong. I attempted to trigger it by applying the light class to my body and using addClassListener. Below is a simplified version of my code but i also plan on doing this on specific classes as well in order to change font and div colors in each different mode as well. Any suggestions?
HTML
<label class="switch">
<input type="checkbox" checked>
<span id="slide" class="slider round"></span>
</label>
CSS
body{
position: absolute;
top: 320px;
left: 0;
width: 100%;
height: 100%;
background-color: hsl(230, 17%, 14%);
z-index: -1;
}
body.light {
background-color: white;
}
Javascript
const checkbox = document.getElementById('slide');
checkbox.addEventListener('change', ()
==>{document.body.classList.toggle('light');
});
You are attempting to get the element by id, but you have not defined any ids in your snippet.
<label class="switch">
<input type="checkbox" checked>
<span id="slider" class="slider round"></span>
</label>
Additionally, you're listening for a change event on a span element. The span element will never fire a change event. If you change that to listen in the input element, it should fire. Documentation

Trigger radio button click without the click

I have two custom styled radio buttons that look like below [just an example]
li {
width: 100px;
border: 1px solid black;
display: inline-block;
}
<ul>
<li>
<input type="radio" name="radio-test" id="radio1">
<div>
<label for="radio1">Radio One</label>
</div>
</li>
<li>
<input type="radio" name="radio-test" id="radio2">
<div>
<label for="radio2">Radio Two</label>
</div>
</li>
</ul>
Once this has been made to look prettier, I would ideally want that clicking anywhere inside the box enclosing a radio button should trigger activation of that choice.
My team mates have used custom styles and images to show selection and hence I do not want to modify CSS.
I was trying to think of a way to implement mentioned functionality with Javascript.
Attack a click event-handler on the li and trigger a click on the underlying input but that causes an infinite recursion of event triggers.
This raised 2 questions in my mind:
Is there a way to stop the the click recursion? I tried preventDefault and stopPropagation on the JS triggered click but
they do not seem to accomplish what I want.
Can we user JavaScript(or jQuery if needed) to differentiate between a real mouse click and a JS triggered click event?
You were on the right track. You just need to stop the propagation from the input back up to the list item:
$('li').click(function() {
$(this).find('input').click()
})
$('input').click(function(e) {
e.stopPropagation();
})
li {
width: 100px;
border: 1px solid black;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
<li>
<input type="radio" name="radio-test" id="radio1">
<div>
<label for="radio1">Radio One</label>
</div>
</li>
<li>
<input type="radio" name="radio-test" id="radio2">
<div>
<label for="radio2">Radio Two</label>
</div>
</li>
</ul>

How to use 3 radio button and relate those button to different styling for div tag?

I have created a div tag and wrote some content in it. and have created 3 types of styling effect for that div tag. so have created 3 radio buttons and now i dont know how to connect these things together. If check one of the radio button the div tag should take one of the styling.
Thanks in Advance.
You could do it with css only.
input[value="blue"]:checked ~ div {
background: blue;
}
input[value="yellow"]:checked ~ div {
background: yellow;
}
input[value="orange"]:checked ~ div {
background: orange;
}
div {
width: 80px;
height: 80px;
}
<label for="blue">blue</label>
<input type="radio" value="blue" id="blue" name="group1">
<label for="yellow">yellow</label>
<input type="radio" value="yellow" id="yellow" name="group1">
<label for="orange">orange</label>
<input type="radio" value="orange" id="orange" name="group1">
<div></div>

How to style radio buttons differently if they fit in a single row?

PLAYGROUND HERE
I'd like to style radio buttons differently if they fit in a single row. For example:
The first container doesn't have enough space to fit all the radio buttons in a single row. Therefore, they appear vertically as normal radio buttons.
The second container has enough space. Therefore, the radio buttons appear as buttons.
Is that possible to achieve this behaviour using CSS only?
If not, Javascript "hack" is welcome.
PLAYGROUND HERE
HTML
<div class="container radio">
<div>
<input id="a1" type="radio" name="radio">
<label for="a1">Yes,</label>
</div>
<div>
<input id="a2" type="radio" name="radio">
<label for="a2">it</label>
</div>
<div>
<input id="a3" type="radio" name="radio">
<label for="a3">is</label>
</div>
<div>
<input id="a4" type="radio" name="radio">
<label for="a4">possible</label>
</div>
<div>
<input id="a5" type="radio" name="radio">
<label for="a5">to</label>
</div>
<div>
<input id="a6" type="radio" name="radio">
<label for="a6">achieve</label>
</div>
<div>
<input id="a7" type="radio" name="radio">
<label for="a7">this</label>
</div>
</div>
<div class="container buttons">
<div>
<input id="b1" type="radio" name="buttons">
<label for="b1">Yes,</label>
</div>
<div>
<input id="b2" type="radio" name="buttons">
<label for="b2">it</label>
</div>
<div>
<input id="b3" type="radio" name="buttons">
<label for="b3">is</label>
</div>
<div>
<input id="b4" type="radio" name="buttons">
<label for="b4">possible</label>
</div>
</div>
CSS (LESS)
.container {
display: flex;
width: 220px;
padding: 20px;
margin-top: 20px;
border: 1px solid black;
&.radio {
flex-direction: column;
}
&.buttons {
flex-direction: row;
> div {
input {
display: none;
&:checked + label {
background-color: #ADFFFE;
}
}
label {
padding: 5px 10px;
margin: 0 1px;
background-color: #ccc;
}
}
}
}
Not possible in CSS, but it doesn't take much JavaScript.
In CSS, add flex-shrink: 0 to > div. This will prevent .container's children from shrinking smaller than their extent.
In JavaScript:
Apply the buttons class.
Use Element.getBoundingClientRect to determine if the last child of .container is outside the extent of .container. If so, switch to the radio class. (You also need to take the right padding into account. Thanks to #Moob for pointing that out.)
Javascript
var container = document.querySelector('.container'),
lastChild= document.querySelector('.container > :last-child'),
paddingRight= parseInt(window.getComputedStyle(container, null).getPropertyValue('padding-right')),
timer;
window.onresize = function() {
clearTimeout(timer);
timer= setTimeout(function() {
container.classList.remove('radio');
container.classList.add('buttons');
if (container.getBoundingClientRect().right-paddingRight <
lastChild.getBoundingClientRect().right) {
container.classList.add('radio');
container.classList.remove('buttons');
}
});
}
Updated JSBin
I can't think of a CSS only solution but you could use JS to test if the items would fit in a row and apply the 'radio' or 'buttons' classname accordingly:
Forgive my rough JS - its inelegant and for modern browsers only but you get the idea:
var containers = document.querySelectorAll(".container"),
test = function(){
for (i = 0; i < containers.length; ++i) {
var container = containers[i],
divs = container.querySelectorAll("div"),
iw = 0;
container.classList.remove("radio");
container.classList.add("buttons");
//get the sum width of the div
for (d = 0; d < divs.length; ++d) {
iw+=divs[d].offsetWidth;
}
var style = window.getComputedStyle(container, null);
var ow = parseInt(style.getPropertyValue("width"));
if(ow<=iw){
container.classList.add("radio");
container.classList.remove("buttons");
}
}
};
window.onresize = function(event) {
test();
};
test();
http://jsbin.com/zofixakama/3/edit?html,css,js,output
(resize the window / panel to see the effect)
Update: If you add .container div {flex-shrink:0;} to the style the JS can be much simpler as we don't have to measure the combined width of the divs (thanks #rick-hitchcock). However, although the code is more elegant, it does not take the container's padding into account.
See: http://jsbin.com/zofixakama/5/edit?html,css,js,output
If I understand what you're asking correctly, you can change your flex-direction portion to row instead of column. This will cause them to align inside the box.
You'll have to do some more styling to properly get the labels to appear the way you want, but this should put them in the row for you. I've updated the playground with my changes.
Try the following example..............
------------HTML-----------
<html>
<head>
<link rel="stylesheet" href="style.css" type="text/css" />
</head>
<body>
<div class="table-row">
<div class="col">
<input type="Radio">This
</div>
<div class="col" style="padding-top: 2px;">
<input type="Radio">Is
</div>
<div class="col">
<input type="Radio">Simply
</div>
<div class="col" style="padding-top: 2px;">
<input type="Radio">Possible
</div>
</div>
</body>
</html>
-------CSS-------------
.table-row{
display:table-row;
/* text-align: center; */
}
.col{
display:table-cell;
/* border: 1px solid #CCC; */
}
Wouldn't it work to test for width then if necessary remove the radio button icon and replace with a graphic or shape?
.checkbox {
display:none;
}
.label {
display: inline-block;
height: 20px;
background: url('picture.png');
}
It's probably not that simple but I use that for check boxes and it seems to work in that situation.
You can achieve this only by using css and no need of scripting.
HTML: You have to place the input within tag which will contain the text.
<div>
<label for="a1">
<input id="a1" type="radio" name="radio">Yes,
</label> </div>
CSS: Here in CSS we will have to hide the radio button, so that only the text will be visible. When the user clicks on the text, it actually clicks the radio button.
div lable input#a1{
display:none;
}
there is pretty solution CSS only, but you have to know maximum amount of elements in row. It is based on counter, but not on real size.
For example, if you are sure, that you can put 4 elements into a row, in any case, you may use following selector:
if amount is more less or equal 4:
div:nth-last-child(-n+5):first-child,
div:nth-last-child(-n+5):first-child ~ div {
}
if amount is more then 4:
div:nth-last-child(n+5),
div:nth-last-child(n+5) ~ div {
}
try this: http://jsbin.com/fozeromezi/2/edit (just remove/add divs)

JQuery UI buttonset misbehaving

I am building a UI app using JQuery UI elements. I need radio buttons as part of the functionality. While using JQuery buttonset by itself works, once I try to incorporate it with the rest of UI elements they don't align properly:
http://jsfiddle.net/sEunS/2/
Including code here:
$(document).ready(function()
{
$("button").button();
$("#tdiDir").buttonset();
$("#acqMode").buttonset();
});
<div id='primaryLatestControl'
class="ui-corner-top pacontainer"
style='padding: 4px; display: inline-block; '>
<button id="setGain" class="button">Set</button>
<span class="label">Gain Value</span>
<input type="text" id="gainValue" class="value" value="2"></input>
<button id="setLineRate" class="button">Set</button>
<span class="label">Line Rate, HZ</span>
<input type="text" class="value" id="lineRateValue" value="3750"></input>
<button id="setExposeTime" class="button">Set</button>
<span class="label">Exposure Time(ms)</span>
<input type="text" class="value" id="exposeTimeValue" value="100"></input>
<button id="setTDI" class="button">Set</button>
<span class="label">TDI Direction</span>
<form>
<div id="tdiDir">
<label class="checkLabel" for="forward">Forward</label>
<label class="checkLabel" for="reverse">Reverse</label>
<input type="radio" class="value" name="tdiDir" id="forward" checked="checked"/>
<input type="radio" class="value " name="tdiDir" id="reverse"/>
</div>
</form>
<button id="setAcqMode" class="button">Set</button>
<span class="label">Acquisition Mode</span>
<form>
<div id="acqMode">
<label class="checkLabel" for="tdi">TDI</label>
<label class="checkLabel " for="area">Area</label>
<input type="radio" class="value" name="acqMode" id="tdi" checked="checked"/>
<input type="radio" class="value" name="acqMode" id="area"/>
</div>
</form>
.pacontainer {
position: relative;
width: 80%;
}
.label {
float: left;
margin: 10px;
}
.checkLabel {
width: 100px;
float: right;
margin: 10px;
}
.endLine {
clear: right;
}
.button {
float: left;
margin-left: 10px;
clear: left;
}
.value {
float: right;
width: 45px;
height: 20px;
margin: 5px;
background-image: none;
}
I quickly made some changes to your code to give you an idea. http://jsfiddle.net/sEunS/3/
You want your buttons in your buttonset to be ordered because the buttonset gives the outer buttons round corners and the inner buttons get 'squished' margins to be close together. Without the right ordering, the buttonset will always not look right.
Floating the radio's labels will cause the radios to be unordered in the buttonset. I suggest floating the radio's containers instead of the labels.
#acqMode, #tdiDir {
float: right;
}
and remove the float on the .checkLabels as they are no longer needed
.checkLabel {
//float: right;
}
You should also keep your radio's labels together with the radio inputs. This is another ordering issue with buttonsets.
<div id="acqMode">
<label class="checkLabel " for="area">Area</label>
<input type="radio" class="value" name="acqMode" id="area"/>
<label class="checkLabel" for="tdi">TDI</label>
<input type="radio" class="value" name="acqMode" id="tdi" checked="checked"/>
</div>
The last issue is you will need has to do with a clearfix. The buttonset is larger than the text on the same line, so the next line will not look straight without a clearfix. JQuery UI has a helper class
ui-helper-clearfix
I added this class to the line above that was uneven. The class goes on the parent of the last floated element. (try removing this class to get an idea of what I mean).

Categories

Resources