How would i be able to find the top, left, bottom and right position of multiple moveable elements on a page? I tried jQuery .position() for it, however the function gives me the position of only the most recent moveable element created (div). Here's the code -
Finding Position -
$(document).on('click', function(e) {
var createdWindow = $(nWindow).position();
var createdWindow_right = $(nWindow).position().left + $(nWindow).width();
var createdWindow_bottom = $(nWindow).position().top + $(nWindow).height();
console.log("Top position: " + createdWindow.top + ", Left position: " + createdWindow.left + ", right position: " + createdWindow_right + ", bottom position: " + createdWindow_bottom);
// returns an object with x/y coordinates of the top-left corner of the element
});
Div Creation -
function windowProperties(containment,x,y,width,height){ //New Window Style and jQuery Functions
$(containment).append('<div id="window'+divCount+'"><p id="para'+divCount+'">Drop Here</p></div>');
nWindow = document.getElementById('window'+divCount);
paragraph = document.getElementById('para'+divCount);
paragraph.style.color = "black";
paragraph.style.fontSize = "20px";
paragraph.style.fontWeight = "bold";
paragraph.style.padding = "10px";
paragraph.style.textAlign = "center";
nWindow.style.width = width+"px"; //680
nWindow.style.position = "absolute";
nWindow.style.height = height+"px"; //294.75
nWindow.style.opacity = "0.5";
nWindow.style.background = "white";
nWindow.style.zIndex = "200";
nWindow.style.top = x+"px";
nWindow.style.left = y+"px";
};
Use draggable event property of an element and send event on drag events.
For Example:-
<div draggable = true ondragstart="abc(event)>
//some HTML CODE
</div>
<script>
function abc(event)
{
console.log(event) // here in this event you get all the data of draggable elements
}
</script>
Consider the following example.
$(function() {
$.fn.getPosition = function() {
var results = $(this).position();
results.right = results.left + $(this).width();
results.bottom = results.top + $(this).height();
return results;
}
$(".drag").draggable({
containment: "parent",
stop: function(e, ui) {
console.log($(this).attr("id"), $(this).getPosition());
}
});
});
.cnt {
width: 340px;
height: 340px;
border: 1px solid black;
}
.drag {
width: 20px;
height: 20px;
background: #ccc;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="cnt">
<div class="drag" id="box-1"></div>
<div class="drag" id="box-2"></div>
</div>
This creates a function that can get you the full position. You can then use that in stop callback for a Drag action.
Related
I have a div that I using Javascript to change the position of. However, it is rounding incorrectly.
#hi{
background-color: blue;
width: 2px;
height: 10px;
position: absolute;
}
<div id = "hi"></div>
<button onclick="myFunction()" style = "margin-top: 100px">Click me</button>
<script>
function myFunction() {
var div = document.getElementById("hi");
div.style.left = "0px";
console.log("BEFORE: " + div.style.left);
var moveBy = 109.8125;
div.style.left = moveBy + 'px';
console.log("MOVE BY: " + moveBy);
console.log("NEW POSITION: " + div.style.left);
}
</script>
It should move it by 109.8125, but instead moves it by 109.813.
Any way to make it more accurate and move it to 109.8125?
It may seem like it is not that important, but I am doing this several times, so then it looks in the wrong place, relative to other elements.
If you really need to prevent precision drift due to rounding error, I'd suggest you keep track of the value independently of the style attribute. Here's an example of how you could do it using a data attribute:
function myFunction() {
var div = document.getElementById("hi");
div.style.left = "0px";
console.log("BEFORE: " + div.style.left);
var moveBy = 109.8125;
// track the current value as a data attribute,
// which won't get rounded
const left = div.dataset.left = parseFloat(div.dataset.left || 0) + moveBy;
// apply the computed value as a style
div.style.left = left + 'px';
console.clear();
console.log(`dataset.left: ${left}, style.left: ${div.style.left}`);
}
#hi {
background-color: blue;
width: 2px;
height: 10px;
position: absolute;
}
<div id="hi"></div>
<button onclick="myFunction()" style="margin-top: 100px">Click me</button>
My HTML has a div and when I hover the div a card will be displayed on the right side. When the div is in left side then this still show right side. When I reduce the browser width then this card partially show the detail.
How to automatically position using jquery.
var thisEl = $(this);
var offsets = thisEl.offset();
var thisElTopOffset = offsets.top;
var thisElLeftOffset = offsets.left;
This will show as i mentioned in the image. But i try to position the div to left when the elements are in right.
Code: I tried so far
allHoverCardTriggers.on({
click: function(event) {
event.preventDefault();
var thisEl = $(this);
cardTimer = setTimeout(function(){
var docWidth = $(document).width();
var rightSide = false;
//return user id
var userLink = thisEl.attr('href');
if($('.ViewProfilePage').length && $('img.lia-user-avatar-profile',thisEl).length){
var userLink = document.location.href;
} else if(thisEl.attr('href')=='#'){
return false;
}
var thisLen = (userLink).split('/');
thisUserID = (thisLen)[thisLen.length-1];
var thisCard = $('.profileCard[data-user='+thisUserID+']',cardWrapper);
var offsets = thisEl.offset();
var thisElTopOffset = offsets.top;
var thisElLeftOffset = offsets.left;
if(thisCard.length && $('.profileCard[data-user='+thisUserID+'] .preloader',cardWrapper).length<1)
{
$('.profileCard',cardWrapper).hide();
rightSide?thisCard.addClass('rightArrow'):thisCard.removeClass('rightArrow');
thisCard.delay(500).css({'top':thisElTopOffset,'left':thisElLeftOffset}).stop().show();
}
else
{
var ajaxReturn = '';
thisCard.remove();
//profile card wrapper markup
var rightArrowClass = rightSide?'rightArrow':'';
var profileCardHtml = '<div class="profileCard '+rightArrowClass+'" style="display:block;top:'+thisElTopOffset+'px;left:'+thisElLeftOffset+'px;" data-user="'+thisUserID+'"><div class="inner"><img src="/html/assets/feedback_loading_trans.gif" class="preloader" style="margin:80px auto;display:block;" /></div></div>';
$.when(
//get the background
$.ajax({
type: 'GET',
url: userApiUrl+thisUserID,
dataType: 'html',
success: function(data) {
$('.profileCard',cardWrapper).hide();
ajaxReturn = data;
}
})
)
.done(function(){
cardWrapper.append(profileCardHtml);
$('.profileCard[data-user='+thisUserID+']',cardWrapper).eq(0).empty().html(ajaxReturn);
if($('.profileCard[data-user='+thisUserID+'] .preloader',cardWrapper).length){
$('.profileCard[data-user='+thisUserID+'] .preloader',cardWrapper).parents('div.profileCard').remove();
}
})
.fail(function(){
// Hide if failed request
$('.profileCard',cardWrapper).hide();
});
}
}
},400);
},
mouseleave: function() {
clearTimeout(cardTimer);
if($('.profileCard[data-user='+thisUserID+']',cardWrapper).length){
$('.profileCard[data-user='+thisUserID+']',cardWrapper).delay(500).fadeOut('fast');
}
}
});
}
Here is a jQuery solution. Prior to displaying the popup, the script checks if the offset position of the trigger div plus the popup width falls beyond the screen width and adjusts the popup position accordingly.
hover = function(e) {
//var position = e.position();
var popup = $('.popup');
popup.attr('style', '');
if (e.offsetLeft + popup.outerWidth() > $( window ).width()) {
// adjust for screen width
popup.css({
right: $( window ).width() - e.offsetLeft - e.offsetWidth + 'px',
top: e.offsetTop - popup.outerHeight()
});
}
else {
// position normally
popup.css({
left: e.offsetLeft,
top: e.offsetTop - popup.outerHeight()
});
}
popup.show();
}
hide = function() {
$('.popup').hide();
}
.left-hover {
position:absolute;
left:20px;
top:80px;
border:1px solid black;
}
.right-hover {
position:absolute;
right:20px;
top:80px;
border:1px solid black;
}
.popup {
position:absolute;
display:none;
border:1px solid red;
width:100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="left-hover" onmouseover="hover(this)" onmouseout="hide()">Hover me</div>
<div class="right-hover" onmouseover="hover(this)" onmouseout="hide()">Hover me</div>
<div class="popup">My popup</div>
I'm trying to add two .height()'s together in order to get a responsive number for my onScroll event how do I add two of these together?
I'm general, I'm just trying to get the animation to fire after getting to the bottom of everything above the element. Is there any other way to do that besides just adding the heights of everything above?
window.addEventListener('load', function() {
$(window).scroll(function() {
var eventScroll = window.pageYOffset;
var eventScrollAmount = ($("#sectionOneImage").height() + $("#bannerOne").height());
if( eventScroll > eventScrollAmount) {
$("#sectionOneImage").addClass("animated slideInLeft ");
}
else {
$("#sectionOneImage").removeClass("animated slideInLeft ");
}
});
});
Here's an example of how to grab two heights using vanilla JS.
var sizeOfOne = document.getElementById('one').offsetHeight;
var sizeOfTwo = document.getElementById('two').offsetHeight;
document.getElementById('hook').innerHTML = 'The first div is ' + sizeOfOne + ' pixels in height, the second div is ' + sizeOfTwo + ' pixels in height. The total size of both div\'s are ' + (sizeOfOne + sizeOfTwo) + ' pixels.';
#one {
height: 50px;
background: red;
}
#two {
height: 75px;
background: blue;
}
<div id="hook"></div>
<div id="one"></div>
<div id="two"></div>
Thanks to a really helpful user on this website (whose name I do not know, but I wish to thank and credit him!), I got the following tip on how to store area elements in an array so that when I mouse over a coordinate, I could display all of the overlay id's of the area elements that existed at that coordinate (even if the area elements were not at the same z-level):
I'm just stuck on one thing- once I have gathered all the elements that exist at the coordinate in the hoveredElements array, how do I show their overlay ids?
EDIT:
Here is an example of the full code (the overlay still does not display when I mouse over)
The file test.txt contains:
cscCSL1A15 700 359 905 318
cscCSL1A14 794 400 905 318
I use the maphilight plugin available online, and blanketaphi.png is the plot I use as a background.
<!DOCTYPE html>
<html>
<head>
<title>Detector Elements</title>
<script type="text/javascript"
src="Demo_imagemap_highlight_files/jquery-1.js"></script>
<!-- add maphilight plugin -->
<script type="text/javascript"
src="Demo_imagemap_highlight_files/jquery_002.js"></script>
</head>
<body>
<div class="content">
<div class="map"
style='display: block; background: transparent
url("Demo_imagemap_highlight_files/blanketaphi.png")
repeat scroll 0% 0%; position: relative; padding: 0px; width: 1037px;
height: 557px;'>
<canvas width="1037" height="557" style="width: 1037px; height: 557px;
position: absolute; left: 0px; top: 0px; padding: 0px; border: 0px none;
opacity: 1;"></canvas>
<img style="opacity: 0; position: absolute; left: 0px; top: 0px; padding: 0px;
border: 0px none;" src="Demo_imagemap_highlight_files/blanketaphi.png"
alt="foo" class="map maphilighted" usemap="#demo" height="557" width="1037"
border="0" />
</div>
</div>
<map name="demo" id="demo"></map>
</body>
</html>
<script type="text/javascript">
window.onload = function(){
var f = (function(){
var xhr = [];
var files = [ "test.txt"];
for (i = 0; i < 1; i++) {
(function (i){
xhr[i] = new XMLHttpRequest();
xhr[i].open("GET", files[i], true);
xhr[i].onreadystatechange = function () {
if (xhr[i].readyState == 4 && xhr[i].status == 200) {
// get text contents
j=20000*i + 50000;
var coords = xhr[i].responseText.split("\n");
coords = coords.filter(Boolean) //prevents extra rect with 0 coords
coords.forEach(function(coord) {
var area = document.createElement("area");
var att = document.createAttribute("data-maphilight");
if (i == 0) { //green
att.value = '{"strokeColor":"000000","strokeWidth":2,' +
'"fillColor":"009900","fillOpacity":0.5}';
}
area.setAttributeNode(att);
area.id = "r"+j;
area.shape = "rect";
area.coords = coord.substring(10,coord.length).trim()
.replace(/ +/g,","); // replaces spaces in txt file with commas
area.href = "#";
area.alt = "r"+j;
// create overlay with first term in string
var div = document.createElement("div");
div.id ="overlayr"+j;
div.innerHTML = coord.substring(0,10);
div.style.display = "none";
//increase j
j++;
// get map element
document.getElementById("demo").appendChild(area);
document.getElementById("demo").appendChild(div);
});
$('.map').maphilight();
//display overlay ids by mousing over
var elementPositions = [];
var hoveredElements = [];
if($('#demo')) {
$('#demo area').each(function() {
var offset = $(this).offset();
var top = offset.top;
var left = offset.left;
var bottom = $(window).height() - top - $(this).height();
var right = $(window).width() - left - $(this).width();
elementPositions.push({
element: $(this),
top: top,
bottom: bottom,
left: left,
right: right
});
//alert(top + "," + left + "," + right + "," + bottom);
});
$("body").mousemove(function(e) {
hoveredElements = [];
var yPosition = e.pageX;
var xPosition = e.pageY;
for (var i = 0; i < elementPositions.length; i++) {
if (xPosition >= elementPositions[i].left &&
xPosition <= elementPositions[i].right &&
yPosition >= elementPositions[i].top &&
yPosition <= elementPositions[i].bottom) {
// The mouse is within the element's boundaries
$("#hovers").append(elementPositions[i].element);
}
}
for (var i = 0; i < hoveredElements.length; i++) {
// The element as a jQuery object
var elem = hoveredElements[i];
var id = hoveredElements[i].attr('id');
$('#overlay'+id).show();
}
});
};
}
};
xhr[i].send();
})(i);
}
})();
};
</script>
Why not just something like this:
var elementPositions = [];
var hoveredElements = [];
if($('#demo')) {
$('#demo area').each(function() {
var offset = $(this).offset();
var top = offset.top;
var left = offset.left;
var bottom = $(window).height() - top - $(this).height();
var right = $(window).width() - left - $(this).width();
elementPositions.push({ element: $(this), top: top, bottom: bottom, left: left, right: right });
//alert(top + "," + left + "," + right + "," + bottom);
});
$("body").mousemove(function(e) {
hoveredElements = [];
var yPosition = e.pageX;
var xPosition = e.pageY;
for (var i = 0; i < elementPositions.length; i++) {
if (xPosition >= elementPositions[i].left &&
xPosition <= elementPositions[i].right &&
yPosition >= elementPositions[i].top &&
yPosition <= elementPositions[i].bottom) {
// The mouse is within the element's boundaries
hoveredElements.push(elementPositions[i].element);
$("#hovers").append(elementPositions[i].element);
}
} //end of for loop over all elements
console.log(hoveredElements);
for (var i = 0; hoveredElements.length; i++)
{ //for loop over all hovered elements
// The element as a jQuery object
var elem = hoveredElements[i];
var id = hoveredElements[i].attr('id');
console.log(id);
$('#overlay'+id).show();
// Do stuff to that jQuery element:
//??? something like elem.show();
}
You've got a lot of stuff here that doesn't make sense to me but here's what I can gather so far.
Your areas need to be in a container called demo area. Not sure how the space in the ID works so in my case I switched it to demoarea. Also somewhere in the page, there has to be another element called demo for anything to even happen.
Once that's done, the script loads demoarea into the elementPositions array. Judging from your description that's not what you want to do, you probably want to load all the elements inside demoareainto the array. So the first change is
$('#demo area').each(function() {
Becomes
$('#demoarea').children().each(function() {
Now what becomes confusing to me is that this script for whatever reason decides that you need to have another element called hover so it can move the element out of demoarea into hover when you mouse over it. If that is what you want, then you can do your show trick with some simple CSS.
<div style="display:none" id="overlayr6064"> Example Overlay ID name </div>
Becomes
<div id="overlayr6064"> Example Overlay ID name </div>
And then you add:
<style>
#demoarea div {
display: none;
}
#hover div {
display: block;
}
</style>
Assuming that is not what you wanted, what #liamEgan did to add the elements to the hoveredElements array is good, but you have an infinite loop here
for (var i = 0; hoveredElements.length; i++)
it should be
for (var i = 0; i < hoveredElements.length; i++)
Then the rest works... except one last thing, you want to load these listeners to your script when the page loads in a document ready method.
So in all it looks a bit like:
//display overlay ids by mousing over (my map is called 'demo')
var elementPositions = [];
var hoveredElements = [];
if($('#demo')) {
$('#demoarea').children().each(function() {
var offset = $(this).offset();
var top = offset.top;
var left = offset.left;
var bottom = $(window).height() - top - $(this).height();
var right = $(window).width() - left - $(this).width();
elementPositions.push({ element: $(this), top: top, bottom: bottom, left: left, right: right });
});
console.log('After Scanning demoarea elementPositions looks like:')
console.log(elementPositions);
$(document).ready(function () {
$("body").mousemove(function(e) {
hoveredElements = [];
var yPosition = e.pageX;
var xPosition = e.pageY;
for (var i = 0; i < elementPositions.length; i++) {
if (xPosition >= elementPositions[i].left &&
xPosition <= elementPositions[i].right &&
yPosition >= elementPositions[i].top &&
yPosition <= elementPositions[i].bottom) {
// The mouse is within the element's boundaries
if (typeof elementPositions[i].element != "undefined") {
hoveredElements.push(elementPositions[i].element);
$("#hovers").append(elementPositions[i].element);
}
}
} //end of for loop over all elements
for (var i = 0; i < hoveredElements.length; i++) { //for loop over all hovered elements
// The element as a jQuery object
console.log(hoveredElements[i]);
if (typeof hoveredElements[i] != "undefined") {
var elem = hoveredElements[i];
var id = elem.attr('id');
$('#overlay'+id).show();
}
// Do stuff to that jQuery element:
//??? something like elem.show();
}
});
});
}
#demoarea {
border: 2px blue dotted;
}
/* Border added so I can see where to mouse over */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="demo">
<div id="demoarea">
<area shape="rect" coords="431,499,458,491" href="#" id="r6064" alt="r6064">
<div style="display:none" id="overlayr6064"> Example Overlay ID name </div>
</div>
<div id="hovers">
</div>
</div>
Edit: sorry I added the undefined tests while fixing this because of the infinite loop but I think they're not really needed. Still nice to have though. Also since the area also gets moved into the hover area this script does try to show an element called overlayoverlayr6064r6064 which fortunately doesn't exist. But ya, again, probably not what you had in mind.
I am trying to get three squares (put ramdomly) on page to disappear on click BUt for a reason I don't understand, some of them (usually the 2nd or 3rd one) reappear elsewhere on the page when I click on them.
They should just disappear.
I made a jsffidle: https://jsfiddle.net/DTcHh/9949/
The code:
HTML
<div class="container">
<div id="square-zone">
<!--
here appear the squares
-->
</div>
</div>
Javascript
//randomly place squares
$(function() {
var numInfoSquares = 3;
var $squareZone = $("#square-zone");
var $toAppend = $('<div class="info-square"><span class="square" data-toggle="modal"></span></div>');
for (var c = 0; c < numInfoSquares; c++) {
$squareZone.append(
$toAppend.clone()
.find('.square').attr("data-target", "#myInfoModal" + (c + 1))
.end()
);
};
// place info squares randomly on the page
function getRandomInt(min, max) {
return Math.random() * (max - min + 1) + min;
}
$(".info-square").each(function () {
var topPosition = getRandomInt(8, 70);
var leftPosition = getRandomInt(8, 92);
$(this).css({
"top": topPosition+"%",
"left": leftPosition+"%"
});
});
// clicked squares disappears on click
$(".info-square").click(function () {
$(this).css("display","none");
$(this).next().css("display","block");
});
});
CSS
body {
margin: 10px;
}
#square-zone > div { position: absolute; }
.info-square > span {
display: inline-block;
cursor: pointer;
background: url(http://cliparts.co/cliparts/ATb/jRa/ATbjRan5c.png) no-repeat center center;
width: 30px;
height: 30px;
}
How can I prevent the squares to reappear ?
Well just remove that line from your code which makes it appear again
$(this).next().css("display","block");
// clicked squares disappears on click
$(".info-square").click(function () {
$(this).css("display","none");
//$(this).next().css("display","block");
});
Updated jsfiddle with commented line https://jsfiddle.net/DTcHh/9950/
that is because of $(this).next().css("display","block");.
Assume you are clicking on 2nd element then it is hidden, then you are clicking on the first element now that is hidden but when the above line is executed it will display the second element back as it is the next sibling of the first info-square
//randomly place squares
$(function() {
var numInfoSquares = 3;
var $squareZone = $("#square-zone");
var $toAppend = $('<div class="info-square"><span class="square" data-toggle="modal"></span></div>');
for (var c = 0; c < numInfoSquares; c++) {
$squareZone.append(
$toAppend.clone()
.find('.square').attr("data-target", "#myInfoModal" + (c + 1))
.end()
);
};
// place info squares randomly on the page
function getRandomInt(min, max) {
return Math.random() * (max - min + 1) + min;
}
$(".info-square").each(function() {
var topPosition = getRandomInt(8, 70);
var leftPosition = getRandomInt(8, 92);
$(this).css({
"top": topPosition + "%",
"left": leftPosition + "%"
});
});
// clicked squares disappears on click
$(".info-square").click(function() {
$(this).css("display", "none");
//$(this).next().css("display", "block"); this displayes the next element back if it was already hidden
});
});
/* Latest compiled and minified CSS included as External Resource*/
body {
margin: 10px;
}
#square-zone > div {
position: absolute;
}
.info-square > span {
display: inline-block;
cursor: pointer;
background: url(http://cliparts.co/cliparts/ATb/jRa/ATbjRan5c.png) no-repeat center center;
width: 30px;
height: 30px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="container">
<div id="square-zone">
<!--
here appear the squares
-->
</div>
</div>
Alternately, changing $(this).css("display","none"); to $(this).css("visibility","hidden"); also solves it.
Here's the jsfiddle