How do I get the coordinates of a div? - javascript

I have used jQuery UI library to drag divs within a web page. While dragging, the div changes it's position and modifies CSS postion,top and left properties.
My questions are:
1) Is their a way in javascript to get the values of CSS properties and save on a variable(so that I can submit it to XML)? Those CSS properties are created on real time when dragging the divs.
2) Can I at least read the new coordinates of the div on the webpage?
My goal is to record those values so that when users logs in next time, their modified version of the web page is preserved.

To read the co-ordinates relative to the viewport, use offset():
var offset = $('#someitem').offset();
console.log('top: '+offset.top+'; left: '+offset.left);
To read the co-ordinates relative to the nearest positioned ancestor, use position():
var pos = $('#someitem').position();
console.log('top: '+pos.top+'; left: '+pos.left);
To get CSS properties, just use the css() function:
console.log($('someitem').css('top'));

you can easily get the offset of an element using jQuery.
var offset = $("#some-element").offset();
// Alert the values
alert("top: " + offset.top+ "left: " + offset.left);

Related

Change background on hover of a draggable div

I have a small draggable division (black) and many nodes with different IDs beside it
I need a hovering effect when I drag the black element on the nodes. What I am doing in allowDrop function is:
var dragObj;
function drag(ev){
dragObj = ev;
}
function allowDrop(ev){
ev.preventDefault();
var Dragged = dragObj;
var Hovered = ev;
var leftIndent = Dragged.layerX;
var hoveredID = Hovered.target.id.toString().split('_');
var nodesOnLeft = Math.floor(leftIndent/12);
var startingNode = hoveredID[0]-nodesOnLeft;
for (i=1;i<=Math.floor(draggableElementLength/12);i++){
var toApplyCssID = startingNode.toString() + '_1';
var toApplyCss = document.getElementById(toApplyCssID);
$('#'+toApplyCssID).css('background-color','lightgreen');
}
}
basically I am using the layerX property to find out the distance between my mouse pointer and draggable division's border and adjusting that to calculate number of nodes where I have to apply new CSS and applying that by finding the ID of node.
This is working but its making the process very slow as it involves many calculations and its not the hover effect as its not going away when I am removing the draggable division.
Is there any other way to achieve this or do I need to make code changes in existing code.
thanks
Without the HTML and the rest of the script, I can only point you in the direction you should be taking in this kind of scenario:
Don't constantly repeat calculations (that do not change) in a loop, store them outside the function:
Use document.getElementById(toApplyCssID) for each node and store the
elements in an array
Get the distance from the mouse position to the required edge or
edges of the div (leftIndent) on initial drag/mousedown and store
that in a variable
Store Math.floor(draggableElementLength/12) in another variable (you
haven't shown where this originates, but it doesn't seem to change in
the function...)
Apply the CSS to the relavent elements (from the array of elements)
using the other stored values to select them
Remove the CSS on those that had it applied earlier
This may not be the ultimate solution, but these are some of the things you can look at to speed up what you (may) have currently.

Unable to calculate the hover element's exact position

I am just trying to get the mouse hover div's position at the right according to the space around. Somehow I am able to do this in first two columns but not for other columns. May be my calculations while writing the condition state are wrong.
Can anyone please help?
JS Fiddle URL:
http://jsfiddle.net/mufeedahmad/2u1zr11f/7/
JS Code:
$('.thumb-over-team li').find('.cover').css({opacity:0});
$('.thumb-over-team li').on('mouseenter', function(){
var $this = $(this),
thisoffset = $this.position().left,
openDivId = $(this).find('.cover'),
thumbContainer = '.thumb-over-team',
speedanim = 200;
if(thisoffset + openDivId.outerWidth() >= $(thumbContainer).outerWidth()){
//thisoffset = $(thumbContainer).outerWidth() - openDivId.outerWidth() - 212;
thisoffset = thisoffset - openDivId.outerWidth()+10;
openDivId.stop().css({'z-index':'9999'}).animate({'opacity':'1', 'left':-thisoffset}, 200);
}else{
openDivId.stop().css({'z-index':'9999'}).animate({'opacity':'1', 'left':'212px'}, 200);
}
}).on('mouseleave', function(){
$(this).find('.cover').stop().css({'z-index':'-1'}).animate({'opacity':'0', 'left':'200px'}, 200);
});
$('.close-parent').on('click', function(){
$(this).parents('.cover').stop().css({'z-index':'-1'}).animate({'opacity':'0', 'left':'200px'}, 200);
});;
In your first conditional, try to calculate the position of the offset as:
thisoffset = ($(thumbContainer).outerWidth() - openDivId.outerWidth() - thisoffset);
That way, you're adjusting the appearing square (.cover) when it doesn't fit inside the container, to be as close possible to its rightmost edge: (maximum width - appearing square width - current li position)
Calculated this way, you can animate it with the new offset in positive:
openDivId.stop().css({'z-index':'9999'}).animate({'opacity':'1', 'left':thisoffset}, 200);
See it working here.
For elements that "almost" fit, the current system isn't completely precise because of what I already pointed out in my previous comment: the appearing square, even if it were at 0 opacity, would still be inside the containing element (($(thumbContainer)) or .thumb-over-team) and it would add its width to the total width of the container.
So your conditional may think that there's enough available space in the container to make the expandable element fit, but that would go out of the screen. As an example, notice that there's a horizontal scrollbar from the very beginning, caused by this effect, where your containing .thumb-over-team element doesn't fit in the screen.
But I would say that more precision in this point would require a fresh new approach to your system where the appearing .cover elements were out of the containing ul .thumb-over-team
Fresh take on the problem, essentially based on the main issue: the expandable text block (.cover) used to add its width to the container (.thumb-over-team). This altered the calculations on available container space, and made the text containers go off screen.
The solution is to make sure the expandable .cover elements aren't contained inside the .thumb-over-team element, so they won't impact the calculations on available width.
Here is a JSFiddle containing this new approach: link.
Explanation of how it works:
The idea was to create a separate element called .cover-container and let's put all the expandable .cover elements in there.
We want to associate every image in the li elements in .thumb-over-team with their appropriate .cover (so the first image triggers the first .cover to show, the second image would show the second cover, and so on.) We achieve is by finding out the index of the element that triggered the event:
thisLiIndex = $this.index() + 1
And then selecting the cover in the matching position:
openDivId = $('.cover-container .cover:nth-child(' + thisLiIndex + ')')
The expandable covers shouldn't interfere with the mouseenter or mouseleave events of .thumb-over-team, so we make it to ignore mouse events via CSS:
.cover-container{pointer-events:none;}
Changing from one image to another would automatically trigger new events, so the expanding covers stay visible when the mouse stays on the images, but close automatically when the mouse exits them.
Since the covers are now outside of $(thumbContainer), openDivID.outerWidth() does not alter $(thumbContainer).outerWidth(), and we can use that safely in our positioning.
If I understand the placement that you want, for covers that fit, the position is the current offset (position of the li element that triggered the event) plus the width of the image and some subtle margin
imageWidth + rightSeparation + thisoffset
And for covers that won't fit inside of the screen, we keep them just inside of the screen
thisoffset = $(thumbContainer).outerWidth() - openDivId.outerWidth();

How can I position a div relative to a list item?

I have an unordered list of pictures, and when I hover over one I want the two pictures to the left to fade out, and a div to appear in their place with text. I've gotten this working, except for positioning the div - I've tried this:
div.position({my: 'left top', at: 'left top', of: other_list_item});
but that just returns an Object ( the new location ) of {left: 0, top: 0}.
I've also tried putting the div in another li element, but it's still a no-go. Here's the div HTML:
<div style="width: 255px; height: 110px; position: absolute;" id="name_popup"><p>Jon Jensen</p><p>Chief Technical Officer</p><p>London, England</p></div>
EDIT I'm working on a JSFiddle example, but there's kind of a lot to put in, so idk when it'll be ready. Anyways, I forgot to mention this bit of fun:
when I call .position() by itself on the element that I'm trying to anchor to, it returns the correct offsets, but when I try to use position() on the other element to match their positions, nothing happens.
I did not quite understand the question, but from my reasoning I get that you are trying to position new divs in place of the faded out images, so here is some code that could fit your situation
$('div').click(function(){
//get the positions of the divs to be faded out
var prev_position = $(this).prev('div').position();
var next_position = $(this).next('div').position();
//create and position new divs
$(this).insertBefore('<div style="position:absolute;top:' +prev_position.top+ 'px;left:' +prev_position.left+ 'px;">Replacing DIV</div>');
$(this).insertAfter('<div style="position:absolute;top:' +next_position.top+ 'px;left:' +next_position.left+ 'px;">Replacing DIV</div>');
//hide the divs
$(this).prev('div').fadeOut();
$(this).next('div').fadeOut();
});
Sometimes, if your parent element has a position set, then the .position() will get the position relative to the parent element, and depending in your needs this might throw off your design. So instead you could get the coordinates of the previous and next divs relative to the WINDOW and you could get those like these:
function getPosition($el){
//get the offset coordinates of the recently clicked link
var offset = $el.offset();
var top = offset.top;
var left = offset.left;
//get position of this link relative to the window
var rel_top = top - $(window).scrollTop();
var rel_left = left - $(window).scrollLeft();
}

How can I get the element visible in the viewport? jQuery

I have a list of images on a page. As I scroll through the page I would like to show some options in a naviationbar of the image currently in the viewport. Therefore I need to get the image element currently in the viewport, is this possible ?
Jakob
Who says there's just one image in viewport? What would you like to do when there are many?
But otherwise you can always get the scroll position of your container with images as well as your images' top offset to see which one is currently in-view.
So these values will get you to your result
container scroll position
container visible client height
images' top offset
Using these values will make it possible to locate all images in the view regardless whether they're fully or partially displayed (at the top or bottom).
This is a simplified JSFiddle that gives red border around the first fully-in-the-view image. The code does this:
// get top positions and references to all images
var pos = $("img").map(function(){
var $this = $(this);
return {
el: $this,
top: $this.offset().top
};
}).get();
// provide document scrolling
$(document).on("scroll", function() {
$("img").removeClass("first-in-view");
var scroll = $(this).scrollTop();
var i = 0;
while(pos[i].top < scroll) i++;
pos[i].el.addClass("first-in-view");
}).scroll();
This should be optimised to only toggle class when it needs to. Otherwise we have flickering in every scroll. But it demonstrates how this can be done and you can get going from here.
IMPORTANT
It is utterly important that you attach your image position determining process on document load event and not the usually use DOM ready, because you have to wait for the document to load in order for your images to have final positions.

How to insert an element in DIV at position X Y

I am trying to create a webpage where users can insert a pin (like google map) in
between the text using context menu.
My problem is that i do not know how to insert the pin at the exact position.
Using the DOM I can arrive only to the nearest DIV (by using this) but a DIV contains a
lot of text and the PIN has to be positioned next to the text.
I can obtain the position of the mouse click using pageX and pageY but
dont know how to insert an element at that position. I tried in JQuery:
insertAfter, prepend, append but not getting the desired result.
Any idea how to solve this problem.
regards,
choesang tenzin
$("#Content").rightClick( function(e) {
$("<div class='pin'/>").insertAfter(this);
});
$("#Content").rightClick( function(e) {
var myTop = ...;
var myRight= ...;
$("<div class='pin' style='position:absolute; top: ' + myTop +'px; right: ' + myRight + 'px;/>").insertAfter(this);
});
sorry, i don't remember how to get x and y from the e parameter. Also, you will need to convert x,y of mouse click to x,y relative to #content element.
Thanks alot for all your ideas. I have come up with another way to do it.
I am using the "RANGE" to insert directly into the clicked zone (div) and not after or before it and adding z-indexes. The positive points with this is:
It is really into the text and not as a layer
texts flow around the pin (text makes space for the pin)
$("div").click( function(e) {
//the following works only for FF at the moment
var range = window.getSelection().getRangeAt(0);
var pin = document.createElement('img');
pin.setAttribute('src','pin_org.png');
pin.setAttribute('class','pin');
range.insertNode(pin);
});
$("img.pin").live( 'mouseover', function () {
alert("hovered!!");
Set the style position:relaitve; on the containing div, so that it becomes a layer. That way it works as origin for the absolutely positioned elements inside it.

Categories