Jquery getting two divs to act as one - javascript

I have the following code for my popup menu, the parent link is the top level link. It causes a popup to show. Popup fades in and fades out when the mouse enters and exits parent link.
However, I need it to not fade out the popup, if the mouse is over the popup! At the moment, as soon as the mouse enters the popup it fades it out. I need both divs to act as one for the hover, if this makes any sense!
// Hovering over the parent <li>
ParentLink.hover(
function()
{
Popup.fadeIn(300, function() {
});
},
function()
{
Popup.fadeOut(400, function() {
});
}
);

You should nest the popup inside the parent. This way when you move the mouse from the parent to the popup, the parent will still be in a mouse-over state because popup's mouse-over event is bubbled onto the parent. When the mouse is out of the parent (plus its children), mouse-out event will fire on the parent.
Edit
If you are not able to (or want to) change the markup, one possibility is to move the elements to the recommended positions using jQuery, like:
ParentLink.append(Popup); // moves the Popup element from its current position
// and places it as the last child of ParentLink
Most probably you'll have to modify your CSS to match the changes so you may want to think first.

you could unbind the hover-event for the parentlink on completion of the fadein.
Popup.fadeIn(300, function() {
$(ParentLink).unbind('hover');
});

This is not a direct answer to your question but a hint how this could work.
Why don't you nest the the 2nd <div> into the first one, so the out will not occur?
<div id="ParentLink">
<div id="Popup"></div>
</div>
Have #ParentLink { display: relative; } and #Popup { display: absolute; } and you will be fine.
But for those menu's I would always use a nested unordered list structure like this one:
<ul id="topLevel">
<li id="level1item">
Link
<ul id="subLevel">
<li>
Link 2
</li>
</ul>
</li>
</ul>

As said, unbind the event while you are hover the popup and then re-bind it when you are hovering out :
ParentLink.hover(
handlerIn,
handlerOut
);
var handlerIn = function()
{
Popup.fadeIn(300, popupFadeIn);
};
var handlerOut = function()
{
Popup.fadeOut(400);
};
var popupFadeIn = function() {
$(ParentLink).unbind('hover');
$(this).mouseleave( function () {
$(ParentLink).hover(
handlerIn,
handlerOut
);
});
};
btw, I didn't tested this

You can try this:
var inn;
$('ParentLink').hover(function() {
inn = false;
$('p').fadeIn(1000);
},
function() {
$('Popup').bind('mouseenter mousemove',
function() {
inn = true;
}).mouseout(function() {
inn = false;
});
if (!inn) $('Popup').fadeOut(1000);
});

Related

How to close sidebar on click for anchor using only JavaScript?

I have a sidebar and I want to close it when someone clicks on a link. In my code, the sidebar just closes for a millisecond when I click on an anchor element. How can I fix this without using jQuery?
The a tags are linking to a html page
JS:
var elem = document.getElementById('slidebar').getElementsByClassName('button')[0]
element.addEventListener("click", slide);
function slide() {
document.getElementById('slidebar').classList.toggle('active');
}
var slidebar = document.getElementById('slidebar');
slidebar.addEventListener('click', handleMenuClick);
function handleMenuClick(event) {
if (event.target instanceof HTMLAnchorElement) {
document.getElementById('slidebar').classList.add('close');
}
}
CSS:
#slidebar.active {
left: 0px;
}
#slidebar.close {
display: none;
}
First, make sure you prevent the default event when clicking the anchor tag. Otherwise, it might be re-rendering the page.
But based on your code, it looks like you're adding two functions onto the slidebar. One that closes and one that opens. Since the anchor tag that closes the slidebar is inside the slidebar - when you click it you first fire off the handleMenuClick function and then it bubbles up and fires off the slide function. So it closes and opens quickly.
Instead, add a third element that is used to open the slidebar and attach the slide function there.
Also, you don't need two classes for managing the state of hidden/not hidden. You can just provide a class that sets the display to none and toggle that class list. If you want transition effects you can do that in CSS
Maybe something like this:
window.addEventListener('DOMContentLoaded', e => {
let slidebar = document.getElementById('slidebar')
let collapseButton = slidebar.getElementById('close-button')
let openButton = slidebar.getElementById('open-button')
collapseButton.on('click', toggleClassList)
openButton.on('click', toggleClassList)
const toggleClassList = e => {
e.preventDefault()
slidebar.classList.toggle('hidden')
}
})
#slide-bar.hidden {
display: none;
}
#slide-bar.hidden #close-button {
display: none;
}
#slide-bar #open-button {
display: none;
}
Obviously, it depends a bit on the code you have already written. But this is a basic example that would work. Just need to add the transitions for the sliding effect in CSS

Only wants to close menu by background div & button

I have two divs:
First div: its the background div ".menu_bg" (width + height 100%)
Second div: its the content (maybe width + height 40%)
So, if I click the "first div / background div" I want that the "first & second div" fades out. My Problem is, that this also happened when I only click the "second div / the content div".
Thats my code:
(function(window) {
'use strict';
var body = document.body,
mask = document.createElement("div"),
toggleSlideTop = document.querySelector(".toggle-slide-top"),
slideMenuTop = document.querySelector(".slide-menu-top"),
activeNav;
mask.className = "mask";
/* slide menu top */
toggleSlideTop.addEventListener("click", function() {
classie.add(body, "smt-open");
document.body.appendChild(mask);
activeNav = "smt-open";
});
/* hide active menu */
[].slice.call(document.querySelectorAll(".close-menu, .menu_bg")).forEach(function(el, i) {
el.addEventListener("click", function() {
classie.remove(body, activeNav);
activeNav = "";
document.body.removeChild(mask);
});
});
})(window);
Whats wrong?
UPDATE:
I create a fiddle.
It seems like your second div is nested to the first one. In this case any event fired on the second div will propagate up to all parent elements, until you call event.stopPropagation() method. So what you need is to call this method from click listener added to nested element. Somthing like:
document.querySelector('ul').addEventListener('click', function(e) {
e.stopPropagation();
});

Using JS, how do I swap out a specifc instance of text instead of all instances?

Sorry if this is a really noobish question but I have just made a form with sections that are toggle-able. Each section has a '.header' which on click will perform a slideToggle on the section div.
I would like to add a triangle either pointing down or sideways to let people know it is toggle-able. (i.e ▶ or ▼).
I have the triangle in a span with the class '.arrowTog'
I was able to get partial success with
$('.header').on('click', function() {
if ($('.arrowTog').text().contains('▼')){
$('.arrowTog').text('▶');
}else{
$('.arrowTog').text('▼');
}
});
When I clicked on one all of the triangles swapped so I tried this (which causes none of them to rotate at all):
$('.header').on('click', function() {
if ($(this).prev('.arrowTog').text().contains('▼')){
$(this).prev('.arrowTog').text('▶');
}else{
$(this).prev('.arrowTog').text('▼');
}
});
This is a sample of the HTML
<div class="header" style="cursor: pointer;">
<span class="arrowTog">▶ </span>
<b>Merchant</b>
</div>
<div class="searchContent" style="display:none;">
Any ideas what I am doing wrong?
Thanks!
In your first version, the problem is you're finding every .arrowTog in the page. You can use the fact that within the click handler, this is bound to the element that was clicked, and then just search within that using find:
$('.header').on('click', function() {
var arrow = $(this).find('.arrowTog');
if (arrow.text().contains('▼')){
arrow.text('▶');
} else {
arrow.text('▼');
}
});
You're using a class. You probably have a number of elements with the same class in it, so jQuery is matching all of them and doing this transformation to all of them.
Use a context (All .arrowTog RIGHT INSIDE THIS NODE):
$('.header').on('click', function(evt) {
if ($('.arrowTog', evt.target).text().contains('▼')){
$('.arrowTog', evt.target).text('▶');
}else{
$('.arrowTog', evt.target).text('▼');
}
});
Why not use CSS?
.arrowTog:before {
content: '▶';
}
.arrowTog.open:before {
content: '▼';
}
And then
$('.header').on('click', function() {
$(this).toggleClass('open');
});

How to change image with onclick while a list is using slideup and slidedown

I would like to change the src of an img when the parent of listed children is clicked. I am using some code I have been working with that I found on StackOverflow because I was having problems with slideup and slidedown.
Next to each uppermost item (parent), to the left will be an arrow icon pointing to the right. Upon clicking the icon, this image should change to an arrow pointing down.
I can get the image to change onClick, but unless you click on the image, the image does not change back. Therefore, I believe I need the change to be pegged to the slideup and slide down functions. The image should also change back if you click on the close link or when clicking on a new Parent.
I can live without the 'only one list can be shown at a time' functionality, which would eliminate the need for the image to also change on clicking a new parent.
For this fiddle, I have only applied what I was trying to do to the first parent of the list: http://jsfiddle.net/9aa5n/51/
HTML:
<li><img src="arrowright.png"></li>
<li class="show_hide" id="1C">
<p>lkjlkjasdfasdf</p>
Close
</li>
<li>Edit</li>
<li class="show_hide" id="2C">
<p>lkjlkjasdfasdf</p>
Close
</li>
<li>Edit</li>
<li class="show_hide" id="3C">
<p>lkjlkjasdfasdf</p>
Close
</li>
jQuery / Javascript:
$(document).ready(function() {
$('.show_hide').slideUp(0);
$('.edit_this').click(function() {
$('.show_hide').slideUp(300);
var takeID = $(this).attr('id');
$('#' + takeID + 'C').slideDown(300);
});
$('.close').click(function() {
var takeID = $(this).attr('id').replace('Close', '');
$('#' + takeID + 'C').slideUp(300);
});
});
$('#img-tag').on({
'click': function() {
var src = ($(this).attr('src') === 'arrowright.png')
? 'arrowdown.png'
: 'arrowright.png';
$(this).attr('src', src);
}
});
I updated your jsfiddle: http://jsfiddle.net/9aa5n/53/
Since you didn't provide absolute paths to images, I added some from the net.
I removed your click event, and replaced it with this, I believe your issue was how you were referencing the elements in jQuery.
$(".edit_button").click(function() {
var img = $(this).find("img").first();
console.log(img.attr("src"));
if (img.attr("src") === 'http://iconizer.net/files/Brightmix/orig/monotone_arrow_right.png') {
img.attr("src", 'http://png-3.findicons.com/files/icons/2315/default_icon/256/arrow_down.png');
console.log(img.attr("src"));
} else {
img.attr("src", 'http://iconizer.net/files/Brightmix/orig/monotone_arrow_right.png');
console.log(img.attr("src"));
}
});
This should get you started to finish polishing up the UI,
i.e. closing all .edit_button and then open only the $(this).find("img").first() element ...

How to fire a unique ID modal when multiple divs with class is clicked using jQuery?

Forgive the strangely worded question, my first StackOverflow post, and I'm a novice to jQuery/JS. I've used the search feature a lot and haven't found exactly what I'm looking for:
I am having an issue essentially, where I have dynamically added divs by the end-user (they pick how many content blocks they want to use), with the same class, that need to hide and show specific divs (with unique IDs) when they are clicked. I finally figured out how to give each div a unique ID, but I'm not sure how to get the child divs of the particular div what was clicked, to fire properly on click. Hope that makes sense.
Here is the HTML I have:
<div class="resource-video">
//Unique thumbnail
</div>
<div class="overlay-container hide" style="width: 50px; height: 50px;">
<div class="video-player hide">
//Included unique video
</div>
</div>
This will end up being duplicated based on how many videos are added.
Here is the JavaScript I am using:
//Generates unique IDs for each of the divs on the page with those classes
var i = 0;
$(".resource-video").each(function(i){
$(this).attr("id","video_"+ (i+ 1) );
});
$(".overlay-container").each(function(i){
$(this).attr("id","container_"+ (i+ 1) );
});
$(".video-player").each(function(i){
$(this).attr("id","player_"+ (i+ 1) );
});
//Currently opens all of them
$(".resource-video").on("click", function(){
openModal(".overlay-container", false, true);
alert($(this).attr("id")); //Alerts the right div clicked
if ($(".video-player").hasClass("hide")){
$(".video-player").removeClass("hide").addClass("show");
$(".overlay-container").animate({ height:'300px', width: '500px' }, "slow");
}
$("#overlay").on("click", function(){
$(".video-player").removeClass("show").addClass("hide");
$(".overlay-container").css({ "height":"50px", "width":"50px",
"display":"none"});
$(this).hide();
});
return false;
});
// Probably not totally necessary, but just in case
function closeModals(){
$("body").find(".modal").hide();
$("#overlay").hide();
$("body, html").removeClass("no-scroll");
};
function openModal(divID, allowScroll, blockScreen){
closeModals();
$(divID).show();
if ( blockScreen == true ){ $("#overlay").show(); };
if ( allowScroll == false ){ $("body, html").addClass("no-scroll"); };
};
As it stands now, all of the overlays open because I am targeting the class not the IDs. Basically, I need to find out a way to have the specific overlay associated with the specific div clicked on to display without hardcoding that, since the number of divs will change all the time. I would think I could use something like $(this) or event.target, but things I tried didn't work.
Hopefully I was clear enough with my issue and made it general enough for other people to use too. Thanks for any help in advance!
This uses DOM traversal functions to find the corresponding DIVs to the one that was clicked.
$(".resource-video").on("click", function(){
var overlayContainer = $(this).next();
var videoPlayer = overlayContainer.children(".video-player");
openModal(overlayContainer, false, true);
if (videoPlayer.hasClass("hide")){
videoPlayer.removeClass("hide").addClass("show");
overlayContainer.animate({ height:'300px', width: '500px' }, "slow");
}
return false;
});
// Only need to bind this once, not every time .resource-video is clicked.
$("#overlay").on("click", function(){
$(".video-player").removeClass("show").addClass("hide");
$(".overlay-container").css({ "height":"50px", "width":"50px",
"display":"none"});
$(this).hide();
});
// Probably not totally necessary, but just in case
function closeModals(){
$(".modal").hide();
$("#overlay").hide();
$("body, html").removeClass("no-scroll");
};
function openModal(div, allowScroll, blockScreen){
closeModals();
div.show();
if ( blockScreen == true ){ $("#overlay").show(); };
if ( allowScroll == false ){ $("body, html").addClass("no-scroll"); };
};

Categories