I have code like this:
<div id="item-menu">
<ul style="padding-top: 10px; padding-left: 20px;">
<li id="item-1">1</li>
<li id="item-2">2</li>
<li id="item-3">3</li>
</ul>
</div>
I want to get each item position relative to the container. In this example I will get each <li> position relative to the <ul>, right?
What should I do to get position of item-1 --> top: 10, left: 20?
Couldn't be simpler. Simply call the position() method on the lis:
var position = $("#item-?").position();
Returns an object with properties top and left. You'll also need to set the ul to position: relative in your CSS.
#item-menu { position: relative; }
fiddle: http://jsfiddle.net/ByZRV/2/
You can use .position() to compute the location of an element:
var offset = $('#item-1').position();
alert(offset.left + ', ' + offset.top); // 20, 10
Here's a demo.
You have to add the style position:relative for your
<ul style="position:relative; padding-top: 10px; padding-left: 20px;">
then
$('#item-menu ul li').each(function(){
console.info( $(this).position());
});
Related
I'm trying to position an element exactly in the same "X" coordinate of another element.
There are many solutions in stackoverflow to get the position using something like this:
var rect = element.getBoundingClientRect();
console.log(rect.top, rect.right, rect.bottom, rect.left);
My problem is that when I try to apply the value on "element.style.left" of elements that are inside other elements positioned as "absolute", the element position becomes larger because the "left: 0" is the beginning of the absolute element and not "left: 0" of the document.
The more "nested" elements exist using "absolute", the greater the difference.
Is there any way to detect elements using "position: absolute" so that I can offset the actual value to be positioned by discounting the "left" of each element with "absolute"?
This is the problem:
<span class="dropdown-label">Some menu</span>
<nav class="dropdown-menu">
<a class="item">Email</a>
<a class="item">Twitter</a>
<a class="item">Tumblr Blog</a>
<span class="dropdown-label">Another menu</span>
<nav class="dropdown-menu">
<a class="item">Foo</a>
<a class="item">Bar</a>
<a class="item">I'm Batman</a>
<span class="dropdown-label">Yet another menu</span>
<nav id="finales" class="power-dropdown">
<a class="item">Foo</a>
<a class="item">Bar</a>
<a class="item">I'm Robin</a>
</nav>
</nav>
</nav>
Each dropdown needs to be positioned with the "lef" of its respective label, but we have dropdowns inside other dropdowns and each dropdown is positioned absolutely.
I know I can avoid the problem by using a "container" for each dropdown positioned as "relative" and so I do not need to dynamically set the "left" to anything.
The problem is that the HTML gets more verbose, which I'd like to avoid, plus I'd like to have control of how the dropdown appears to prevent it from being drawn off the screen.
But it seems like I've run into a problem that's impossible to solve, since I can not find anywhere a way to detect elements using "absolute" to be positioned.
Is there anything similar to "element.position" that gives me this information?
You asked for a way to detect position: absolute on elements.
Use window.getComputedStyle(element).position.
function findAbsoluteElementsFromList(list){
var ret = [];
for (var i = 0; i < list.length; i++)
if (window.getComputedStyle(list[i]).position === 'absolute')
ret.push(list[i]);
return ret;
}
console.log(findAbsoluteElementsFromList(document.querySelectorAll('div')));
.div {
width: 100px;
height: 100px;
position: absolute;
top: 0;
transform: translateY(50%);
}
#a {
position: relative;
left: 0;
background-color: #f00;
}
#b {
left: 25px;
background-color: #0f0;
}
#c {
left: 50px;
background-color: #00f;
}
<div class="div" id="a">
<div class="div" id="b">
<div class="div" id="c"></div>
</div>
</div>
Same function can be used to get all other CSS values.
What's the difference between Window.getComputedStyle and Element.getBoundingClientRect()? Read here.
Why can't you just use element.style.position? Read here.
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/
To show what I want to do, here is a url. http://octopuscreative.com .
I want something that when I scroll down the height, the cyan div disappears like the website above.
I currently have the scrolling working in my code, however, I cannot see the rest of my HTML that is below my #main div. I don't know if this has anything to do with my new #slideshow div (with a fixed position).
I thought since the #slideshow div had its height reduced to 0, I would be able to see the HTML underneath the #main div, but all I see below is white.
var header = $('#slideshow'),
headerH = header.height();
$(window).scroll(function() {
if (header.height() >= 0) {
header.css({
height: -($(this).scrollTop() - headerH), position: 'absolute'
});
}
else if (header.height() < 0 ) {
header.css('height', 0);
header.css('position', 'absolute');
}
});
</script>
</head>
<body>
<div id="top">
<div id="stallion">
<img id="stallionpic" src="stallion1.png" />
<h1 class="h1">Stallion Stride</h1>
<div id="navigation">
<ul>
<li>Home</li>
<li>About</li>
<li>Register</li>
<li>Contact Us</li>
</ul>
</div>
</div>
</div>
<div id="main">
<div id="slideshow">
<div id="leftbutton"></div>
<div id="rightbutton"></div>
<div id="slideshownav">
<ul>
<li><a class="active"></a></li>
<li><a></a></li>
<li><a></a></li>
<li><a></a></li>
</ul>
</div>
<div id="slideshow_inner">
<li id="pic1"><a><img src="pic2.jpg" /></a></li>
<li id="pic2"><a><img src="pic1.jpg" /></a></li>
<li id="pic3"><a><img src="pic3.jpg" /></a></li>
<li id="pic4"><a><img src="pic4.jpg" /></a></li>
</div>
<p>a;lsdfja;lskdjf;laskdjf;aslkdjf;alsdjkfa;sldfkja;sldkfja;sldkfja;</p>
</div>
<div id="mainContent">
<p>a;lsdfja;lskdjf;laskdjf;aslkdjf;alsdjkfa;sldfkja;sldkfja;sldkfja;</p>
</div>
</div>
<div id="footer">
</div>
</body>
I'm the lead dev at Octopus. Here's the bare minimum amount of code to make something like that header effect work (it does use fixed position).
HTML
<div id="hero">
<h2>I am the hero</h2>
</div>
<div id="main-content">
<h3>I am the main content</h3>
</div>
CSS
* {
margin: 0;
}
div#hero {
position: fixed;
top: 0;
left: 0;
width: 100%;
background: #3D6AA2;
height: 300px;
}
div#main-content {
height: 1500px;
background: #fff;
margin-top: 300px;
position: relative;
z-index: 1;
}
I also threw together a jsFiddle that demonstrates it, along with the bit of parallax stuff the site does: http://jsfiddle.net/paulstraw/FW4FF/
Hope that helps!
position: fixed; positions the element based on viewable screen coordinates, so when you scroll, the position will update to reflect the 'new' top/left boundaries. position: absolute; is more like what you are describing, it will keep the element in the same place, regardless of the content around it, or the browser's scroll position. However, this will take the element out of the 'flow' of the page, and other elements will act like it is not there (and might overlap it). In which case, you will likely have more luck just floating your header left: float: left;.
If you do this, you will probably need to clear the floats in your main div by adding the css style: clear: both;. This will push the main div below any floated content above.
Using element.offset().left gets you the element's offset position from its parent. Is there any way to get the offset position from another element? For example, here's my html:
<div id="tile_id_579" class="product_tile">
<div class="selectContainer">
<table style="width:100%;">
<tbody>
<tr>
<td>
<div id="select-undefined" class="tzSelect">
<div id="options-undefined" class="tzOptions" style="max-height: 500px; width: 250px; display: none; min-width: 118px;">
<ul class="dropDown" id="dropdown-undefined">
<li><div class="header">Hand-Tossed Style Pizza</div>
<div class="subheader">The crowd-pleasing pizza that everyone can agree on.</div>
<div class="optkey">0</div>
</li>
<li><div class="header">Pan Pizza</div>
<div class="subheader">Our Pan Pizza is America's favorite!</div>
<div class="optkey">1</div>
</li>
</ul>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
It's generated from a database. Using offset().left gets me the offset from the #selecct-undefined div, but I need to get how far the #options-undefined div is from the .selectContainer div. Is this possible?
EDIT TO ADD
Tried both of these, and both return the same thing: top: 381, left: 0. But left is NOT 0 in relation to the document; it can't be.
var tip = $('#tile_id_579 #options-undefined .header');
tip.first().position();
and
var tip = $('#tile_id_579 #options-undefined .header');
tip.first().offset();
How is it possible that left is 0 for both when this is where the div is? Doesn't 0 left imply that it's all the way at the left of the browser window?
Since your element is indeed within that parent you specified you can use .position() instead of .offset(). But if .selectContainer is not the closest relative parent you will need to get the position of both your element and that "other" element and calculate the difference.
var myPos = $('#options-undefined').offset();
var otherPos = $('#options-undefined').closest('.selectContainer').offset();//if #options-undefined wasn't a child of .selectContainer you would do $('.selectContainer').offset();
var _offset = {
top: otherPos.top - myPos.top,
left: otherPos.left - myPos.left
}
I'm trying to use Jquery to have scroll on a UL list, with two span to move up and down.
it works for one li child, but how for an ul filled dynamically ?
thank you, i'm totally lost
$('span.scrollDown').click(function () {
$('.liste-grostitres li:first-child').css('margin-top', 0 - $('.liste-grostitres li').outerHeight());
$('.liste-grostitres').css('overflow', 'hidden');
});
$('span.scrollUp').click(function () {
$('.liste-grostitres li:first-child').css('margin-top', 0);
$('.liste-grostitres').css('overflow', 'visible');
});
<div id="grostitres">
<div class="gInner">
<span class="scrollUp"></span>
<span class="scrollDown"></span>
<div class="scrollable" id="divlist" runat="server">
<ul>
<li></li>
<li></li>
...
</ul>
</div>
</div>
heres a fiddle with slidetoggle:
http://jsfiddle.net/RMQLM/
also the working code example:
HTML:
<div id="up">up</div>
<div id="list">
<ul>
<li>foo1</li>
<li>bar1</li>
<li>foo2</li>
<li>bar2</li>
<li>foo3</li>
<li>bar3</li>
<li>foo4</li>
<li>bar4</li>
<li>foo5</li>
</ul>
</div>
<div id="down">down</div>
CSS:
div#list {
height: 93px;
overflow: hidden;
border: 1px solid red;
}
jQuery:
var listcount = $('li').size();
var cli = 1;
$('#down').click(function() {
if (cli < listcount) {
$('li:nth-child(' + cli + ')').slideToggle();
cli++;
}
});
$('#up').click(function() {
if (cli > 1) {
cli--;
$('li:nth-child(' + cli + ')').slideToggle();
}
});
Set your UL to be position: relative; and have top: 0;.
Add a function to handle the animation:
var scroll_ul = function(offset) {
// Target the UL to scroll
var to_scroll = $('#divlist').find('ul');
// Store the distance to scroll (assumes LIs are all equal height)
var scroll_distance = $('#divlist').find('li').outerHeight(true);
// Animate
to_scroll.stop().animate({ top: '-=' + (offset * scroll_distance) });
};
Then change your click handlers to be something like this:
$('span.scrollDown').click(function() {
scroll_ul(1);
});
$('span.scrollUp').click(function() {
scroll_ul(-1);
});
You may experience strange scroll distances if you hammer the scrollDown/scrollUp buttons. That's when you should look into jQuery's .one() function.
I think it would be more efficient to animate the whole UL instead of individual LIs. You already wrap the UL in a DIV, so why not animate the UL relative to the wrapper? That would work the same way as animating a single LI inside UL, so you don't need to reinvent the wheel.