I have reached out to the developer on this one and he indicated I'd be on my own modifying the code to support this method as the code as currently written was not very hack friendly...I have attempted to modify without 100% success.
Currently JCrop is using jquery to track .mousedown to start the selection and .mouseup to accept/stop the selection. What happens on the blackberry device(with trackpad) when you click the trackpad using jcrop it starts to draw the selection as you move the cursor(you cannot click(hold) and drag on the trackpad its more of a click event). The issue is when you click again it removes the selection and starts to redraw it from the current cursor position. It seems to me that JCrop is using the mousedown to track the click and drag selection process and then mouseup to release the selection and keep the crop box.
I thought about assigning a variable like clickCount track the clicks and a function to fireoff the events. So everytime the user clicks it would run a function to track the clickCount and fireoff either the start selection or finish selection events.
Below are all the references to .mousedown and .mouseup:
var $trk = newTracker().width(boundx + (bound * 2)).height(boundy + (bound * 2)).css({
position: 'absolute',
top: px(-bound),
left: px(-bound),
zIndex: 290
}).mousedown(newSelection);
function dragDiv(ord, zi) //{{{
{
var jq = $('<div />').mousedown(createDragger(ord)).css({
cursor: ord + '-resize',
position: 'absolute',
zIndex: zi
});
if (Touch.support) {
jq.bind('touchstart', Touch.createDragger(ord));
}
$hdl_holder.append(jq);
return jq;
}
var $track = newTracker().mousedown(createDragger('move')).css({
cursor: 'move',
position: 'absolute',
zIndex: 360
});
function toFront() //{{{
{
$trk.css({
zIndex: 450
});
if (trackDoc) {
$(document)
.bind('mousemove',trackMove)
.bind('mouseup',trackUp);
}
}
//}}}
function toBack() //{{{
{
$trk.css({
zIndex: 290
});
if (trackDoc) {
$(document)
.unbind('mousemove', trackMove)
.unbind('mouseup', trackUp);
}
}
if (!trackDoc) {
$trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp);
}
Help / ideas would be greatly appreciated. Thanks
What about something along the lines of this:
var isDragging = false;
function onMouseDown(event) {
isDragging = !isDragging;
}
function onMouseUp(event) {
if (isDragging) {
event.preventDefault();
}
}
window.addEventListener('mousedown', onMouseDown, false);
window.addEventListener('mouseup', onMouseUp, false);
This way, onMouseUp should technically only fire every other time, potentially preventing the release trigger from stopping selection. This would require some deeper integration with your code of course.
Related
I'm fiddling with drag&drop in HTML and Javascript, setting the draggable attribute of elements and implementing dragstart, dragover and drop events to be able to drag and drop elements into a "drop field" and to drag & drop them out again.
That part works for me.
I now want to be able to move those elements using a similar gesture: press the mouse button over the element I want to move, move the mouse and release the button again, without having to press some modifier like CTRL.
Such a behavior can be implemented by handling mousedown/mousemove and mouseup events as described here.
But what if I want to combine them? To me it looks like dragging an element out of a field when moving it should also be possible, somehow get into each others way. However the workflow still seems valid: just register both events, pretend you just want to move until you leave the parent and then decide to either handle the drop event and return the element to it's original position or have it moved.
My first naive approach would be to just implement both (drag and drop and mouse-move) and somehow make sure, positions and event handling don't interfere.
Another approach would be to forget about the mouse events and stick to drag&drop instead which had to be configured to provide seamless moving.
Since I expect my resulting code to become quite dirty I was hoping for some more sophisticated approach to exist for a hybrid drag&drop and move behavior.
Can you give me a hint? how would you do this?
Here is some current state which allows creating a new element via drag&drop and move it around. As you can see I had to deactivate draggable for the mouse-events to work.
<!DOCTYPE html>
<html>
<head><style>
body, html, div, figure {
margin: 0; padding: 0;
background-color: grey;
position: absolute;
text-align: center;
}
.fullsize {
background-color: rgb(200, 250, 250);
width: 15cm; height: 15cm;
}
.dragZone {
background-color: rgb(200, 250, 200);
width: 3cm; height: 3cm;
border-style: solid;
border-width: 2px;
}
#source {
background-color: rgb(200, 200, 250);
left: 17cm; top: 2cm;
}
</style></head>
<body>
<div class="dragZone" id="source" draggable=true>drag me</div>
<div class="fullsize" id="target_area">target</div>
</body>
<script>
(function() {
const target_area = document.getElementById("target_area");
target_area.addEventListener("drop", (event) => {
const relpos = JSON.parse(event.dataTransfer.getData("relpos") || "null");
if (!relpos) return;
const new_element = document.createElement("div");
new_element.setAttribute("class", "dragZone");
new_element.draggable = true;
new_element.style.left = `${event.offsetX - relpos[0]}px`;
new_element.style.top = `${event.offsetY - relpos[1]}px`;
new_element.innerHTML = "drag&drop or move me";
var isDown = false;
new_element.addEventListener('mousedown', (e) => {
console.log(`mouse down ${e}`);
isDown = true;
e.srcElement.draggable=false;
}, true);
new_element.addEventListener('mouseup', (e) => {
console.log(`mouse up ${e}`);
isDown = false;
e.srcElement.draggable=true;
}, true);
new_element.addEventListener('mousemove', (e) => {
e.preventDefault();
if (!isDown) return;
const elem = e.srcElement;
const rect = elem.getBoundingClientRect();
elem.style.left = `${rect.x + e.movementX}px`;
elem.style.top = `${rect.y + e.movementY}px`;
}, true);
target_area.appendChild(new_element);
});
target_area.addEventListener("dragover", (event) => {
event.preventDefault();
});
document.getElementById("source").addEventListener("dragstart", (event) => {
event.stopPropagation();
event.dataTransfer.setData("relpos", JSON.stringify([event.offsetX, event.offsetY]));
});
})();
</script>
</html>
Found it - instead implementing your own movement based on mouse events and fiddling with the drag/drop events you can just use the drag&drop mechanism for both.
To make it work you have to deactivate pointer-events for the dragged item to avoid unwanted dragenter/dragleave events for the parent and turn it back on again afterwards (it has to be activated by default to enable dragging in the first place).
draggable_element.addEventListener("dragstart", (e) => {
e.srcElement.style.pointerEvents = "none";
... // rest of code
});
elem.addEventListener("dragend", (e) => {
e.srcElement.style.pointerEvents = "auto";
... // rest of code
});
Here is a working example: https://jsfiddle.net/03a9s4ur/10/
Started using RxJs. Can't find a way around this problem. I have a draggable control:
startDrag = rx.Observable.fromEvent(myElem,'mousedown')
now, because the control is too small mousemove and mouseup events should be at document level (otherwise it won't stop dragging unless cursor exactly on the element)
endDrag = rx.Observable.fromEvent document,'mouseup'
position = startDrag.flatMap ->
rx.Observable.fromEvent document,'mousemove'
.map (x)-> x.clientX
.takeUntil endDrag
now how do I "catch" the right moment when is not being dragged anymore (mouseup).
you see the problem with subscribing to endDrag? It will fire every time clicked anywhere, and not just myElem
How do I check all 3 properties at once? It should take only those document.mouseups that happened exactly after startDrag and position
Upd: I mean the problem is not with moving the element. That part is easy - subscribe to position, change element's css.
My problem is - I need to detect the moment of mouseup and know the exact element that's been dragged (there are multiple elements on the page). How to do that I have no idea.
I have adapted the drag and drop example provided at the RxJS repo to behave as you need.
Notable changes:
mouseUp listens at document.
The targeted element is added to the return from select.
Drag movements are handled inside of map and map returns the element that was targeted in the mouseDown event.
Call last after takeUntil(mouseUp) so subscribe will only be reached when the drag process ends (once per drag).
Working example:
function main() {
var dragTarget = document.getElementById('dragTarget');
// Get the three major events
var mouseup = Rx.Observable.fromEvent(document, 'mouseup');
var mousemove = Rx.Observable.fromEvent(document, 'mousemove');
var mousedown = Rx.Observable.fromEvent(dragTarget, 'mousedown');
var mousedrag = mousedown.selectMany(function(md) {
// calculate offsets when mouse down
var startX = md.offsetX;
var startY = md.offsetY;
// Calculate delta with mousemove until mouseup
return mousemove.select(function(mm) {
if (mm.preventDefault) mm.preventDefault();
else event.returnValue = false;
return {
// Include the targeted element
elem: mm.target,
pos: {
left: mm.clientX - startX,
top: mm.clientY - startY
}
};
})
.map(function(data) {
// Update position
dragTarget.style.top = data.pos.top + 'px';
dragTarget.style.left = data.pos.left + 'px';
// Just return the element
return data.elem;
})
.takeUntil(mouseup)
.last();
});
// Here we receive the element when the drag is finished
subscription = mousedrag.subscribe(function(elem) {
alert('Drag ended on #' + elem.id);
});
}
main();
#dragTarget {
position: absolute;
width: 20px;
height: 20px;
background: #0f0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.7/rx.all.min.js"></script>
<div id="dragTarget"></div>
I'm working with Google Maps API V3, and I'd like to display a clickable image near to a drawed polygon when the mouse hovers it.
Until now, I'm able to create this event, but I have no idea how to display this image near to my polygon. Ideally, I'd like this image appears where the mouse entered in the polygon.
Here is a piece of my code, but it's just a try and the image is not displayed, so it is very incomplete (and maybe wrong). You can suggest me to do otherwise, Javascript is not my preferred language...
google.maps.event.addListener(polygon, 'mouseover', function(e) {
this.setOptions( {fillOpacity: 0.1} );
polygon["btnMyButtonClickHandler"] = {};
polygon["btnMyButtonImageUrl"] = MyImage;
displayMyButton(polygon);
});
function displayMyButton(polygon) {
var path = polygon.getPath();
var myButton = getMyButton(path.btnMyButtonImageUrl);
if(myButton.length === 0)
{
console.log("IN"); //Is displayed in the console
var myImg= $("img[src$='http://linkToMyImage.png']");
myImg.parent().css('height', '21px !important');
myImg.parent().parent().append('<div style="overflow-x: hidden; overflow-y: hidden; position: absolute; width: 30px; height: 27px;top:21px;"><img src="' + path.btnMyButtonImageUrl+ '" class="myButtonClass" style="height:auto; width:auto; position: absolute; left:0;"/></div>');
// now get that button back again!
myButton = getMyButton(path.btnMyButtonImageUrl);
myButton.hover(function() {
$(this).css('left', '-30px'); return false; },
function() { $(this).css('left', '0px'); return false; });
myButton.mousedown(function() { $(this).css('left', '-60px'); return false;});
}
// if we've already attached a handler, remove it
if(path.btnDeleteClickHandler)
myButton.unbind('click', path.btnMyButtonClickHandler);
myButton.click(path.btnMyButtonClickHandler);
}
function getMyButton(imageUrl) {
return $("img[src$='" + imageUrl + "']");
}
Thanks for your suggestions !
EDIT
#MrUpsidown, unfortunately no, click event can't be a solution, I really need your Something here div appears at mouseover.
I modified your code like this :
google.maps.event.addListener(polygonPath, 'mouseover', function (event) {
if( $("#map_overlay").css('display') == "none")
{
$("#map_overlay").css({
'position': 'absolute',
'display': 'block',
'left': event.Sa.pageX,
'top': event.Sa.pageY
});
}
});
The div appears when my mouse enter the polygon and don't move except if my mouse hovers the div (which hovers the polygon). On this case, the event seems called continuously. How can we avoid this and let the div at its inital position once the mouse enter the polygon ?
Here is your modified : fiddle
You need to create an element to hold your clickable image. Make it position:absolute; with a bigger z-index than your map container. To place it at a specific place, check the mouse position on your polygon mouseover event and set the element position accordingly. Hope this helps.
Edit: Yes, wrap it in a DIV is a good idea. Here is a simple fiddle to show the concepts. And sorry, of course it was mouseover and not mouseenter like I first wrote.
http://jsfiddle.net/upsidown/zrC2D/
Updated ( Fixed ) Fiddle Here
Uncaught RangeError: Maximum call stack size exceeded
It's a simple customized Title that displays when mousing over elements. It breaks after several displays.
function showtitle(title) {
$('.button').bind('mousemove', function(e){
$('.message').fadeIn(600);
var message = $('.message').css({
'position' : 'absolute',
'left' : e.pageX,
'top' : e.pageY + 25
});
var print = title;
$('.message').html('<span>' + print + '</span>');
});
}
function hidetitle() {
$('.message').hide();
}
You’re rebinding the mousemove event every time the mouse moves over the element, but never taking it off.
function moveHandler(e) {
$('.message').fadeIn(600);
var message = $('.message').css({
position: 'absolute',
left: e.pageX,
top: e.pageY + 25
});
$('.message').empty().append($('<span>', {text: title}));
}
function showtitle(title) {
$('.button').bind('mousemove', moveHandler);
}
function hidetitle() {
$('.message').hide();
$('.button').unbind('mousemove', moveHandler);
}
You could also keep the mousemove event on all the time and use CSS’s :hover to show and hide the tooltip.
I’m guessing this isn’t because of the browser’s event loop, but rather because of either jQuery’s handling of events or jQuery’s queuing of animations. You should also fade in the appropriate message once, in showtitle, and set its text at the same time; not every time the mouse moves.
It may be because you are binding mousemove to an anonymous function. Every time that event fires the function is being created again. Try defining the function before binding it to the event.
I've put together a small script (JavaScript - jQuery) for testing an image resize operation that is dependent on the mousemove event. In short, the idea is to click on the image once and then drag the cursor around. The image resizes at every mouse move, its bottom-right corner "following" your cursor around.
The problem I've encountered is this: right after you start moving the cursor around, the resize works a bit jerky. After 1-2 seconds, it runs very smoothly. The same situation occurs if you stop moving the cursor around for a bit and then move it again.
This issue appears to happen only in Google Chrome, so my first thought is that it has something to do with this browser's anti-aliasing feature. But I'm not an expert.
The image is quite big (width&height - wise, not "KB"-wise)
You can test this "mini-app" here: http://picselbocs.com/projects/helsinki-map-application/test.php
And bellow is the code:
<img src="Helsinki.jpg" id="map" style="width: 526px; height:300px; position: absolute; top:0; left:0" />
<script>
var drag = false;
(function(){
$('#map').on('click',function(){
drag = true;
});
$(document).on('mousemove',function(e){
if (drag)
$('#map').css({ 'height': e.pageY, 'width': e.pageX });
});
})();
</script>
If anyone can provide a solution to this problem I would greatly appreciate it.
http://asp-net-by-parijat.blogspot.in/2014/09/aspnet-image-magnifying-effect-with.html
!function ($) {
"use strict";
var Magnify = function (element, options) {
this.init('magnify', element, options)
}
Magnify.prototype = {
constructor: Magnify
, init: function (type, element, options) {
var event = 'mousemove'
, eventOut = 'mouseleave';
this.type = type
this.$element = $(element)
this.options = this.getOptions(options)
this.nativeWidth = 0
this.nativeHeight = 0
if(!this.$element.parent().hasClass('magnify')) {
this.$element.wrap('<div class="magnify" \>');
this.$element.parent('.magnify').append('<div class="magnify-large" \>');
}
this.$element.siblings(".magnify-large").css("background","url('" + this.$element.attr("src") + "') no-repeat");
this.$element.parent('.magnify').on(event + '.' + this.type, $.proxy(this.check, this));
this.$element.parent('.magnify').on(eventOut + '.' + this.type, $.proxy(this.check, this));
}