JQuery - Position Popup in relative to button(s) - javascript

I'm trying to position a popup relative to its button or the button that is clicked with jquery. I'd like to position the popup in a way that doesn't cover up the button itself. Position it to the left, right, above or below the button that is clicked.
Now I know I can do this by writing more html popups and css but there got to be a way to dynamically use one div and position it with jquery. I tried using offsets and position (at one point) but I couldn't get it to work. Frankly, I'm very entry level with js and jquery so forgive my noobness.
Any help would be greatly appreciated!!
JS:
$('.trends').click(function () {
$('.questions').fadeIn();
$('.question').html('<p>What trends could potentially drive growth in the U.S.?</p>');
/* if I add this and zero out the positioning via css the pop gets offset but its way far away from this parent.
var offset = $(this).offset();
$('.questions').css('left',offset.left);
$('.questions').css('top',offset.top);*/
});
$('.consumer').click(function () {
$('.questions').fadeIn();
$('.question').html('<p>Even though we have low inflation, consumers are not increasing their spending. Why?</p>');
});
$('.industry').click(function () {
$('.questions').fadeIn();
$('.question').html('<p>What factors drove crude oil prices to fall and which industries benefited?</p>');
});
$('.henn').click(function () {
$('.questions').fadeIn();
$('.question').html('<p>MESSAGE FROM OUR PRESIDENT</p>');
var offset = $(this).offset();
$('.question').html('<p>What trends could potentially drive growth in the U.S.?</p>');
});
$('.equity').click(function () {
$('.questions').fadeIn();
$('.question').html('<p>The U.S. stock market has been rising for more than six years. What do you see ahead for equities?</p>');
});
$('.balance').click(function () {
$('.questions').fadeIn();
$('.question').html('<p>what does it look like for companies balance sheets?</p>');
});
$('.close').click(function (e) {
e.stopPropagation();
$(this).parent().hide();
$('.items').removeClass('no-effect');
});
jsFiddle

Create a separate function to display the question, which takes the clicked button and the question as parameters:
function showQuestion(button, question) {
var offset = button.offset();
$('.question').html(question);
$('.questions')
.fadeIn()
.css({
left: Math.min(offset.left, $(window).innerWidth()-$('.questions').outerWidth()),
top: offset.top + button.innerHeight()
});
}
Call it like this:
$('.trends').click(function () {
showQuestion(
$(this),
'<p>What trends could potentially drive growth in the U.S.?</p>'
);
});
Updated Fiddle
The css left calculation ensures that the question will always be on-screen.

Part of your problem was .filter being set to position: relative;.
If an absolute positioned element has a relative positioned parent the absolute element will be positioned in relation to the parent not the document.
If you remove that it gets a little easier to use .offset() to position the question:
Working Example
$('.trends').click(function () {
$('.questions').fadeIn();
$('.question').html('<p>What trends could potentially drive growth in the U.S.?</p>');
/* See change here*/
var offset = $(this).offset();
$('.questions').css('top', offset.top + $(this).height());
});
.filter {
width: 98.1481481481%;
float: left;
margin-left: 0.9259259259%;
margin-right: 0.9259259259%;
margin-bottom: 10px;
/*position: relative; see change here */
}

There's a $(...).position() function in jQuery that should help you out. I refactored your code a bit to avoid repeating lines, but the gist of it is:
function popup(jqBtn, question){
// mind that the .position does not account for borders etc.
var btn = $(jqBtn).parents('.buttons'),
posLeft = btn.position().left + btn.outerWidth(),
posTop = btn.position().top;
$('.questions').fadeIn();
$('.question').html(question);
$('.questions')
.appendTo(btn.parent())
.css('left', posLeft + 'px')
.css('top', posTop + 'px');
}
// a sample of binding a button to the popup() function
$('.trends').click(function () {
popup(this, '<p>What trends could potentially drive growth in the U.S.?</p>');
});
So the function re-appends the 'questions' div to have the same parent as the button. The button is found based on the element clicked, traversing up the structure to find an element of '.buttons' class. That might need adjusting if the structure gets more complex.
jsFiddle

Related

Stop element from being fixed once scrolled past value

I have a fixed .widget element that remains visible at all times. Currently however, it scrolls over the footer area. My goal is to stop the widget before it hits the footer.
CSS
.widget {
position:fixed;
height:450px;
width:300px;
}
footer {
height:450px;
width:100%;
}
My route I'm taking is currently:
jQuery
var $bodyheight = $('body').height();
var $footerheight = $('footer').height();
var $widgetheight = $('.game_widget').height();
var $pageheight = $bodyheight - $footerheight - $widgetheight;
$(window).on('scroll', function() {
console.log($(this).scrollTop())
});
My next step would be to loop through to see if scrollTop > $pageheight then update some CSS.
Is this the best way of going about this? Is there a cleaner/simpler way to achieve the same result?
I have managed to solve this quite simply. Inside the scroll function I set 2 variables, one for the position of the fixed element, the other for the position of the footer. These return the exact value from how far the top of the element is from the top of the page. For the fixed element I need to know the distance to the bottom of this element so I also include the height.
var $fixedpos = $(".game_widget").offset().top + $('.game_widget').height();
var $footerpos = $("footer").offset().top - 25; // 25 accounts for margin
Using a simple if/else the CSS is updated to display none/initial depending on whether $fixedpos > $footerpos (i.e. the fixed element is overlapping the footer).
if ($fixedpos > $footerpos) {
$('.game_widget').css('display','none');
} else {
$('.game_widget').css('display','initial');
}
This works, however there is a 'flicking' effect as the fixed element overlaps the footer. This is due to the function executing extremely rapidly. The solution to the flicker is to use this simple 'throttling' plugin that adds a short delay (of your choice) between each execution of a function - http://benalman.com/projects/jquery-throttle-debounce-plugin/
You then just need to bind the on scroll function to the throttle:
function scrolling() {
console.log($(".game_widget").offset().top + $('.game_widget').height());
console.log($("footer").offset().top - 25);
var $fixedpos = $(".game_widget").offset().top + $('.game_widget').height();
var $footerpos = $("footer").offset().top - 25;
if ($fixedpos > $footerpos) {
$('.game_widget').css('display', 'none');
} else {
$('.game_widget').css('display', 'initial');
}
};
$(window).on('scroll', $.throttle(250, scrolling)); // 250ms between executing the function
});
This 250ms delay stops the function from executing so rapidly that the flickering effect occurs.
Hope this helps others trying to solve this problem.

fixed position for a div inside a div

i was working on woocommerce site.My Site . The single product page has a control generator with a number of drop down options.So when a user selects each options he cannot see the changes happening at the top.So i position the image div as fixed.As follows.
.single-product .images{position:fixed;}
this made the image fixed but it is floating till down the page.I only need it just before the description/review tabs starts.Is there any other css or any js/jquery solutions to solve this .Please help.Thanks!!
Based on your website environment, you need something like this:
var images = jQuery('.images');
jQuery.fn.followTo = function (pos) {
var $this = this,
$window = jQuery(window);
$window.scroll(function (e) {
if ($window.scrollTop() > pos) {
$this.css({
position: 'absolute',
top: pos - $this.height()
});
} else {
$this.css({
position: 'fixed',
top: 'auto' //earlier it was 0
});
}
});
};
images.followTo(jQuery('#myTab').offset().top - images.height());
You may need to re-position the elements a bit, but the script will work on your website, as I tested with firebug.
I have note written this script, the script attributed to: Stopping fixed position scrolling at a certain point?
Let me know if you can take it forward from here :)

jQuery - have popup box appear on screen regardless of how low they scroll

I'm trying to create a popup box on a list of items that goes very much to the bottom of the browser.
I want the POPUP to be in the center of the page where the user is at regardless of how low they scrolled
i have to use POSITION ABSOLUTE not FIXED
but when i use POSITION ABSOLUTE the popup always appears on top and i know its due to my top: 0
.lightbox-container{
border: solid red 1px;
width: 100px;
height: 40px;
background: yellow;
position: absolute;
top: 0;
}
I want to use something like scrollTop or one of those to get the popup to always stay in the users viewpoint regardless of how low they scrolled
$('a').on('click', function(e){
var lightBox = $('<div class="lightbox-container"> <p>click to remove</p>');
lightBox.appendTo('body');
$('.lightbox-container').on('click', function(e){
$(this).remove();
});
});
here is the fiddle im working on http://jsfiddle.net/2RNAN/1/
I know there are other posts about this but im very new to jquery and cant seem to get it working.
This works working fiddle here
$('a').on('click', function (e) {
e.preventDefault();
var lightBox = $('<div class="lightbox-container"> <p>click to remove</p>');
lightBox.appendTo('body');
$('.lightbox-container').css('top', $(document).scrollTop() + 'px');
$('.lightbox-container').on('click', function (e) {
$(this).remove();
});
});
$(document).on('scroll', function () {
$('.lightbox-container').css('top', $(document).scrollTop() + 'px');
});
Edit: I think its a bit unclean and also unnecessary to center the pop-up box via jQuery. You can easily do this with CSS. Check out my updated JsFiddle: http://jsfiddle.net/kCC8p/9/ Edit End
I set the overflow to hidden on the body and included the pop-up outside the scrollable element. This way the scroll position of the user doesn't matter anymore.
JS
var lightbox = $('.lightbox-container');
$('a').click(function(e) {
e.preventDefault();
lightbox.show();
lightbox.addClass('open');
lightbox.append('<p>Click to remove</p>');
});
lightbox.click(function(e) {
lightbox.removeClass('open');
lightbox.find('p').remove();
$(this).hide();
});
See rest on jFiddle...
I may be a little late but I think this might be closer to what you were after:
Working Example
$(function () {
var lightbox = $('.lightbox-container'),
center = function () {
var T = $(window).height() / 2 - lightbox.height() / 2 + $(window).scrollTop(),
L = $(window).width() / 2 - lightbox.width() / 2;
lightbox.css({
top: T,
left: L
}).click(function () {
$(this).hide();
});
};
$('a').click(function (e) {
e.preventDefault();
lightbox.show().text('Click to remove');
center();
});
$(window).scroll(center);
$(window).resize(center);
});
Note that this method centers the popup and keeps it centered regardless of scrolling or re-sizing.
Are you avoiding the use of position fixed due to IE9 compatibility or some other reason? Using position fixed is probably the simplest answer and then address whatever compatibility issue you're having with specific browsers, such as with this answer for IE9 regarding quirks mode.

How to dynamically display position of a div on hover

Hi i am creating a website in wordpress,where i am using javascript to display a description div on hover a list of elements but my problem is according to screen size the description div must vary its position in order to display the content completely.I am not sure that i expressed my query clearly could anyone suggest me how can i get this.
jQuery:
(function($) {
$(document).ready( function() {
$('#linkcat-4 .xoxo li:nth-child(1)').mouseover(function(e) {
$('#text1').css(
'visibility' , 'visible'
);
$('#linkcat-4 .xoxo li:nth-child(1)').mouseout(function(e) {
$('#text1').css(
'visibility' , 'hidden'
);
});
});
});
})(jQuery);
HTML:
<ul class="xoxo blogroll">
<li>Admirality</li>
<li>Banking</li>
<li>Commercial</li>
<li>Contract</li>
<li>test</li>
<li>Corporate</li>
</ul>
<div class="desc-text" id="text1" style="visibility: hidden;">
<p>We represent protection and indemnity clubs that provide insurance
for many of the ships coming to Guyana. We deal with all the familiar
problems encountered by ships, both contentious and non-contentious,
including arrests arising from accidents and claims for wages and damaged
cargo. We advise masters, obtain surveys, note protests, negotiate
settlements and advise on or deal with stowaways and medical emergencies.
Our admiralty practice is the largest in Guyana.
</p>
</div>
CSS:
.desc-text {
position: absolute;
top: 12%;
left: 50%;
}
#text1 {
visibility:hidden;
background:#f1f1f1;
padding: 15px;
width: 150px;
}
You need to check the window.innerHeight and window.innerWidth properties before setting the top and left of your popup div. Here is a fiddle to get you started.
The important part is inside the .hover() call:
$( function() {
pop = $("#popup");
$(".item").hover( function() {
row = $(this);
pop.html(row.data("extra"))
.css("top", (function(r) {
if(r.offset().top > window.innerHeight - pop.height())
return window.innerHeight - pop.height();
else
return r.offset().top;
})(row))
.css("left", (function(r) {
if(r.offset().left + r.width() > window.innerWidth - pop.width())
return window.innerWidth - pop.width();
else
return r.offset().left + r.width();
})(row))
.show();
}, function() {
pop.hide();
});
});
Basically, .hover() takes two functions, one for mouseover and one for mouseout. On mouseout, I just hide the popup. On mouseover, I fill the popup div with content (here coming from the item's data-extra attribute, but it could come from anywhere) then decide where to put it based on the location of the item and the window bounds.
Hope that helps. Leave a comment if you need more.
Update
So, the short answer is to make your content fit a normal browser window. I have to maximize my browser to be able to see everything in that popup. It seems like important information, too. So maybe it deserves its own page? These are opinions, not facts, so I'll move on to the latest version of the fiddle which you can more easily look at here.
There were changes to make everywhere, in the CSS, HTML, and Javascript, to make this work. Probably the biggest issue is visibility:hidden. There might be a way to get jQuery to work with that, but I just use the default display:none, which is what .show() and .hide() toggle.
New css
#text1
{
display:none;
background:#f1f1f1;
padding: 15px;
width: 150px;
}
And I needed to wrap your ul with a div of id linkcat-4. Now for the new js. The most interesting change is that I realized we need to take the div's padding into account. Since the padding parameter applies to all sides, we actually need to double the padding and add that to our offset from the window bounds:
New javascript
(function($) {
$(document).ready( function() {
var pop = $("#text1");
$('#linkcat-4 .xoxo li:nth-child(1)').hover(function(e) {
var row = $(this);
pop.html(row.data("extra"))
.css("top", (function(r) {
if(r.offset().top > window.innerHeight - pop.height())
return window.innerHeight - pop.height() - parseInt(pop.css("padding"))*2;
else
return r.offset().top;
})(row))
.css("left", (function(r) {
if(r.offset().left + r.width() > window.innerWidth - pop.width())
return window.innerWidth - pop.width() - parseInt(pop.css("padding"))*2;
else
return r.offset().left + r.width();
})(row))
.show();
},
function(e) {
pop.hide();
});
});
})(jQuery);
Let me know if that works.

Scrollable ul list up and down from links with classes

I want to scroll a news article list up and down depending on which buttons is clicked
I wanted to adapt this way of animating if possible:
function smoothAdd(id, text)
{
var el = $('#scroller' + id);
var h = el.height();
el.css({
height: h,
overflow: 'hidden'
});
var ulPaddingTop = parseInt(el.css('padding-top'));
var ulPaddingBottom = parseInt(el.css('padding-bottom'));
el.prepend('<li>' + text + '</li>');
var first = $('li:first', el);
var last = $('li:last', el);
var foh = first.outerHeight();
var heightDiff = foh - last.outerHeight();
var oldMarginTop = first.css('margin-top');
first.css({
marginTop: 0 - foh,
position: 'relative',
top: 0 - ulPaddingTop
});
last.css('position', 'relative');
el.animate({ height: h + heightDiff }, 1500)
first.animate({ top: 0 }, 250, function() {
first.animate({ marginTop: oldMarginTop }, 1000, function() {
last.animate({ top: ulPaddingBottom }, 250, function() {
last.remove();
el.css({
height: 'auto',
overflow: 'visible'
});
});
});
});
}
$('.scrollUp').click(function() {
smoothAdd('scrollUp', 'A new item');
});
Example here: http://www.fiveminuteargument.com/blog/scrolling-list
My HTML looks like this:
<ul id="scroller">
<li class="current"><span>/</span>News Article Title</li>
<li><span>/</span>News Article Title 2</li>
<li><span>/</span>News Article Title 3</li>
</ul>
<div class="btnWrap"><p>Scroll Up
Scroll Up</p></div>
Can anyone point me in the right direction?
Basically maintain the animation style but keep it as a defined UL as per a normal carousel.
Here : http://jsfiddle.net/sDedY/13/
I've written form scratch. as you notice I've added css directly in a css file, it's better than adding css via jquery, especially for future mainenance/ decorateion etc.., but I havent spent much time for different caluclations. This is a blueprint I guess, you can modify and make it much better, like make top and bottom combined to make the function small or things like that, i jsut dont have time anymore ... so again : redo the calculations based on css yourself and modify it !
EDIT : regarding variable height, you need to keep in mind that I haven't finalised the whole function. next step in coding this function would be auto-calculation of margin-top and top rather than manually entering them, which is pretty easy. all that's needed is to pass a variable to get the position and dimensions of li elements and then pass them to our code.
I've change a few lines of your code:
var el = $('#scroller' + id); to var el = $('#' + id);
and
smoothAdd('scrollUp', 'A new item'); to smoothAdd('scroller', 'A new item');
see http://jsfiddle.net/nCWAP/
I made a slightly simpler solution. Check it out here
You don't need to mess with absolute or relative position neither with top. The list has height as auto so it grows/shrinks according to the height of their li elements
EDIT
Now the height is automatically adjusted to show all items.
Also supports li elements of any height.

Categories