i'm developing a canvas-based timeline.
I want to trigger the onClick event to get informations about the clicked element.
canvas.onclick = function(e){
var evt = e || event;
var x = evt.offsetX;
var y = evt.offsetY;
for(var i=0;i<items_loaded.length;i++){
var item = items_loaded[i];
alert(x + ' | ' + y);
if((x > item['x_start'] && x < item['x_end']) && (y > item['y_start'] && y < item['y_end'])){
alert('Trovata fermata con ID: ' + item['id']);
}
}
}
I checked the code and the event seems to not fire right.
Related
I'm defining a class Session that is created for every new session.
In window.onload, the Session object has a mouse click event listener , on click, it fires the handler and 1. checks if anchor tag was clicked and saves href 2. saves the x and y of mouse click.
The problem: The function user.onclick is not working. Doesn't call the anchorLinkClickHandler(); OR window.addEventListener i.e. the click event handler that saves x and y. NO ERRORS. I think there is a syntactical issue with the below code.. don't know what. Ideas?
As shown (in window.onload):
var user = new UserSession('001');
user.onclick = function(event) {
// check if an anchor tag link is clicked, if so, save the href.
user.aTagHref = anchorLinkClickHandler();
// CLICK event listener - save the x and y of mouse click
window.addEventListener("load", function(event){
document.body.addEventListener("click", handleClick)
});
}
Here is the full code:
function UserSession(campaignId) {
this.campaignId = campaignId;
var aTagHref = aTagHref;
this.greeting = function() {
alert('Hi! I\'m ' + this.name + '.');
};
// get the position of click - Event Listener Function
this.getPosition = function(el) {
var xPosition = 0;
var yPosition = 0;
while (el) {
if (el.nodeName == "BODY") {
// deal with browser quirks with body/window/document and page scroll
var xScrollPos = el.scrollLeft || document.documentElement.scrollLeft;
var yScrollPos = el.scrollTop || document.documentElement.scrollTop;
xPosition += (el.offsetLeft - xScrollPos + el.clientLeft);
yPosition += (el.offsetTop - yScrollPos + el.clientTop);
} else {
xPosition += (el.offsetLeft - el.scrollLeft + el.clientLeft);
yPosition += (el.offsetTop - el.scrollTop + el.clientTop)
}
el = el.offsetParent;
}
return {
x: xPosition,
y: yPosition,
a: "hahah",
};
};
// On click handler
this.handleClick = function(event) {
// Return the current element clicked on
var el = event.currentTarget;
// Return the offset values of the element clicked on
var relOffsetValues = getPosition(el);
// Find the true value of x and y by adding the offset and the to clicked value of x and y
var realValueX = (relOffsetValues.x + event.clientX );
var realValueY = (relOffsetValues.y + event.clientY);
// display the x and y of the mouse click
alert("Clicks x:" + realValueX + ", y:" + realValueY);
// alert("clientx:" + event.clientX + ", real valie:" + realValueX);
}
// On click ANCHOR TAGS SAVE THEM
// Anchor Tags - Capture the href of the link clicked
this.anchorLinkClickHandler = function() {
var aTags = document.getElementsByTagName('a');
for (var i = aTags.length - 1; i >= 0; --i) {
aTags[i].onclick = function() {
aTagHref[i] = this.getAttribute("href");
alert(aTagHref);
};
}
}
// END OF CLASS
}
Window.onload function (where everything is called)
window.onload = function() {
var user = new UserSession('001');
user.onclick = function(event) {
// check if an anchor tag link is clicked, if so, save the href.
user.aTagHref = anchorLinkClickHandler();
// CLICK event listener - save the x and y of mouse click
window.addEventListener("load", function(event){
document.body.addEventListener("click", handleClick)
});
}
// SCROLL Event Listener
// Get the x and y of the scroll
window.addEventListener("scroll", function(event) {
// document.getScroll= function(){
var sx, sy;
if(window.pageYOffset!= undefined){
sx = pageXOffset;
sy = pageYOffset;
console.log(sx +" if " + sy);
// return [pageXOffset, pageYOffset];
}
else{
var d= document, r= d.documentElement, b= d.body;
sx= r.scrollLeft || b.scrollLeft || 0;
sy= r.scrollTop || b.scrollTop || 0;
console.log(sx +" else " + sy);
// return [sx, sy];
}
// }
});
};
Take a look at https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onclick to better understand.
The click event is raised when the user clicks on an element. The click event will occur after the mousedown and mouseup events.
You will have to create a HTML element first and when that element is clicked you have to execute a function that does all the actions you want.
HTML:
<button id="btn">Click me</button>
JavaScript:
document.querySelector("#btn").onclick = function(event) {
// do things here
}
I have an object with the name "element". If somebody touches the tablet, I would like to return the x and y coordinates of the touch position relative to the object, i. e. the upper left corner of the object has the coordinates x=0 and y=0.
I know how to implement this on desktops:
$(function() {
$(document).mousedown(function(e) {
var offset = $("#element").offset();
var relativeX = (e.pageX - offset.left);
var relativeY = (e.pageY - offset.top);
alert(relativeX+':'+relativeY);
$(".position").val("afaf");
});
});
So the word "mousedown" should be replaced by "touchstart", I guess. However, it still doesn't work.
How do I change the above code such that it works on tablets with "touchstart" instead of "mousedown"?
UPDATE: See Daniel Lavedonio de Lima's answer below
You have to explicitly pull a touches object out of the event, it doesn't contain the coordinates directly. Look at line two of the code below.
Here is the code I always use to get touch/pointer coordinates:
if(e.type == 'touchstart' || e.type == 'touchmove' || e.type == 'touchend' || e.type == 'touchcancel'){
var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
x = touch.pageX;
y = touch.pageY;
} else if (e.type == 'mousedown' || e.type == 'mouseup' || e.type == 'mousemove' || e.type == 'mouseover'|| e.type=='mouseout' || e.type=='mouseenter' || e.type=='mouseleave') {
x = e.clientX;
y = e.clientY;
}
Put this inside an event listener that listens for any or all of those events and add your offset calculation and this should work.
Christopher Reid's answer almost worked for me, but I had to make a few ajustments because originalEvent property was not part of the event when I was testing in Google Chrome version 81.0.4044.138 and Mozila Firefox version 76.0.1.
Since I found some answers that use directly the event and other that uses event.originalEvent property, I added a check to use the first if the latter is undefined.
So instead of:
var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
I used:
var evt = (typeof e.originalEvent === 'undefined') ? e : e.originalEvent;
var touch = evt.touches[0] || evt.changedTouches[0];
So the full answer then becomes:
if(e.type == 'touchstart' || e.type == 'touchmove' || e.type == 'touchend' || e.type == 'touchcancel'){
var evt = (typeof e.originalEvent === 'undefined') ? e : e.originalEvent;
var touch = evt.touches[0] || evt.changedTouches[0];
x = touch.pageX;
y = touch.pageY;
} else if (e.type == 'mousedown' || e.type == 'mouseup' || e.type == 'mousemove' || e.type == 'mouseover'|| e.type=='mouseout' || e.type=='mouseenter' || e.type=='mouseleave') {
x = e.clientX;
y = e.clientY;
}
Normally you would use e.g. e.touches[0].clientX to handle touch events
A non jquery solution, Assuming you have the following HTML
<div id="touchme" style="width: 200px; height: 200px; background: blue;">
And script
document.getElementById("touchme").addEventListener("touchstart",
function clicked(e) {
var br = document.getElementById("touchme").getBoundingClientRect();
// x & y are relative to the clicked element
var x = e.touches[0].clientX - br.left;
var y = e.touches[0].clientY - br.top;
console.log("x: " + x + " y: " + y);
});
Note the following script handles only the first (of all the possible) touch input
Try this:
$(function(){
$('body').on('touchstart', function(e) {
var offset = $("#element").offset();
var t = e.targetTouches.length > 0 ? e.targetTouches.item(0) : e.touches.item(0);
var relativeX = t.pageX - offset.left;
var relativeY = t.pageY - offset.top;
console.log(relativeX+':'+relativeY);
$(".position").val("afaf");
});
});
PointerEvent supports mouse and touch both.
For example, let's see Sortable.js.
Bind events #L423
el.addEventListener('pointerdown', handler);
Get coords #L574
let touch = (evt.touches && evt.touches[0]) || (evt.pointerType && evt.pointerType === 'touch' && evt);
let clientX = (touch || evt).clientX;
let clientY = (touch || evt).clientY;
I adapted the Domenico solution to move the camera on pc and mobile for threeJS without orbitcontrols:
window.addEventListener("touchmove", function clicked(e) {
cursor.x = e.touches[0].clientX / sizes.width - 0.5
cursor.y = -(e.touches[0].clientY / sizes.height - 0.5)});
In case you have some built-in scroll, you should do it as follows:
const rect = event.target.getBoundingClientRect();
x = event.targetTouches[0].pageX - (rect.left + document.documentElement.scrollLeft);
y = event.targetTouches[0].pageY - (rect.top + document.documentElement.scrollTop);
Can somebody please give me advice on how to delete events from the FullCalendar Version 2 by dragging it out of the calendar, please?
I saw some solution here: Remove Elements from fullcalendar (by dragging to trash can)
but it seems to address the version 1.
My first approach would be:
eventDragStop: function(event,jsEvent) {
alert('Coordinates: ' + jsEvent.pageX + ',' + jsEvent.pageY);
if( (300 <= jsEvent.pageX) & (jsEvent.pageX <= 500) & (130 <= jsEvent.pageY) & (jsEvent.pageY <= 170)){
alert('delete: '+ event.id);
$('#MyCalendar').fullCalendar('removeEvents', event.id);
}
}
This allows to drag events to the area (in pixels) corresponding to the if condition order to delete. Tested with fullcalendar 2.1.1.
An improvement would be to check and compare jsEvent coordinates with $(window).height() and $(window).width(), this way would confirm/test dragging out of calendar area, much neat of course.
Actually the improvement is (an elegant solution), based on the solution mentioned:
Create a div element with the icon trash:
<div id="calendarTrash" class="calendar-trash"><img src="path/to/static/images/trash.png" /></div>
The eventDragStop is:
eventDragStop: function(event,jsEvent) {
var trashEl = jQuery('#calendarTrash');
var ofs = trashEl.offset();
var x1 = ofs.left;
var x2 = ofs.left + trashEl.outerWidth(true);
var y1 = ofs.top;
var y2 = ofs.top + trashEl.outerHeight(true);
if (jsEvent.pageX >= x1 && jsEvent.pageX<= x2 &&
jsEvent.pageY >= y1 && jsEvent.pageY <= y2) {
alert('SIII');
$('#calendario').fullCalendar('removeEvents', event.id);
}
}
Tested on Fullcalendar 2.1.1
Without jQuery :
eventDragStop: function(e) {
let trashEl = document.getElementById('fcTrash') //as HTMLElement;
let x1 = trashEl.offsetLeft;
let x2 = trashEl.offsetLeft + trashEl.offsetWidth;
let y1 = trashEl.offsetTop;
let y2 = trashEl.offsetTop + trashEl.offsetHeight;
if (e.jsEvent.pageX >= x1 && e.jsEvent.pageX <= x2 &&
e.jsEvent.pageY >= y1 && e.jsEvent.pageY <= y2) {
e.event.remove();
}
}
eventDragStop: function(event,jsEvent) {
var trashEl = jQuery('#calendarTrash');
var ofs = trashEl.offset();
var x1 = ofs.left;
var x2 = ofs.left + trashEl.outerWidth(true);
var y1 = ofs.top;
var y2 = ofs.top + trashEl.outerHeight(true);
if (jsEvent.pageX >= x1 && jsEvent.pageX<= x2 &&
jsEvent.pageY >= y1 && jsEvent.pageY <= y2) {
if (confirm("Are you sure to detete " + event.title +" ?")) {
//pour annuker les informations
$('#external-calendar').fullCalendar('removeEvents', event._id);
}
}
}
`
event._id not event.id (all events will be deleted)
<div id="calendarTrash" class="calendar-trash"><img src="images\trash.png" alt="image"/></div>
I want to capture the event when my drop action fails, either because the user did not drop at the right location or may be he himself has cancelled it by hitting 'Esc' key.
Take a look at this script. Took me some time to write and finish it. => DEMO
If this is what you want, let me know.
Note: => this code isn't compatible with legacy (browsers that don't have HTML5 support) browsers (e.g. IE8 etc)
First, we define our draggable element by setting its draggable attribute to true
<div id="draggable" draggable="true"> Drag this div </div>
Then we define our dropzone (target:where the element should be dropped on)
<div class="dropzone" id="dropzone">Dropzone</div>
We need to get the coordinates of the mouse when the element is being released, so we know if the mouse was released on the dropzone or not (I've put an alert notification showing whether the dragend event occurred on the dropzone. If on the dropzone than it will alert dropped on the dropzone, else it will alert dropped not on the dropzone)
function cords(event)
We also need to get the coordinates of the dropzone element, so we will be able to find where the drop event (successful or not (*manually cancelled (Esc) or dropped on the wrong place)) occurred.
var elTop = dragZone.getBoundingClientRect().top + getDocTopLeftPos().fT;
var elLeft = dragZone.getBoundingClientRect().left;
var elBottom = elTop + parseInt(getElProps(dragZone,'height'));
var elRight = elLeft + parseInt(getElProps(dragZone,'width'));
We will know whether the drag operation was successful or not via (on)dragend event
HTML
<div id="draggable" draggable="true">
Drag this div
</div>
<div class="dropzone" id="dropzone">Dropzone</div>
CSS
#draggable {
width: 200px;
height: 50px;
text-align: center;
background: red;
margin-bottom:50px;
}
.dropzone {
width: 200px;
height: 200px;
background: brown;
margin-bottom: 10px;
padding: 10px;
text-align:center
}
Javascript
//checking if the browser is Internet Explorer
var isIEX = navigator.userAgent.match(/Trident/);
var doc = isIEX ? document.documentElement : document.body;
function getDocTopLeftPos() {
scrollTop = window.pageYOffset || doc.scrollTop;
scrollLeft = window.pageXOffset || doc.scrollLeft;
clientTop = doc.clientTop || 0;
clientLeft = doc.clientLeft || 0;
fromTop = Math.round(scrollTop - clientTop);
fromLeft = Math.round(scrollLeft - clientLeft);
return {fT:fromTop, fL:fromLeft}
}
//get the value of the property of the specified element
function getElProps(el,attr){
whaT_ = isIEX ? el.currentStyle : window.getComputedStyle(el);
getWhaT_ = isIEX ? whaT_.getAttribute(attr) : whaT_.getPropertyValue(attr);
return getWhaT_;
}
//getting the coordinates of the mouse
function cords(ev) {
if (ev.pageX == null && ev.clientX != null ) {
var html = document.documentElement;
var body = document.body;
ev.pageX = ev.clientX + (html && html.scrollLeft || body && body.scrollLeft || 0) - (html.clientLeft || 0)
ev.pageY = ev.clientY + (html && html.scrollTop || body && body.scrollTop || 0) - (html.clientTop || 0)
}
return {x:ev.pageX,y:ev.pageY}
}
var x,y;
var dragZone = document.getElementById("dropzone");
//getting our element's coordinates
//the mouse should be between these coordinates, otherwise that wouldn't be the dropzone
//from top
var elTop = dragZone.getBoundingClientRect().top + getDocTopLeftPos().fT;
//from left
var elLeft = dragZone.getBoundingClientRect().left;
//the height of the draggable element + its top coordinate
var elBottom = elTop + parseInt(getElProps(dragZone,'height'));
//the width of the draggable element + its left coordinate
var elRight = elLeft + parseInt(getElProps(dragZone,'width'));
var dragElement;
document.getElementById("draggable").addEventListener("dragstart",function(event){
evt = event || window.event;
if(navigator.userAgent.match(/Firefox/)) event.dataTransfer.setData('text/plain',null)
},false);
document.addEventListener("dragstart",function(event){
evt = event || window.event;
//the element that is being dragged
dragElement = evt.target || evt.srcElement
//make our target half transparent;
dragElement.style.opacity = 0.5;
},false);
document.addEventListener("dragend",function(event){
console.log(x + ' ' + y + ' ' + elTop + ' ' + elLeft + ' ' + elBottom + ' ' + elRight);
//if the dragged element was dropped at the right place
if(x>elLeft && x<elRight && y>elTop && y<elBottom){
alert('dropped on the dropzone');
}else{
//if the destination was wrong or the drag was cancelled (Esc)
alert('dropped not on the dropzone')
}
//reset our element's transparency
dragElement.style.opacity = 1;
dragZone.style.background = "brown";
},false);
document.addEventListener("dragover",function(event){
evt = event || window.event;
x = cords(evt).x;
y = cords(evt).y;
console.log(x + ' ' + y);
//this will prevent browser's default behaviour which will allow the drop event to occur
if(evt.preventDefault) evt.preventDefault() ; else return false;
},false);
document.addEventListener("dragenter",function(event){
evt = event || window.event;
dropTarget = evt.target || evt.srcElement;
//this will highlight potential drop target when the draggable element enters it
if(dropTarget.className == "dropzone" ){
dropTarget.style.background = "purple";
}
}, false);
document.addEventListener("drop",function(event){
evt = event || window.event;
if(evt.preventDefault) evt.preventDefault() ; else return false;
}, false);
i have this js object:
var tags = [{ 'x' : '42','y' : '25','id' : '1', 'linea' : '1'},{ 'x' : '378','y' : '24','id' : '2', 'linea' : '1'}];
i try to loop in this way:
for(var i = 0; i < tags.length; i++){
var x = tags[i].x -10;
var y = tags[i].y -10;
var offsetX = x + 20;
var offsetY = y + 20;
if( left >= x && left <= offsetX ){
$(myDiv).bind('click',function(){
document.location.href = 'x.php?a='+ tags[i].linea +'&b=' + tags[i].id;
}).css('cursor','pointer');
}else{
$(myDiv).unbind('click').css('cursor','none');
}
}
But i loose the first!
Is this the correcy way??
Thanks!
You don't loose the first (sounds like it was a car key). You problem is your anonymous function, that closes over its parent scope when executed( for your .bind() method). It creates, what we call, a Closure.
Its a very common mistake in ECMAscript there. You need to invoke an additional context to avoid this issue.
$(myDiv).bind('click',(function( index ){
return function() {
document.location.href = 'x.php?a='+ tags[index].linea +'&b=' + tags[index].id;
};
}( i ))).css('cursor','pointer');
If you don't do that, all of those anonymous function context will share the same parent context in their scope-chain. Without describing that too much in detail now, it'll end up that all event handlers would reference the same variable i.
Beside that, it looks like you're binding multiple click event handlers to the same element myDIV. Each handler would cause the browser to redirect to another url, so, this will bring trouble. I can't even tell if the first or the last handler will win this race.
Variable scope.. change to this and it should work fine:
var lineA = tags[i].linea;
var id = tags[i].id;
$(myDiv).bind('click',function(){
document.location.href = 'x.php?a='+ lineA +'&b=' + id;
}).css('cursor','pointer');
The problem is with i being the loop iterator, so when you click myDiv it will have the last value always.
Edit: after looking into it, I could see you are taking the wrong approach. What you are after is identifying where the user clicked inside the <div> and redirect to different location according to your array. For this, such code should work:
var tags = [{ 'x' : '42','y' : '25','id' : '1', 'linea' : '1'},{ 'x' : '378','y' : '24','id' : '2', 'linea' : '1'}];
$("#myDiv").bind('click',function(event) {
var left = event.pageX - $(this).position().left;
for(var i = 0; i < tags.length; i++){
var x = tags[i].x -10;
var y = tags[i].y -10;
var offsetX = x + 20;
var offsetY = y + 20;
if( left >= x && left <= offsetX ){
var lineA = tags[i].linea;
var id = tags[i].id;
document.location.href = 'x.php?a='+ lineA +'&b=' + id;
break;
}
}
});
The code should be pretty clear, anyway it's not possible to have only parts of the element with hand cursor - I advise you not to mess too much as it will be really complicated.
Live test case.
Edit 2: Having the "clickable" parts of the element with different cursor is easier than I initially thought, you just have to handle the onmousemove event as well and in there set the cursor:
var posLeft = $("#myDiv").position().left;
$("#myDiv").bind('click',function(event) {
var tag = GetHoveredTag(event);
if (tag) {
var lineA = tag.linea;
var id = tag.id;
document.location.href = 'x.php?a='+ lineA +'&b=' + id;
}
}).bind("mousemove", function(event) {
var tag = GetHoveredTag(event);
var cursor = (tag) ? "pointer" : "";
$(this).css("cursor", cursor);
});
function GetHoveredTag(event) {
var left = event.pageX - posLeft;
for(var i = 0; i < tags.length; i++){
var x = tags[i].x -10;
var y = tags[i].y -10;
var offsetX = x + 20;
var offsetY = y + 20;
if( left >= x && left <= offsetX )
return tags[i];
}
return 0;
}
Updated fiddle.