Save State flex menu after reload - javascript

I'm trying to save the last active state of a flex menu after page reload.
The localStorage function doesn't seem to work …
var $elements = $('li.b-accordion__cell');
$elements.click(function() {
localStorage.activeItem = $elements.index(this);
});
$(document).ready(function() {
if (localStorage.activeItem) {
$elements
.get(localStorage.activeItem)
.css({
'flex': '3'
});
}
});
See Codepen here

try wrapping the whole thing in the doc ready, maybe the elements aren't created for the click handler to be added to them, made it an answer as it worked......[enter link description here][1]
Updated Codepen
$(document).ready(function() {
var $elements = $('li.b-accordion__cell');
$elements.click(function() {
$(this).css({
'flex': '3'
});
$elements.not(this).css({
'flex': '1 3'
});
});
var $elements = $('li.b-accordion__cell');
$elements.click(function() {
localStorage.activeItem = $elements.index(this);
});
if (localStorage.activeItem) {
$($elements.get(localStorage.activeItem))
.css({
'flex': '3'
});
}
});
body {
padding: 0 0px;}
.b-accordion {
display: flex;
width: 600px;
height: 200px;
padding: 0;
margin: 0;
flex-wrap: row nowrap;}
.b-accordion__cell {
padding: 16px;
overflow: hidden;
transition: flex 0.3s;
flex: 1 3;}
.b-accordion__cell: {
flex: 3;}
a {color: white !important;}
.b-accordion__cell:nth-child(1) {
background: red;}
.b-accordion__cell:nth-child(2) {
background: blue;}
.b-accordion__cell:nth-child(3) {
background: green;}
.b-accordion__content {
position: relative;
display: block;
color: black;
width: 600px;}
.b-accordion__content__title {
position: absolute;
top: 2px;
left: 0;
display: block;
width: 300px;
transform-origin: 0 0 0;}
.b-accordion__content__text {
padding-left: 0px;
padding-top: 75px;
font-size: 20px;
margin: 0;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul class="b-accordion">
<li class="b-accordion__cell">
<article class="b-accordion__content">
<h3 class="b-accordion__content__title">Section 1</h3>
<p class="b-accordion__content__text">
tag1
tag2
tag3
tag4
tag5
</p>
</article>
</li>
<li class="b-accordion__cell">
<article class="b-accordion__content">
<h3 class="b-accordion__content__title">Section 2</h3>
<p class="b-accordion__content__text">
tag6
tag7
tag8
tag9
tag10
</p>
</article>
</li>
<li class="b-accordion__cell">
<article class="b-accordion__content">
<h3 class="b-accordion__content__title">Section 3</h3>
<p class="b-accordion__content__text">
tag11
tag12
tag13
tag14
tag15
</p>
</article>
</li>
</ul>

Great work creating this accordion. I luv it! You were so close.
Instead of using an assignment operator:
localStorage.activeItem = $elements.index(this);
use the .setItem() method.
localStorage.setItem("activeItem", $elements.index(this));
Forked your PEN here
peace all

Related

How to use <ul> to display scrolling contents?

I came across https://minimill.co/ and saw it as a good example to what I'm trying to achieve.
I made an attempt to display the listed items like the site:
.wrap {
display: block;
list-style: none;
position: relative;
padding: 0;
margin: 0;
border: 0;
li {
background-color: green;
}
}
.content {
margin: 0 auto;
max-width: 66rem;
width: 90%;
padding: 0;
border: 0;
position: relative;
}
.right-details {
display: inline-block;
float: right;
box-size: border-box;
width: 33.33333%;
}
.left-img {
display: inline-block;
float: left;
box-sizing: border-box;
width: 66.66666%;
img {
width: 50px;
}
}
<ul class="wrap">
<li>
<div class="content">
<div class="left-img">
<img src="/assets/img/macbook-image.png"/>
</div>
<h2 class="right-details">
Item 1
</h2>
</div>
</li>
<li>
<div>
<h2>
Item 2
</h2>
</div>
</li>
</ul>
But the first <li> disappears.
How can I display my contents in one long scroll-like how https://minimill.co/ is doing? Am I doing it correctly as implemented on the site? Any guidance or insight on mimicking it more closely would be appreciated.
You should use min-height:100vh instead of height:100vh;. Please check my fiddle
// select all elements with data-background attribute
var lis = document.querySelectorAll("[data-background]");
// create empty array
var heights = [];
// use for loop to "discover" all of the elements in lis array
for(var i = 0; i < lis.length; i++){
// get element's distance from top
var distanceFromTop = lis[i].offsetTop;
// get value from data-backgrount attribute
var background = lis[i].getAttribute("data-background");
// push background and distance to heights array
heights.push({background: background, distance: distanceFromTop});
};
// check if page was scrolled
window.addEventListener("scroll", function(evt){
// if page was scrolled what's the user's distance from top
var distanceFromTop = this.scrollY;
// find distances in heights array
heights.forEach(function(height) {
// check if user reached another checkpoint
if(height.distance < distanceFromTop) {
// if so, change the background to value that we got from data-background attribute
//
document.body.className = height.background;
}
});
});
body {
transition: background-color .8s ease;
-webkit-transition: background-color .8s ease;
}
body.blue { background-color: #39f; }
body.red { background-color: #FF351A; }
body.dark { background-color: #222; }
body.yellow { background-color: #fd3; }
body.deep-blue { background-color: #417ABA; }
body.white { background-color: #fff; }
body.beige { background-color: #F7D693; }
li {
min-height: 100vh;
list-style-type:none;
}
<body class="blue">
<ul>
<li data-background="blue"></li>
<li data-background="red"></li>
<li data-background="dark"></li>
<li data-background="yellow"></li>
<li data-background="deep-blue"></li>
<li data-background="white"></li>
<li data-background="beige"></li>
</ul>
</body>
You should use min-height:100vh instead of height:100vh;. Please check my fiddle
So easiest approach seems to be using height: 100vh;, which stands for hundredths of the viewport height. (see: quirksmode.org).
body, ul, li {
height: 100%;
}
li { height: 100vh; }
ul { list-style-type: none; }
.a { background-color: red; }
.b { background-color: yellow; }
.c { background-color: black; }
.d { background-color: green; }
.e { background-color: orange; }
.f { background-color: pink; }
<body>
<ul>
<li class="a"></li>
<li class="b"></li>
<li class="c"></li>
<li class="d"></li>
<li class="e"></li>
<li class="e"></li>
</ul>
</body>
But: it is not supported for IE <= 10 and Android <= 4.3.
(see: caniuse).
What minimill does on their website is using two <ul> tags:
<ul class="backgrounds"> which has it's position: fixed (love self-descriptive class names);
<ul class="sections"> which stores actual content of the web site;
and the key to make it all work: .sections li with padding: 16rem 0 0; (which means: padding-top: 16rem;). It is all customized to the need of images they use.
See here:
body, li, ul { /* RESET */
margin: 0;
padding: 0;
border: 0;
font: inherit;
vertical-align: baseline;
}
html, body { height: 100%; }
body {
line-height: 1.5;
position: relative;
}
ul { list-style-type: none; }
.backgrounds {
height: 100%;
display: block;
bottom: 0;
left: 0;
position: fixed;
right: 0;
top: 0;
z-index: 1;
}
.backgrounds li {
height: 100%;
left: 0;
opacity: 0;
position: absolute;
top: 0;
transition: .5s ease opacity;
width: 100%;
z-index: 1;
}
.sections {
position: relative;
transition: .5s ease opacity;
z-index: 2;
}
.sections li { padding: 16rem 0 0; }
.a { background-color: red; }
.b { background-color: yellow; }
.c { background-color: black; }
.d { background-color: green; }
.e { background-color: orange; }
.f { background-color: pink; }
<body>
<ul class="backgrounds">
<li class="a"></li>
<li class="b"></li>
<li class="c"></li>
<li class="d"></li>
<li class="e"></li>
<li class="f"></li>
</ul>
<ul class="sections">
<li class="a"><p>Lorem ipsum dolor sit amet;</p></li>
<li class="b"><p>Lorem ipsum dolor sit amet;</p></li>
<li class="c"><p>Lorem ipsum dolor sit amet;</p></li>
<li class="d"><p>Lorem ipsum dolor sit amet;</p></li>
<li class="e"><p>Lorem ipsum dolor sit amet;</p></li>
<li class="f"><p>Lorem ipsum dolor sit amet;</p></li>
</ul>
</body>
Furthermore, all the background swaping is made with JS.
Based on the example you provided, the first list item should be height: 100vh; and the height of the other items will be based on the content itself. In the code below, I added a bit of script that scrolls from the first item to the second when the "Scroll Down" anchor tag is clicked.
Check out my jsfiddle.
Here's the HTML:
<ul id="wrap">
<li>
<div>
<h2>Item 1</h2>
<div id="scroll-down">
Scroll Down
</div>
</div>
</li>
<li id="scrollto">
<div>
<h2>Item 2</h2>
</div>
</li>
<li>
<div>
<h2>Item 3</h2>
</div>
</li>
</ul>
Here's the SCSS:
$width: 100%;
$height: 100%;
html, body {
width: $width;
height: $height;
margin: 0;
padding: 0;
}
#wrap {
display: inline-block;
list-style: none;
padding: 0;
margin: 0;
width: $width;
height: $height;
li {
display: block;
overflow: hidden;
position: relative;
width: $width;
}
li:first-child {
background-color: green;
height: 100vh;
}
li:not(:first-child) {
min-height: 400px;
}
li:nth-child(2) {
background-color: lightgreen;
}
li:last-of-type {
background-color: lightblue;
}
}
h2 {
margin-top: 0;
}
#scroll-down {
position: absolute;
bottom: 15px;
width: $width;
}
#scroll-down a {
display: block;
text-align: center;
color: #ffffff;
}
Here's a bit of JQuery:
$(document).ready(function(){
$("#scroll-down").click(function() {
$('html, body').animate({
scrollTop: $("#scrollto").offset().top
}, 1000);
});
});
What you are looking at https://minimill.co/ is in fact two ul's, one is being used to show the background color and the other is used to show the content. It seems that the ul associated with the background color does have a javascript event listener that tracks your the window scroll and depending on what content is being shown, the corresponding background color is displayed.
Yes, you are on the right path. In fact, this particular page has a very large top padding (16rem = 16 * 16px = 256px) to centralize the content and depending on the window size, it has different css classes.
Regarding your question, I did try it and the first item appears to me.
It depends on what from Minimill's site, that you want to achieve. Minimill does have that fancy background-color-change, which is an event-listener - but it sounds like, that you just want to have the sections as they do?
Such as:
Section about: We are Minimill
Section about: Redspread
Section about: KPCB
...
...
If it's just that you want to have sections in the same way, then that can achieve quite easily. If you haven't heard of it, then I would point you in the direction of Bootstrap which is a CSS-library that does A LOT for you. When I first heard of it, then I thought 'That sounds like a hassle to look into', - but it's really quite magical, how much time you save by spending a couple of hours understanding how it works.
You can also code the whole thing yourself, such as: https://jsfiddle.net/2awczzcc/2/
And here's the code:
<ul class="wrap">
<li>
<div class="content">
<div class="left-container">
<img src="http://vignette2.wikia.nocookie.net/fantheories/images/4/43/Toy-Story-Theme-Song-6.jpg/revision/latest?cb=20140624192735"/>
</div>
<div class="right-container">
<h2>
Item 1
</h2>
<p>
Text text text.
</p>
</div>
</div>
</li>
<li>
<div class="content">
<div class="left-container">
<img src="http://vignette2.wikia.nocookie.net/fantheories/images/4/43/Toy-Story-Theme-Song-6.jpg/revision/latest?cb=20140624192735"/>
</div>
<div class="right-container">
<h2>
Item 2
</h2>
<p>
Text text text.
</p>
</div>
</div>
</li>
<li>
<div class="content">
<div class="left-container">
<img src="http://vignette2.wikia.nocookie.net/fantheories/images/4/43/Toy-Story-Theme-Song-6.jpg/revision/latest?cb=20140624192735"/>
</div>
<div class="right-container">
<h2>
Item 2
</h2>
<p>
More text, more text, more text.
</p>
</div>
</div>
</li>
</ul>
And the CSS:
.wrap {
display: block;
list-style: none;
position: relative;
padding: 0;
margin: 0;
border: 0;
width: 100%;
}
.wrap li {
width: 100%;
clear: both;
display: block;
min-height: 200px;
float: left;
margin: 0;
padding: 0;
}
.wrap li:first-child {
background-color: green;
}
.wrap li:nth-child(2) {
background-color: blue;
}
.wrap li:nth-child(3) {
background-color: yellow;
}
.content {
margin: 0 auto;
max-width: 66rem;
width: 90%;
padding: 0;
border: 0;
position: relative;
}
.left-container {
float: left;
width: 48%;
overflow: hidden;
}
.right-container {
float: right;
width: 48%;
overflow: hidden;
}
.left-container img {
display: inline-block;
float: left;
box-sizing: border-box;
max-width: 100%;
height: auto;
margin: 25px 0 0 0;
}
Link to jsFiddle
HTML Code:
<ul>
<li id="one" data-color="#16A085">
<h2>Section One</h2>
</li>
<li id="two" data-color="#C0392B">
<h2>Section Two</h2>
</li>
<li id="three" data-color="#ff44AD">
<h2>Section Three</h2>
</li>
<li id="four" data-color="#f88f18">
<h2>Section Four</h2>
</li>
<li id="five" data-color="#E91E63">
<h2>Section Five</h2>
</li>
</ul>
Javascript
$(window).on("scroll touchmove", function() {
if ($(document).scrollTop() >= $("#one").position().top) {
$('body').css('background', $("#one").attr("data-color"));
};
if ($(document).scrollTop() > $("#two").position().top) {
$('body').css('background', $("#two").attr("data-color"))
};
if ($(document).scrollTop() > $("#three").position().top) {
$('body').css('background', $("#three").attr("data-color"))
};
if ($(document).scrollTop() > $("#four").position().top) {
$('body').css('background', $("#four").attr("data-color"))
};
if ($(document).scrollTop() > $("#five").position().top) {
$('body').css('background', $("#five").attr("data-color"))
};
});
CSS
li {
display: block;
width: 100%;
height: 100vh;
}
body {
background: #16A085;
color: #fff;
margin: 0;
transition: all 550ms ease;
will-change: background;
}
All you have to do is add height: 100vh; to the style for LI and you should be set.
Working codepen (I had to modify the CSS a bit since codepen doesn't support sass).
If I misunderstood the question and that's not what you're looking for, let me know.
You can set the height of ul or your div.
Also, set overflow to auto:
<ul style="width: 300px; height: 200px; overflow: auto">
<li>items</li>
<li>items</li>

Make expandable div start closed

I have this code which, when the 'A' is clicked, extra content comes down. But, I want the extra content to start hidden. How would I do this?
Here is the code:
HTML:
<section class="box2">
<header class="box-head">
<div class="box-title fr"> <span class="box-icon"></span>
</div> <a class="box-toggle fl active" href="#">A</a>
</header>
<div class="box-content active">
Content</div>
</section>
Javascript:
$("a.box-toggle").on('click', function () {
$('div.box-content').slideToggle(200).toggleClass('active');
});
CSS:
.widget-toggle {
display: block;
overflow: hidden;
text-indent: -9999px;
width: 18px;
height: 9px;
margin-top: 15px;
margin-left: 13px;
background: url(../img/sidebar-arrows.png) no-repeat 0 -18px;
}
.widget-toggle.active {
background: url(../img/sidebar-arrows.png) no-repeat 0 0;
}
Set the .box-content elements to display: none in CSS by default:
.box-content {
display: none;
}
Updated fiddle
Use this way. Replace your code:
$("a.box-toggle").on('click', function () {
$('div.box-content').slideToggle(200).toggleClass('active');
});
With the following:
$('div.box-content').hide();
$("a.box-toggle").on('click', function () {
$(this).closest(".box-head").next('div.box-content').slideToggle(200).toggleClass('active');
});
The reason for change is, if you have multiple .box-head, then it will trigger the slide on everything and not just one.

How do I stop my toggle function at the first and last list items?

I have an unordered list of numbers that scroll.
The selected/middle list item needs to show in a yellow font color.
I have applied a class toggle function to my scroll buttons. I just need help figuring out a solution that will stop the class toggle function when I get to my first and last list item.
The solution I need must allow for the addition and removal of list items without the need to adjust the JavaScript if possible.
As usual, I know this is light work for you guys.
Any and all help is very much appreciated.
HTML
<div id="container">
<div class="box">
<ul id="ulscroller">
<li value="22"> </li>
<li id="1" class="active">1</li>
<li id="2" class="target">2</li>
<li id="3" class="active">3</li>
<li id="4" class="target">4</li>
<li id="5" class="active">5</li>
<li value="21" class="lastitem"> </li>
</ul>
</div>
<!--Button Controls-->
<div class="buttholder">
<a href="#">
<button class="scrollup">UP</button>
</a>
<a href="#">
<button class="buttok">OK</button>
</a>
<a href="#">
<button class="scroll">Down</button>
</a>
</div>
CSS
.box li.target {
color: #fff;
}
.box li.active {
color: #fada15;
}
#container {
position: relative;
width: 310px;
height: 268px;
background: #000;
}
button {
width: 72px;
height: 72px;
margin-top: 5px;
margin-bottom: 5px
}
#container div {
position: absolute;
}
ul li {
font-size: 42px;
color: #fff;
overflow: hidden;
font-family: arial;
text-align: center;
}
li {
list-style-type: none;
margin-bottom: 30px;
margin-top: 32px;
}
.box {
border: 0px #00f solid;
height: 247px;
width: 199px;
overflow: hidden;
}
#container div.buttholder {
position: relative;
float: right;
border: 0px #0f0 solid;
width: 72px;
height: 236px;
top: 11px;
right: 13px;
}
.lastitem {height: 22px;}
JavaScript
$(document).ready(function() {
$('.scroll').click(function() {
$('li').toggleClass('active', 'target');
$('.box').animate({
scrollTop: '+=80'
}, 100);
});
});
$(document).ready(function() {
$('.scrollup').click(function() {
$('li').toggleClass('active', 'target');
$('.box').animate({
scrollTop: '-=80'
}, 100);
});
});
When toggleClass() has two parameters, the second parameter is expected to be a boolean (and not just truthy/falsy).
Therefore, 'target' is ignored in this code:
$('li').toggleClass('active', 'target');
What you could do is set the first li as "active," then move the active class to the previous or next li, depending on which button is pressed.
If the next li is the last child, or the previous li is the first child, then don't move the active class.
Snippet
$(document).ready(function() {
$('.scroll').click(function() {
var current= $('li.active'),
next= current.next().not(':last-child');
if(next.length) {
next.addClass('active');
current.removeClass('active');
}
$('.box').animate({
scrollTop: '+=80'
}, 100);
});
$('.scrollup').click(function() {
var current= $('li.active'),
prev= current.prev().not(':first-child');
if(prev.length) {
prev.addClass('active');
current.removeClass('active');
}
$('.box').animate({
scrollTop: '-=80'
}, 100);
});
});
.box li.target {
color: #fff;
}
.box li.active {
color: #fada15;
}
#container {
position: relative;
width: 310px;
height: 268px;
background: #000;
}
button {
width: 72px;
height: 72px;
margin-top: 5px;
margin-bottom: 5px
}
#container div {
position: absolute;
}
ul li {
font-size: 42px;
color: #fff;
overflow: hidden;
font-family: arial;
text-align: center;
}
li {
list-style-type: none;
margin-bottom: 30px;
margin-top: 32px;
}
.box {
border: 0px #00f solid;
height: 247px;
width: 199px;
overflow: hidden;
}
#container div.buttholder {
position: relative;
float: right;
border: 0px #0f0 solid;
width: 72px;
height: 236px;
top: 11px;
right: 13px;
}
.lastitem {
height: 22px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div class="box">
<ul id="ulscroller">
<li value="22"> </li>
<li id="1" class="active">1</li>
<li id="2">2</li>
<li id="3">3</li>
<li id="4">4</li>
<li id="5">5</li>
<li value="21" class="lastitem"> </li>
</ul>
</div>
<!--Button Controls-->
<div class="buttholder">
<a href="#">
<button class="scrollup">UP</button>
</a>
<a href="#">
<button class="buttok">OK</button>
</a>
<a href="#">
<button class="scroll">Down</button>
</a>
</div>
There are two solutions:
Solution #1
You can use the .first and .last functions of jQuery:
$('li').not($('li').first()).not($('li').last())
I am choosing all "li" elements,and then remove the first one and the last one.
https://api.jquery.com/last/
Solution #2:
You can also use slice function, like in arrays:
$('li').slice(1,-1)
This will remove the first and last item in the 'li' array of elements.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
Answer of Rick Hitchcock is perfect, however I would just like to add one point.
For every jQuery function you call, you don't need to encapsulate it in a $(document).ready(function() or jQuery(document).ready(function($). A page manipulation begins only when the page has been loaded. So you don't need to check it twice whether the page has been loaded or not.

Remove class from parent on child click - jQuery

I am completely stuck on this problem (see jsfiddle here). I have a very simple set up where an onclick adds a class which displays an element. Within this element is a close button for which the onclick should remove the class from the parent. But this is not working.
I have tried removeAttr('class') which also fails. Looking in chrome inspector I can see the selector is right and is targeting the parent, but the class cannot be removed.
This is part of a larger project so I cannot change the html structure. But welcome any suggestions on how to do this in jQuery.
HTML:
<div class="print-wrap">
<ul>
<li class="settings-tab">+</i>
<div class="settings-wrap">
<div class="iphone-close">x</div>
<div class="content"></div>
</div>
</li>
<li class="img">
<img src="http://placehold.it/250x166">
</li>
</ul>
</div>
jQuery:
jQuery(function(){
jQuery('.settings-tab').click(function(){
var $this = jQuery(this);
$this.addClass('settings-out');
});
jQuery('.settings-wrap .iphone-close').click(function(e){
var $this = jQuery(this);
var $parent = $this.parent('.settings-wrap').parent('.settings-tab');
$parent.removeClass('settings-out');
});
});
Use event.stopPropagation in the event handler of close button. The event is bubbled up to the parent .settings-tab and the handler of is is executed which is adding the class again.
Updated Fiddle
jQuery(function() {
//settings tab:
jQuery('.settings-tab').click(function() {
jQuery(this).addClass('settings-out');
});
//Settings tab close
jQuery('.settings-wrap .iphone-close').click(function(e) {
jQuery(this).closest('.settings-out').removeClass('settings-out');
e.stopPropagation();
});
});
.print-wrap {
width: 250px;
height: 250px;
overflow: hidden;
position: relative;
display: block;
margin: 0 auto;
margin-bottom: 20px;
background-color: #D6A0A0;
}
.print-wrap ul {
list-style: none;
margin: 0;
padding: 0;
height: 100%;
position: relative;
left: 0;
}
.settings-tab {
width: 30px;
height: 30px;
position: absolute;
top: 0;
right: 0;
text-align: center;
background: #f5d43f;
transition: all .3s ease-in-out;
transition-delay: .25s;
z-index: 4;
cursor: pointer;
}
.settings-tab .settings-wrap {
width: 250px;
right: -250px;
height: 250px;
background: lightblue;
position: absolute;
top: 0;
}
.settings-out {
right: 250px;
}
.iphone-close {
background: pink;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="print-wrap">
<ul>
<li class="settings-tab">+</i>
<div class="settings-wrap">
<div class="iphone-close">x</div>
<div class="content"></div>
</div>
</li>
<li class="img">
<img src="http://placehold.it/250x166">
</li>
</ul>
</div>
jQuery(document).on('click','.settings-wrap .iphone-close',function(e){
var $this = jQuery(this);
var $parent = $this.parent('.settings-wrap').parent('.settings-tab');
$parent.removeClass('settings-out');
});
});
try changing jQuery(document).on('click','.settings-wrap .iphone-close',function(e){
demo

How can you make CSS on-hover content stay in place when you click or stop hovering using Javascript?

I have a body system feature I'd like to implement. When the user hovers over a body part, it highlights and shows information on that specific body part. I've coded the CSS the way I want it, but I don't know anything about JavaScript to get the information to stick when the body part is clicked or the mouse leaves the hover state.
I've searched the forum and found similar issues and have spent hours trying to figure this out myself from others' javascript solutions - I'm at the point where I need to ask for help.
Here is a flash prototype I made of my desired effect:
http://inwavemedia.com/temp/proto/Main.html
Here is the live HTML if you want to take a look at what I have now:
http://inwavemedia.com/temp/excretory.html
Here is my code:
<style type="text/css">
#bodysystem-excretory {
width: 618px;
height: 504px;
background: url(excretory.png) no-repeat;
margin: 10px auto; padding: 0;
position: relative;
border: 1px solid #999;
}
#bodysystem-excretory li {
margin: 0;
padding: 0;
list-style: none;
display: block;
position: absolute;
}
#bodysystem-excretory a {
display: block;
/* text-indent: -9999px;*/
text-decoration: none;
}
#esoph {
left: 85px;
top: 41px;
width: 46px;
height: 94px;
z-index: 10;
}
#lungs {
left: 76px;
top: 84px;
width: 84px;
height: 68px;
z-index: 20;
}
#bladder {
left: 87px;
top: 148px;
width: 64px;
height: 104px;
z-index: 30;
}
#esoph a {
height: 94px;
}
#lungs a {
height: 67px;
}
#bladder a {
height: 104px;
}
#esoph a:hover {
background-image: url(excretory.png);
background-repeat: no-repeat;
background-position: -25px -561px;
}
#lungs a:hover {
background-image: url(excretory.png);
background-repeat: no-repeat;
background-position: -105px -523px;
}
#bladder a:hover {
background-image: url(excretory.png);
background-repeat: no-repeat;
background-position: -114px -618px;
}
.info span{
display: none
}
.info{
position:relative;
z-index:1124;
color:#000;
}
.info:hover{
z-index:1125;
}
.info:hover span{
display:block;
position:absolute;
top:-30px;
left:155px;
width:370px;
color:#000;
background-color:#FFFFFF;
}
</style>
</head>
<body>
<ul id="bodysystem-excretory">
<li id="esoph">
<span id="esoph-info"><h3>Esophagus</h3><p>This is esophagus information. This is esophagus information. This is esophagus information. This is esophagus information. This is esophagus information. This is esophagus information. This is esophagus information. </p></span>
</li>
<li id="lungs"><span id="lungs-info"><h3>Lungs</h3></span></li>
<li id="bladder"><span id="bladder-info"><h3>Bladder</h3></span></li>
</ul>
Below is the required changes you would require to do:
<head>
<title>Untitled Page</title>
<style type="text/css">
#bodysystem-excretory
{
width: 618px;
height: 504px;
background: url(excretory.png) no-repeat;
margin: 10px auto;
padding: 0;
position: relative;
border: 1px solid #999;
}
#bodysystem-excretory li
{
margin: 0;
padding: 0;
list-style: none;
display: block;
position: absolute;
}
#bodysystem-excretory a
{
display: block; /* text-indent: -9999px;*/
text-decoration: none;
}
#esoph
{
left: 85px;
top: 41px;
width: 46px;
height: 94px;
z-index: 10;
}
#lungs
{
left: 76px;
top: 84px;
width: 84px;
height: 68px;
z-index: 20;
}
#bladder
{
left: 87px;
top: 148px;
width: 64px;
height: 104px;
z-index: 30;
}
#esoph a
{
height: 94px;
}
#lungs a
{
height: 67px;
}
#bladder a
{
height: 104px;
}
#esoph a:hover
{
background-image: url(excretory.png);
background-repeat: no-repeat;
background-position: -25px -561px;
}
#lungs a:hover
{
background-image: url(excretory.png);
background-repeat: no-repeat;
background-position: -105px -523px;
}
#bladder a:hover
{
background-image: url(excretory.png);
background-repeat: no-repeat;
background-position: -114px -618px;
}
.info span
{
display: none;
}
.info
{
position: relative;
z-index: 1000;
color: #000;
}
#bodysystem-excretory li[selected='true'] .info
{
z-index:1200;
}
#bodysystem-excretory li[selected='true'] .info span
{
display: block;
position: absolute;
top: -30px;
left: 155px;
width: 370px;
color: #000;
background-color: #FFFFFF;
}
.info:hover
{
z-index: 1125;
}
.info:hover span
{
display: block;
position: absolute;
top: -30px;
left: 155px;
width: 370px;
color: #000;
background-color: #FFFFFF;
}
</style>
<script type="text/javascript">
function SelectOrgan(obj)
{
var parentObj = obj.parentNode;
var organs = document.getElementById("bodysystem-excretory").getElementsByTagName("li");
for (var i = 0, len = organs.length; i < len; i++)
{
organs[i].setAttribute("selected", "false");
}
parentObj.setAttribute("selected", "true");
}
</script>
</head>
<body>
<ul id="bodysystem-excretory">
<li id="esoph" selected="false"><a href="#" class="info" onclick="SelectOrgan(this)"><span id="esoph-info">
<h3>
Esophagus</h3>
<p>
This is esophagus information. This is esophagus information. This is esophagus
information. This is esophagus information. This is esophagus information. This
is esophagus information. This is esophagus information.
</p>
</span></a></li>
<li id="lungs" selected="false"><a href="#" class="info" onclick="SelectOrgan(this)"><span id="lungs-info">
<h3>
Lungs</h3>
</span></a></li>
<li id="bladder" selected="false"><a href="#" class="info" onclick="SelectOrgan(this)"><span id="bladder-info">
<h3>
Bladder</h3>
</span></a></li>
</ul>
</body>
</html>
Note that each of the organs have been assigned an absolute position with different positions in the space. If you keep all of them the same with same left, top, width, and height, then you would achieve what you require.
I don't think either of the previous answers quite do what you were looking for. This is my suggestion. Note that the CSS is altered as well as javascript added at the end.
<html>
<head><style type="text/css">
#bodysystem-excretory {
width: 618px; height: 504px;
background: url("excretory.png") no-repeat;
margin: 10px auto; padding: 0;
position: relative;
border: 1px solid #999;
}
#bodysystem-excretory li {
margin: 0; padding: 0;
list-style: none;
display: block;
position: absolute;
}
#bodysystem-excretory a {
display: block;
/* text-indent: -9999px;*/
text-decoration: none;
}
#esoph {
left: 85px; top: 41px;
width: 46px; height: 94px;
z-index: 10;
}
#lungs {
left: 76px; top: 84px;
width: 84px; height: 68px;
z-index: 20;
}
#bladder {
left: 87px; top: 148px;
width: 64px; height: 104px;
z-index: 30;
}
#esoph a {
height: 94px;
}
#lungs a {
height: 67px;
}
#bladder a {
height: 104px;
}
#esoph:hover, #esoph.selected {
background-image: url("excretory.png") no-repeat -25px -561px;
}
#lungs:hover, #lungs.selected {
background-image: url("excretory.png") no-repeat -105px -523px;
}
#bladder:hover, #bladder.selected {
background-image: url("excretory.png") no-repeat -114px -618px;
}
.info span{
display: none
}
.info{
position:relative;
z-index:1124;
color:#000;
}
.selected .info{
z-index:1125;
}
.selected .info span {
display:block; position:absolute;
top:-30px; left:155px;
width:370px;
color:#000; background-color:#FFFFFF;
}​</style></head>
<body>
<ul id="bodysystem-excretory">
<li id="esoph">
<a href="#" class="info">
<span id="esoph-info"><h3>Esophagus</h3>
<p>
This is esophagus information. This is esophagus information.
This is esophagus information. This is esophagus information.
This is esophagus information. This is esophagus information.
This is esophagus information. </p></span></a>
</li>
<li id="lungs"><a href="#" class="info">
<span id="lungs-info"><h3>Lungs</h3></span></a>
</li>
<li id="bladder"><a href="#" class="info">
<span id="bladder-info"><h3>Bladder</h3>
</span></a></li>
</ul>​<script type="text/javascript">
// Get the <li> elements as a list called 'parts'
var parts =
document.getElementById('bodysystem-excretory').getElementsByTagName('li');
function getClickFunction(part) {
return function() {
// This is the function that will be called when one of the <li>s is clicked
if (part.className == 'selected') { // if the body part is already selected
part.className = ''; // ... then deselect it
}
else { // otherwise,
// first deselect all of the body parts
for (var i = 0; i < parts.length; i++) {
parts[i].className = '';
}
// then select the one that's been clicked
part.className = 'selected';
}
}
}
// Now, attach this function to all of the <li> elements representing body parts
for (var i = 0; i < parts.length; i++) {
parts[i].onclick = getClickFunction(parts[i]);
}​
</script></body></html>
You could add a click event which looks at what we clicked on and then changes the style permanently on clicking. This would then 'reveal' the new part permanently.
Your HTML:
<li id="lungs" onclick="highlight(this.id)">
<!--some stuff-->
</li>
And in javascript (to keep things simple, I've put it into <script> tags, just add this + your other cases into your header somewhere):
<script>
function highlight(id) {
var part = document.getElementById(id);
switch(id){
case "lungs":
part.style.backgroundImage="url(excretory.png)";
part.style.backgroundRepeat="no-repeat";
part.style.backgroundPosition="-105px 523px";
break;
//rinse repeat for all cases, don't forget the : after your case and to add break; at the end of each line
default:
//do nothing, or something, whatever
}
</script>
You can learn more about javascript switch statements here.
I think the most elegant way to go about is having two background images for each organ, [organ].png and [organ]_hover.png. then create one hover event for all the organs by applying the same class to all of them (like .organ);
at this point you can use the .css() function of JQuery to change the background of the specific organ (after getting it by using $(this).attr("id")) by adding the _hover suffix to it.
You should also maintain record of the current organ, so whenever the user hovers over a new organ, you change the previous organ's background back to [organ].png, and then save the new organ as the current one.
As for the info, just use the organ name you already fetched to make it display:block;, and the previous one display:none;
EDIT: here is a fiddle demonstrating the core functionality
HTML:
<div id="human_body">
<div class="organ" id="lungs"></div>
<div class="organ" id="liver"></div>
<div class="organ" id="pancreas"></div>
<div class="organ" id="heart"></div>
<div class="organ" id="kidneys"></div>
</div>
<div id="info">
<div id="lungs_info">
Lungs
</div>
<div id="pancreas_info">
Pancreas
</div>
<div id="liver_info">
Liver
</div>
<div id="heart_info">
Heart
</div>
<div id="kidneys_info">
Kidneys
</div>
</div>
CSS:
.organ {
width:40px;
height:40px;
margin:10px;
}
#lungs {
background:url("http://www.fishweb.co.il/organs/lungs.png");
}
#heart {
background:url("http://www.fishweb.co.il/organs/heart.png");
}
#pancreas {
background:url("http://www.fishweb.co.il/organs/pancreas.png");
}
#kidneys {
background:url("http://www.fishweb.co.il/organs/kidneys.png");
}
#liver {
background:url("http://www.fishweb.co.il/organs/liver.png");
}
#info>div {
display:none;
}
​
​JS (JQuery):
var current='';
$(".organ").mouseover(
function(){
if (current!='') {
$("#" + current).css("background","url(http://www.fishweb.co.il/organs/" + current +".png)"); // remove the highlight from the prev organ
$("#" + current + "_info").hide();
}
current = $(this).attr("id");
$(this).css("background","url(http://www.fishweb.co.il/organs/" + current +"_hover.png)"); // highlight the current organ
$("#" + current + "_info").show();
}
);​
You need to create a simple set of identifiers on the links and containers which correspond with each other.
JSFiddle: http://jsfiddle.net/Y4Wtn
<style>
.btn {font-weight:normal}
.btn.active {font-weight:bold;}
.pane {display:none;border:1px #ccc solid;padding:10px;}
.pane.active {display:block;}
</style>
<script>
// insert jquery here
$(document).read(function(){
$('.btn').click(function(){
// grab the rel value of the the link that was clicked
var thisRel = $(this).attr('rel');
// remove active class from all .btn
$('.btn').removeClass('active');
// add active class to link that was clicked
$(this).addClass('active');
// remove all active classes from .pane
$('.pane').removeClass('active');
// add class active to pane with the same rel value clicked link
$('.pane[rel="'+thisRel+'"]').addClass('active');
});
});
</script>
<ul>
<li>Item One</li>
<li>Item Two</li>
<li>Item Three</li>
</ul>
<div class="pane active" rel="1">Pane One</div>
<div class="pane" rel="2">Pane Two</div>
<div class="pane" rel="3">Pane Three</div>

Categories