distinguishing html with css sectors - javascript

I would like to restyle the nav id="jive-breadcrumb" with CSS. I want to have a different style when div class="jive-alert-type jive-alert-announcement" is present and when div class="jive-alert-type jive-alert-announcement" is not present.
I've gotten this for with the css sectors:
section#j-main div#jive-body nav#jive-breadcrumb ul { }
My second css selector
section#j-main :not(???) div#jive-body nav#jive-breadcrumb ul { }
How do I write the selector to be different?
Here is the section of css with
<section>
<span>
<script>...</script>
</span>
<div id="jive-alert-container">
<!-- the presence or absence of this inner div is what makes
the two html fragments different -->
<div id="jive-alert-global" role="marquee" class="clearfix">
</div>
</div>
<div id="jive-body" class="clearfix" role="main">
<nav id="jive-breadcrumb" aria-label="Communities Breadcrumbs" role="navigation">
<ul><li>Support Communities</li><li>The Lounge</li>
<li>Full Host Bar</li>
</ul>
</nav>
</div>
</section>
Here is the case where div class="jive-alert-type jive-alert-announcement" is not present.
<section>
<span>
<script>...</script>
</span>
<!-- The following div doesn't have any tags in it. I need to detect this with a css selector to generate different css. -->
<div id="jive-alert-container">
</div>
<div id="jive-body" class="clearfix" role="main">
<nav id="jive-breadcrumb">
<ul><li>The Lounge</li>
<li>Full Host Bar</li>
</ul>
</nav>
...
</div>
...
</section>

css presently does not select parent element. You can use MutationObserver to perform a task when an element is appended to or removed from DOM, or a specific parent element within DOM.
var jive = document.getElementById("jive-alert-container");
var breadcrumb = document.getElementById("jive-breadcrumb");
breadcrumb.classList.toggle("present");
var config = {childList: true};
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation);
if (mutation.addedNodes.length
&& mutation.addedNodes[0].id === "jive-alert-global") {
breadcrumb.classList.toggle("present");
}
if (mutation.removedNodes.length
&& mutation.removedNodes[0].id === "jive-alert-global") {
breadcrumb.classList.toggle("present");
}
})
});
observer.observe(jive, config);
var clone = jive.querySelector("#jive-alert-global").cloneNode(true);
setTimeout(function() {
jive.querySelector("#jive-alert-global").remove();
setTimeout(function() {
jive.appendChild(clone);
}, 5000);
}, 5000)
#jive-breadcrumb.present {
color: green;
}
#jive-breadcrumb:not(.present) {
color: blue;
}
<section>
<span>
<script></script>
</span>
<div id="jive-alert-container">
<!-- the presence or absence of this inner div is what makes
the two html fragments different -->
<div id="jive-alert-global" role="marquee" class="clearfix">
jive alert global
</div>
</div>
<div id="jive-body" class="clearfix" role="main">
<nav id="jive-breadcrumb" aria-label="Communities Breadcrumbs" role="navigation">
<ul>
<li>Support Communities</li>
<li>The Lounge</li>
<li>Full Host Bar</li>
</ul>
</nav>
</div>
</section>

The css selector section#j-main implies that there is an html element with the given id: <section id="j-main">.
Replacing the section you want to modify with <section id="j-main"> should make that section respond to the css block you have defined above.
Also note that you can only have one unique id per element on the page, so the jive-body, and jive-breadcrumb ids should be changed to classes.
This should yield:
section#j-main div.jive-body nav.jive-breadcrumb ul { css customizations here }
...
<div class="jive-body" class="clearfix" role="main">
<nav class="jive-breadcrumb" aria-label="Communities Breadcrumbs" role="navigation">
<ul><li>Support Communities</li><li>The Lounge</li>
<li>Full Host Bar</li>
</ul>
</nav>
</div>
</section>
...
<div class="jive-alert-type jive-alert-announcement" is not present.
<!-- This section will not have the changes -->
<section>
<div class="jive-body" class="clearfix" role="main">
<nav class="jive-breadcrumb">
<ul><li>The Lounge</li>
<li>Full Host Bar</li>
</ul>
</nav>
...
</div>
...
</section>

Related

Bootstrap 4 change accordion behaviour

I'm using HTML templates, which are based on Bootstrap 4.3.1 to present my students with learning content. In the current templates, all accordion panels are closed on page load and each accordion panel can be opened regardless of how many others have also been opened.
A working example can be found on this CodePen: https://codepen.io/hagelslag1001/pen/MWGeZJr
The HTML code is as follows:
<h2>Accordion: Group of 2</h2>
<p class="small">Accordion: start copy</p>
<!-- Accordion headings should be changed to respect page hierarchy -->
<div class="accordion shadow mb-5">
<div class="card">
<div class="card-header">
<h2 class="card-title">
Accordion 1 of 2
</h2>
</div>
<div class="collapse">
<div class="card-body">
<p>Insert Accordion 1 of 2 content here.</p>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h2 class="card-title">
Accordion 2 of 2
</h2>
</div>
<div class="collapse">
<div class="card-body">
<p>Insert Accordion 2 of 2 content here.</p>
</div>
</div>
</div>
</div>
<p class="small">Accordion: end copy</p>
Is it possible to change this default behaviour so that only one panel can be opened at a time? (i.e. as soon as a new panel is opened, the previously opened panel will automatically close)
The Bootstrap examples use (data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne") to accomplish this for the accordions in these templates
I can't figure out how to accomplish this, since the HTML code for the accordions in these templates look different than the Bootstrap 4 examples, which use either an a or button tag to trigger the collapsible event.
Here is a simpler answer based on your CodePen: https://codepen.io/mrtcntn/pen/MWGeZdP
According the Bootstrap 4 docs, you need id="accordion" on the top level div and you don't need to give ids like id="accordion_1" and id="accordion_2".
Therefore I removed the first portion from the JS and added id="accordion" at line 18 in the HTML.
You can do this by letting javascript check for active classes and only allowing one at the time. Here's a simplified example.
// DOM here
let nav = document.querySelector(".nav");
// Handlers here
const clickHandler = function (e) {
if (e.target.classList.contains("nav__link")) {
const link = e.target;
const siblings = link.closest(".nav").querySelectorAll(".nav__link");
link.classList.toggle("active");
// removes all actives except for the clicked one
siblings.forEach((el) => {
if (el !== link) el.classList.remove("active");
});
}
};
// Listeners here
nav.addEventListener("click", clickHandler);
body {
font-family: sans-serif;
}
.nav__link {
display: block;
width: 100%;
}
.active {
background: #0f0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<div class="nav">
<ul class="nav__links">
<li class="nav__item">
<a class="nav__link" href="#accordeon--1">Accordeon 1</a>
</li>
<li class="nav__item">
<a class="nav__link" href="#accordeon--2">Accordeon 2</a>
</li>
<li class="nav__item">
<a class="nav__link" href="#accordeon--3">Accordeon 3</a>
</li>
<li class="nav__item">
<a class="nav__link" href="#accordeon--4"
>Accordeon 4</a
>
</li>
</ul>
</div>
</div>
<script src="src/index.js"></script>
</body>
</html>

HTML, Javascript: How to share a container under specified bootstrap panels

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<div class="container-fluid">
<div id="header">
<div>
</div>
<div id="content">
<ul id="tabs" class="nav nav-tabs" data-tabs="tabs">
<li class = "nav-tabs">A</li>
<li class = "nav-tabs">B</li>
<li class = "nav-tabs">C</li>
</ul>
<div id="my-tab-content" class="tab-content">
<div class="tab-pane" id="a">
<div class="panel-body">A content</div>
</div>
<div class="tab-pane" id="b">
<div class="panel-body">B content</div>
</div>
<div class="tab-pane" id="c">
<div class="panel-body">C content</div>
</div>
</div>
</div>
<br>
<div class="row" id="container"> image </div>
</body>
This is the HTML code, I have a three column panel showing A, B and C using bootstrap.
Underneath the content, there is a container with id = "container" at the bottom of all panels.
Here is my question:
I want to only have id = "container" shown under panel A, B. However, I don't want the panel C showing id = "container" . Is there any way to realize this?
You can use Hide()
<script src="scripts/jquery-1.10.2.js"></script>
<script>
$(document).ready(function () {
$("#c").hide();
})
</script>
Try this using jQuery:
$("#c").hasClass("active") {
$("#container").hide()
} else {
$("#container").show()
}
Or if you prefer a more CSS method:
$("#c").hasClass("active") {
$("#container").css("visibility", "hidden")
} else {
$("#container").css("visibility", "visible")
}
First add the class for the all '''li''' items
class = "nav-tabs"
Second, we need to add '''$(document).ready(function()''' to refresh the page, thus the "class" will be updated
$(".nav-tabs").on( "click", function() {
$(document).ready(function() {
bindClick();
})
});
function bindClick(){
if ( $("#c").hasClass("active")){
$("#container").hide()
} else {
$("#container").show();
}
}

Bootstrap 3 panel group collapse outside of group

I think I am doing this a slightly silly way, and so am happy to take suggestions for a new approach.
I am creating a accordion style dropdown nav for mobile but I want the target divs to be outside of the panel group. My code is of the form:
<div class='panel-group' id='accordian'>
<div class='mystyles'>
<ul>
<li>
<div class='nav-item'>
<a data-toggle='collapse' data-parent='#accordian' href='#target-one-id'>Item 1</a>
</div>
</li>
.... more list items here...
</ul
</div>
<!-- the collapsed divs start here -->
<div id='target-one-id' class='clearfix collapse panel-collapse'>
...content
</div>
... more target divs here
</div> <!-- end panel group -->
I have chosen to do this as I need to style the links differently to the collapsed divs and I want them to appear lower down the page. It does generally work, however, to make a target div collapse you have to click on it's parent link. I want the child to collapse whenever any of the list links are clicked. Or in other words I want only one target div visible at any one time.
I may just not understand bootstrap but how would I go about doing this?
EDIT: A bad solution
So I have a slightly rough solution where I add js code of the form:
$("#target-one").on("show.bs.collapse", function(){
$("#target-two").collapse('hide');
$("#target-three").collapse('hide');
});
This works but the transition animation is jerky and the targets being closed appear to reopen and close as they are hidden. What is a better solution?
$("#target-one").on("show.bs.collapse", function(){
$("#target-two").collapse('hide');
$("#target-three").collapse('hide');
});
$("#target-two").on("show.bs.collapse", function(){
$("#target-one").collapse('hide');
$("#target-three").collapse('hide');
});
$("#target-three").on("show.bs.collapse", function(){
$("#target-two").collapse('hide');
$("#target-one").collapse('hide');
});
.mystyles ul {
list-style-type:none;
margin: 0;
padding: 0;
}
.mystyles ul li {
display:inline-block;
}
.mycontent {
background-color:orange;
}
.one {
height:300px;
background-color:pink;
}
.two {
width:200px;
height:500px;
}
<head>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<div class='panel-group' id='accordian'>
<div class='mystyles'>
<ul>
<li>
<div class='nav-item'>
<a data-toggle='collapse' data-parent='#accordian' href='#target-one'>Item 1</a>
</div>
</li>
<li>
<div class='nav-item'>
<a data-toggle='collapse' data-parent='#accordian' href='#target-two'>Item 2</a>
</div>
</li>
<li>
<div class='nav-item'>
<a data-toggle='collapse' data-parent='#accordian' href='#target-three'>Item 3</a>
</div>
</li>
</ul </div>
<!-- the collapsed divs start here -->
<div id='target-one' class='clearfix collapse panel-collapse'>
<div class='mycontent one'>
content...
</div>
</div>
<div id='target-two' class='clearfix collapse panel-collapse'>
<div class='mycontent two'>
content...
</div>
</div>
<div id='target-three' class='clearfix collapse panel-collapse'>
<div class='mycontent three'>
content...
</div>
</div>
</div>
<!-- end panel group -->
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
Ok so the snippet seems to work properly... I am now a little confused. My actual code is almost identical except for some dynamic content which is inserted into the target divs.
Could resizing of the hidden diff cause problems? I do not know how to simulate that in the snippet.

Toggle only this item

i've a problem to toggle only (this) 1 'card'
$('a[rel="toggle_comments"]').click(function(){
var div = $('.comments');
$(div, this).slideToggle('slow');
});
<!-- This is a example code -->
<section>
<div class="mainclass">
[...]
<div class="select">
Test
</div>
</div>
<ul class="comments">
<!-- Content -->
</ul>
</section>
<section>
<div class="mainclass">
[...]
<div class="select">
Test
</div>
</div>
<ul class="comments">
<!-- Content -->
</ul>
</section>
[...]
When I clicked at 'toggle_comments', toggle all '.comments' classes, not only that, I have clicked. Anyone have any ideas?
Sorry for my bad english.
I hope you understand what I mean - Thanks :-)
If you want to toggle only the .comments under the <section> tag your link is in, do this:
$('a[rel="toggle_comments"]').click(function(){
// find the closest section tag (parent) and find all child `.comments`
var $comments = $(this).closest('section').find('.comments');
$comments.slideToggle('slow');
});
If you want to toggle all .comments:
$('a[rel="toggle_comments"]').click(function(){
$('.comments').slideToggle('slow');
});

Make One NAV link active across multiple sections (using classes???)

I need to have only one nav link in active state when a user goes through multiple sections of my website. How do I make the proper edits to this JS to make that happen?
For instance, if the default nav link id = #dinos_
I want all my sections that use section ids like #dinos_trex, #dinos_raptor, #dinos_triceratops to keep making the nav id that = #dinos_ to stay in the active state in the nav.
After further research, would someone be able to code something with 'classes'?
Lets say a set of divs share a certain class name, in this case "dinos_" how can I set an active state for just one nav item if the user is on 'any' of the related "dinos_" sections????
here is the current jquery Im using:
var sections = $('section'), nav = $('nav'), nav_height = nav.outerHeight();
$(window).on('scroll', function () {
var cur_pos = $(this).scrollTop();
sections.each(function() {
var top = $(this).offset().top - nav_height,
bottom = top + $(this).outerHeight();
if (cur_pos >= top && cur_pos <= bottom) {
nav.find('a').removeClass('active');
sections.removeClass('active');
$(this).addClass('active');
nav.find('a[href="#'+$(this).attr('id')+'"]').addClass('active');
}
});
});
Im guessing this snippet of code in particular is where I need someone to help me redefine?
nav.find('a[href="#'+$(this).attr('id')+'"]').addClass('active');
Here is my HTML
<header id="header">
<!-- Nav -->
<nav id="nav">
<ul>
<li>DINOS</li> /*multiple unique section ids that contain the word dinos_ in their id name should set this to 'active */
<li>ROBOTS</li> /*multiple unique section ids that contain the word robots_ in their id name should set this to 'active */
<li>UNDEAD</li> /*multiple unique section ids that contain the word undead_ in their id name should set this to 'active */
</ul>
</nav>
</header>
<section id="dinos_" class="main style2 right dark fullscreen">
<div class="content box style2">
<header>
<h2>DINOSAURS INTRO</h2>
</header>
<p>
Intro to the dinos</p>
</div>
up
down
</section>
<section id="dinos_trex" class="main style2 left dark fullscreen">
<div class="content box style2">
<header>
<h2>T-REX</h2>
</header>
<p>
Section for the T-rex</p>
</div>
up
down
</section>
<section id="dinos_raptor" class="main style2 left dark fullscreen">
<div class="content box style2">
<header>
<h2>THE RAPTOR</h2>
</header>
<p>
Section for the raptor/p>
</div>
up
down
</section>
<section id="robots_" class="main style2 left dark fullscreen">
<div class="content box style2">
<header>
<h2>ROBOTS INTRO</h2>
</header>
<p>
Section for the Robots Intro</p>
</div>
up
down
</section>
<section id="robots_gunner" class="main style2 left dark fullscreen">
<div class="content box style2">
<header>
<h2>THE ROBOT GUNNER</h2>
</header>
<p>
Section for the gunner</p>
</div>
up
down
</section>
Using the waypoints plugin:
http://imakewebthings.com/waypoints/
UPDATED
JS:
$('section').waypoint({
handler: function (direction) {
$(".active").removeClass("active");
$("nav a[href=\"#" +this.element.id + "\"").addClass("active");
}
});
HTML with some minor changes:
<header id="header">
<!-- Nav -->
<nav id="nav">
<ul>
<li>DINOS
</li>
<li>ROBOTS
</li>
<li>UNDEAD
</li>
</ul>
</nav>
</header>
<section id="dinosaurs" class="main style2 right dark fullscreen">
<div class="content box style2">
<header>
<h2>DINOSAURS INTRO</h2>
</header>
<p>Intro to the dinos</p>
</div> up
down
</section>
<section id="dinosaurs_trex" class="main style2 left dark fullscreen">
<div class="content box style2">
<header>
<h2>TREX</h2>
</header>
<p>Section for the Trex</p>
</div> up
down
</section>
<section id="dinosaurs_raptor" class="main style2 left dark fullscreen">
<div class="content box style2">
<header>
<h2>THE RAPTOR</h2>
</header>
<p>Section for the Trex</p>
</div> up
down
</section>
Here's a fiddle:
http://jsfiddle.net/4qwawrgx/
change your this code
nav.find('a[href="#'+$(this).attr('id')+'"]').addClass('active');
to this
function activateNav() {
var hashValue = window.location.hash.substr(1);
$('body').find('a[href="#'+ hashValue +'"]').addClass('active');
}
$( document ).ready(function() {
activateNav();
$('a').on('click', function() {
activateNav();
});
});

Categories

Resources