Vertical Tabs with JQuery? - javascript

I want tabs along the left side of the page instead of across the top. I'm already loading jQuery for other reasons (effects), so I prefer using jQuery to another UI framework. Searches on "vertical tabs jquery" yield links to works-in-progress.
Is getting Vertical Tabs to work across browsers fraught, or is it so trivial that, once you have a solution, it doesn't seem worthwhile to post example code?

Have a look at the jQuery UI vertical Tabs Docu.
I try out it, it worked fine.
<style type="text/css">
/* Vertical Tabs
----------------------------------*/
.ui-tabs-vertical { width: 55em; }
.ui-tabs-vertical .ui-tabs-nav { padding: .2em .1em .2em .2em; float: left; width: 12em; }
.ui-tabs-vertical .ui-tabs-nav li { clear: left; width: 100%; border-bottom-width: 1px !important; border-right-width: 0 !important; margin: 0 -1px .2em 0; }
.ui-tabs-vertical .ui-tabs-nav li a { display:block; }
.ui-tabs-vertical .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 0; padding-right: .1em; border-right-width: 1px; border-right-width: 1px; }
.ui-tabs-vertical .ui-tabs-panel { padding: 1em; float: right; width: 40em;}
</style>
<script>
$(document).ready(function() {
$("#tabs").tabs().addClass('ui-tabs-vertical ui-helper-clearfix');
$("#tabs li").removeClass('ui-corner-top').addClass('ui-corner-left');
});
</script>

Try here:
http://www.sunsean.com/idTabs/
A look at the Freedom tab might have what you need.
Let me know if you find something you like. I worked on the exact same problem a few months ago and decided to implement myself. I like what I did, but it might have been nice to use a standard library.

I've created a vertical menu and tabs changing in the middle of the page. I changed two words on the code source and I set apart two different divs
menu:
<div class="arrowgreen">
<ul class="tabNavigation">
<li> Tab 1</li>
<li> Tab 2</li>
</ul>
</div>
content:
<div class="pages">
<div id="first">
CONTENT 1
</div>
<div id="secund">
CONTENT 2
</div>
</div>
the code works with the div apart
$(function () {
var tabContainers = $('div.pages > div');
$('div.arrowgreen ul.tabNavigation a').click(function () {
tabContainers.hide().filter(this.hash).show();
$('div.arrowgreen ul.tabNavigation a').removeClass('selected');
$(this).addClass('selected');
return false;
}).filter(':first').click();
});

//o_O\\ (Poker Face) i know its late
just add beloww css style
<style type="text/css">
/* Vertical Tabs ----------------------------------*/
.ui-tabs-vertical { width: 55em; }
.ui-tabs-vertical .ui-tabs-nav { padding: .2em .1em .2em .2em; float: left; width: 12em; }
.ui-tabs-vertical .ui-tabs-nav li { clear: left; width: 100%; border-bottom-width: 1px !important; border-right-width: 0 !important; margin: 0 -1px .2em 0; }
.ui-tabs-vertical .ui-tabs-nav li a { display:block; }
.ui-tabs-vertical .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 0; padding-right: .1em; border-right-width: 1px; border-right-width: 1px; }
.ui-tabs-vertical .ui-tabs-panel { padding: 1em; float: right; width: 40em;}
</style>
UPDATED ! http://jqueryui.com/tabs/#vertical

I wouldn't expect vertical tabs to need different Javascript from horizontal tabs. The only thing that would be different is the CSS for presenting the tabs and content on the page. JS for tabs generally does no more than show/hide/maybe load content.

Another options is Matteo Bicocchi's jQuery mb.extruder tabs plug-in:
http://pupunzi.open-lab.com/mb-jquery-components/jquery-mb-extruder/

Have a look at Listamatic. Tabs are semantically just a list of items styled in a particular way. You don't even necessarily need javascript to make vertical tabs work as the various examples at Listamatic show.

super simple function that will allow you to create your own tab / accordion structure here: http://jsfiddle.net/nabeezy/v36DF/
bindSets = function (tabClass, tabClassActive, contentClass, contentClassHidden) {
//Dependent on jQuery
//PARAMETERS
//tabClass: 'the class name of the DOM elements that will be clicked',
//tabClassActive: 'the class name that will be applied to the active tabClass element when clicked (must write your own css)',
//contentClass: 'the class name of the DOM elements that will be modified when the corresponding tab is clicked',
//contentClassHidden: 'the class name that will be applied to all contentClass elements except the active one (must write your own css)',
//MUST call bindSets() after dom has rendered
var tabs = $('.' + tabClass);
var tabContent = $('.' + contentClass);
if(tabs.length !== tabContent.length){console.log('JS bindSets: sets contain a different number of elements')};
tabs.each(function (index) {
this.matchedElement = tabContent[index];
$(this).click(function () {
tabs.each(function () {
this.classList.remove(tabClassActive);
});
tabContent.each(function () {
this.classList.add(contentClassHidden);
});
this.classList.add(tabClassActive);
this.matchedElement.classList.remove(contentClassHidden);
});
})
tabContent.each(function () {
this.classList.add(contentClassHidden);
});
//tabs[0].click();
}
bindSets('tabs','active','content','hidden');

Related

Counting li elements --> Then applying CSS = Loading Problem

I am working with a CMS. In order to show some list content I need a count on the list items to spread them evenly over the page. I did this function:
$(document).ready(function() {
$("button").click(function() {
var count = $("#page_menu ul li").length;
var breit = 945 / count;
$("#page_menu li").css("width", breit);
})
})
#page_menu ul {
margin: 0px;
top: 0px;
}
#page_menu li {
border: 1px solid #fff;
margin: 0 -1px 0 0;
display: flex;
justify-content: center;
text-align: center;
align-items: center;
}
#page_menu ul li {
height: 50px;
float: left;
list-style: none;
font-size: 13px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="page_menu">
<ul class="nav menu mod-list">
<li class="item-121"><a href="/index.php/about/querfloete" >Querflöte</li><li class="item-123"><a href="/index.php/about/autor" >Autor</li></ul>
</div>
<button>change</button>
This does exactly what it is supposed to do - TOO LATE!
To be precise: The page loads and builds the list. The javascript afterwards performs its counting function and releases it to the CSS. However, by then the CSS relating to the list doesn't get the information anymore. The button stays blank and without function regardless if it was placed before the javascript section or after. And it stays that way until I go a level down in the submenu with the same menu. Then it works fine.
And the other thing is, that I would like to load it by itself and not via clicking a button. How can I achieve this?
Sorry, I haven't been working this kind of stuff for the past 10 yrs. I am completely somewhat lost.

Weird behavior of CSS nth-child after editing dom

I have four div container in the following order:
Every container has CSS class "chart multi-mode" with style:
.chart.multi-mode {
width: 300px;
height: 200px;
margin: 0 15px 15px 0;
}
Every second div should have no right margin, so I use:
.chart.multi-mode:nth-child(2n) {
margin-right: 0px;
}
This is working fine until I use jQuery sortable()
When dragging one div and holding, jQuery adds an placeholder, which I also gave the classes "chart multi-mode" and the original object becomes absolute and I remove the class "multi-mode".
But nth-Child doesn't care about removing the class "multi-mode" and still counts the absolute div and so the margins are set wrong, see here:
Any solution?
To select the second element with the class, after the changes, there's not much you could do. The only kind of selector I can think of is to set the hierarchy starting from the element that does not contain the class, and follow using immediate forward sibling selector +, to target the second one:
Untested
li:not(.chart.multi-mode) + .chart.multi-mode + .chart.multi-mode {
}
I solved it with Javascript:
this.$chartList.sortable({
placeholder : "chart chart-placeholder " + chartTypeClass,
handle : ".opt-drag",
start : function(event, ui) {
ui.item.addClass('drag-state');
$('.multi-mode:not(.drag-state):odd').addClass('odd');
$('.multi-mode:not(.drag-state):even').addClass('even');
},
change : function(event, ui ) {
$('.multi-mode').removeClass('odd');
$('.multi-mode').removeClass('even');
$('.multi-mode:not(.drag-state):odd').addClass('odd');
$('.multi-mode:not(.drag-state):even').addClass('even');
},
stop : function(event, ui) {
ui.item.removeClass('drag-state');
$('.multi-mode').removeClass('odd');
$('.multi-mode').removeClass('even');
},
update : function() {
uiBehavior.startSpinner();
var newUuidOrder = [];
$('.chart').each(function() {
newUuidOrder.push($(this).attr('uuid'));
});
_this.restSetChartsOrder(newUuidOrder, function() {
uiBehavior.stopSpinner();
});
}
});
On start Draggin or when list change I count elements and add class odd or even.
CSS looks like this:
.chart.multi-mode.odd {
margin-right: 0px !important;
}
.chart.multi-mode.even {
margin-right: 15px !important;
}
Thanks to all!
I knocked something workable up that uses a different approach laying out the boxes (see my comment Weird behavior of CSS nth-child after editing dom):
Basically is a non-responsive light version of a Bootstrap grid:
* { box-sizing: border-box; }
body {
padding: 50px;
}
#chartlist {
list-style: none;
margin: 0 -8px;
padding: 0;
width: 600px;
}
#chartlist::after {
content:"";
display:table;
clear:both;
}
.chart.multi-mode {
float: left;
width: 300px;
height: 200px;
margin-bottom: 16px;
padding: 0 8px;
position: relative;
}
.chart-holder {
border: 1px solid #333;
background: #999;
height: 100%;
}
.chart.placeholder {
background: rgba(255, 0, 0, 0.5);
position: absolute;
right: -20px;
top: 20px;
}
<ul id="chartlist">
<li class="chart multi-mode">
<div class="chart-holder">Chart #1</div>
</li>
<li class="chart multi-mode">
<div class="chart-holder">Chart #2</div>
</li>
<li class="chart multi-mode placeholder">Chart Placeholder</li>
<li class="chart multi-mode">
<div class="chart-holder">Chart #3</div>
</li>
<li class="chart multi-mode">
<div class="chart-holder">Chart #4</div>
</li>
</ul>
(Or http://jsfiddle.net/maryisdead/vfm5d3au/)
negate the placeholder using this
.chart.multi-mode:not(.chart-placeholder):nth-child(2n)

How to make this working Java-script more efficient

I've got a working jQuery script that runs ok meaning it serves its purpose.
The question is: how to make this script more efficient?
Currently the script becomes active the moment a user places the mouse over (hover) a certain HTML5 section-tag with an ID. At this moment the script removes the existing class named 'noDisplay' from a subordinate nav-tag containing a submenu list, hence content becomes visible to the user. This submenu list may be three to four levels deep. The submenus are held in classes (subMenu1, subMenu2, subMenu3, subMenu4, etc.).
The script is written to serve individually each of the given section IDs and its sublevel classes.
Basically the script interacts with the DOM by removing the class 'noDisplay' upon mouse hover and restores the same class upon mouse leave.
(Tried to give a clear explanation. If not please ask.)
Here is a JSfiddle: enter link description here
I hope someone can suggest a way to do this much more efficiently.
Possibly with more sections (#ID's) and subMenu-levels (a class per level).
Using the CSS properties 'display: none;' and 'display:block;' would be the simplest solution but this is not desired because a search-bot my decide to skip content flagged as invisible to the user or a screenreader. The class 'NoDisplay' in use here keeps content invisible to users and keeps its readability to screen readers (and thus to most of the search bots).
So basically the script function remains as is to remove and add the class 'noDisplay' upon hover.
The goal is to obtain a script that is more efficient that could use for instance variables for each section, instead of writing code for each new section and hence extending the current script.
//section1$("#section1 .NavUL1 .subMenu1").hover(function(){
$(".NavUL2").removeClass("noDisplay"); //display
},function(){
$(".NavUL2").addClass("noDisplay"); //no display
});
$("#section1").hover(function(){
$("#section1 .NavUL1").removeClass("noDisplay"); //display
},function(){
$("#section1 .NavUL1").addClass("noDisplay"); //no display
});
$("#section1 .NavUL1 .subMenu1").hover(function(){
$(".NavUL2").removeClass("noDisplay"); //display
},function(){
$(".NavUL2").addClass("noDisplay"); //no display
});
//#section2
$("#section2").hover(function(){
$("#section2 .NavUL1").removeClass("noDisplay"); //display
},function(){
$("#section2 .NavUL1").addClass("noDisplay"); //no display
});
$("#section2 .subMenu1").hover(function(){
$(".subMenu1 .NavUL2").removeClass("noDisplay"); //display
},function(){
$(".subMenu1 .NavUL2").addClass("noDisplay"); //no display
});
$("#section2 .subMenu2").hover(function(){
$(".subMenu2 .NavUL2").removeClass("noDisplay"); //display
},function(){
$(".subMenu2 .NavUL2").addClass("noDisplay"); //no display
});
$("#section2 .subMenu3").hover(function(){
$(".subMenu3 .NavUL2").removeClass("noDisplay"); //display
},function(){
$(".subMenu3 .NavUL2").addClass("noDisplay"); //no display
});
$("#section2 .subMenu4").hover(function(){
$(".subMenu4 .NavUL2").removeClass("noDisplay"); //display
},function(){
$(".subMenu4 .NavUL2").addClass("noDisplay"); //no display
});
My suggestion would be to create a new class, call it whatever but for demonstrative purposes we'll call it hover-class
Then it becomes simple:
$('.hover-class').hover(
function() { $(this).addClass('noDisplay'); },
function() { $(this).removeClass('noDisplay'); }
);
I'd recommend just using CSS, there shouldn't be a need for JS:
nav ul{
position: absolute;
border: 1px solid #444444;
box-shadow: 8px 8px 11px #222222;
background: #888;
padding: 0.5em 0.5em 0.5em 0em;
list-style-type: none;
margin-left: 15%;
display: none;
}
.sectionBox:hover nav > ul, nav li:hover > ul {
display: block;
}
This does away with all the IDs and classes while keeping the same effect. You html looks like this now (just a snippet):
<ul>
<li><h2>various whatever1</h2></li>
<li>link11</li>
<li>link12</li>
<li>link13</li>
<li>link14</li>
<li><h2>sub1</h2>
<ul>
<li>sub1-link11</li>
<li>sub1-link12</li>
<li>sub1-link13</li>
<li>sub1-link14</li>
</ul>
</li>
</ul>
Here it is working: http://jsfiddle.net/VGXNz/1/
Update:
If you want to use your original noDisplay styles then this would be the CSS:
nav ul{
position:absolute;
border: 0;
clip: rect(0 0 0 0);
width: 1px;
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
}
.sectionBox:hover nav > ul, nav li:hover > ul{
height: auto;
width: auto;
margin: 0 0 0 15%;
border:1px solid #444444;
box-shadow:8px 8px 11px #222222;
background:#888;
padding:0.5em 0.5em 0.5em 0em;
list-style-type:none;
clip: auto;
overflow: visible;
}
Here's a fiddle: http://jsfiddle.net/KKmVU/1/
why would you use js in the first place? Css is perfectly capable of handling hover states, and IMO you should always go for the css solution if there is one.
I made some quick (and dirty) changes to your fiddle:http://jsfiddle.net/3epRN/1/
I removed a bunch of classes and id's from the markup, removed all js, and tweaked the css a bit. The relevant css looks like this:
.sectionBox nav {
display: none;
}
.sectionBox:hover nav {
display: block;
position: absolute;
top: 90%;
left: 50px;
background-color:#646464;
z-index: 5;
}
.sectionBox nav ul ul {
display: none;
}
.sectionBox nav ul li {
position: relative;
}
.sectionBox nav ul li:hover ul {
display: block;
position: absolute;
top: 0;
left: 80%;
background-color:#646464;
z-index: 5;
}
Obviously this needs some finetuning, but I'm sure you get the idea...
edit
I must admit I missed the part about the display:none beeing a problem for you. I do have to say I disagree with your arguments as to why (it is used al over the net, and crawlers and screen readers are smart enough nowadays).
That beeing said, nothing prevents you to use the css styling you now use to hide content (by adding the noDisplay class) directly in your css where I used the display:none;, and countering it when you want to display content by adding the following in stead of an ordinary display:block:
height: auto;
width: auto;
clip: auto;
overflow: visible;
The result would be identical to your js solution. I updated my fiddle to demonstrate:
http://jsfiddle.net/3epRN/2/

Display only one list item at the center of the <div> with overflow:hidden

I'm trying out a vertical ticker that displays a few text list items one after the other, but I need some help in positioning them.
You'll see a web ticker with two items. To display only one item at a time, I have to set 'overflow:hidden' in #tickerContainer.
However, the text in the ticker is not being positioned at the center of the ticker(As you see it is sitting at the bottom).
Also, when I remove 'overflow:hidden' from #tickerContainer, which is the whole ticker moving away from the top of the page?
Please help me fix this.
http://jsfiddle.net/nodovitt/NYhY4/2/
<div id="tickerContainer">
<ul id="ticker" class="js-hidden">
<li class="news-item">Item Number 1</li>
<li class="news-item">Item Number 2</li>
</ul>
</div>
The jQuery function:
<script>
function tick() {
$('#ticker li:first').slideUp(1000, function () {
$(this).appendTo($('#ticker')).slideDown(1000);
});
}
setInterval(function () {
tick()
}, 2000);
</script>
The CSS:
#tickerContainer {
background-color:white;
border-radius:15px;
text-align:center;
margin:10px;
box-shadow:0 0 8px black;
color:#2B7CD8;
font-size:50px;
width:500px;
height:100px;
overflow:hidden;
}
.news-item {
font-family:Times New Roman;
font-style:oblique;
}
#ticker li {
list-style-type:none;
}
You haven't put any specifications on your ticker id. So something like this http://jsfiddle.net/NYhY4/10/
#ticker {
padding:0px;
margin:0px;
padding-top:20px;
height:55px;
overflow:hidden;
}
Here is my answer as requested by OP
Add this css to your #ticker
#ticker {
margin: 0;
padding: 0;
line-height: 100px;
}
NOTE The line-height will always have to be the height of the #tickerContainer
You can see it here http://jsfiddle.net/NYhY4/3/
#ticker li {
list-style-type:none;
position: relative;
bottom:20px;
}
I didn't like the current item being hidden by seemingly "nothing" (the blank part of li box above the text) so I used this approach:
Remove the margins from the '#ticker'
set '#ticker' padding-top (.5em worked best for me)
set '#ticker li' padding-bottom to push the next item out of view (I used '1em' to be safe but '.5em' worked too)
The words didn't look perfectly centered so
set '#ticker li' line-height to '1em'
#ticker {
margin: 0;
padding-top: .5em;
}
#ticker li{
line-height: 1em;
padding-bottom: 1em;
list-style-type: none;
}
http://jsfiddle.net/JvuKU/2/
Note This depends on the font-size of the '#tickerContainer'. If you change the height or font-size of the '#tickerContainer', just adjust the values of '#ticker' padding-top and '#ticker li' padding-bottom.

Function only works on second click, then works fine?

I am having trouble with a navigation menu I have created. Basically, the navigation consists of several tabs that is collapsible upon click a button and then expandable when you click that button again. When collapsed, the ends of the tabs are still visible, and when you hover over the tabs will go back out, and go back in when hovering out.
So I have the following navigation laid out:
<ul id="navigation">
<li>Name1</li>
<li>Name2</li>
<li>Name3</li>
<li id = "collapser">Collapse All</li>
</ul>
And I have the following jQuery/javascript laid out to do this:
$("#collapser").click(function(){
if($("#collapser").hasClass("clicked")){
$(function() {
$('#navigation a').stop().animate({'marginLeft':'-118px'},1000);
$('#navigation > li').hover(
function () {
$('a',$(this)).stop().animate({'marginLeft':'0px'},400);
},
function () {
$('a',$(this)).stop().animate({'marginLeft':'-118px'},400);
}
);
});
$("#collapser").removeClass("clicked");
$("#collapser").addClass("unclicked");
$("#collapser").html('Expand All')
}
else{
$(function() {
$('#navigation a').stop().animate({'marginLeft':'0px'},1000);
$('#navigation > li').hover(
function () {
$('a',$(this)).stop().animate({'marginLeft':'0px'},400);
},
function () {
$('a',$(this)).stop().animate({'marginLeft':'0px'},400);
}
);
});
$("#collapser").removeClass("unclicked");
$("#collapser").addClass("clicked");
$("#collapser").html('Collapse All')
}
})
The code works, but only when you click the link a second time. I can't seem to figure out what I did to make it work only after clicking it once already.
Any help would be appreciated, thank you very much!!
-Quintin
EDIT:
Here is the CSS for the navigation:
ul#navigation {
position: fixed;
margin: 0px;
padding: 0px;
font-size:14px;
top: 14px;
left: 0px;
list-style: none;
z-index:9999;}
ul#navigation li {
width: 100px;
}
ul#navigation li a {
display:block;
margin-bottom:3px;
width:126px;
padding:3px;
padding-left:15px;
background-color:#ffffff;
background-repeat:no-repeat;
background-position:center center;
opacity:0.7;
filter:progid:DXImageTransform.Microsoft.Alpha(opacity=60);
-moz-box-shadow: 0px 1px 3px #000;
-webkit-box-shadow: 0px 1px 3px #000;
}
ul#navigation .checked a{
color:#ffffff;
background-color:#000000;
}
You are verifying if your collapser div has or not the class clicked or unclicked, but you not initialize the div with some class. Adding the class clicked should adjust your effect:
<li id = "collapser" class='clicked'>Collapse All</li>
You can see it with this jsfiddle

Categories