I have following code:
html:
<ul>
<li>
1111111111111
</li>
<li>
22222222222222
</li>
<li>
33333333333333
</li>
<li>
44444444444444
</li>
<li>
555555555555555
</li>
<li>
66666666666666
</li>
</ul>
<br>
<br>
<div type="button" class="on">on </div>
<div type="button" class="off">off </div>
js:
$(".on").click(function(){
$.fancybox.showLoading();
});
$(".off").click(function(){
$.fancybox.hideLoading();
});
DEMO
you can click on on or off it leads to showing/hiding animation.
I want that concrete html tag(ul in my exampel) was overlayed when animation shows.
following area:
Please help to correct my example
If I understand you correctly, it should require a few CSS changes, and little bit of math in your click event. DEMO
Start by giving your target element some sort of identifier:
<ul id="target">
<li>
1111111111111
</li>
<li>
22222222222222
</li>
<li>
33333333333333
</li>
<li>
44444444444444
</li>
<li>
555555555555555
</li>
<li>
66666666666666
</li>
</ul>
<div id="overlay"></div>
Then since by default a <ul> is a block object, we should make it inline-block to make it easier to get its width:
#target {
display:inline-block;
border: solid 1px;
}
#overlay {
display:none;
position: absolute;
background: rgba(0,0,0,.5);
}
Finally, in the click event we will obtain the target's width, subtract the width of the popup loader, and divide the remaining width by 2 to center it up. The same with the height:
$(".on").click(function(){
var target = $('#target');
var overlay = $('#overlay');
overlay.width(target.width()).height(target.height()).css({
'left': target.position().left,
'top': target.position().top
}).fadeIn(200);
$.fancybox.showLoading();
$('#fancybox-loading').css({
'left': (target.width() - $('#fancybox-loading').width()) / 2,
'top': (target.height() - $('#fancybox-loading').height()) / 2,
'margin': 0
});
});
$(".off").click(function(){
$('#overlay').fadeOut(200);
$.fancybox.hideLoading();
});
I hope this helps! Let me know if you have any questions.
Something like this?
var $el = $('ul');
var $cover = $('#dummy');
var coverPos = $el.position();
$cover.css({
position:'absolute',
top: coverPos.top,
left:coverPos.left,
width:$el.width()+'px',
height:$el.height()+'px',
background:'#f00'
}).show();
http://jsfiddle.net/daveSalomon/PudLq/582/
A ul has display:block;. If you only want the block to cover the width of the text, you'll need to calculate the required width of the ul. Here's the same code where the ul has an arbitrary width of 150px.
http://jsfiddle.net/daveSalomon/PudLq/583/
Edit
To also position the 'loading' icon in the center of the element....
$('#fancybox-loading').css({
position:'absolute',
top: coverPos.top + ($el.height()/2),
left:coverPos.left + ($el.width()/2),
});
http://jsfiddle.net/daveSalomon/PudLq/585/
Related
I'm trying to change the sub-menu behavior of a site. The original sub-menu appears as a drop-down, and instead I'd like it to appear in a separate full horizontal div.
So far I've done this:
jQuery(document).ready(function( $ ){
$(".header").append("<div class='subber'><div class='sub-menu'></div></div>");
$(".main-navigation ul li.menu-item-has-children").mouseover( function() {
var a = $(this).find(".sub-menu").html();
$(".subber .sub-menu").html(a);
});
});
... with some css, and it works well. the original sub-menu HTML is copied to the subber sub-menu.
I'd like each subber sub-menu to be positioned relatively to the original menu item, even though they occur in separate areas of the HTML. Can I somehow bind the two?
My HTML code:
<div class="header">
<div id="navigation">
<div class="site-navigation">
<nav class="main-navigation">
<ul class="menu-main-menu">
<li class="menu-item">
some text
</li>
<li class="menu-item menu-item-has-children">
some text
<ul class="sub-menu">
<li class="menu=item">
sub item text
</li>
</ul>
</li>
<li class="menu-item">
some text
</li>
</ul>
</nav>
</div>
</div>
<div class="subber">
<div class="sub-menu"></div>
</div>
</div>
Since there's no actual parent-child relationship in the HTML structure, there's no CSS-way of positioning your new sub-menu relative to a top-level menu item.
Instead, you'll have to manually position the new sub-menu with JS, using the coordinates of the original menu item.
Keep in mind this basic positioning won't create a "stickyness" between the two, so if your main menu moves (e.g. a sliding menu bar with up/down toggle states), you'll have to trigger an update to the sub-menu positioning using a listener and function.
Codepen
$("#menuItem1").mouseover( function() {
/* get original menu */
var origMenu = $(this);
/* grab content out of original sub-menu */
var myContent = origMenu.find(".sub-menu").html();
/* copy content over to new sub-menu outside of navigation */
$(".subber .sub-menu").html(myContent);
/* get the coordinates of the original menu item */
var subberLeftOffset = origMenu.offset().left;
var subberTopOffset = origMenu.offset().top + origMenu.innerHeight(true);
/* re-position the new sub-menu so it appears below the original menu */
$(".subber").offset({top: subberTopOffset, left: subberLeftOffset});;
});
#origNavigation .sub-menu {
visibility: hidden;
height: 0px;
}
#menuItem1 {
margin-top: 8em;
margin-left: 8em;
padding: 1em;
width: 200px;
border: 1px solid black;
}
<div id="origNavigation">
<div id="menuItem1">
Hello
<div class="sub-menu">Sub-menu</div>
</div>
</div>
<div class="subber">
<div class="sub-menu"></div>
</div>
I have a menu which opens a sub-navigation on clicking a header which I am trying to get to close by clicking anywhere on the page except an open element.
My Code Snippet is as follows:
function showSubMenu(show, hide1, hide2, hide3, hide4) {
document.getElementById(show).className = "subNavShow";
document.getElementById(hide1).className = "subNavHide";
document.getElementById(hide2).className = "subNavHide";
document.getElementById(hide3).className = "subNavHide";
document.getElementById(hide4).className = "subNavHide";
}
.subNavHide {
display: none;
}
.subNavShow {
display: block;
}
<ul class="topnavList" id="siteTopnavList">
<li>
<a onclick="showSubMenu('text1','text2','text3','text4','text5')" href="javascript:void(0);">Nav 1</a>
<article id="text1" class="subNavHide">
<ul>
<li>Sub Nav 1</li>
</ul>
</article>
</li>
<li>
<a onclick="showSubMenu('text2','text1','text3','text4','text5')" href="javascript:void(0);">Nav 2</a>
<article id="text2" class="subNavHide"> text2 </article>
</li>
<li>
<a onclick="showSubMenu('text3','text1','text2','text4','text5')" href="javascript:void(0);">Nav 3</a>
<article id="text3" class="subNavHide"> text3 </article>
</li>
<li>
<a onclick="showSubMenu('text4','text1','text2','text3','text5')" href="javascript:void(0);">Nav 4</a>
<article id="text4" class="subNavHide"> text4 </article>
</li>
<li>
<a onclick="showSubMenu('text5','text1','text2','text3','text4')" href="javascript:void(0);">Nav 5</a>
<article id="text5" class="subNavHide"> text5 </article>
</li>
</ul>
Ideally I would like to use pure Javascript for this but if Jquery is absolutely necessary then I would be OK with that too
The easiest way to do this with your current implementation, in my opinion, is to add a click event listener to the document and use .closest to determine if the element clicked is the element open:
document.addEventListener(`click`, hideSubMenus);
function hideSubMenus(event) {
if (!event.target.closest(`.topnavList li a, .subNavShow`)) {
document.getElementById(`text1`).className = `subNavHide`;
document.getElementById(`text2`).className = `subNavHide`;
document.getElementById(`text3`).className = `subNavHide`;
document.getElementById(`text4`).className = `subNavHide`;
document.getElementById(`text5`).className = `subNavHide`;
}
}
closest is however not compatible with older browsers: https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
But I would probably add classes to the links and add event listeners to them instead of using the "onclick" attribute. That way, for example, if you add the "subNavLink" class to each link, you can use a loop to deal with the links, instead of repeating the same line for each link:
let links, i, n;
links = document.getElementsByClassName(`subNavLink`);
for (i = 0, n = links.length; i < n; i++) {
links[i].addEventListener(`click`, showSubMenu);
}
function showSubMenu(event) {
let currentLink, i, link, n;
currentLink = event.currentTarget;
for (i = 0, n = links.length; i < n; i++) {
link = links[i];
if (link === currentLink) {
// this link was clicked, so we have to show its submenu
link.nextElementSibling.className = `subNavShow`;
} else {
// this link was not clicked, so we have to hide its submenu
link.nextElementSibling.className = `subNavHide`;
}
}
}
By doing this you can change the hideSubMenus function to:
function hideSubMenus(event) {
let i, n;
if (!event.target.closest(`.subNavLink, .subNavShow`)) {
for (i = 0, n = links.length; i < n; i++) {
links[i].nextElementSibling.className = `subNavHide`;
}
}
}
I've found that the easiest way to pull this off is to create a layer, underneath the menu (or more commonly a modal window). And then use that layer as the element to test if it has been clicked (versus the element sitting on top of it).
(The example uses a grayed out background to show the overlay's presence, but it could just as easily be a transparent DIV and still have the same effect)
// Get the elements that will show/hide
const overlay = document.getElementById('overlay');
const menu = document.getElementById('menu');
// Change the className to have the CSS that will hide
// the elements
// Since the 'menu' element is on top of the 'overlay'
// element, clicking on the 'menu' should not click
// through the 'overlay' -- thus ignoring this section
// of code to hide things
overlay.onclick = function(){
menu.className = 'hide';
overlay.className = 'hide';
};
// Quick and dirty code to reset the page and display
// the 'menu' and 'overlay' DIVs
function open(){
menu.className = '';
overlay.className = '';
}
#overlay{
display: block;
position: fixed;
top: 0; left: 0;
height: 100%; height: 100vh;
width: 100%; width: 100vw;
background-color: rgba( 0, 0, 0, 0.25 );
}
#overlay.hide{ display: none; }
#menu{
position: absolute;
background-color: white;
padding: 15px; border-radius: 5px;
}
#menu ul, #menu li{
margin: 0; padding: 0;
list-style: none;
}
#menu.hide{ display: none; }
OPEN
<div id="overlay"></div>
<div id="menu">
<ul>
<li>Menu Item</li>
<li>Menu Item</li>
<li>Menu Item</li>
<li>Menu Item</li>
</ul>
</div>
With the bubble and how elements are stacked, clicking on the menu won't close it -- but clicking anywhere outside of it will.
The more general the code is, the better.
Using an eventListener set on the document lets you listen to all "click" events (that bubbles up the DOM tree) on the page. You can close all articles no matter what, then display the clicked entry (and its ancestors) if appropriate.
The code below, yet short as many benefits:
It is dynamic. Meaning it can handle any amount of sub-levels. article elements neither require id attributes nor show/hide classes at first render. The code becomes loosly coupled.
Only a single handler function will live in memory instead of one per menu entry.
It will handle entries added later (after eventListener registration) to the menu.
Your code is factorized which makes it easier to read and reuse.
let topNavList = document.querySelector('#siteTopnavList');
document.addEventListener('click', function (e) {
let t = e.target;
// At this point, close menu entries anyway
topNavList.querySelectorAll('a ~ article').forEach(el => {
el.classList.add('subNavHide'); el.classList.remove('subNavShow');
});
// Drop clicks on the "active" link or any element that is outside the `#siteTopnavList` menu
if (!t.nextElementSibling || t.nextElementSibling.classList.contains('subNavShow')) {
return;
}
if (t.nodeName.toLowerCase() == 'a' && topNavList.contains(t)) {
topNavList.querySelectorAll('article').forEach(x => {
if(x.contains(t) || x === t.nextElementSibling) {
x.classList.remove('subNavHide');
x.classList.add('subNavShow');
}
});
// Prevent the browser to process the anchor href attribute
e.preventDefault();
}
});
#siteTopnavList article {display:none}
#siteTopnavList .subNavShow {display:block}
<ul class="topnavList" id="siteTopnavList">
<li>
Nav 1
<article>
<ul>
<li>Sub Nav 1</li>
</ul>
</article>
</li>
<li>
Nav 2
<article> TEXT2 </article>
</li>
<li>
Multi level
<article>
<ul>
<li>
Sub Nav 1
<article>
<ul>
<li>Deep 1</li>
<li>Deep 2</li>
<li>
Even deeper 3
<article>
<ul>
<li>Even deeper 1</li>
</ul>
</article>
</li>
</ul>
</article>
</li>
</ul>
</article>
</li>
</ul>
I have an issue and really don't know how to solve this.. I have an sticky footer like this:
<!-- FOOTER ICON TABS -->
<div data-role="footer" data-position="fixed" data-tap-toggle="false">
<div class="footer" data-role="navbar">
<ul>
<li>
<a href="#dashboard" data-icon="dashboard" class="ui-btn-active" id="icon-dashboard">
<span class="navbar-text">Dashboard</span>
</a>
</li>
<li>
<a href="#" data-icon="progress" id="icon-progress">
<span class="navbar-text">Voortgang</span>
</a>
</li>
<li>
<a href="#map" data-icon="security" id="icon-security">
<span class="navbar-text">Plattegrond</span>
</a>
</li>
<li>
<a href="#" data-icon="security" id="icon-security">
<span class="navbar-text">Securitycheck</span>
</a>
</li>
</ul>
</div>
</div>
Thereby I set this styling:
.ui-footer, .footer, .footer li, .footer a, .footer a:after {
background-color: transparent !important;
border-color: transparent !important;
height: 70px;
}
But It is annoying because my content is behind the icons and it is not nice. It looks like this:
I allready have changed the heights of the white blocks, but the blocks are not having a hard height. This ecause the notification block is dynamic and the content vary from length. Thereby the second block has an collapsable block where Boardingpass is writen.
How it has to look:
Here is a FIDDLE which recreates the problem. I hope someone could help me out on this :)
You could just set the bottom margin:
#flight-info-block {
margin-bottom: 80px !important;
}
also in code, use the third parametef of the slideToggle function to achieve the same effect at the end of the animation:
//open up the content needed - toggle the slide- if visible, slide up, if not slidedown.
$content.slideToggle("slow", "swing", function() {
$("#flight-info-block").css("margin-bottom", "80px");
$("#flight-info-block").trigger("updatelayout");
});
BTW: i also dislike the transparent background, then i added following rule at the bottom of your CSS:
.footer {
background-color: #00a0e5 !important;
}
and removed also your -350 offset in scrollTop:
$('html, body').animate({
scrollTop: $header.offset().top
}, 1000);
Your updated Fiddle: http://jsfiddle.net/yTt9b/1787/
I have an RSS blog feed (hidden overflow) with buttons on the top and bottom of the div which will smoothly scroll through-out the feed. I'm looking for a way so that on each button click, it will scroll to the top of the next 'rss-item' (class). The div looks like this:
So what I'm trying to achieve is so each time you click the down arrow (or up) the scroll will stop when each 'rss-item' is at the top of the div.
I explored many similar questions but couldn't quite achieve what I wanted.
Here is the function used to smooth scroll within the div:
$(document).ready(function() {
var scrollTime = 900;
$('#upClick').click(function() {
$('#homeBlogs').animate({
scrollTop: $('#homeBlogs').scrollTop() + 200
}, scrollTime);
});
$('#downClick').click(function() {
$('#homeBlogs').animate({
scrollTop: $('#homeBlogs').scrollTop() - 200
}, scrollTime);
});
});
Here is a screen grab of the generated source html:
Ok, so I re-created this as best I could in a jsfiddle. Here is the HTML structure. I've tried to build this according to the screenshot so they should be similar. Note: I've added a CSS class of "active" to the first "rss-item". This should only be applied in HTML to the first item and needs to stay here in order for the Javascript portion to function correctly.
<div id="blogSection">
<div class="row" id="scrollUp">
<button class="scrollButton" id="upClick">Scroll Up</button>
</div>
<div id="homeBlogs">
<div class="rss-box">
<p class="rss-title"></p>
<ul class="rss-items">
<li class="rss-item active">
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
</li>
<li class="rss-item">
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
</li>
<li class="rss-item">
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
</li>
<li class="rss-item">
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
</li>
<li class="rss-item">
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
</li>
<li class="rss-item">
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
<p>ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent</p>
</li>
</ul>
</div>
</div>
<div id="scrollDown" class="row">
<button class="scrollButton" id="downClick">Scroll Down</button>
</div>
</div>
Next, here is the CSS I used. This is purely to support the demo. I set it up so whichever "rss-item" has the "active" class will be highlighted in red. This should hopefully provide a visual cue as to what's going on when a button is clicked.
button {
display: block;
width: 100%;
background-color: black;
color: white;
height: 50px;
cursor: pointer;
}
#scrollUp {
position: fixed;
top: 0;
left: 0;
width: 100%;
}
#scrollDown {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
}
.active {
color: red;
}
Finally, here is the Javascript I used in order to get things done. I've changed it a lot to help make things more efficient and to correct some errors.
$(document).ready(function() {})
//we can use one single event and modify the behavior based on the direction that was clicked
.on('click', '.scrollButton', function() {
var scrollTime = 900,
direction = $(this).attr('id'),
$currentItem = $('.rss-item.active'),
$newItem;
switch (direction) {
case 'upClick':
$newItem = $currentItem.prev('.rss-item');
break;
case 'downClick':
$newItem = $currentItem.next('.rss-item');
break;
}
//if we aren't at the top or bottom of the list already
if ($newItem.length > 0) {
//since we know we can now change the active item, we need to remove this class so we can apply it to the new item
$('.rss-item').removeClass('active');
$newItem.addClass('active');
}
//Now that the logic is out of the way, we can run the scroll animation
//Also, I think you will want to use 'html, body' as a selector so the page itself moves
$('html, body').animate({
scrollTop: $('.rss-item.active').offset().top - 200 //this will keep content positioned correctly, but you shouldn't need both a '+ 200' and '- 200' here. Adjust this value as needed.
}, scrollTime);
});
Finally, here is the jsfiddle: https://jsfiddle.net/sm1215/sebgbnr4/
Here is my html look :
<div class="right fly" style="top: 45px;">
<div class="dataContainer">
<div class="fuelLvlInfo">
<div class="header"><i class="ion-arrow-down-b"></i>Paliwo - poziomowskaz</div>
<ul>
<li class="usage"><div class="n"><span>Zużycie [l]:</span></div><div class="v">24</div></li>
<li class="lvl"><div class="n"><span>Poziom paliwa [l]:</span></div><div class="v">---</div></li>
<li class="avgUsageKm"><div class="n"><span>Śr. zużycie [l/100km]:</span></div><div class="v">46.4</div></li>
<li class="avgUsageHour"><div class="n"><span>Śr. zużycie [l/h]:</span></div><div class="v">---</div></li>
</ul>
</div>
<div class="fuelflowInfo">
<div class="header"><i class="ion-arrow-down-b"></i>Paliwo - przepływomierz</div>
<ul>
<li class="usage"><div class="n"><span>Zużycie [l]:</span></div><div class="v">1</div></li>
<li class="avgUsageKm"><div class="n"><span>Śr. zużycie [l/100km]:</span></div><div class="v">1.9</div></li>
<li class="avgUsageHour"><div class="n"><span>Śr. zużycie [l/h]:</span></div><div class="v">---</div></li>
<li class="counter"><div class="n"><span>Licznik [l]:</span></div><div class="v">---</div></li>
</ul>
</div>
</div>
Here is preview:
What i need: make to .right be auto width, and divs in li must be 50% width or width equal to the longest div.n content.
Tried white-space:nowrap; display:inline-block etc. not working.
https://jsfiddle.net/eta71Lbx/
Preview what i expect :
50% width
or width fixed to content length (on left side or right side)
You're using the span element that will shrink the with based on the content. I would avoid using span.
But if you need to use it, then here is a work around to solve the .right part of the menu using jQuery.
Remove the 50% at the > div { width:50%; }
Add white-space:nowrap; to
the .n class.
(If you already included jQuery after the list is created, then
don't do this step). Include jQuery:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js">
Add the folowing to the ready or inside a function you want:
$(document).ready(function() {var maxWidth = 0;$( "li .n" ).each(function( index ) {var w = parseInt($(this).css('width').replace('px', ''));if(maxWidth<w){maxWidth = w;}});var m = maxWidth + 'px';$( ".n" ).css('width', m);});
https://jsfiddle.net/eta71Lbx/3/
Hope that helps!