Get Element by Position determined in Z-Index - Javascript - javascript

I am using the following sentence to get the element in some position, but he takes the first ...
$(this.cTaskItem[0]).mouseup(function(event){
var posX = event.clientX, posY = event.clientY;
var overElem = document.elementFromPoint(posX, posY);
overElem.style.border = "3px solid red";
});
I wonder how do I get the element at a given position and Z-Index.
Thank You

If the first element (the one that's selected by document.elementFromPoint(posX, posY)) is not supposed to be clickable you can set the css prepoerty pointer-events: none; to it and it will not be selected anymore

As #t.niese suggested above you could do this:
$(this.cTaskItem[0]).mouseup(function(event)
{
var posX = event.clientX, posY = event.clientY;
var elements = [];
var elm = document.elementFromPoint(posX, posY);
while(elm.tagName != "HTML")
{
elements.push(elm);
elm.style.display = "none";
elm = document.elementFromPoint(posX, posY);
}
});
Then all you would need to do is go through your elements array and select the one you need.

Related

How do I calculate and determine the area at which the div must be dropped?

I am building a drag and drop application purely in Javascript. I have coded the drag part where the element can be dragged and dropped randomly in the page. Now, I have built a drop zone that contains 9 boxes(divs) wherein 9 divs must be dropped. I can't think of an approach that will help me accomplish this task. I am thinking of making those divs 'absolute' and re-build them use top & left attributes. But how should I proceed further? How will the div that I drag i.e onmousedown will come to know that onmouseup it should drop at the specified location. Example: If I select a div numbered 1, it should drop at target numbered 1.
Here's the Javascript I am using for selecting and dragging:
window.onload = function() {
var el = document.getElementById('block1');
var mover = false, x, y, posx, posy, first = true;
el.onmousedown = function() {
mover = true;
};
el.onmouseup = function() {
mover = false;
first = true;
};
el.onmousemove = function(e) {
if (mover) {
if (first) {
x = e.offsetX;
y = e.offsetY;
first = false;
}
posx = e.pageX - x;
posy = e.pageY - y;
this.style.left = posx + 'px';
this.style.top = posy + 'px';
}
};
};
I would have the targets recognize a "onmouseenter" and set a Boolean to be true for that target, then set it to false "onmouseleave". then "onmouseup" check all of the booleans and if div1 has been dropped and target1 is true then div1 position = target position.
I know this is a pseudo code answer but its just my thought process on ho to solve the problem.

Javascript get coordinate of highlight text

I would like to get the position of highlighted text but not the bounded yellow rect (using range.getBoundingClientRect()) here I'm talking about the red area in the picture meaning it have an indent. Basically I want to save selection area and be-able to replicate them. I could not use the technique to save and restore Range object.
Here is what I'm trying to do:
function addMarkerOnSelection(){
var range = window.getSelection().getRangeAt(0);
var rect = range.getBoundingClientRect();
var scrolltop = jQuery('body,html').scrollTop();
//var scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
var marker = document.createElement('div');
marker.style.position = 'absolute';
marker.style.display='block';
marker.style.left = rect.left + 'px';
marker.style.top = scrolltop + rect.top + 'px';
marker.style.height = rect.bottom-rect.top + 'px';
marker.style.width = rect.right-rect.left + 'px';
marker.style.border='1px solid black';
marker.style.background='yellow';
marker.style.opacity = 0.5;
document.body.appendChild(marker);
}
You can try google docs, try no highlight multiple line of text and add an comment. They wrap the highlight area correctly.
I have another approach, using Range.surroundContents I am able to wrap content with an element and its work as expected. BUT how to save it without saving the whole text content?
function surround(){
var range = window.getSelection().getRangeAt(0);
var marker = document.createElement('span');
marker.style.border='1px solid black';
marker.style.background='yellow';
marker.style.opacity = 0.5;
range.surroundContents(marker);
};

How to check if one element is in same position as another javascript

I am creating a thing that is kind of cool and basically, it's just drawing without the use of a canvas because I thought "What the hell, I'll play around with some JS". Right now my computer can handle around 4,000 different elements before becoming laggy and I can make that number larger if I could tell if there was a div under the new div I am creating, and then remove it.
How can I detect if there is already an element where the script is going to be creating a new element and remove the existing element without the use of external libraries?
<!DOCTYPE html>
<html>
<head>
<title>Drawing thing</title>
</head>
<body onmousedown="setYes()" onmouseup="setNo()">
<div id="appendThingsHere"></div>
<style>
.circle{
height:50px;
width:50px;
background:blue;
border-radius:50%;
position:absolute;
-moz-user-select:none;
-webkit-user-select:none;
user-select:none;
}
body{
overflow:hidden;
}
#appendThingsHere{
height:100%;
width:100%;
background:none;
position:absolute;
top:0;
left:0;
}
</style>
<script>
var mouseDown = "no";
var elements = 0;
function setYes(){
mouseDown = "yes";
}
function setNo(){
mouseDown = "no";
}
document.body.onmousemove = function(e){
if(mouseDown === "yes"){
if(elements < 4000){
var newCircle = document.createElement("div");
newCircle.className = "circle";
newCircle.style.top = e.clientY - 25 + 'px';
newCircle.style.left = e.clientX - 25 + 'px';
try{
var elem = document.elementFromPoint(e.clientX - 25 + 'px', e.clientY - 25 + 'px');
elem.parentElement.removeChild(elem);
elements = elements - 1;
alert("Got one!");
}
catch(err){
}
elements ++;
document.getElementById('appendThingsHere').appendChild(newCircle);
}
}
}
</script>
</body>
</html>
http://jsbin.com/hocowa/edit?html,output
Assuming this is an experiment to tinker with js... you could do this
On the handler where you draw each new div, keep track of the last one drawn
var previousCircle,
yThreshold = 10,
xThreshold = 10;
document.body.onmousemove = function(e){
if(mouseDown === "yes"){
if(elements < 4000){
var ty = Math.abs(parseInt(previousCircle.style.top, 10) - e.clientY) < yThreshold;
var tx = Math.abs(parseInt(previousCircle.style.left, 10) - e.clientX) < xThreshold;
if (ty && tx){
// if thresholds pass (new is far away enough from old) then draw a new one
var newCircle = document.createElement("div");
newCircle.className = "circle";
newCircle.style.top = e.clientY - 25 + 'px';
newCircle.style.left = e.clientX - 25 + 'px';
previousCircle = newCircle;
}
You basically decide to draw a new circle or not, based on the distance to the last circle drawn. You can tweak the "decision" with the threshold vars, the threshold condition ìf (ty || tx) or you could even calculate a vector magnitude (radius from center of each circle) to keep things geometrically correct: radius = sqrt( (newY - oldY)^2 + (newX - oldX)^2 ).
Granted, this only tracks drawings in sequence, not previous iterations. For that to work you would need to do collision checking on each draw cycle and that means iterating over all drawn divs and comparing their position to the position of the new circle. This is highly inefficient. You could speed up things a bit if you keep track of drawn circles in a index which avoids querying the DOM, only memory.
var drawnCircles = [];
for (var i in drawnCircles){
if (Math.abs(drawnCircles[i].top - e.clientY) < yThreshold && //same for x){
// draw your new circle
var newCircle = document.createElement("div");
newCircle.className = "circle";
newCircle.style.top = e.clientY - 25 + 'px';
newCircle.style.left = e.clientX - 25 + 'px';
// and keep track of it
drawnCircles.push({top: e.clientY, left: e.clientX});
}
}
The best option is to do all the logic in JavaScript and track using an array. Use the DOM only for display purposes and you should see an improvement.
You could use document.elementFromPoint(x, y);
Don't think you'd be able to handle multiple elements in a single point though. May have to iterate whilst there is an element at point to either remove or ignore.
If you want to ensure no new element with same position with the elements before, you can create Array to hold the drawn positions and draw new element only if the new position is not exist in the array. Example:
var mouseDown = "no";
var elements = 0;
var elmList = [];
function setYes() {
mouseDown = "yes";
}
function setNo() {
mouseDown = "no";
}
document.body.onmousemove = function (e) {
if ( mouseDown === "yes" ) {
if ( elements < 4000 ) {
var offset = (e.clientY - 25) + 'x' + (e.clientX - 25);
if ( elmList.indexOf(offset) < 0 ) {
var newCircle = document.createElement("div");
newCircle.className = "circle";
newCircle.style.top = e.clientY - 25 + 'px';
newCircle.style.left = e.clientX - 25 + 'px';
elements++;
elmList.push(offset);
document.getElementById('appendThingsHere').appendChild(newCircle);
}
}
}
}

Fixing the canvas offset in Raphael.js when DOM element centered

I'm creating circles in a Raphael.js Canvas with a clicking action. When the canvas is drawn at the origin of the website it works fine. But when I move it to the middle some type offseting happens and only when you click on the right side of the canvas the circles are drawn at the left side of the canvas. Even though I have my listener action to the canvas and not the div that the is append to, here is the code:
<body>
<div id="container"></div>
</body>
Here is the JS:
var canvas = Raphael("container", 500, 500);
var ourCanvas = $('svg').last();
ourCanvas.attr("id", "canvas");
var canvasHandler = $("#canvas");
//We create a div with a class to append our canvas
var containerHandler = $("#container");
var circleClass = $("circle.quincy");
var justDragged = false;
canvasHandler.mouseup(function (e) {
var mouseX = e.pageX;
var mouseY = e.pageY;
makeCircle(mouseX, mouseY);
});
function makeCircle(mouseX, mouseY) {
var radius;
var fill;
var thisCirclesID = String(new Date().getTime());
var circle = canvas.circle(mouseX, mouseY, 50).attr({
fill: "hsb(.8, 1, 1)",
stroke: "none",
opacity: .5,
});
}
Here is a JSFiddle
I wonder if the way that I'm using the event position is correct. Any suggestion is more than welcome.
Thanks
M
I figured it out after realizing that the offset of the new position of svg was causing the mouse event to not recognize its real position. I found this blog post that shows how to use the offsetParent method to calculate the new position of my canvas relative its parent . Here is the code:
$(document).ready(function () {
//We create our canvas and add an ID
var canvas = Raphael("container", 500, 500);
var ourCanvas = $('svg').last();
ourCanvas.attr("id", "canvas");
var canvasHandler = $("#canvas");
//We create a div with a class to append our canvas
var containerHandler = $("#container");
var circleClass = $("circle.quincy");
var justDragged = false;
canvasHandler.mouseup(function (e) {
var mouseX = e.pageX - findPos(this)[0];
var mouseY = e.pageY - findPos(this)[1];
makeCircle(mouseX, mouseY);
findPos(this);
console.log("This is the position of the mouse in X: " + e.pageX);
console.log("This is the position of the mouse in Y: " + e.pageY);
});
function findPos(obj) {
var curleft = curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj == obj.offsetParent);
console.log(curleft);
console.log(curtop);
// return [curleft, curtop];
}
return [curleft, curtop];
}
As you can see the findPos(obj) returns and array of the new position of X and Y. So I substract that to my mouseX and mouseY to get the real position on the svg when clicking.
Update
Doing more reading and asking around. I didn't realize what type of elements the web browser returns. Instead of using e.pageX and e.pageY. offsetX offers the position of the mouse in respect to the parent giving the real coordinates. So the code will look like this:
canvasHandler.mouseup(function (e) {
var mouseX = e.offsetX;
var mouseY = e.offsetY;
makeCircle(mouseX, mouseY);
findPos(this);
});
This makes it easier since the offset takes into consideration the real position of the mouse in respect to the element.

HTML5 Multiple Canvases event listener - how to determine which canvas experienced the event?

I'm new to JS. I'm not using jQuery, and I have a question. I've created a variable number of canvases on a page, all have an eventlistener like so:
for (i=0; i<numberOfCanvases; i++){
var canv = document.createElement("canvas");
canv.addEventListener('click', clickReporter, false);
document.body.appendChild(canv); }
Given the listener function clickReporter:
function clickReporter(e){...}
I am trying to use this function to tell me the mouse position of the click event relative to the canvas:
function getMousePos(canvas, evt){
// get canvas position
var obj = canvas;
var top = 0;
var left = 0;
while (obj && obj.tagName != 'BODY') {
top += obj.offsetTop;
left += obj.offsetLeft;
obj = obj.offsetParent;
}
// return relative mouse position
var mouseX = evt.clientX - left + window.pageXOffset;
var mouseY = evt.clientY - top + window.pageYOffset;
return {
x: mouseX,
y: mouseY
};
}
which i found from this tutorial: http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/
The problem is, it assumes there is only one canvas, and I do have a list of canvases right now that are placed on a webpage, but I was wondering, given just the clickReporter() function, is there an easy way to determine which canvas was selected? a function like evt.getCanvas() or evt.getParentCanvas()?
I'm asking because when an event occurs (a mouse click on 1 of many canvases, I want to create actions at that location for ONLY that canvas)
function clickReporter(e){
console.log( this ); // in a eventListener , this point to the element fire the event
console.log( e.target ); // in fireFox and webkit, e.target point to the element fire the event
}
I would think evt.target (event.target) would work.

Categories

Resources