Javascript - simplifying a bunch of long repetative hide/show functions - javascript

Things have gotten out of hand for me. What started off as the simplest solution has ballooned to the point where it is no longer manageable. I need to come up with a way to simplify a process.
Currently I have a map with pins denoting specific countries world-wide. As the mouse hovers over a pin, a hidden div appears. When you mouse over another one, the previous div disappears and a new one opens. I started with like 5 of these and it wasn't an issue but I keep getting requests for more and want to manage the script in a different way now.
$('#PH1').mouseenter(function () {
$('#BO2').hide();
$('#US2').hide();
$('#UK2').hide();
$('#CH2').hide();
$('#BZ2').hide();
$('#QC2').hide();
$('#OT2').hide();
$('#VA2').hide();
$('#RU2').hide();
$('#JT2').hide();
$('#HK2').hide();
$('#SH2').hide();
$('#BJ2').hide();
$('#XI2').hide();
$('#BE2').hide();
$('#AT2').hide();
$('#FR2').hide();
$('#MX2').hide();
$('#PH2').show();
});
$('#PH1').click(function (e) {
e.stopPropagation();
});
$('#mint').click(function () {
$('#PH2').hide();
});
In this instance div id #PH1 is the pin, when the mouse enters the div it hides all of the other div's #**2 and displays the one related to #PH1, which is #PH2
This list is repeated for each DIV. Every time I need to add a new DIV I need to make each existing list longer as well as create a new one. How can this process be made much simpler?

Thats not a right way to do this, you should use classes for this. But their is a wayaround for this all you need to is add a class add class ele1 to all #**1 and ele2 to all #**2:
then
$('.ele1').mouseenter(function () {
$(".ele2").hide();
var id = this.id;
var newId = id.substring(0,2)+"2";
$("#"+newId).show();
});

Make a loop:
var all= ['#BO2', '#US2', '#UK2', '#CH2', '#BZ2', '#QC2', '#OT2', '#VA2', '#RU2', '#JT2', '#HK2', '#SH2', '#BJ2', '#XI2' , '#BE2', '#AT2', '#FR2', '#MX2', '#PH2']
all.forEach(function (i){
$(i).hide();
});

Use a class selector on all of the DIVs you want to hide/show instead of an ID.
First, add a shared class to all DIVs so we target all of them by class.
HTML: class="hidden-divs"
jQuery: $('.hidden-divs').hide();
Then show the relevant DIV.
$('#PH2').show();
Using your first example, it would look like this:
$('#PH1').mouseenter(function () {
$('.hidden-divs').hide();
$('#PH2').show();
});

You can use jquery to hide multiple divs if you can select them. For example, suppose you have a common class ".map_divs" on all your divs, you could easily do:
$(".map_divs").hide();
On a side-note, you could solve all this on CSS, using :hover. For example:
.map_divs:hover {
display: block;
}

If you can edit the div's yourself (if it is not generated by a library) I would do it like this.
Add a common class to all your divs. Then on each div, add a data attribtue to the related id.
<div class="pin" id="PH1" data-rel="PH2"></div>
Then you can have a simple function like this:
$(".pin").mouseenter(function() {
var relatedId = $(this).data("rel");
$(".pin[id$='2']").hide(); // Hide all pins with id ending in 2
$("#" + relatedId).show() //show PH2
})

Using classes might be a better option here. You can then just attach the mouseenter event on document ready to all pins. This will work for an infinite number of pins too.
$('.pin').mouseenter(function () {
$('.popup').removeClass('show');
var id = this.id.split('_')[1];
$('#popup_' + id).addClass('show');
});
.pin {
width:30px;
height:30px;
margin-bottom:20px;
background-color:red;
}
.popup {
display:none;
width:100px;
height:100px;
margin-bottom:20px;
background-color:blue;
}
.popup.show {
display:block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="pin_1" class="pin"></div>
<div id="popup_1" class="popup"></div>
<div id="pin_2" class="pin"></div>
<div id="popup_2" class="popup"></div>

If your div element is ordered like below, you can get the same result using css only, which will increase speed and overall experience (especially on phones and tablets).
When "hover" the yellow squares, the popup will be visibible even when "hover" the popup.
.pin {
width:30px;
height:30px;
margin-bottom:20px;
background-color:red;
}
.popup {
display:none;
width:100px;
height:100px;
margin-bottom:20px;
background-color:blue;
}
.pin:hover + .popup {
display:block;
}
.pin.type2 {
background-color:yellow;
}
.pin.type2:hover .popup {
display: inline-block;
margin-top: 30px;
}
<div id="pin_1" class="pin"></div>
<div id="popup_1" class="popup"></div>
<div id="pin_2" class="pin"></div>
<div id="popup_2" class="popup"></div>
<div id="pin_3" class="pin type2"><div id="popup_3" class="popup"></div></div>
<div id="pin_4" class="pin type2"><div id="popup_4" class="popup"></div></div>

Related

Replacing and restoring div html with jquery

I have a couple of functions, the first replaces the contents of a div the second restores the original div. The problem is because I'm using the replaceWith method, the second div no longer exists if I try to call it a second time. Is there a better way to do this? I've experimented creating a variable that stores the contents of the second div so I can resuse it, but could not get it to work.
The code that I have is:
$(document).ready(function() {
$('#trigger_adults').click(function() {
var mainClone = $("#main-content").clone();
$('#main-content').fadeOut('fast', function() {
$('#main-content').replaceWith($('#adults'));
$('#slider-sec').slideUp('slow');
$('#adults').fadeIn('fast');
$(window).scrollTop(0);
});
$('#return').click(function() {
$("#adults").replaceWith(mainClone.clone());
$('#adults').fadeOut('fast');
$('#slider-sec').slideDown('slow');
});
});
});
Thanks in advance!
You could have both contents in the same div and toggle the visibility of their parent divs. Use javascript just to toggle the wrapper's class.
$('#toggle').click(function() {
$('#wrapper').toggleClass('init-state new-state');
});
#wrapper {
border:1px solid #d8d8d8;
}
.init-state #new,
.new-state #init { display:none; }
.inner {
padding:25px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<div id="wrapper" class="init-state">
<div id="init" class="inner">Initial Content</div>
<div id="new" class="inner">New Content</div>
<button id="toggle" type="button">Toggle</button>
</div>
From the docs
The .fadeOut() method animates the opacity of the matched elements. Once the opacity reaches 0, the display style property is set to none, so the element no longer affects the layout of the page
you either need to manually set the display style property back to its original value, or call jQuery's .fadeIn() function which will do the opposite of .fadeOut()

slideDown does not work for the first time

I'm adding animation to show a hidden div when a checkbox is changed,
The first time it's clicked the div appears with no animation but it works both ways after the first time.
How can I make it work also on the first time?
Here is my div (also using bootstrap)
var postOptionsSourcesWrapper = $("#post-options-sources-wrapper");
var postOptionsExclusiveCheckbox = $("#post-exclusive-cb");
postOptionsExclusiveCheckbox.change(function() {
if ($(this).is(":checked")) {
postOptionsSourcesWrapper.slideUp(300, "easeOutCirc", function() {
postOptionsSourcesWrapper.addClass("hidden");
});
} else {
postOptionsSourcesWrapper.removeClass("hidden");
postOptionsSourcesWrapper.slideDown(300, "easeOutCirc");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="post-options-sources-wrapper" class="margin-b-5 hidden">
<label class="text-md thick-600">Original post references</label>
<div class="box-marker box-marker-white">
<div class="thick-600 color-gray text-sm text-uppercase">
Add one or multiple sources.
</div>
</div>
</div>
UPDATE: this issue is solved by adding display:none; to the div
When adding the bootstrap class .hidden to hide for some reason it's not adding the display:none; that is part of the .hidden class in bootstrap... not sure why, but adding the style display:none; or calling postOptionsSourcesWrapper.hide() solves this issue.
This code will achieve what you want to achieve.
You just have to replace your script with this one.
var postOptionsSourcesWrapper = $("#post-options-sources-wrapper");
var postOptionsExclusiveCheckbox = $("#post-exclusive-cb");
postOptionsSourcesWrapper.hide();
postOptionsExclusiveCheckbox.change(function() {
postOptionsSourcesWrapper.slideToggle(300,postOptionsSourcesWrapper.is(":checked"));
});

Remove class if display = none

How to add and remove class with the condition of CSS display. For example, I have some Div that can be hidden and shown. I want that, if the div is hidden with the display:none;, then the class of the div is removed.
But if the div is shown with the display:block;, I want to add a class to the div.
Here is what I have been trying:
$(document).ready(function(){
if($('.bigPicture').css('display') == 'block')
{$('.bigPicture').find('div').addClass('easyzoom easyzoom--overlay');};
if($('.bigPicture').css('display') == 'none')
{$('.bigPicture').find('div').removeClass('easyzoom easyzoom--overlay');}
});
EXPLANATION
I have multiple slideshows in one pages. Not all of the slideshow is going to be shown in the page, one of them will only show if the link to that slideshow is clicked. It sames like auto hide and show function. If one slideshow is shown, then other slideshows are hidden.
Each slideshow has their own thumbnails to control them.
The problem is all of the slideshow has no ID and has the same class, while all the slideshow is run with the same script.
If the thumbnail in the second slideshow I click, the slideshow doesn't move. And I realize it slides only the first slideshow.
SO, the solution is I have to remove the class of the slideshow.
Try is visible:
$(document).ready(function(){
if($('.bigPicture').is(':visible')){
$('.bigPicture').find('div').addClass('easyzoom easyzoom--overlay');
} else {
$('.bigPicture').find('div').removeClass('easyzoom');
}
});
This is what you are trying to do?
If so, it's easy to convert it to jquery syntax instead.
It would be easier if you had provided a jsFiddle of your problem.
CSS
.bigPicture {
width: 50px;
height: 20px;
border-style: solid;
border-width: 2px;
}
.hidden {
display: none;
}
.easyzoom {
background-color: red;
}
HTML
<div class="bigPicture">
<div>One</div>
</div>
<div class="bigPicture hidden">
<div class="easyzoom easyzoom--overlay">Two</div>
</div>
<div class="bigPicture hidden">
<div class="easyzoom easyzoom--overlay">Three</div>
</div>
Javascript
document.addEventListener('load', function () {
Array.prototype.forEach.call(document.querySelectorAll('.bigPicture'), function (bigPicture) {
var div = bigPicture.querySelector('div:first-of-type');
if (div) {
if (window.getComputedStyle(bigPicture).display === 'none') {
div.classList.remove('easyzoom', 'easyzoom--overlay');
} else {
div.classList.add('easyzoom', 'easyzoom--overlay');
}
}
});
}, true);
On jsFiddle
I think your code is somewhat working. Here is a fiddle where I have shown and hidden on the click of the buttons.
Code Snippet:
$(document).on('click','#addBigPicture',function(){
$('.bigPicture').css('display','block');
if($('.bigPicture').css('display') == 'block')
{$('.bigPicture').find('div').addClass('easyzoom easyzoom--overlay');};
});
$(document).on('click','#hideBigPicture',function(){
$('.bigPicture').css('display','none');
if($('.bigPicture').css('display') == 'none')
{$('.bigPicture').find('div').removeClass('easyzoom easyzoom--overlay');}
});
The if loops are as desired by you. Hope it helps!!

Cloning a DIV & amending the ID

I need to clone a styled DIV (id="#mirrorBG1") and amend the new div id to id="#mirrorBG2" then apply the class #mirrorBG2 in CSS to control the new div position & size etc.
Any ideas, please!
<div id="mirrorBG1">IMAGE#1 (*main image*) </div>
resulting in adding: <div id="mirrorBG2">IMAGE#1 (*same image*) </div>
#mirrorBG1 { width:50%; height:300px; background-color:#0F0"; float:left; clear:both; }
#mirrorBG2 { width:50%; height:300px; background-color:#FF0"; float:right; clear:both; }
Updated version:
var div2 = document.getElementById("mirrorBG1").cloneNode(true);
div2.setAttribute("id","mirrorBG2");
div2.className = "mirrorBG2";
After that you append your div wherever you want it to.
For example:
document.body.insertBefore(div2, null);
see jsfiddle
edit:
as stavarotti noted, classList isn't fully supported by IE versions previous to 10.
so instead of:
div2.classList.remove("mirrorBG1");
div2.classList.add("mirrorBG2");
You can do this instead:
div2.className = "mirrorBG2";
This will replace the class "mirrorBG1" with "mirrorBG2".
I updated the jsfiddle to show these changes.
If it isn't too much of a dependency for you, consider using jQuery and its clone() and append() methods. For more info see the jQuery API.

How to show the child div on mouse hover of parent div

I have a number of parent divs (.parent_div), which each contain a child div (.hotqcontent) where I output data from my database using a loop.
The following is my current markup:
<div class="content">
<div class="parent_div">
<div class="hotqcontent">
content of first div goes here...
</div>
<hr>
</div>
<div class="parent_div">
<div class="hotqcontent">
content of second div goes here...
</div>
<hr>
</div>
<div class="parent_div">
<div class="hotqcontent">
content of third div goes here...
</div>
<hr>
</div>
<div class="parent_div">
<div class="hotqcontent">
content of fourth div goes here...
</div>
<hr>
</div>
</div>
What I would like to achieve is when a user hovers / mouseovers a parent div, the contents of the child div contained within should be revealed.
To achieve this I wrote the following jQuery script but it doesn't appear to be working. It's not even showing the alert!
<script>
$(document).ready(function() {
$(function() {
$('.parent_div').hover(function() {
alert("hello");
$('.hotqcontent').toggle();
});
});
});
</script>
How can I modify or replace my existing code to achieve the desired output?
If you want pure CSS than you can do it like this....
In the CSS below, on initialization/page load, I am hiding child element using display: none; and then on hover of the parent element, say having a class parent_div, I use display: block; to unhide the element.
.hotqcontent {
display: none;
/* I assume you'll need display: none; on initialization */
}
.parent_div:hover .hotqcontent {
/* This selector will apply styles to hotqcontent when parent_div will be hovered */
display: block;
/* Other styles goes here */
}
Demo
Try this
$(document).ready(function() {
$('.parent_div').hover(function() {
alert("hello");
$(this).find('.hotqcontent').toggle();
});
});
Or
$(function() {
$('.parent_div').hover(function() {
alert("hello");
$(this).find('.hotqcontent').toggle();
});
});
You can use css for this,
.parent_div:hover .hotqcontent {display:block;}
This can be done with pure css (I've added a couple of bits in just to make it a bit neater for the JSFIDDLE):
.parent_div {
height: 50px;
background-color:#ff0000;
margin-top: 10px;
}
.parent_div .hotqcontent {
display: none;
}
.parent_div:hover .hotqcontent {
display:block;
}
This will ensure that your site still functions in the same way if users have Javascript disabled.
Demonstration:
http://jsfiddle.net/jezzipin/LDchj/
With .hotqcontent you are selecting every element with this class. But you want to select only the .hotqcontent element underneath the parent.
$('.hotqcontent', this).toggle();
$(document).ready(function(){
$('.parent_div').on('mouseover',function(){
$(this).children('.hotqcontent').show();
}).on('mouseout',function(){
$(this).children('.hotqcontent').hide();
});;
});
JSFIDDLE
you don't need document.ready function inside document.ready..
try this
$(function() { //<--this is shorthand for document.ready
$('.parent_div').hover(function() {
alert("hello");
$(this).find('.hotqcontent').toggle();
//or
$(this).children().toggle();
});
});
and yes your code will toggle all div with class hotqcontent..(which i think you don't need this) anyways if you want to toggle that particular div then use this reference to toggle that particular div
updated
you can use on delegated event for dynamically generated elements
$(function() { //<--this is shorthand for document.ready
$('.content').on('mouseenter','.parent_div',function() {
alert("hello");
$(this).find('.hotqcontent').toggle();
//or
$(this).children().toggle();
});
});
you can try this:
jQuery(document).ready(function() {
jQuery("div.hotqcontent").css('display','none');
jQuery("div.parent_div").each(function(){
jQuery(this).hover(function(){
jQuery(this).children("div.hotqcontent").show(200);
}, function(){
jQuery(this).children("div.hotqcontent").hide(200);
});
});
});

Categories

Resources