Popover Placement depending up on space available. - javascript

Please have a look at the attached image.
As you can see i am showing a popover. Basically i want to change the placement of the popover depending up on the space available( left or right ). Right now its going outside of an image.
Its a fancy-box(iframe)
Showing the popover using this code.
// Position and show the message.
this.message
.css({
left: (tPosition.left + "px"),
top: ((tPosition.top + t.outerHeight()) + "px")
})
.show();

I would do something like this:
this.message
.css({
left : function () {
if ( tPosition.left + $(this).width() >= $(this).parent().width() ) {
return $(this).parent().width() - $(this).width();
}
else {
return tposition.left;
}
},
top : function () {
if ( tPosition.top + $(this).height() > $(this).parent().height() ) {
return $(this).parent().height() - $(this).height();
}
else {
return tposition.top;
}
}
});
Basically you need to check if the popup is going to exceed your containing box boundaries before you show it and adjust it appropriately. On the horizontal axis this is as simple as making sure that mouse position x + the width of the popup is not greater than the width of the parent container. On the vertical axis you want to make sure that mouse position y + the popup height is not greater than the parent container height.

Related

How to add a jQuery scrollTop offset?

I'm trying to get the div to snap to the center of the viewport, right now it just snaps to the top. I was trying to put an offset of 50% but can only get it in px's.
EDIT
I added a new fiddle where I tried to include $(window).scrollTop() / 2)
http://jsfiddle.net/kZY9R/84/
$("#item").offset().top - 100
var body = $("html, body");
var items = $(".item");
var animating = false;
$(window).scroll(function() {
clearTimeout($.data(this, 'scrollTimer'));
if (!animating) {
$.data(this, 'scrollTimer', setTimeout(function() {
items.each(function(key, value) {
if ($(value).offset().top > $(window).scrollTop()) {
animating = true;
$(body).stop().animate( { scrollTop: $(value).offset().top }, 1000,'swing');
setTimeout(function() { animating = false; }, 2000);
return false;
}
});
}, 50));
}
});
I found this:
$('html, body').animate({scrollTop: $('#your-id').offset().top -100 }, 'slow');
Source: Run ScrollTop with offset of element by ID
Here's the trick to keep your viewport centralized on a particular div.
Prerequisites
You need to take into account the following three criteria to be able to centralize the viewport on a given item:
height of the last item that appeared on the viewport.
The distance of the last item from the top of the page, i.e. the offset().top of the item.
The height value of the viewport (i.e the window object).
Calculating Vertical Position of the Item
The required scrollTop value for the window can be calculated as in the following:
var scrollValue = itemOffset // offset of the item from the top of the page
- .5 * windowHeight // half the height of the window
+ .5 * itemHeight; // half the height of the item
You are basically, moving the top of your viewport to the item under view's top offset initially. This, as you've already experienced, snaps the item to the top of the window.
The real magic part comes when you subtract half of the window's height to go halfway along it vertically, and then shifting your view back down by adding half the item's height. This makes the item appear vertically centralized with regards to the viewport.
Note:
To be able to query the last item that appeared on the viewport, you have to iterate over all of the elements that have a top offset value (i.e. offset().top) less than or equal to that of the window's scrollTop value:
$.each($('.item'), function(i, value) {
if ($(viewport).scrollTop() >= $(this).offset().top) {
lastItemInView = $(this);
}
});
With the above, the lastItemInView variable will always end up with the last element visible in the window.
Demo
Not sure if you figured this out yet or not but I took some code from this answer (How to tell if a DOM element is visible in the current viewport?) that shows how to tell if an element is visible in the view port.
Using that I modified your code to loop through each item and find the first visible one in the viewport and then center that one also factoring in the margin-top you have. Let me know if this helps!
Fiddle: http://jsfiddle.net/kZY9R/86/
var body = $("html, body");
var items = $(".item");
var animating = false;
$(window).scroll(function() {
clearTimeout($.data(this, 'scrollTimer'));
if (!animating) {
$.data(this, 'scrollTimer', setTimeout(function() {
items.each(function(key, value) {
if (elementInViewport(value)) {
animating = true;
var margin = parseInt($(value).css('margin-top'));
$('html,body').animate({
scrollTop: $(value).offset().top - ($(window).height() + margin - $(value).outerHeight(true)) / 2
}, 200);
setTimeout(function() {
animating = false;
}, 2000);
return false;
}
});
}, 50));
}
});
function elementInViewport(el) {
var top = el.offsetTop;
var left = el.offsetLeft;
var width = el.offsetWidth;
var height = el.offsetHeight;
while (el.offsetParent) {
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;
}
return (
top < (window.pageYOffset + window.innerHeight) &&
left < (window.pageXOffset + window.innerWidth) &&
(top + height) > window.pageYOffset &&
(left + width) > window.pageXOffset
);
}

position div related to another div with responsive arrow

am trying to make responsive menu related to div as you see in my jsfiddle Demo link,
my problem with arrow and menu position , i need to add class if menu closest to right border of container or even to left border or top border or bottom border , i mean change position of menu and change arrow position and also to make menu not ever come out of container..
Demo
This Is My Code :
var popupid,gid = 0;
$(".box").on("click",function(e){
e.preventDefault();
placeholder();
var self = $(this),
pos = self.position(),
selftop = pos.top,
selfleft = pos.left,
width = self.outerWidth(),
popup_Options = self.find(".popup");
popupid = 'placeholder-' + gid++;
popup_Options
.attr('placeholder', popupid)
.before('<div class="placeholder ' + popupid + '"></div>')
.appendTo('.Container');
popup_Options.css({
position: "absolute",
top: selftop + "px",
left: (selfleft + width) + 20 +"px"
}).show();
e.stopPropagation();
});
$('html').on('click',function(e)
{
placeholder();
});
function placeholder()
{
// Move back out of container
$('div[placeholder="'+popupid+'"]')
.appendTo('.placeholder.' + popupid)
.unwrap()
.removeAttr('placeholder')
.hide(); // Unset placeholder data
}

jquery slide div by changing margin

I'm making left/right buttons to make a div slide. It slides by changing the left margin. What I'm trying to do is have it check the left margin and then add/subtract pixels to it. So when the page loads, left margin should be 0. Then you click the button and it checks the margin, finds it's 0, adds 150 and sets the left margin to 150. And then if you click it again, it checks the margin, finds it's 150 and adds another 150 and sets the margin to 300.
It succeeds in moving the margin from 0 to 150, but i can't get it to go to 300. I'm thinking it's not able to determine the margin correctly. Any ideas how I can fix this? Thanks!
$('#left').click(function(){
var pos=$('#contentarea').css("margin-left").replace('px', '');
pos=pos+150;
$('#contentarea').animate({ 'margin-left': '-' + pos + 'px'}, 1000);
return false;
});
There is no need to get current margin-left value, you can use the '+=%value%' and '-=%value%' operators. This will add/substract from the current value the specified value.
$('#left').click(function(){
$('#contentarea').animate({ 'margin-left': '+=150px'}, 1000);
return false;
});
try this,
use for Get Margin
$('#contentarea').css("margin-left")
it will return margin default is "PX".
Use For Set Margin
$('#contentarea').css("margin-left","Your Size");
Default size is "PX" not need to provide size with "PX".
Try this function
$(document).ready(function () {
$('#contentarea').css("margin-left", "0");
});
$('#left').click(function () {
var pos = $('#contentarea').css("margin-left");
var size = 0;
if (pos == "0px") {
$('#contentarea').css("margin-left", "150");
}
else {
size = parseInt(pos.slice(0, -2));
size = size + 150;
}
var pos = $('#contentarea').css("margin-left", size);
$('#contentarea').animate({ 'margin-left': '-' + pos }, 1000);
return false;
})
Use parseInt instead of replace to get css margin left value.
$('#left').click(function(){
var pos = parseInt($('#contentarea').css("margin-left")) + 150;
$('#contentarea').animate({'margin-left' : '-' + pos + 'px'}, 1000);
return false;
});

How to extend element width both ways?

Does that title sound confusing? I thought it might well anyways.
When I person clicks on the page I want them to be able to me a little line shorter and long.
You can see what I mean here:
http://jsfiddle.net/shawn31313/HKLhE/9/show/
Do a Mousedown and them move your move to the right. It works fine.
But now, move you mouse to the left. See the problem? It goes the same direction as it did when you dragged to the right. I know this is because i'm using width and obviously width on goes one way.
This is my code so far:
$(document).ready(function() {
var dragStatus = 0,
getPos, giveRandomID;
$(document).mousedown(function(event) {
dragStatus = 0;
getPos = {
top: event.clientY,
left: event.clientX
};
giveRandomID = Math.floor(Math.random() * 99999);
});
$(document).mousemove(function() {
var line = $('#line' + giveRandomID);
if (dragStatus == 0) {
$('body').append("<div id='line" + giveRandomID + "' class='line' style='position:absolute;top:" + getPos.top + "px;left:" + getPos.left + "px;background:black;width:2px;height:5px'></div>");
dragStatus = 1;
}
if (dragStatus == 1) {
if (event.clientX > line.offset().left) {
line.css({
width: event.clientX - line.offset().left
});
} else {
line.css({
width: line.offset().left - event.clientX
});
}
//for DEG "-" Top-Math.abs(DEG*2) for Deg "+" Top+(DEG*2)
}
});
$(document).mouseup(function() {
dragStatus = 2;
});
});​
I hope someone can help me out with this. Maybe a complete different way to set this up. Just something to fix this issue
To make the line stretch to the left, you have to update the left property:
if (event.clientX > getPos.left) {
line.css({
left: getPos.left,
width: event.clientX - getPos.left
});
} else {
line.css({
left: event.clientX,
width: getPos.left - event.clientX
});
}
jsFiddle: http://jsfiddle.net/HKLhE/16/
You'll need to modify the else case (moving right) to set the left property to auto and the right property to the initial mouse click X position. Comparing to the offset().left when moving left won't work because that value is changing.
Try this out for size:
http://jsfiddle.net/HKLhE/20/
Edit: Brilliand's solution is much more elegant.

How to get amount of portions of a HTML element is visible in viewport

Is it possible to know whether or not an HTML element like image is viewable in current viewport or it will be visible on scroll?
If it is viewable completely or partially then how can I get the amount of portions is visible?
I am trying to explain it from the following image:
The two images at the bottom is partially visible within the viewport and these will be completely visible if one scroll down a little bit.
Now I want to get the the aforesaid information.
In the actual scenario I am trying to get the popup-zoom effect on hover of image in my album like google image search. Everything is fine, except if the images are placed in the described manner then the zoomed div also displaying in half.
Normal condition where image is completely in viewport:
And partially in viewport:
I really appreciate your help.
The code:
var albumDetailOnReady = function() {
$('.image').each(function(){
var photo = $(this);
var wrap = $(findParentByClassName(document.getElementById(photo.attr('id')), 'wrap'));
var row = $(findParentByClassName(document.getElementById(wrap.attr('id')), 'albumDetailRow'));
var visibleZone = $(wrap).find('.alDtlColumn');
var pictureBlock = $(visibleZone).find('.pictuteBlock');
var hiddenZone = $(wrap).find('.hiddenZone');
$(photo).load(function(){
if(177 > $(photo).width()){
var imgleft = ($(pictureBlock).width() - $(photo).width())/2 + 'px';
$(photo).css({'left': imgleft});
}
});
$(photo).hover(function(){
var y;
if($(photo).height() > $(photo).width()) {
y = ($(visibleZone).offset().top - 50) + 'px';
} else {
y = ($(visibleZone).offset().top + 50) + 'px';
}
var x;
if($(row).find('.wrap:first').attr('id') === $(wrap).attr('id')) {
x = ($(visibleZone).offset().left - 10) + 'px';
} else if($(row).find('.wrap:last').attr('id') === $(wrap).attr('id')) {
x = ($(visibleZone).offset().left - 50) + 'px';
} else {
x = ($(visibleZone).offset().left - 20) + 'px';
}
$(hiddenZone).css({
'top': y,
'left': x,
'position': 'absolute',
'z-index': '10'
});
$(hiddenZone).fadeIn('fast');
}, function(){
});
$(hiddenZone).hover(function(){},function(){
$(hiddenZone).hide().stop(true, true);
});
});
}
var findParentByClassName = function(element, clazz) {
while (element.parentNode) {
element = element.parentNode;
if (hasClass(element, clazz)) {
return element;
}
}
return null;
}
function hasClass(element, cls) {
var regex = new RegExp('\\b' + cls + '\\b');
return regex.test(element.className);
}
I am unable to show any HTML as I haven't have any, I am working in ADF framework.
But for an explanation:
I have two zone for each image: visible and hidden. Both of them are in a wrap. Now on hover an image I am showing the hidden div. The top and left of the hidden div is measured by the top and left of the visible div with some condition.
jQuery.Viewport
Very helpfull and lightweight jQuery plugin that makes an element as a handy viewport for displaying elements with absolute position. The plugin is hosted on GitHub. You can see it in action right there:
https://github.com/borbit/jquery.viewport

Categories