positioning the popup menu with jquery based on element position in window - javascript

I am sure this question may have been asked, but I couldn't find the right solution..
I need to show a menu on mouse over of an icon which can be placed anywhere on the page. Example code is here: ( http://jsfiddle.net/Qfjdk/2/ )
This shows the popup, however if I change the code from
#nav {
margin:0;
padding:0;
list-style:none;
float: left;
}
to
#nav {
margin:0;
padding:300px;
list-style:none;
float: right;
}
As can be seen, the position of the menu is always centered below. I want to change the position of the menu based on where the icon is displayed.
If the icon element is aligned right, I want to position the menu to start on right edge of icon. If the icon element is towards bottom left of displayed page, I want the menu bottom left to align with element top left etc..
I am not looking for the algorithm, am looking for the right way of setting parameters..
Appreciate your help

I would first define how many alternatives you want to support (for example, 4: button on right-top, right-bottom, left-top or left-bottom), and create a set of classes with these different options (.pos1, .pos2, .pos3, .pos4).
Then I'd use JS or jQuery to calculate the offset of the icon relative to the window. Depending on that result, I would give the popup the correct class from the ones you previously created. You can do this on load as well as on window resize. For example, calculating a distance to the right and applying css changes (you could apply a class instead, but this is just to show how it'd work):
var callback = function () {
// when hover on an element, calculate offset to right
$('.yourElement').mouseover(function(){
var currentElement = $(this);
var distanceRight = $(window).width() - ($(currentElement).offset().left + $(currentElement).width());
// If the distance is less than 50, then do...
if (distanceRight < 50) {
$('.yourPopup').css("left","-200px");
}
else {}
});
};
$(document).ready(callback);
$(window).resize(callback);

Related

Animate div from bottom to top and back

I have a div element which represents a navigation bar and has the id #navbar. It is positioned absolutely and is set to bottom: 20px;. Now I want it to move to the top, while keeping a 20px distance to the top, on the click of a button. When clicking the button again it should move back to the bottom of the page (again keeping the 20px distance) even if the window has been resized. In general, the resizing of the window should have no effect on the navigation bar. Here is the JavaScript code I have.
var isUp = false;
function animate() {
if(!isUp) {
$("#navbar").animate({top: 20}, 2000);
} else {
$("#navbar").animate({bottom: 20}, 2000);
}
}
But it doesn't work and the bar always ends up in the middle of the page. Any help is greatly appreciated.
EDIT:
Here is an example: https://jsfiddle.net/6knLw3a3/
bottom and top will position an absolutely positioned element according to it's closest explicitly positioned ancestor. So make sure that you put position:relative on the container element.
Advice to animate only one prop bottom or top.
Example: https://jsfiddle.net/17oy80c3/
I found a solution: Wrap the navbar element in an overlay div. Set this overlay div to lay above all other elements and make it transparent. Position the navbar at the top of the overlay. Now simply set the height of the overlay.

Fixed placed element within certain area

I have a page where I display a long list of results from a DB query.. and I also show a Google Map to the RIGHT of this long list.
Map is roughly 240px wide and maybe 600px long/height.
This MAP is inside a container DIV (#mapContainer).. that contains the map, and a dropdown box above the map canvas.
Currently, the mapContainer scrolls along with the page itself.. what I would like to do is have it be static/fixed element. So it starts/displays/is placed where I have it currently on the page.... if I scroll the page.. the map should stay fixed.. until the end (bottom) of the results are scrolled to..
(I dont want the mapContainer to scroll and cover the footer element/div)
Following this tutorial:
http://www.webgeekly.com/tutorials/jquery/a-simple-guide-to-making-a-div-static-as-you-scroll-past-it/
It doesnt stay fixed..
//sticky map placement
$(function () {
var msie6 = $.browser == 'msie' && $.browser.version < 7;
if (!msie6) {
console.log("NOT IE 6");
var top = $('#mapContainer').offset().top;
$(window).scroll(function (event) {
console.log("scrolling.......");
var y = $(this).scrollTop();
if (y >= top) {
$('#mapContainer').addClass('fixed');
console.log("class added");
}else {
$('#mapContainer').removeClass('fixed');
console.log("class removed");
}
});
}
});
The first console.log() outputs fine.. but nothign in the window.scroll() portion fires ever.
Rest of code used:
#mapContainer{
display:table;
width:240px;
float:right;
/* sticky map */
position: absolute;
top: 458px;
left: 50%;
/* width: 100px; */
margin-left: 339px;
}
#<span class="skimlinks-unlinked">mapContainer.fixed</span> {
position: fixed;
}
On the tutorials page itself.. he has a toolbar on the left side..
that stops 'being fixed' when you scroll all the way to the top.. (it will start to move with the rest of the page scroll at a certain point).. and it doesnt go all the way down to cover the footer either.
I'm not clear why the jQuery portion isnt firing.. and I'm not clear what that last style is for? (seems odd looking)
All this absolute, fixed, relative, to parent, to viewport..etc.. is confusing.
Any easy to read/follow/understand tutorials that will get me to where I want to be? Or suggestions on what I am doing wrong with the correct approach?
I looked at your Fiddle and noticed a couple things:
Your "fixed" class was not represented in the CSS. When I looked into the CSS I saw a span element wrapping a ".fixed" reference with a position property set.
You are styling the mapContainer div using the ID. This is a very rigid selector as the order of CSS selectors goes. The hierarchy of CSS selectors is specifid and IDs will override types and classes. See: http://htmlhelp.com/reference/css/structure.html
The when scrolling, I am seeing the console logging in my dev tools. Also, when inspecting the element, I am seeing it add and remove the class name.
Based on my observations, modifying the CSS selector for your container should do the trick. Adding the ID to the class will keep the CSS rule specific enough:
#mapContainer.fixed { position: fixed; }
Refer to this updated Fiddle for an example with these changes in place:
http://jsfiddle.net/pmurst8e/4/
Update: For demonstration purposes of what I was referring to with the resize I modified your example a bit. It isn't the prettiest, but it conveys the point: http://jsfiddle.net/pmurst8e/6/
Update: There are a couple issues with the latest Fiddle (v12):
The sidebar will always go fixed the moment you scroll because "top" is never calculated. It's being set to zero, and the offset calculation is commented out.
Absolute positioning is relative to the closest positioned parent. If no parent is positioned, it's relative to the window. To constrain an absolute positioned element, set the constraining parent to "position:relative;".
Instead of using a percentage and left position rule, consider positioning the sidebar to the right, relative to the "contentContainer", by a set number of pixels.
When the fixed position takes effect, we also need to set the sidebar fixed left position. Otherwise, it will use the positioning in the CSS. In contrast to absolute positioning, Fixed positioning is relative to the window, meaning an absolute element "right: 10px" will be 10px from the right of the positioned parent, but will appear 10px from the right of the window when fixed.
You don't need a float when you have absolute positioning. Absolute position removes an element from the normal flow of the document, and because of this float does not apply.
I updated the Fiddle to show how to make these adjustments. I cleaned out the float and margin from the mapContainer and left the absolute positioning. With that I set the contentContainer to relative to constrain mapContainer to it. You will also see, on the script side, I added a line to set the offset of mapContainer. Without this, when it becomes fixed it will be 10px off the right border of the window.
Updated Fiddle: http://jsfiddle.net/pmurst8e/14/
Also, you want to leave your top offset line in tact. Without that, it goes fixed the moment the scroll moves and never goes back. When that becomes the case, you're better off just setting fixed permanently.
var top = $('#mapContainer').offset().top; // you want this
Regarding the bottom boundary, you can do a couple things:
Resize the sidebar so that it shrinks to the window size. This is demoed in my example from my first post in this and the downside is it forces the sidebar to become a scrollable div so the child content is all visible.
Use a check for the bottom so that when you hit the limit, the container goes back to an absolute position, but one set at the bottom: 0 of the parent.
Something like:
var limit = $('footer').offset().top;
var $mc = $('#mapContainer');
var pos = $mc.offset().top + $mc.outerHeight();
if (pos >= limit) {
$mc.removeClass('fixed')
.addClass('bottom-set').css('left',''); // define this in CSS for bottom absoluteness
}
#mapContainer.bottomFixed {
bottom: 0;
top: auto;
}
And to be fully honest, you might save yourself some time working this all out if you take a look at the ScrollToFixed plug-in (https://github.com/bigspotteddog/ScrollToFixed). I seem to be mentioning it quite a bit lately, but this issue seems to be a popular one right now.
Incidentally, go to your OP and click the Edit button. Shrink the height of your browser and scroll down. You should see SO has a fixed sidebar that passed the footer. ;)

Any way to tell if a floated element has been bumped down?

Imagine a responsive menu where the the elements are set to float. They're all, say, 150px wide. As the menu is reduced in width, individual elements will, one by one, get bumped down to the next row.
You're trying to determine whether an element has been bumped down. My thought was to design things in such a way where I could find out if the top of the floated element!= 0. If not, it's been bumped down to the next row. I could also evaluate element heights to figure out if an element is in row 2, 3, etc.
Is there a simpler way to determine if a floated element has been wrapped/bumped down due to parent width constraints?
I would try to find offset of element f.e. this way:
$(window).on('resize', function () {
$(".some-menu-item-selector").each(function(e) {
elementOffset = $(this).offset().top,
$(this).html(elementOffset);
});
});
Now when I have offsets I can group elements by "rows". There is only one assumption: elements have same height. If not, thing gets complicated.
Since your elements are a fixed size, 150px, you can simply use some math to figure out where they are at in the container element.
floor(container width / element width) = number of elements per line
element index % element per line = column
floor(element index / elements per line) = row
Simply add an event listener for the containers resize event and do your check there.
This might not be the best way to do it, but it is one possibility using javascript or jQuery.
You can get the position from the top of the first menu item, then check the distance for the next elements. if they are different, you would know that the the element has been displaced.
You would have to do this on load and on window change.
Good Luck!
I know very little JS but you can check height. I'm using a menu for an example to addClass or removeClass.
DEMO: https://jsbin.com/gapaqe/1/
jQuery:
$(window).on("resize", function() {
if ($('nav').height() >= 62) {
$('nav').addClass('test');
} else {
$('nav').removeClass('test');
}
}).resize();
CSS
nav a {
float: left;
padding: 20px;
border: 1px solid red;
}
.test a {
background: blue
}
/* to clear the floats all fast like dude */
nav {
display: table;
}
HTML
<nav>
Link 1
Link 2
Link 3
Link 4
Link 5
Link 6
Link 7
Link 8
Link 9
</nav>

Fix position of div tag inside dialog op-up

I have dialog box which comes on clicking a button. In the dialog box i have a button and other content. I want to make that button position fixed inside dialog pop-up.
$(window).bind('scroll', function() {
if ($(window).scrollTop() > 50) {
$('#footer_buttons').addClass('sticky');
}
else {
$('##footer_buttons').removeClass('sticky');
}
});
<style>
.sticky{
position : fixed;
}
</style>
I used above code to make the button position fix, it worked outside the dialog box but not working when the same code is used inside the dialog box. I can make a button fix by adding a min-height to dialog and make the dialog content scrollable. But I don't want to add any scroll to the content inside dialog box.
Can any one help me out. Thanks in advance
From MDN CSS position property:
fixed:
Do not leave space for the element. Instead, position it at a specified position relative to the screen's viewport and don't move it
when scrolled. When printing, position it at that fixed position on
every page.
So it doesn't matter where your element is. If you apply the fixed position, the top, left, right, bottom values are relative to the screen's viewport (visible area in browser).
In your case you should use absolute positioning and set the position using two of the four positioning properties: top, right, bottom, left. Don't forget to add position: relative or absolute to the modal container.

jQuery .offset() not retrieving correct position

I'm working on a site which dynamically creates facebook-like buttons via PHP. However, the <div> that the buttons are contained in needs to have the CSS property overflow: hidden; This is the only way I've found that works to make a two-column format which forces both columns to expand to be the length of the longest one. The only problem with this method is that any facebook-like buttons placed near the bottom of the container get clipped when someone clicks on them and they expand.
Here's the way I've tried to solve this issue:
Using jQuery, I loop through all facebook like buttons on the page and calculate their document offset using the offset() method.
I then clone() each button as well as give it absolute positioning and the calculated offset using jQuery's css() method. I hope that each cloned button will be placed in the same position of the button it was cloned from when I append it to the document.
Finally, I change each old facebook-like button's css to visibility: hidden; in order to make it invisible but still take up the space it would have previously on the page. I add the clones of the facebook-like buttons to a div without the overflow: hidden; property using the appendTo() function.
Here's my entire code for this process:
// Replaces functional facebook recommend buttons with identical ones
// in a div where they won't get clipped when they expand.
// Hides the old buttons so space is still left for new ones
$(window).load(function(){
$(".fb-recommend").each(function(){ // cycle through each recommend button
var offset = $(this).offset(); // calculate offset of each button
var newButton = $(this).clone(); // clone the button
newButton.css({'position':'absolute', 'left':offset.left, 'top':offset.top});
$(this).css("visibility","hidden"); // hide the old button
newButton.appendTo("#wrapper"); // put the new button in the wrapper where it won't get clipped
});
});
At the end of all this, I expect to have clones of each button placed where the old button was but in a different <div>. The whole process works, except that the cloned facebook-like buttons are appearing at a slightly different position than the ones they were cloned from (as PitaJ points out they seem to be off by vertical offset multiples of around 39px). You can view the issue here:
LINK TO TEST WEBSITE
As you can see, the first button is placed in the correct location (the empty space filled by its hidden clone) but the other offsets were not calculated correctly.
I'd appreciate any ideas or help offered. Let me know if you'd like me to explain better or post more code!
Edit: I figured I'd post the CSS for the facebook-like buttons here (even though all I'm changing is the margin):
#content .fb-recommend {
margin: 15px 0 5px 0;
}
Edit 2: As per UnLoco's suggestion, I added a min-height property to the fb-reccommend CSS and commented out the line of code that was hiding the old buttons so it's easier to see the problem (which is still there, though slightly lessened. The CSS now looks like this:
#content .fb-recommend {
margin: 15px 0 5px 0;
min-height: 39px;
}
Edit 3: The problem appears to have been solved in all browsers but IE by changing the CSS to this:
.fb-recommend {
min-height: 24px; // I used 24 because the fb-buttons are 24px in height
}
Final Edit? This seems to work on all browsers on my end, including IE:
.fb-recommend {
min-height: 39px;
}
I'm thinking now that the 39 might have come from the 15px margin of the old fb-button + its 24px height. I think I can get around it by simply setting the height to be 39px and not having a margin.
this is because you are retrieving the offset before the fb iframes actually load. just add a css rule like this
div.fb-recommend{min-height:39px}
I believe you're problem is some odd jQuery weirdness.
To fix this, simple change your code to this:
$(window).load(function(){
$(".fb-recommend").each(function(index){ // cycle through each recommend button
var offset = $(this).offset(); // calculate offset of each button
var newButton = $(this).clone(); // clone the button
newButton.css({'position':'absolute', 'left':offset.left, 'top':offset.top + (39*index)});
$(this).css("visibility","hidden"); // hide the old button
newButton.appendTo("#wrapper"); // put the new button in the wrapper where it won't get clipped
});
});
This will account for the weird offset problem.

Categories

Resources