How to reposition a relative DIV using left/top? - javascript

I have a div with the attribute position: relative;. Now, there are three of these divs. They all get a unique ID etc.
Now if I click a div, I want it to animate to a certain position in the document. Although I cannot determine the left/top values since if I use "top" and "left", it will relatively set the left to its parents position.
Maybe a bit unclear, but here is what I got.
The CSS of the clickable DIV that will move.
div#left_hldr .switch_project {
z-index: 1001;
position: relative;
margin: 10px 0px 0px 0px;
cursor: pointer;
}
// Open project.
$(".switch_project").live('click', function() {
// Get the ID value.
var More_Id = $(this).attr("id");
// Explode the Id.
var Id_Split = More_Id.split("_");
// Get the project ID.
var Project_Id = Id_Split[2];
/*
Replacement of the switch project div.
1 ) Define the current position.
2 ) Define the new position.
3 ) Replace the DIV to the new position.
4 ) Fade the new page in.
5 ) Put the DIV back to its original position.
*/
// Current Position.
var Ori_Left = $(this).offset().left;
var Ori_Top = $(this).offset().top;
// New Position. [ Based on the content_hldr container ]
var New_Top = $("div#content_hldr").offset().top;
var New_Left = $("div#content_hldr").offset().left;
// Define the current div.
var Div_Rep = $(this);
// Hide the More Info tab.
$(Div_Rep).children(".more_info").fadeOut("fast");
// Fade content out.
$("div#content_hldr").fadeOut("fast");
// Replace the div.
$(Div_Rep).animate({
top: New_Top,
left: New_Left
}, "slow", function() {
// Load Home page in.
$("div#content_hldr").load("content/content.projects.php?id=" + Project_Id, function() {
// Re-define Cufon.
Cufon.replace('h2');
});
// Fade in the content.
$("div#content_hldr").fadeIn("fast", function() {
// Hide the replaced div.
$(Div_Rep).hide();
// Replace it back to its position.
$(Div_Rep).css({
top: Ori_Top,
left: Ori_Left
});
// Show the More Info tab again.
$(Div_Rep).children(".more_info").show();
// Fade back in.
$(Div_Rep).fadeIn("medium");
});
});
});

...it will relatively set the left to its parents position.
Actually, no. If you use left and top with a position: relative element, they'll offset it from where it otherwise would be if it weren't positioned (e.g., in the static flow), while continuing to reserve its space in the static flow. A subtle but important distinction (and hugely useful for drag-and-drop).
If you want to animate it to the top left of the document, you can figure out its offset (via offset), and then provide those as negative numbers for left and top, since of course if it's at (say) [100,50], then positioning it at [-100,-50] compared to its default position will...put it at [0,0].
Like this:
$("selector_for_your_divs").click(function() {
var pos, $this;
$this = $(this);
pos = $this.offset();
$this.animate({
left: "-" + pos.left + "px",
top: "-" + pos.top + "px"
});
});
Live example
Similarly, if you want to move it to be where another element is, simply subtract its position from the other element's position — that gives you the delta to apply:
$("selector_for_your_divs").click(function() {
var mypos, otherpos, $this;
// Move to the target element
$this = $(this);
pos = $this.offset();
otherpos = $('selector_for_other_element').offset();
pos.left = otherpos.left - pos.left;
pos.top = otherpos.top - pos.top;
$this.animate({
left: pos.left + "px",
top: pos.top + "px"
});
});
Live example

Related

javascript issue with fixed position side menu

I'm building a website with a sidebar that, once the user scrolls past a certain point it becomes fixed on the site. This code works fine.
The issue that I am coming into is that the sidebar is overlapping the footer when the user scrolls to the bottom of the page. I wrote code to detect when the bottom of the sidebar hits the same position as it's containing element - when that happens I am taking the position of the bottom of the containing element and subtract the height of the sidebar element and using that number to give the sidebar it's new "top" (while also changing the position to "absolute").
This is where I am running into the issue - once the sidebar is overtop of the footer as the user scrolls the code that is getting called alternates between the normal "fixed" position code and the "absolute" positioned code giving it this flickering effect.
For the life of me I can't figure out why the "fixed" code keeps getting called.
Here is the code:
( function( $ ) {
var sidebar_pos = $('#secondary')[0].getBoundingClientRect();
var pos_top = sidebar_pos.top + window.scrollY; //need this to get the pos of TOP in the browser - NOT the viewport
var main_pos = $('.main-content')[0].getBoundingClientRect();
var main_bottom = main_pos.bottom + window.scrollY;
var stop_pos;
var i = 0;
$(window).scroll(function(event){
var scroll = $(window).scrollTop();
var produce_pos = $('.produce')[0].getBoundingClientRect();
var pos_bottom = produce_pos.bottom + window.scrollY;
//console.log("scroll "+scroll);
//console.log("top " + pos_top);
console.log(main_bottom);
console.log('bottom ' + pos_bottom);
if( scroll >= pos_top){
if ( pos_bottom >= main_bottom ){
//if the sidebar would end up overlapping the footer
if(i == 0){
//only need to set this once, not on every scroll
stop_pos = main_bottom - $('#secondary').height() ;
}
$('#secondary').removeClass('hover').css({
position: 'absolute',
margin:0,
left: sidebar_pos.left,
top: stop_pos
});
i++;
} else {
$('#secondary').addClass('hover').css({
position: 'fixed',
left: sidebar_pos.left,
marginTop: '1.5em',
top: 20
});
setTimeout(() => {
$('*[data-widget="comet"]').addClass('active');
}, 5000);
setTimeout(() => {
$('*[data-widget="produce"]').addClass('active');
}, 7000);
}
} else if( scroll < pos_top && $('#secondary').hasClass('hover') ){ //if user scrolls up past original pos of sidebar, remove effects
$('#secondary').removeClass('hover').css({
position: 'relative',
left: 'auto',
top: 'auto'
});
i = 0;
}
});
}( jQuery ) );
I also have a codepen of the script in action.
https://codepen.io/antlaur00/pen/ExyrgYR
Any help is much appreciated! Thanks!
Well its pretty simple, just add Z-index property to your footer CSS, that way it will always overlap your sidebar .
You can refer to this article regarding the z-index property
https://www.w3schools.com/cssref/pr_pos_z-index.asp

positioning new element based on position of existing element?

I am using the following code (Javascript within a webpage) to create a 'new' element in the DOM dynamically. I wish to position this say 200px 'below' an existing element. However my output has the positioning of the new element(s) all wrong...as if the position (top, left) I am specifying is ignored.
var _reference = document.getElementById("outputs");
for (_count = 0; _count < _limits; _count++) {
var _structure = document.createElement("div");
_structure.setAttribute("class", "container-fluid");
_structure.setAttribute("id", "struct_" + _tally);
if (_count === 0){
_rect = _reference.getBoundingClientRect();
//get the bounding box of the "outputs" id element...
document.getElementById("outputs").appendChild(_structure);
_structure.style.top = _rect.top + "200px"; //NOT positioned 200px below 'outputs'
_structure.style.left = _rect.left; //NOT positioned same position as 'outputs'
} //_count is "0"
} //for loop
I would have thought this should be fairly straightforward...however it is driving me crazy...any help appreciated.
You'll need to set _structure.style.position to 'relative', 'absolute', 'fixed', or 'sticky' in order to use top, left, right, bottom.
You need to set your position to realtive or absolute in order for this to work, also note that position: absolute sets the position according to the nearest relative positioned parent while position: relative positions according to the current position of the element

Popup should display on top of element if no proper space in bottom

I want to display the popup on the top of element if there is no proper space on the top. Currently it hides inside the window as seen in the image below:
I can update the top position but I only want when there is no proper space otherwise it is ok.
Please let me know how to determine if the clicked position in near window edges.
JSFiddle Link :http://jsfiddle.net/g4g4negf/
Code I am using to get the position:
$(document).ready( function() {
$('.clickme').on('click', function(e) {
$('#popup').offset({ top: e.pageY, left: e.pageX}).fadeIn();
});
Check out this JSFiddle
To check if clicked position is near window edge, you have to get window's height ($(window).height()) and scroll position (window.pageYOffset). By adding these two values, you can find the scrolled position of the window. Then compare this sum with e.pageY+$("#popup").height() (this is the sum of the clicked position's height and the popup's height). If the latter is less than the former, it means the popup can be shown. If (e.pageY+$("#popup").height())>($(window).height()+window.pageYOffset) it means the popup will overflow the window's bottom border, then its top offset should be changed to e.pageY-$('#popup').height().
Here is the complete function:
$('.clickme').on('click', function(e) {
var h;
if((e.pageY+$('#popup').height())<($(window).height()+window.pageYOffset)) h=e.pageY;
else h=e.pageY-$('#popup').height();
$('#popup').offset({ top: h, left: e.pageX}).fadeIn();
});
Considering your popup height is 100px, you can try this...
$(document).ready( function() {
var h = window.innerHeight;
$('.clickme').on('click', function(e) {
alert(h + ", " + e.pageY);
if( h - e.pageY < 125) {
$('#popup').offset({ top: h-125, left: e.pageX}).fadeIn();
}
else {
$('#popup').offset({ top: e.pageY, left: e.pageX}).fadeIn();
}
});
});

Check position of two elements

Is there a way to check positioning of two elements?
For example:
.bigBox {
width: 100%;
height: 200px;
}
.btn {
position: fixed
display: none;
top: 10px;
right: 0;
}
There is a big box over the whole website. And i have a button with positioning fixed and display none. The button should fadeIn() if it is 100px under the .bigBox.
First thing, the the position of .bigBox's dimensions:
var bottomBigBox = $(".bigBox").offset().top + $(".bigBox").height();
var topOfBtn = $(".btn").offset().top;
// Check the condition and fade it.
if (bottomBigBox + 100 == topOfBtn)
$(".btn").fadeIn();
You can use position() or offset() methods to know the position of the element relative to the parent or relative to the document respectively.
$('.element').position().top; // returns the top value relative to parent
$('.element').position().left; // returns the left value relative to parent
$('.element').offset().top; // returns the top value relative to document
$('.element').offset().left; // returns the left value relative to document
See more:
http://api.jquery.com/offset/
https://api.jquery.com/position/
You can get an element position with offset(). Then you can sum its computed .height() and the desired margin by 100:
var bb = $(".bigBox");
var o = bb.offset();
var h = bb.height();
$(".btn").css("top", o.top + h + 100).fadeIn();
Working demo
Why use height() ? It will get the element computed height, so if you change on CSS or even if you use an relative value, it will work.
With plain Javascript
var bb = document.querySelector(".bigBox");
var t = bb.offsetTop;
var h = bb.offsetHeight;
document.querySelector(".btn").style.top = t + h + 100 + "px";
$(".btn").fadeIn(); // jQuery only for fadeIn effect
Working demo

Unable to getting current element hover is firing on

first here is the JSFiddle I've been working on
http://jsfiddle.net/rastlin80/P53Le/
I've created a new plugin called sopopup
what is does is match an element as a pop-up that will appear around some text when the text is hovered.
it works correctly when the selector for the element that will be hovered is a single element
$('#message').sopopup({ target: $('#ho')});
the pop up appears right above the text, but when the selector has multiple items it always hovers over the first item.
$('#message2').sopopup({ target: $('.meds')});
my problem is in the code for the hover event.
settings.target.hover( //where target are the elements selected such as $('.meds')
function() {
//here is my problem the var this is not the target being hovered
//the var this is refering to the settings it seems
var pos;
var hgt;
if(settings.location === 'top'){
pos = settings.target.position();
//i wanted to do this.position() but that show an error
hgt = settings.pop.height();
settings.pop.css({
position: "absolute",
top: (pos.top - hgt) + "px",
left: pos.left + "px"
});
}
else if( settings.location === 'bottom'){
pos = settings.target.postion();
hgt = settings.target.height();
settings.pop.css({
position: "absolute",
top: (pos.top + hgt) + "px",
left: pos.left + "px"
});
}
settings.pop.show();
}.bind(settings)
I am unable to use the variable this to refer to the item that is currently being hovered over. instead the variable this within the hoverIn function seems to refer to the settings object.
any help appreciated.
This fork of your Fiddle uses a combination of $.each and setting a variable named self to reference the appropriate this (wrapped with jQuery) to achieve what I believe it is you're asking for:
$.each(settings.target, function(){
var self = $(this);
self.hover(function() {
var pos;
var hgt;
if(settings.location === 'top'){
pos = self.position();
[...]

Categories