toggle pictures by hovering ul li - javascript

I need it to be a javascript solution only please. Please refer to this demo.
The goal is to hover the dots on the right bottom corner and swap the images accordingly. But what it does now is showing a blank page when hovering, and the whole ul becomes vertical and goes to top left corner. What did I do wrong here???
HTML:
<div id="wrapper">
<section id="contentWrapper">
<div id="resistorContent" class="content">
<section id="resistorDetail1"><img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic1.jpg"></section>
<section id="resistorDetail2"><img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic2.jpg"></section>
<section id="resistorDetail3"><img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic3.jpg"></section>
<section id="resistorDetail4"><img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic4.jpg"></section>
<ul>
<li onMouseOver="showDetail(resistorDetail1)"></li>
<li onMouseOver="showDetail(resistorDetail2)"></li>
<li onMouseOver="showDetail(resistorDetail3)"></li>
<li onMouseOver="showDetail(resistorDetail4)"></li>
</ul>
</div>
</section>
</div>
JAVASCRIPT:
<script type="text/javascript">
var children = document.querySelectorAll('.content > section[id]')
function showDetail(target){
for (var i = 0, child; child = children[i]; i++) {
child.style.display = 'none';
}
document.getElementById(target).style.display = 'block';
}
</script>
POSSIBLE COLLIDING CSS ?:
.content section:not(:first-child) {
display: none;
}
Thank you in advance!!

TL;DR
Here is the working fiddle: https://jsfiddle.net/2qz2srqs/3/
Reason
Your code was very close, but it had a few minor issues.
The first was a copy-paste error, you had two elements with the id of resistorDetail3.
Second, your syntax for the onmouseover event was incorrect. Prefix any javascript with javascript: and ensure it has proper syntax.
Third, your showDetail method expected a string id of the element to show. In your onmouseover declaration you had showDetail(resistorDetail1) instead of showDetail('resistorDetail1').
Finally, when you javascript is referenced in the HTML, you need to make sure you load the javascript first. Just by taking a look at the developer's console you could see that it through an error "showDetail is not defined.. I switched it to No wrap - in <body> and it worked fine.
BUT I highly recommend against directly referencing javascript from your HTML. Instead, load the HTML first and then use the DOM ready event of javascript to bind your events. That will increase your load time and make it easier to switch to something like jQuery/Zepto if needed.
Full Code
HTML
<section id="contentWrapper">
<div id="resistorContent" class="content">
<section id="resistorDetail1">
<img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic1.jpg" />
</section>
<section id="resistorDetail2">
<img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic2.jpg" />
</section>
<section id="resistorDetail3">
<img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic3.jpg" />
</section>
<section id="resistorDetail4">
<img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic4.jpg" />
</section>
<ul>
<li onmouseover="javascript: showDetail('resistorDetail1')"></li>
<li onmouseover="javascript: showDetail('resistorDetail2')"></li>
<li onmouseover="javascript: showDetail('resistorDetail3')"></li>
<li onmouseover="javascript: showDetail('resistorDetail4')"></li>
</ul>
</div>
</section>
JS
var children = document.querySelectorAll('.content > section[id]');
function showDetail(target) {
for (var i = 0, child; child = children[i]; i++) {
child.style.display = 'none';
}
document.getElementById(target).style.display = 'block';
}
CSS
(unchanged)

Here's another working fiddle.
https://jsfiddle.net/2qz2srqs/4/
The issue was a couple things.
You were passing undefined vars into your onmouseover attributes. You wanted strings (I quoted them)
In JSFiddle, you don't automatically get the window scope, so you have to assign a function as a property of a window if you want to be able to hit it with an event attribute.

Related

Targeting all li's instead of just the first

I'm using the Superslides script to create a responsive slideshow for a site. I have created a basic caption box that I want to be hidden and then slide in from the bottom when the slide going with the caption is display.
In the Superslide script the current slide gets a higher z-index (of 2, otherwise it is set to 0) and a display: block (otherwise 'none') change to it when it's coming into view.
I am not very good with Javascript so I am having a bit of trouble targeting my captions to animate in at the right time. I put together a script that is supposed to evaluate all the li tags (each li is a different slide) and if it has a z-index of 2 it changes the bottom margin of the caption div so it slides into view. My problem is that my script only targets the very first li instead of running through all of them. For the first li it works great, I just need it to run though the rest of the li's as well. Any suggestions are appreciated!
Script:
var li = document.querySelector('li[style]'),
inlinezIndex = li.style.zIndex;
console.log(inlinezIndex);
if(inlinezIndex == 2){
document.getElementById('caption').style.bottom = '300px';
$('#caption').css({'transition': '10s'});
}
else{
document.getElementById('caption').style.bottom = '0px';
}
HTML:
<div id="slides">
<ul class="slides-container">
<li class="slide1">
<img src="images/people.jpeg" alt="Cinelli">
<div id="caption">
<h1>Hello</h1>
<h2>This is a test</h2>
<p>To see if I can get this to work1</p>
</div>
</li>
<li class="slide1">
<img src="images/surly.jpeg" width="1024" height="682" alt="Surly">
<div id="caption">
<h1>Hello</h1>
<h2>This is a test</h2>
<p>To see if I can get this to work1</p>
</div>
</li>
<li class="slide1">
<img src="images/cinelli-front.jpeg" width="1024" height="683" alt="Cinelli">
<div id="caption">
<h1>Hello</h1>
<h2>This is a test</h2>
<p>To see if I can get this to work2</p>
</div>
</li>
<li class="slide1">
<img src="images/affinity.jpeg" width="1024" height="685" alt="Affinity">
<div id="caption">
<h1>Hello</h1>
<h2>This is a test</h2>
<p>To see if I can get this to work3</p>
</div>
</li>
<li class="slide1">
<img src="images/cinelli-front.jpeg" width="1024" height="683" alt="Cinelli">
<div id="caption">
<h1>Hello</h1>
<h2>This is a test</h2>
<p>To see if I can get this to work4</p>
</div>
</li>
</ul>
<nav class="slides-navigation">
<i class="icon-chevron-right"></i>
<i class="icon-chevron-left"></i>
</nav>
</div>
Try using querySelectorAll instead of querySelector.
You could then loop through the li's and apply your styling, etc.
Also I see you are using multiple elements with the same id ("caption") and this is bad practice. Actually, I think it's invalid HTML according to the HTML5 specification as id's are supposed to be unique (look at this stackoverflow thread).
Example
var list = document.querySelectorAll('.slides-container li');
for (var i = 0; i < list.length; i++) {
var li = list[i];
var zIdx = li.style.zIndex;
// Use a class instead of id for captions
var caption = li.querySelector('.caption');
if (zIdx == 2) {
caption.style.bottom = '300px';
} else {
caption.style.bottom = '0px';
}
}
I'd also put css transitions in css (handy-dandy transitions):
.caption {
transition: bottom 10s;
}

Grabbing parent pages css with postMessage

I have the following JavaScript which lies on a page within an iframe, and grabs the parent pages css to make the page have a seamless look to the rest of the page. I'm having an issue with it picking up the wrong styling however. How can I target specific tags(such as h1, h3`, etc to use on the page within the iframe?
var getFontFamily = function(){
for(var i = 0; i < document.styleSheets.length; i++){
for(var j = 0; j < document.styleSheets[i].rules.length; j++){
if(document.styleSheets[i].rules[j].style.fontFamily){
return document.styleSheets[i].rules[j].style.fontFamily;
}
}
}
return 'not-found';
};
window.addEventListener('load', function(){
var data = getFontFamily();
window.frames[0].postMessage(data, 'http://localhost:3000');
console.log('Message sent -->');
});
Current version: jsfiddle
This is the HTML that the css of the parent page needs to be applied to:
<div class="info">
<div class="lead">Message Lead</div>
<h2>Title</h2>
<div class="ticker">
<div class="ticker__also">Also</div>
<ul class="ticker__list">
<li>sub headline</li>
<li>sub headline</li>
<li>sub headline</li>
</ul>
</div>
</div>
<div class="extras">
<div class="title">Extra info</div>
<a class="link" href="http://www.url.tv" target="_blank">Link</a>
<div class="share">
<a class="twitter">Twitter</a>
<a class="facebook">Facebook</a>
<a class="email">E-mail</a>
</div>
</div>
You can get styles from elements directly via the style attribute and the window.getComputedStyle method. This is more accurate than just taking the first result that appears in the list of CSS rules (where you also just find selectors, not actual elements the style is applied to).
The MDN page about the style attribute has some easy examples, for your purpose, it could be look like this.
var getFontFamily = function() {
var el = document.getElementById(id);
var cs = window.getComputedStyle(el, null);
return cs.fontFamily || '';
}

Change tab styling for all tabs except the one being clicked

So I have a few tabs. There can be multiple tabs, but I currently have 3. What I am trying to do is to change the styling of the tab when it is clicked and the other tabs to have some other styling. My code is as follows:
<div id="ClaimTabs" class="TabbedPanels">
<div class="TabbedPanelsTabGroup">
<div id="list1" class="TabbedPanelsTab TabbedPanelsTabSelected">
<a id="anchor1" class="TabbedPanelAnchor" href="javascript:showTab(1);">Tab 1 </a>
</div>
<div id="list2" class="TabbedPanelsTab">
<a id="anchor2" href="javascript:showTab(2);" >Tab 2</a>
</div>
<div id="list3" class="TabbedPanelsTab">
<a id="anchor3" href="javascript:showTab(3);">Tab 3</a>
</div>
</div>
<div id="ClaimContent" class="TabbedPanelsContentGroup">
<div id="tab1" class="TabbedPanelsContent TabbedPanelsContentVisible" style="display: block;">
Screen 1
</div>
<div id="tab2" class="TabbedPanelsContent" style="display: none;">
Screen 2
</div>
<div id="tab3" class="TabbedPanelsContent" style="display: none;">
Screen 3
</div>
</div>
</div>
My script that manipulates the styling is as follows:
function showTab(tabNumber) {
var children = document.getElementById('TabbedPanelsTabGroup').childNodes;
document.getElementById('tab'.concat(tabNumber)).style.display = 'block';
document.getElementById('list'.concat(tabNumber)).setAttribute("class", "TabbedPanelsTab TabbedPanelsTabSelected");
document.getElementById('anchor'.concat(tabNumber)).setAttribute("class", "TabbedPanelAnchor");
for(i=1; i <= children.length ; i++)
{
if(i != tabNumber){
document.getElementById('tab'.concat(i)).style.display = 'none';
document.getElementById('list'.concat(i)).setAttribute("class", "TabbedPanelsTab");
document.getElementById('anchor'.concat(i)).setAttribute("class", "");
}
}
}
I was wondering if my logic is right. I am concatenating the tab, list and anchor with the number and updating styles. But this does not seem to be working.
You appear to have at least two problems here.
First, you're trying to use document.getElementById for TabbedPanelsTabGroup, but that's a class.
Second, you're using .childNodes when you are probably looking for .children. .childNodes includes all child nodes, including the text inside the tags (which is a node). So when you use that number to loop over it, your loop isn't counting to 3 (your # of divs), it's counting to 7, and that's giving errors.
But, .children isn't supported before IE9, so like others have suggested, you may want to consider jQuery to get at that with better support.
With plain JavaScript I would recommend EventListener:
<div id="elem"> "some content here" </div>
var elem = document.getElementById('elem');
elem.addEventListener ('click', show, false);
function show() {
//add css Class
var element = document.getElementById("elem");
element.classList.add("activeTab");
}
But as mentioned in the comment, jQuery is perfect for that kind of things.
best
M

mouseenter/leave & mouseover/out problems

Script:
$( ".title").mouseenter(function() {
var which = $(this).index();
$('.globalnav li').find('.dropdown').hide().eq(which).show();
}).mouseleave(function() {
var which = $(this).index();
$('.globalnav li').find('.dropdown').hide().eq(which).hide();
});
Navigation:
<ul class="globalnav">
<li>
<div class="title">Home</div>
<div class="dropdown">
<div class="navlinks">
<div class="linkstitle">Title</div>
<div class="navlink">Link1</div>
<div class="navlink">Link1</div>
</div>
</div>
</li>
...
The above code is what I am using right now which does not work in Chrome as intended *I need to hold my click down to view the div. I use mouseover, it does not work properly in IE and FF.
I am also having trouble showing the associated div of the title (on title hover, show specific div) due to the nature of the coding format itself (client given code). Right now, on hovering over a title, it shows the first li's content for "navlinks".
Here's a fiddle to show you
Thanks
Why are you using the index of the .title element, if the other LI's look like that, the which variable will always be 0, and it's not the way to target the right .dropdown ?
Try something more like this
$( ".title").on('mouseenter mouseleave', function(e) {
var dropdown = $(this).closest('li').find('.dropdown').toggle(e.type=='mouseenter');
$('.dropdown').not(dropdown).hide();
});
And if you want the dropdown to be visible while hovering it, place it inside the element that triggers the mouseleave
<li>
<div class="title">
Home
<div class="dropdown">
<div class="navlinks">
<div class="linkstitle">Title</div>
<div class="navlink">Link1</div>
<div class="navlink">Link1</div>
</div>
</div>
</div>
</li>
FIDDLE

Selecting siblings on hover

I have a code that goes like this on HTML:
<div class="blog_highlight">
<ul class="calendar">
<li>Nov</li>
<li>25</li>
</ul>
<ul class="commentaries">
<li>16</li>
</ul>
<div class="entry_info">
<div>
<img src="images/blog_pix_1.jpg" width="230" height="210" alt="" />
</div>
<h2>Title</h2>
<p>Text</p>
<p>Leer mas</p>
</div><!-- end entry info -->
</div><!-- end blog highlight -->
I would like to achieve that on hover on the UL (with classes calendar and commentaries), the border color for div.entry_info and background of a.read_more changes via jQuery. This is what I have however the second one isn't working.
<script>
$(document).ready(function(){
$('ul.calendar').hover (
function () {
$(this).nextAll('.entry_info').addClass('hover_border');
$(this).nextAll('a.read_more').addClass('more_jquery');
$(this).next('ul.commentaries').addClass('bubble_hover');
},
function () {
$(this).nextAll('div.entry_info').removeClass('hover_border');
$(this).nextAll('a.read_more').removeClass('read_more_jquery');
$(this).next('ul.commentaries').removeClass('bubble_hover');
});
});
</script>
My current issue is that everything except the second line works.
This is the line with the issue:
$(this).nextAll('a.read_more').addClass('more_jquery');
I am fairly new to jQuery and have tried siblings and next and everything but it won't work. I tried with eq(0) which worked but how do I loop it? The reason I go with classes and not ID is because this is a box that gets repeated multiple times.
Thank you for you help.
Why not simply use CSS?
ul.calendar:hover ~ .entry_info {
// selects all .entry_info's which are on the same level (siblings) as the ul.calender which is hovered over
}
BTW I'm sure that jQuery's magic $-function also supports the general sibling combinator, so $("item ~ sibling") should work just fine:
$("...").hover(function() {
$("... ~ siblings");
}
See:
http://www.w3.org/TR/selectors/#sibling-combinators (selectors CSS 3)
http://api.jquery.com/category/selectors/ (selectors CSS 1 - 3 are supported)
It does not work because nextAll gets all siblings based on the selector. Your hyperlink is not a sibling. Instead you can use find to search entry_info for the link.
http://jsfiddle.net/U7hNS/
<ul class="calendar">
<li>Nov</li>
<li>25</li>
</ul>
<div class="entry_info">
<p>Leer mas</p> <!-- NOT A SIBLING! -->
</div>
$('ul.calendar').hover (
function () {
$(this).nextAll('.entry_info').addClass('hover_border');
$(this).nextAll('.entry_info').find('a.read_more').addClass('more_jquery');
$(this).next('ul.commentaries').addClass('bubble_hover');
},
function () {
$(this).nextAll('div.entry_info').removeClass('hover_border');
$(this).nextAll('.entry_info').find('a.read_more').removeClass('more_jquery');
$(this).next('ul.commentaries').removeClass('bubble_hover');
});

Categories

Resources