I am using jQuery's isotope plugin to filter a list of entries, using the markup below for my listing of possible filters. All top-level list items are initially visible, and if I click a specific filter button then any sub-filters (if any) are then shown.
All of this works great. I am however running into a few issues getting the CSS to display the list correctly. The markup is:
<ul class="filter-list">
<li><button data-filter="*">show all</button></li>
<li>
<button data-filter=".filter1">Filter 1</button>
<ul class="sub-filter">
<li>
<button data-filter=".filter1.filtera">Filter 1,A</button>
<ul class="sub-filter">
<li><button data-filter=".filtera.filteri">Filter 1,A,i</button></li>
<li><button data-filter=".filtera.filterii">Filter 1,A,ii</button></li>
<li><button data-filter=".filtera.filteriii">Filter 1,A,iii</button></li>
</ul>
</li>
<li><button data-filter=".filter1.filterb">Filter 1,B</button></li>
<li>
<button data-filter=".filter1.filterc">Filter 1,C</button>
<ul class="sub-filter">
<li><button data-filter=".filterc.filteri">Filter 1,C,i</button></li>
<li><button data-filter=".filterc.filterii">Filter 1,C,ii</button></li>
</ul>
</li>
<li>
<button data-filter=".filter1.filterd">Filter 1,D</button>
<ul class="sub-filter">
<li><button data-filter=".filterd.filteri">Filter 1,D,i</button></li>
<li><button data-filter=".filterd.filterii">Filter 1,D,ii</button></li>
</ul>
</li>
</ul>
</li>
<li><button data-filter=".filter2">Filter 2</button></li>
<li><button data-filter=".filter3">Filter 3</button></li>
</ul>
The CSS that I have so far is:
ul.filter-list {
display:inline-block;
position: relative;
width: 100%;
margin:0;
padding:0;
}
ul.filter-list ul {
display: none;
position:relative;
}
.filter-list ul.active-filter {
display: block;
position:absolute;
top:50px;
left:0px;
}
ul.filter-list li {
list-style-type: none;
display: inline-block;
}
The expected output that I need is to have each 'level' of the list on a single line, followed by the next 'level' of filters if any for the one that is currently active. Initially, it should look like this:
show all Filter 1 Filter 2 Filter 3
If I click on Filter 1, then the next level of buttons underneath that filter should show on the next line:
show all Filter 1 Filter 2 Filter 3
Filter 1,A Filter 1,B Filter 1,C Filter 1,D
If I were to then click on Filter 1,C, the third level of buttons will need to display on the third line:
show all Filter 1 Filter 2 Filter 3
Filter 1,A Filter 1,B Filter 1,C Filter 1,D
Filter 1,C,i Filter 1,C,ii
One of the biggest issues I still am having is that, since the active lists are absolutely positioned, they are being displayed on top of content that is immediately following this list of filters rather than pushing it down. You can see this behavior in this fiddle. Also, when screen size is reduced, things are not flowing / breaking in the way I would expect them to (as well as having absolutely positioned buttons sitting on top of other absolutely positioned items).
Is there a way to accomplish this using just CSS (perhaps using relative positioning?), or am I going to have to add some inordinate amount of Javascript to what I have? Or should I just take out the nested lists in favor of having multiple 'flat' lists?
You can achieve must of this using just regular CSS and jQuery/Javascript to toggle the items visibility:
$(function() {
$('button').on('click', function() {
// The element to be toggled (show/hide).
var toToggle = $(this).next('.sub-filter');
// Go through its parents until the element
// with class sub-filter and find its
// children with this same class to hide
// them, excluding itself.
$(this).parents('.sub-filter').find('.sub-filter').not(toToggle).hide();
// Toggle the target.
toToggle.toggle();
});
});
* {
box-sizing: border-box;
}
ul.filter-list,
ul.filter-list li {
list-style-type: none;
margin: 0;
padding: 0;
}
ul.sub-filter {
/* Giving them the full width and
floating them you guarantee their
place in a new line. */
width: 100%;
float: left;
display: none;
/* Setting their padding to 0 will
keep them aligned to the line above
them. */
padding: 0;
}
ul.filter-list > li,
ul.sub-filter > li {
/* Setting their display to inline
will show them next to each other. */
display: inline;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="filter-list">
<li>
<button data-filter="*">show all</button>
</li>
<li>
<button data-filter=".filter1">Filter 1</button>
<ul class="sub-filter">
<li>
<button data-filter=".filter1.filtera">Filter 1,A</button>
<ul class="sub-filter">
<li>
<button data-filter=".filtera.filteri">Filter 1,A,i</button>
</li>
<li>
<button data-filter=".filtera.filterii">Filter 1,A,ii</button>
</li>
<li>
<button data-filter=".filtera.filteriii">Filter 1,A,iii</button>
</li>
</ul>
</li>
<li>
<button data-filter=".filter1.filterb">Filter 1,B</button>
</li>
<li>
<button data-filter=".filter1.filterc">Filter 1,C</button>
<ul class="sub-filter">
<li>
<button data-filter=".filterc.filteri">Filter 1,C,i</button>
</li>
<li>
<button data-filter=".filterc.filterii">Filter 1,C,ii</button>
</li>
</ul>
</li>
<li>
<button data-filter=".filter1.filterd">Filter 1,D</button>
<ul class="sub-filter">
<li>
<button data-filter=".filterd.filteri">Filter 1,D,i</button>
</li>
<li>
<button data-filter=".filterd.filterii">Filter 1,D,ii</button>
</li>
</ul>
</li>
</ul>
</li>
<li>
<button data-filter=".filter2">Filter 2</button>
</li>
<li>
<button data-filter=".filter3">Filter 3</button>
</li>
</ul>
Demo jsFiddle
Related
I have created the fiddle for the menu-header section for my webpage. I have made it by seeing this image. Once I click PROGRAMS and WORLD OF NORTHMAN, it should dropdown and show elements but it should only start the dropdown from the border of that header and that is I am not able to make it work.
Below is my HTML code:
<div class="topnav">
<img src="https://s4.postimg.org/ojd13poal/northman_wordmark_CMYK.png">
<nav>
<ul>
<li class="dropdown">
<b>PROGRAMS</b> <i class="fa fa-angle-down"></i>
<ul class="dropdown-content">
<li><i>INDIVIDUAL</i>
</li>
<li><i>CORPORATE</i>
</li>
</ul>
</li>
<li class="dropdown">
<b>WORLD OF NORTHMAN</b> <i class="fa fa-angle-down"></i>
<ul class="dropdown-content">
<li><i>BE EXTRODINARY</i>
</li>
<li><i>RISK & REWARD</i>
</li>
<li><i>BLOG</i>
</li>
<li><i>OUR STORY</i>
</li>
</ul>
</li>
</ul>
</nav>
</div>
How can I make sure that dropdown starts from the border of that menu instead coming directly from each of those text?
Try adding margin-top: 14px to the .topnav ul > li > ul selector:
.topnav ul > li > ul {
display: none;
margin-top: 14px;
width: 200px;
padding: 0;
position: absolute;
background-color: #f76c38;
}
https://jsfiddle.net/2nv4dd2w/15/
As a plus, if you want to close other opened menus: https://jsfiddle.net/2nv4dd2w/16/
Just add this
.dropdown-content{ margin-top:14px; }
You need to add the padding to .topnav a rather than .topnav ul > li. https://jsfiddle.net/2nv4dd2w/14/. This is because the ul html tag sits below the a html tag. If you want to keep the background-color the same size, use margin for the a tag, instead of padding, but I think it looks better with padding in my opinion :)
EDIT: Updated fiddle with inline-block image and navigation. https://jsfiddle.net/2nv4dd2w/19/. This should get you close to what you want. The rest is up to you. Happy Coding.
i'm trying to create a seperate mobile navigation for a website i'm creating. this is the basic html layout right now
<nav class="mobile-navigation">
<ul class="header-mobile">
<li>
<i class="fa fa-bars" aria-hidden="true"></i>
</li>
<li>
<img src="{$WEB_ROOT}/templates/{$template}/img/logo/logo.svg" alt="logo">
</li>
<li>
<ul>
<li><span class="icon icon-nav-account"></span></li>
<li>
<a href="{$WEB_ROOT}/cart.php?a=view">
<span class="icon icon-cart"></span>
<span class="notification-amount">{$cartitemcount}</span>
</a>
</li>
</ul>
</li>
</ul>
</nav>
<div class="row">
<ul class="nav-mobile">
<li>About us</li>
<li>Services</li>
<li>Domains</li>
<li>Support</li>
</ul>
</div>
with a simple script to toggle the menu
$('.fa-bars').click(function(evt) {
$('.nav-mobile').slideToggle('down');
});
Now i'm trying to create something where if a list item is chosen, the dropdown is displayed like the images below.
first list -->
second list with selected item
anyone an idea how i achieve this?
First of all you should change your arrow's direction and position. or create two of them one on left and one on right then when user clicks on a li toggle class clicked or something else to that li element(if you want others to collapse you should remove clicked class). Then in css
li > ul{
display:none;
}
li .left-arrow{
display:none;
}
li.clicked > .left-arrow{
display:inline;
}
li.clicked > ul{
display: block;
}
should do the trick
So I'm trying to to make a horizontal menu with CSS and JavaScript that is multi-level. I have a toggle function that shows the div container of the submenu, however, when it displays it pushes the links below the container. How can I make it so when I click the link to show a div container that it appears below the rest of the links. Also I would like to make it where only one link can be selected and I have no clue how to do it. I've never used JavaScript before and I'm fairly new to CSS.
I've removed almost all styling from my code. but here is the functionality.
#togglebox {
display:none;
}
#togglebox li{
display: inline-block;
}
#extrabox {
display:none;
background: #E6ECF2;
text-align: center;
min-width: 100%;
}
#extrabox li{
display: inline-block;
}
#extrabox2 {
display:none;
background: #E6ECF2;
text-align: center;
min-width: 100%;
}
#extrabox2 li{
display: inline-block;
}
function toggle_visibility(id) {
var e = document.getElementById(id);
if(e.style.display == 'block')
e.style.display = 'none';
else
e.style.display = 'block';
}
<ul class="sub-menu" style="display:inline;">
<li id="NSM1">Normal Sub Menu</li></td>
<li id="SMEL">Sub-menu Item with Second Level</li>
<li id="NSM2">Normal Sub Menu</li>
<br />
</ul>
<div id="togglebox">
<li id="NSSL1">[Normal Link]</li>
<li id="SSL2">[Has extra Level]</li>
<div id="extrabox">
<li id="sublinkea">3rd level item1</li> <li id="sublinkeb">3rd level item2</li> <li id="sublinkea">3rd level item3</li>
<li id="sublinkeb">3rd level item4</li>
</div>
<li id="SSL3"><li id="sublinksc">[Has Extra Level]</li>
<div id="extrabox2">
<li id="sublinkea">3rd level item1</li>
<li id="sublinkeb">3rd level item2</li>
<li id="sublinkea">3rd level item3</li>
<li id="sublinkeb">3rd level item4</li>
</div>
<li id="NSSL2">[Normal Link]</li>
</div>
</div>
It looks to me like the trouble is that you have #extrabox as a child of #togglebox, when you really want it to a sibling. As it is, #extrabox will affect the positioning of any block-level elements that come after it (as siblings) under #togglebox. A quick fix looks like:
<div id="togglebox">
<ul>
<li id="NSSL1">
[Normal Link]
</li>
<li id="SSL2">
<a href="#" onclick="toggle_visibility('extrabox');">
[Has extra Level]
</a>
</li>
</ul>
</div>
<div id="extrabox">
<!-- put #extrabox contents here -->
</div>
(I also went ahead and fixed the a tags that were children of ul; ul only takes li tags as children.)
Similarly, you'll want to move #extrabox2 out from under #extrabox so that it doesn't affect the positioning of its siblings there.
I'm not sure what you mean by, "Also I would like to make it where only one link can be selected." Could you clarify that?
Hope that helps!
I have an assignment that needs to be done in a very specific way. I have all the back end code done, but cant seem to figure this part out, and it's driving me mad. Essentially the UI is required to have 2 tree views one on the right and one on the left. The left tree view will be populated with states, and each state will have multiple children. The right will be empty to start. There will be two buttons. Include, and exclude. when children from the left view are selected, and then include is clicked they will move to the right tree. If the user decides to move them back they need to move to the same place they were under the same parent. Last, but not least, there can only be one of each child so we can't have duplicates when moving the children to new parents.
I can use any combination of html, css, javascript, and jquery.
here is what i have so far. I have tried many other things, but this is just the most recent.
CSS
#menutree li {
list-style: none; /* all list item li dots invisible */
}
li .menu_label + input[type=checkbox] {
opacity: 0; /* checkboxes invisible and use no space */
} /* display: none; is better but fails in ie8 */
li .menu_label {
cursor: pointer; /* cursor changes when you mouse over this class */
} /* could add the many user-select: none; commands here */
li .menu_label + input[type=checkbox] + ol > li
{
display: none; /* prevents sublists below unchecked labels from displaying */
}
li .menu_label + input[type=checkbox]:checked + ol > li
{
display: block; /* display submenu on click */
}
.selected {
background-color:#efefef;
}
jquery
$('#move_left').click(function() {
$('.list1').append($('.list2 .selected').removeClass('selected'));
});
$('#move_right').click(function() {
$('.list2').append($('.list1 .selected').removeClass('selected'));
});
$('body').on('click', 'li', function() {
$(this).toggleClass('selected');
});
HTML
<body>
<ol id="menutree">
<li>
<label class="menu_label" for="c1">Menu Gen14 Am0a1</label>
<input type="checkbox" id="c1" /> <!-- input must follow label for safari -->
<ol>
<li>
<ul class="list1">
<li class="page">Page Ap1a1</li>
<li> Page Ap1a2</li>
</ul>
</ol>
</ol>
</body>
<input type='button' value='<<' id='move_left'/>
<input type='button' value='>>' id='move_right'/>
Stupid example that does not take children ordering under consideration, but logic that you presented should be preserved
Demo
<div class="half">
<ol id="one">
<li id="alaska">
Alaska
<ul>
<li data-id="alaska"><input type="checkbox"> Children 1</li>
<li data-id="alaska"><input type="checkbox"> Children 2</li>
<li data-id="alaska"><input type="checkbox"> Children 3</li>
</ul>
</li>
<li id="washington">
Washington
<ul>
<li data-id="washington"><input type="checkbox"> Children 1</li>
<li data-id="washington"><input type="checkbox"> Children 2</li>
<li data-id="washington"><input type="checkbox"> Children 3</li>
</ul>
</li>
<li id="texas">
Texas
<ul>
<li data-id="texas"><input type="checkbox"> Children 1</li>
<li data-id="texas"><input type="checkbox"> Children 2</li>
<li data-id="texas"><input type="checkbox"> Children 3</li>
</ul>
</li>
</ol>
<button type="button" class="include">Include</button>
</div>
<div class="half">
<ol id="two"></ol>
<button type="button" class="exclude">Exclude</button>
</div>
$(function(){
$('.include').click(function(e){
var $checks = $("input:checked");
$.each($checks, function(k,v){
var tempid = $(this).parent().data('id');
if( !$('#two').find('[data-id="'+tempid+'"]').length ){
var element = $(this).parent().detach();
$('#two').append(element);
}
});
});
$('.exclude').click(function(e){
var $checks = $("input:checked");
$.each($checks, function(k,v){
var tempid = $(this).parent().data('id');
var element = $(this).parent().detach();
$('#one').find('#'+tempid+' ul').append(element);
});
});
});
in the YUI Carousel, i want nav button include prev and next buttons showing under the items.by default these buttons placed in upper items and i want placed those after the items (or images)
<div id="container">
<ol id="carousel">
<li>
1111111
</li>
<li>
222222
</li>
<li>
3333333
</li>
<li>
444444
</li>
<li>
5555555
</li>
<li>
66666666
</li>
<li>
7777777
</li>
<li>
8888888
</li>
<li>
999999999
</li>
</ol>
<div class="yui-carousel-nav">
<button id="next" class="yui-carousel-button yui-carousel-next"><span>next</span></button>
<button id="prev" class="yui-carousel-button yui-carousel-prev"><span>prev</span></button>
</div>
</div>
i use above but still navigation appear in above of items
you must use custom navigation buttons for solve this problem, follow this:
use below css in the stylesheed
.yui-carousel .yui-carousel-item-selected {
border: none;
}
.yui-skin-sam .yui-carousel-nav {
position: relative;
top: 0px;
right: 1px;
height: 1px;
background: none;
}
.yui-skin-sam .yui-carousel-button {
display: none;
}
.yui-carousel-nav ul {
display: none;
}
use a think like this for js function call:
(function () {
var carousel;
YAHOO.util.Event.onDOMReady(function (ev) {
var carousel = new YAHOO.widget.Carousel("container", {
isCircular: false,
numVisible: 3,
navigation: { prev: 'prevButton' , next: 'nextButton' }
});
carousel.set("selectedItem", 0);
carousel.render(); // get ready for rendering the widget
carousel.show(); // display the widget
});
})();
then for custom navigation use a div like this:
......
<li>
999999999
</li>
</ol>
<div>
<button id="prevButton"><</button>
<button id="nextButton">></button>
</div>
see here
http://developer.yahoo.com/yui/carousel/#cssref
i have understand it like this
{ prev: prev_id, next: nextId }