Switch menu with pure css? - javascript

Update
I used radio buttons, so you can only open one Item. But you cant close it. Fiddle
I'm wondering if its possible to make my menu in pure CSS. Now I modify the css with javascript.
Note: I'm not using Jquery or any other lib, thats not my question.
Fiddle of the menu I want to make in pure css
HTML:
<div class="menuItem" onclick="mySwitch(0)">Click Item 1</div>
<div class="subItem">Hi there</div>
<div class="menuItem" onclick="mySwitch(1)">Click Item 2</div>
<div class="subItem">Some text over here.</div>
<div class="menuItem" onclick="mySwitch(2)">Click Item 3</div>
<div class="subItem">Tnx for clicking</div>
CSS:
.menuItem {
display:block;
width:100%;
height:20px;
background:#ff0;
}
.subItem {
display: none; -- Hide the submenu
}
Javascript
function mySwitch(nr) {
var itemsArr = document.getElementsByClassName('subItem');
for(var i = 0; i < itemsArr.length; i++) {
var item = itemsArr[i];
if(i == nr) {
if(item.style.display == 'none') {
item.style.display = 'block';
}
else {
item.style.display = 'none';
}
} else {
item.style.display = 'none';
}
}
}

It is good practice to prevent the excessive use of JavaScript when you can reach the same result with CSS but sometimes it is necessary to change DOM elements and apply some "tricks" to get it to work and that is not so good at all.
Look at this DEMO with only CSS3. You can do a similar effect but with hover event instead of a click event. You can change :hover to :active but that will only work if you keep pressing mouse button inside the DIV elements.
This .menuItem:hover + .subItem CSS rule is showing the next .subItem element of hovered .menuItem
Since you do not want to use JavaScript events, you can't apply a class to the element. If you did so it would be easier. This way, using only CSS, you can apply some tricks like using checkboxes instead of DIV elements and use their :checked property as CSS rules to show the sublinks.
Something like this:
<label for="m1" class="menuItem">Click Item 1</label>
<input id="m1" class="cb" type="checkbox">
<div class="subItem">Hi there</div>
<label for="m2" class="menuItem">Click Item 2</label>
<input id="m2" class="cb" type="checkbox">
<div class="subItem">Some text over here.</div>
<label for="m3" class="menuItem">Click Item 3</label>
<input id="m3" class="cb" type="checkbox">
<div class="subItem">Tnx for clicking</div>
.cb {
display: none;
}
.cb:checked + .subItem {
display: block;
}
Working demo

I think you could take a look to this tutorial: Link
hope this helps

Related

Toggle language between divs

I'm working on a simple page with 8 different languages, it's just a simple onepager.
All the text in the different languages are set in divs with a style="display:none" to be hidden, until the language is choosen then the div with that particular language is shown.
Currently the main language is English and that div is shown on pageload but when selecting a language will load the div UNDER the english div, but this need to be replaced.
I'm not good in Javascript, but found some codes here which I implemented, but it's still not working as it should be.
This is the JS code:
<script type="text/javascript">
var _hidediv = null;
function toggle_visibility(id) {
if(_hidediv)
_hidediv();
var div = document.getElementById(id);
div.style.display = 'block';
_hidediv = function () { div.style.display = 'none'; };
}
</script>
and in my language selector I've the following as example:
EN | ES | SV
What am I doing wrong here, the default language is english, so the div is as follows: and the other languages have style="display:none"
<div id="english" style="display:block">
How about using CSS to hide/show the divs and only use js/jQuery to change a class on body or any parent element?
$('button').click(function() {
$('#body').removeClass().addClass($(this).data('lang'));
});
.lang {
display: none;
}
#body.en .en {
display: block;
}
#body.es .es {
display: block;
}
#body.de .de {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="body" class="en">
<button data-lang="en">English</button>
<button data-lang="es">Spanish</button>
<button data-lang="de">German</button>
<div class="lang en">English</div>
<div class="lang es">Spanish</div>
<div class="lang de">German</div>
<br/>
<div class="lang en">English 2</div>
<div class="lang es">Spanish 2</div>
<div class="lang de">German 2</div>
</div>
You need to handle the default case of English language also. Only that's missing.
var _hidediv = null;
function toggle_visibility(id) {
if(_hidediv) {
_hidediv();
} else {
document.getElementById('english').style.display = 'none';
}
var div = document.getElementById(id);
div.style.display = 'block';
_hidediv = function () { div.style.display = 'none'; };
}
Language:
English
Spanish
Hindi
French
<div id="content">
<div id="english">
English
</div>
<div id="spanish" style="display: none;">
Spanish
</div>
<div id="hindi" style="display: none;">
Hindi
</div>
<div id="french" style="display: none;">
French
</div>
</div>
Problems in your code
_hidediv will never fire because it is always null.
Logic you used in _hidediv is wrong. It is supposed to set div.style.display = 'none' to other divs than the div you passing as parameter in 'toggle_visibility(id)'. According to your code, even if you manage to fire your _hidediv function, it will reset your target div from div.style.display = 'block' to div.style.display = 'none'.
A jQuery-based solution would work like in this example: https://codepen.io/shikifujin/pen/PowqOjB
You create CSS-classes for .language (hidden by default) and .language.active (visible):
div.language {
display: none;
}
div.language.active {
display: block;
}
Then, create all language divs with content like so (only the default one is given the active class) with the id= property containing the content's language:
<div id="english" class="language active">
english content
</div>
<div id="spanish" class="language">
contenido en español
</div>
Then you need to have jQuery sourced in your document, as well as the <script> below to make the language switching work. Once the DOM is loaded, all .switch-language elements (they do not need to be necessarily) need to have the id= attribute specify the language to switch to (exactly matching the id of the corresponding div):
EN
Once the entire DOM is loaded, or after the content and switching elements are present, you can enable the switcher by handling each click on any of them with the following actions:
get language to switch to from id (switchTo)
hide all content divs
show the desired one (with id switchTo)
This can be done with vanilla javascript, too, but I chose to use jQuery:
<script>
$(document).ready(function() {
$(".switch-language").on("click", function() {
var switchTo = $(this).data("language");
$(".language").hide();
$(".language#" + switchTo).show();
});
});
</script>
Again, you may try it out here: https://codepen.io/shikifujin/pen/PowqOjB

JS toggle for multiple div elements

What should I do if I have multiple elements in HTML foreach and I need to make them all a toggle slider what opens div block with specific information about the element and I need to add close button too if a user wants to close the div. Sorry, I don't have any code to show because I did not find anything that suits my needs. The main idea is to have a product page with products that are displayed on a page using foreach... Then when you click on a product toggle div block is opened with information about a product. What should I search and what to use, I can't find anything because I am limited with my knowledge. Sorry for terrible English.
You can easily control the visibility of an element either within the div you're clicking or after it using a class you toggle. Here's an example controlling the div after one of the divs that controls the toggle:
document.getElementById("container").addEventListener("click", function(e) {
var toggleDiv = e.target.closest(".toggle");
if (toggleDiv && this.contains(toggleDiv)) {
toggleDiv.classList.toggle("closed");
}
});
.closed + .detail {
display: none;
}
<div id="container">
<div class="toggle closed">Product A</div>
<div class="detail">Details about Product A</div>
<div class="toggle closed">Product B</div>
<div class="detail">Details about Product B</div>
<div class="toggle closed">Product C</div>
<div class="detail">Details about Product C</div>
</div>
The key bits there are:
Hiding the details via CSS with the adjacent sibling combinator (+)
Toggling the class on the toggling div
I used event delegation to hook up the handler, but you could instead hook it up to each individual div if you preferred. Note that the Element#closest method I used is relatively new, you may need a polyfill or a loop on parentNode instead.
From what i have understood.
You need to toggle div elements using button tag and the button u click will show that particular div element.
<div id="container1" class={container1 ? "show" : "hide"}>
container1
</div>
<div id="container2"class={container2 ? "show" : "hide"}>
container2
</div>
<div id="container3"class={container3 ? "show" : "hide"}>
container3
</div>
and three button tags to call toggle function to show the three div element.
<div class="container">
<button name="container1" onclick=(toggle())>Container1</button>
<button name="container2" onclick=(toggle())>Container2</button>
<button name="container3" onclick=(toggle())>Container3</button>
</div>
toggle function
function toggle(e) {
if(e.target.name === 'container1'){
container1 = true;
}
else if(e.target.name === 'container2'){
container2 = true;
}
else if(e.target.name === 'container3'){
container3 = true;
}
}
css part
.show{
display: block;
}
.hide{
display: none;
}

Detect click outside divs with particular class and hide them

My DOM looks like this:
<div class = filter x>
<div class = a>
<ul><li>……..</li></ul>
</div>
</div>
<div class = filter y>
<div class = a>
<ul><li>……..</li></ul>
</div>
</div>
Both the divs with class a are dropdown menus. The expected functionality is:
Whenever I click on divs with class filter, js-active class is added
and the dropdown opens.
Whenever I click anywhere outside the div or
the dropdown, js-active class is removed and the dropdown hides.
At a time, only one out of the two dropdowns will be open.
Another event that I am handling is that if one dropdown is visible and I click on another dropdown, first one hides (remove class js-active)
I am able to achieve this with the following code:
$(document).on('mouseup touchend', function(e){
var xContainer = $(‘.filter x’);
var yContainer = $(‘.filter y’);
if (!xContainer.is(e.target) && xContainer.has(e.target).length === 0)
{
xContainer.removeClass('js-active');
}
if (!yContainer.is(e.target) && yContainer.has(e.target).length === 0)
{
yContainer.removeClass('js-active');
}
});
I want to optimize this code. I tried using jQuery "each" to iterate over all the divs with class filter and use the same logic but it didn’t work as expected. Any suggestions would be helpful. Thanks.
There is no need to handle both x & y separately, you can do something like
$(document).on('mouseup touchend', function(e) {
var $filter = $(e.target).closest('.filter');
if ($filter.length) {
$filter.addClass('active');
}
$('.filter.active').not($filter).removeClass('active');
});
.filter {
min-height: 20px;
background-color: lightgrey;
margin-bottom: 5px;
}
.filter .a {
display: none;
}
.filter.active .a {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="filter x">
<div class="a">
<ul>
<li>……..</li>
</ul>
</div>
</div>
<div class="filter y">
<div class="a">
<ul>
<li>……..</li>
</ul>
</div>
</div>
Some other content
After trying more, I got this to work too:
$(document).on('mouseup touchend', function(e){
$('.filter').each(function(){
if(!$(this).is(e.target) && $(this).has(e.target).length === 0)
{
$(this).removeClass('js-active');
}
});
});
Works on all devices.

Hide divs by class name instead of id in javascript

I have this JavaScript function that hides div tags from the condition if a checkbox is checked.
following is JavaScript Code:
function showMeA (div) {
var chboxs = document.getElementsByName("enableA");
var vis = "none";
for(var i=0;i<chboxs.length;i++) {
if(chboxs[i].checked){
vis = "block";
break;
}
}
document.getElementById(div).style.display = vis;
}
The problem is that function works based on the div's ID. I want to make it work based on the div's class name.
I have tried replacing the getElementById part with getElementsByClassName but, it doesn't work. Can someone propose an exact change that i need to implement in the function in order for it to work based on the div's class?
Thanks in advance.
Instead of using getElementById, you can use getElementsByClassName.
document.getElementsByClassName('className')
You can do this without any Javascript, just with pure CSS and some clever HTML structuring.
.switchme {
display: none;
}
#switch:checked ~ .switchme {
display: block;
}
<input type="checkbox" checked="checked" id="switch" />
<div class="switchme">Switch this div!</div>
<div class="dontswitchme">This div won't be switched.</div>
<ul class="switchme">
<li>This works without any JS.</li>
<li>It is based on CSS 3's :checked pseudo selector.</li>
</ul>
<img class="switchme" src="http://placehold.it/300x200&text=SwitchMe" alt="" />

Javascript if(condition) then addclass

I'm trying to get a class added on when a div is inside a certain parent div.
<div class="parent1">
<div class="child">
Content
</div>
</div>
.parent1 only exists on one page, while .child exists on others as well as this one.
So when .child is everywhere else, its color is red, but when it's inside .parent1 I want its color to be blue.
Here's what I'm using.
if ($('.child').parents('.parent1').length == 1) {
.addClass('.new-class');
}
I'm having no success with this. Can anyone help?
$(".parent1 .child").addClass("new-class");
Or
$(".parent1>.child").addClass("new-class");
If you want to make sure only first child will be populated with class:
<div class="parent1">
<div class="child"> <!-- will have also "new-class" class -->
<div class="child"> <!-- will NOT have "new-class" class -->
</div>
</div>
</div>
.addClass('.new-class'); adds that class to something. You forgot to tell jQuery what something is, and caused a syntax error instead (which your browser console would have told you about if you had it open). I believe you want this:
$('.parent1 .child').addClass('.new-class');
Well, since you did tag this as just javascript...
HTML
<div class="parent1" id="parent">
<div class="child" id="child">
Content
</div>
</div>
CSS
.has-parent {
color: blue;
}
Javascript
var child = document.getElementById('child');
var parent = document.getElementById('parent');
if (child.parentNode == parent) {
child.className += ' has-parent';
}
DEMO
You could also do this with just CSS:
.child
{
color: red;
}
.parent .child
{
color: blue;
}
So long as the .parent .child rule comes after the single .child rule, it will override the color with blue. No extra work to change the color. If you need this extra class for some other reason the The User 518469 's answer is probably best.

Categories

Resources