I have a table, and when the user clicks on each cell, some details should appear in a small popup div that appears where the user clicked. I'm using jQuery, but not to bind the function to the onClick event.
function detailPopup(cell, event, groupName, groupID, ...)
{
var newDiv = document.createElement("div");
newDiv.id = "detailPop" + groupID;
newDiv.className = "priceDetailPopup";
newDiv.innerHTML = "<p>" + groupName + "</p>"; // more will go here
$(newDiv).click(function()
{
$(this).fadeOut("fast").remove();
}
);
$("#main").append(newDiv);
$(newDiv).css({"left" : event.pageX, "top" : event.pageY}).fadeIn("fast");
}
Everything is working wonderfully in FF, Safari, and Chrome. In IE, it all works except that the detail div appears below the table. event.pageX/Y aren't working. I know jQuery will fix those for IE if I bind the function through jQuery like this:
$(cell).click(function(e) { ... e.pageX ... })
But I can't do that. (I don't think I can - if you do, please explain how I can get six variables into that function without having to use non-xhtml tags in the cell.)
Is there a way to have jQuery "fix" the event object without binding the function through jQuery? $JQuery.fixEvent(event); or something? I can't find any reference to doing so on their site.
e = jQuery.event.fix(e); //you should rename your event parameter to "e"
I found the fix function by searching through the jQuery source code.
Alternatively, you could use this to get the mouse coordinates without jQuery...
var posx = 0;
var posy = 0;
if (!e) var e = window.event;
if (e.pageX || e.pageY) {
posx = e.pageX;
posy = e.pageY;
}
else if (e.clientX || e.clientY) {
posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
Via PPK: http://www.quirksmode.org/js/events_properties.html
This blog post seems to be relevant: http://www.barneyb.com/barneyblog/2009/04/10/jquery-bind-data/
Seems it's just jQuery("#selector").bind("click", {name: "barney"}, clickHandler);, then e.data.name to access it in the event.
You might find that the issue you're facing is not a positioning issue at all. Based on the syntax you posted, you may be experiencing an IE bug relating to the use of the CSS ID selector.
$("#main").append(newDiv);
If IE doesn't recognize the "#main" element, the append() function will not work correctly. IE (pre-v7) has spotty support for the ID (#) selector. Instead try:
$('div[id="main"]').append(newDiv);
Try this and let me know how it works for you.
Related
I am using raphael.js to manipulate images inside a "paper". I have realized that all mouse events (click, mousedown, mouseup, dragstart...) are triggered by any mouse button.
In this JSFiddle there is an example to drag two objects, it is possible to drag them around with left, right or middle mouse buttons
JSFiddle
How can I filter the events depending on which button was clicked? For instance, I would like to drag only with the left mouse button
I have read in another StackOverflow post that it is possible to identify the mouse button with e.which, it will return 1, 2, or 3 depending on the pressed button but I cannot find a way to use this variable to filter the event triggers.
I have found a Bug report about this issue but it is open since 2012. I have tried to use part of the code to filter the mouse button with if(e.which == 1) and then I made a console entry. In this way the console entry only appears when I attempt to make a drag with the left button, it won't appear with the other buttons. I have not found a way to implement the rest of the code
Does anybody know what is g.doc.documentElement or g.doc.body (From the bug report code)?
Thank you in advance for your support
Have a good day
I have found a way to do it, instead of installing raphael using npm install raphael I have downloaded the js file from github and then edited the drag function in the following way:
elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) {
function start(e) {
if (e.which == 1) {
(e.originalEvent || e).preventDefault();
var x = e.clientX,
y = e.clientY,
scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft;
this._drag.id = e.identifier;
if (supportsTouch && e.touches) {
var i = e.touches.length, touch;
while (i--) {
touch = e.touches[i];
this._drag.id = touch.identifier;
if (touch.identifier == this._drag.id) {
x = touch.clientX;
y = touch.clientY;
break;
}
}
}
this._drag.x = x + scrollX;
this._drag.y = y + scrollY;
!drag.length && R.mousemove(dragMove).mouseup(dragUp);
drag.push({el: this, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope});
onstart && eve.on("raphael.drag.start." + this.id, onstart);
onmove && eve.on("raphael.drag.move." + this.id, onmove);
onend && eve.on("raphael.drag.end." + this.id, onend);
eve("raphael.drag.start." + this.id, start_scope || move_scope || this, this._drag.x, this._drag.y, e);
}
}
this._drag = {};
draggable.push({el: this, start: start});
this.mousedown(start);
return this;
};
This works fine, I have to do the same for each mouse event but I think the information would be helpful for someone else.
i have a function to get the co-ordinates of the recently clicked position with respect to a div element without using JQuery which is working fine .
without jquery (working) :
var Board = document.getElementById("board"); // div element
function mouseListener(e)
{
var posX = e.clientX - Board.getBoundingClientRect().left,
posY = e.clientY - Board.getBoundingClientRect().top
console.log(posX+" : "+posY);
}
window.addEventListener("mousedown", mouseListener,false);
But this one uses JQuery and giving different co-ordinates as compared to the previous code
using jquery(not working) :
var Board = $("#board");
function mouseListener(e)
{
var posX = e.clientX - Number(Board.css("left").replace("px", "")),
posY = e.clientY - Number(Board.css("top").replace("px", ""));
console.log(posX+" : "+posY);
}
$(window).mousedown(mouseListener);
How to write this properly on jQuery so that it'll work like the first code?
With jQuery you have to use .offset() to get the same values as with .getBoundingClientRect():
function mouseListener(e) {
var posX = e.clientX - parseFloat(Board.offset().left),
posY = e.clientY - parseFloat(Board.offset().top);
console.log(posX+" : "+posY);
}
jQuery.fn.offset() Reference here;
There are three ways to attach the event-handler. Used in jQuery < 1.7 but still working in newer versions:
$(window).bind('mousedown', mouseListener);
As of jQuery 1.7 method .on() is used, it has the greatest flexibility also for event delegation:
$(window).on('mousedown', mouseListener);
The third is what you have used, it's only a shortcut and calls internally .on().
Reference jQuery.fn.bind() - - - - Reference jQuery.fn.on()
Whatever you have done is absolutely correct logicwise, just minor syntactical mistakes.
var Board = $("#board");
function mouseListener(e)
{
var posX = e.clientX - Number(Board.css("left").replace("px", "")), //you forgot to put closing braces here and in the next line.
posY = e.clientY - Number(Board.css("top").replace("px", ""));
console.log(posX+" : "+posY);
}
$(window).mousedown(mouseListener);
Make sure you have used style left and top in the element with id "#board" else output will be NaN : NaN.
I have the following code which will allowed a user running iOS to move a <div> with the class .drag around on the page. This works fine when there is one istance of .drag, but fails to work when there are two instances of it. Is it possible to have the code find all of the <div>'s, then allow them to be draggable?
var drag = $(".drag")[0];
xPos = drag.offsetWidth / 2;
yPos = drag.offsetHeight / 2;
drag.addEventListener("touchmove", function() {
event.preventDefault();
$(this).css({
'left' : event.targetTouches[0].pageX - xPos + 'px',
'top' : event.targetTouches[0].pageY - yPos + 'px'
});
});
When you use $(selector)[0], you get the first DOM element that matches the selector. Use .each() instead to add the event listener to all elements that match the selector:
$(".drag").each(function () {
var drag = this;
xPos = drag.offsetWidth / 2;
yPos = drag.offsetHeight / 2;
drag.addEventListener("touchmove", function() {
event.preventDefault();
$(this).css({
'left' : event.targetTouches[0].pageX - xPos + 'px',
'top' : event.targetTouches[0].pageY - yPos + 'px'
});
});
});
Yes, it's possible. But you are using a jQuery selector (which can select and return multiple elements) and then immediately unwrapping it to return the first element. You can modify your code to use jQuery functions throughout and avoid this.
// an array of all elements with class "drag"
// each element is wrapped
var drag = $(".drag");
// selects all matching elements, but then references
// the first raw DOM element in the array
var drag = $(".drag")[0];
Another way of looking at it:
var matches = $(".drag");
// each() executes a function for each matched element
matches.each(function () {
var drag = this; // raw dom element
// or, wrap to get jQuery object
// var drag = $(this);
});
As I mentioned, you can also use jQuery functions throughout your code. Two quick examples I see are the x/y coordinate calculation and the event binding.
First, you declare that you want only the first element by using [0].
Second, you should use jQuery's on() method. Here's how I see you function:
var drag = $(".drag");
drag.on("touchmove", function(event) {
xPos = $(this).offsetWidth / 2;
yPos = $(this).offsetHeight / 2;
event.preventDefault(); // preventDefault is IE-specific, is it?
$(this).css({
'left' : event.targetTouches[0].pageX - xPos + 'px',
'top' : event.targetTouches[0].pageY - yPos + 'px'
});
});
This is probably obvious to most experienced devs, but could be helpful to some junior devs who like myself have had trouble getting jQuery to apply to multiple elements.
Today I learned that you have to make sure you’re loading your script outside the div itself.
I was mistakenly loading the script inside the first element, and wondering why the jQuery function wasn’t applying to the other div farther down the page.
Screenshot showing < script > inside parent < div >
^ I was doing it wrong
Is there any way how to get element selector which was clicked by trigger? I'm trying to avoid specification of certain element in trigger method like $("#certain_element").trigger(e); I want to call a trigger on some position in the page defined by pageX and pageY params and then get an element which was clicked.
var e = new jQuery.Event("click");
e.pageX = 80;
e.pageY = 40;
$('*').trigger(e);
$('*').click(function() {
alert('This element was clicked:'+$(this).get(0).tagName);
});
This script isn't working correctly.
Based on the comments from Andrew and Anurag:
$(document.elementFromPoint(80, 40))
.trigger('click')
.css('background-color', 'blue');
You are triggering it BEFORE binding the click.
var e = new jQuery.Event("click");
e.pageX = 80;
e.pageY = 40;
// binds
$('*').click(function() {
alert('This element was clicked:'+$(this).get(0).tagName);
});
// then triggers
$('*').trigger(e);
Eventhough, if I were you, I'd use another selector, which would not trigger the event for window, document and another unecessary tags.
$(documnet.body).find('*').click(...);
$(document.body).find('*').trigger(e);
Setup
I'm making an HTML page that replaces the cursor with a div element. The Javascript is below. The div element is simply <div id="cursor"/>.
function fixCursor()
{
var cPos = getCursorPosition();
cursor.style="top:" + (cPos.y) + "; left:" + (cPos.x) + "; position:fixed; width:16px; height:16px; background-color:#DDDDDD; box-shadow: 2px 2px 4px rgba(0,0,0,.5); border:2px solid #111111; border-radius:0 100% 100% 100%;";
return;
}
function getCursorPosition(e) {
e = e || window.event;
var cursor = {x:0, y:0};
if (e.pageX || e.pageY) {
cursor.x = e.pageX;
cursor.y = e.pageY;
}
else if (e.screenX || e.ecreenY) {
cursor.x = e.screenX;
cursor.y = e.screenY;
}
else if (e.x || e.y) {
cursor.x = e.x;
cursor.y = e.y;
}
else if (e.clientX || e.clientY) {
var de = document.documentElement;
var b = document.body;
cursor.x = e.clientX;
cursor.y = e.clientY;
}
return cursor;
}
Problem
This only works on Opera, and shows signs of working on IE, but doesn't show the cursor. On Firefox and Chrome, nothing appears. I haven't tried Safari, as I uninstalled it a while ago, but in my experience, its rendering works alot like Chrome, anyway.
In your code, getCursorPosition takes an event object, e. In fixCursor, you are not passing anything in. You should probably make fixCursor take an event object as well and pass it through to getCursorPosition. Then, in your event handler where you're presumably calling fixCursor, pass in the event object passed into your event handler.
Also, you cannot set style equal to a string. You can, however, set style.cssText.
You can add custom cursors with the CSS cursor property, all major browsers but Opera support it to one extent or another. If you want it to work in IE you'll need to use a .cur or .ani cursor file, the other browsers support at minimum .cur, .png, .jpg and .gif.
Alternatively this answer points to a jQuery plugin that might be easier to use than implementing it yourself.
Personally I've never found a situation where I had to use a custom cursor, I usually just use a .png cursor in my stylesheet and leave a sensible default value for the browsers that don't support .png cursors.
Are you planning to do this onmousemove? That's a lot of overhead. In any case, I see a few problems, but I don't know if fixing them alone will get you a cross-browser solution.
First, let's assume you're triggering this function onmousemove, so you have this in your script:
document.onmousemove = fixCursor;
You have to have fixCursor() pass an event object to getCursorPosition() like this:
function fixCursor(e)
{
var cPos = getCursorPosition(e);
...
And you have to explicitly set each style attribute:
cursor.style.cursor = 'none'; // Didn't see you set this
cursor.style.top = cPos.y;
cursor.style.left = cPos.x;
cursor.style.position = "fixed";
A quick test showed me that this worked in Firefox but not IE. Setting position to "absolute" got closer in IE, but not in a useful way.
EDIT: Oh, and it appears you're not properly referencing the "cursor" div in your fixCursor() function. Use
var cursor = document.getElementById('cursor');