Can I capture the mouse pointer in a Figma plugin window? - javascript

I have some code that I've used to create controls for a long time, and it works well, in that it properly captures and releases the mouse (at least in chrome).
function createSlider(slider, width, height)
{
slider.width = width;
slider.height = height;
slider.style.display = 'inline';
//
slider.onchange = new Event('onchange');
//
slider.addEventListener('mousedown', function(e)
{
var e = window.event || e;
if (e.button == 0)
{
e.preventDefault();
if (slider.setCapture)
slider.setCapture();
slider.mouseDown0 = true;
slider.sx = e.clientX;
slider.sv = slider.value;
}
});
slider.addEventListener('losecapture', function()
{
slider.mouseDown0 = false;
});
document.addEventListener('mouseup', function(e)
{
var e = window.event || e;
if (e.button == 0 && slider.mouseDown0)
slider.mouseDown0 = false;
}, true);
(slider.setCapture ? slider : document).addEventListener('mousemove', function(e)
{
if (slider.mouseDown0)
{
var dx = slider.sx - e.clientX;
var adaptive = 10 * Math.pow(Math.abs(dx), slider.acc);
slider.value = Math.min(Math.max(slider.min, slider.sv - dx*slider.scale*adaptive), slider.max);
//TODO: if (log) do log scaling
slider.paint();
slider.dispatchEvent(slider.onchange);
}
}, true);
slider.onmousewheel = function(e)
{
e.preventDefault();
var s = e.target;
s.value = Math.min(Math.max(s.min, s.value + (e.wheelDeltaY > 0 ? 1 : -1) * s.scale), s.max);
s.dispatchEvent(s.onchange);
s.paint();
};
slider.paint = function()
{
//...
};
//
slider.paint();
}
But when I tried using this code inside of a Figma plugin window, it loses mouse capture as soon as the mouse leaves the window. Is there something that I need to adjust for this to work?

Apparently you cannot, but you can use pointer lock to solve the issue for some situations.

Related

Dragenter, dragover and dragend not firing in safari

i'm trying to do a drag and drop card game (solitaire). It works in all browsers and mobile devices. But the drag events are not firing in safari desktop only (only the dragstart,mousedown and mouse up work). I tried adding the e.preventDefault() in the dragenter but it doesn't work. I put a console log in the beginning of every drag event but only the dragstart message show.
Do you have any suggestions please?
enter image description here
This is the code for each event:
var dragIcon = doc.createElement('img');
Game.prototype.dragstart = function(e) {
console.log('start dragstart')
e.dataTransfer.effectAllowed = 'copy';
e.dataTransfer.setData('text/html', '');
// Create blank image to hide the ghost
e.dataTransfer.setDragImage(dragIcon, -10, -10);
this.dragging = true;
console.log('end dragstart')
};
Game.prototype.dragenter = function(e) {
console.log('drag enter')
var t = e.target;
var column = t.classList.contains("column");
var stack = t.classList.contains("stack");
var canDrop = t.card || column || stack;
if ( this.activeColumn ) {
this.activeColumn.classList.remove("over");
}
if ( canDrop ) {
if ( column || stack ) {
this.activeColumn = t;
} else {
this.activeColumn = t.parentNode;
}
this.activeColumn.classList.add("over");
}
console.log('end dragenter')
}
Game.prototype.dragover = function(e) {
e.preventDefault();
e.dataTransfer.dropEffect = 'over';
// Physically drag the card instead of using the D&D ghost
if ( this.activeCard && this.dragging ) {
var c = this.activeCard;
var x = e.pageX - c.origin.x;
var y = e.pageY - c.origin.y;
var css = "pointer-events: none; transform: scale(1.05, 1.05) rotateX(0deg) translate3d("+x+"px, "+y+"px, 0px);";
this.activeCard.el.style.cssText = css;
}
console.log('end dragover')
}
Game.prototype.dragend = function(e) {
if ( this.activeCard && this.dragging ) {
var c = this.activeCard;
c.el.classList.remove("dragging");
var x = e.pageX - c.origin.x;
var y = e.pageY - c.origin.y;
c.el.style.cssText = "";
if ( this.activeColumn ) {
this.activeColumn.classList.remove("over");
}
if ( this.isLegalMove() ) {
var prev = c.el.previousElementSibling;
// Flip the last card
if ( prev ) {
var card = this.pack.cards[prev.idx];
if ( !card.flipped ) {
card.prevState = card.flipped;
card.flip();
this.score += 5;
}
}
this.stackToColumn = c.el.parentNode.classList.contains("stack");
this.pickCount = c.el.parentNode.childElementCount;
this.dropCount = this.activeColumn.childElementCount;
this.activeColumn.appendChild(c.el);
this.startParent.classList.toggle("empty", !this.startParent.childElementCount);
this.activeColumn.classList.toggle("empty", !this.activeColumn.childElementCount);
this.emit("change");
}
else(
this.move=this.move+1,
document.getElementById("moves1").innerHTML=this.move
)
}
console.log('end dragend')
}

"tap" for mobile adding to "keydown" event jquery

var gameLink = $("#theGame");
$(window).keydown(function (e) {
if (e.which === 32) {
window.location.href = "thegame.html;
}
});
I am very new to jQuery and I can't seem to figure out where to add the "tap" event for mobile to this code.
This is pretty much all you need: http://jsfiddle.net/gianlucaguarini/56Szw/
*code from fiddle
var getPointerEvent = function(event) {
return event.originalEvent.targetTouches ? event.originalEvent.targetTouches[0] : event;
};
var $touchArea = $('#touchArea'),
touchStarted = false, // detect if a touch event is sarted
currX = 0,
currY = 0,
cachedX = 0,
cachedY = 0;
//setting the events listeners
$touchArea.on('touchstart mousedown',function (e){
e.preventDefault();
var pointer = getPointerEvent(e);
// caching the current x
cachedX = currX = pointer.pageX;
// caching the current y
cachedY = currY = pointer.pageY;
// a touch event is detected
touchStarted = true;
$touchArea.text('Touchstarted');
// detecting if after 200ms the finger is still in the same position
setTimeout(function (){
if ((cachedX === currX) && !touchStarted && (cachedY === currY)) {
// Here you get the Tap event
$touchArea.text('Tap');
}
},200);
});
$touchArea.on('touchend mouseup touchcancel',function (e){
e.preventDefault();
// here we can consider finished the touch event
touchStarted = false;
$touchArea.text('Touchended');
});
$touchArea.on('touchmove mousemove',function (e){
e.preventDefault();
var pointer = getPointerEvent(e);
currX = pointer.pageX;
currY = pointer.pageY;
if(touchStarted) {
// here you are swiping
$touchArea.text('Swiping');
}
});

Dragging div selects text on page (some browsers)

Im using the following function to drag a div with a handle.
Problem is that in some browsers when i drag at the same time text is selected and highlighted on the page..
Any ideas how to fix it?
function enableDragging (ele) {
var dragging = dragging || false,
x, y, Ox, Oy,
current;
enableDragging.z = enableDragging.z || 1;
var grabber = document.getElementById("myHandle");
grabber.onmousedown = function (ev) {
ev = ev || window.event;
var target = ev.target || ev.srcElement;
current = target.parentElement;
dragging = true;
x = ev.clientX;
y = ev.clientY;
Ox = current.offsetLeft;
Oy = current.offsetTop;
current.style.zIndex = ++enableDragging.z;
console.log(dragging);
document.onmousemove = function(ev) {
ev = ev || window.event;
//pauseEvent(ev);
if (dragging == true) {
var Sx = ev.clientX - x + Ox,
Sy = ev.clientY - y + Oy;
current.style.top = Sy + "px";
current.style.left = Sx + "px";
document.body.focus();
// prevent text selection in IE
document.onselectstart = function () { return false; };
// prevent IE from trying to drag an image
ev.ondragstart = function() { return false; };
return false;
}
}
document.onmouseup = function(ev) {
//alert("stop");
dragging && (dragging = false);
}
};
}
function pauseEvent(e){
if(e.stopPropagation) e.stopPropagation();
if(e.preventDefault) e.preventDefault();
e.cancelBubble=true;
e.returnValue=false;
return false;
}
Drag is started by:
var ele = document.getElementById("divWrapper");
enableDragging(ele);
I'm sorry, I forget the second question in your previous post. However, you need to prevent default from onmouseup too:
document.onmouseup = function(ev) {
ev = ev || window.event;
dragging && (dragging = false);
if (ev.preventDefault) {
ev.preventDefault();
} else {
ev.cancelBubble=true;
ev.returnValue=false;
}
return false;
}
EDIT
Or simply use your pauseEvent() function. Notice, that in your code there's this: ev.ondragstart = function () {...};. It's no use to assign the eventhandler to the Event object, rather assign that to the document or document.body. And also use that pauseEvent() in every eventhandler function too.
It looks like it's better to move document.onselectstart and document.ondragstart to the onmousedown handler, since those events have already fired when execution moves to onmousemove().

Splitting HTML page into different sections using sliding panel dividers? How is it done?

I'm wanting to divide a web page up into different sections as shown here. I'm trying to figure it out what this technique is called and an efficient way to implement it?
The page is divided up into different sections giving the user the flexiblity to expand and contract the different sections using panel handles.
I'm assuming these aren't regular frames (which I'd like to avoid using anyways).
Does anybody know of a tutorial or good example out there besides the one on jsfiddle?
the idea is quite simple.
you break up the screen with some elements, it does not really matter which (say divs) with a given height.
then attach a onclick event to the handle that starts the drag. what the onclick does is attach a mousemove event to the body which will resize the elements.
here is something i wrote a while back (before my jquery days), i'm sure it could be written much better, and you might find a plugin for this, i don't know of one:
function WidenHandle(widenedELement, handleElement, ondblClick, startWidth, withCoverDiv, onDrop)
{
this.Handle = handleElement;
this.IsClosed = false;
this.Element = widenedELement;
this.LastX = 0;
this.LastY = 0;
this.AttachedDragFunction = null;
this.AttachedDropFunction = null;
this.StartWidth = startWidth ? startWidth : 300;
this.CoverDiv;
this.OnDrop = onDrop;
this.IsDragging = false;
if (withCoverDiv)
{
var coverDiv = document.createElement("div");
coverDiv.style.width = "2000px";
coverDiv.style.height = "2000px";
coverDiv.style.display = "none";
coverDiv.style.position = "fixed";
coverDiv.style.zIndex = "1000";
// coverDiv.style.backgroundColor = "red";
// coverDiv.style.opacity = "0.3";
coverDiv.style.top = '0px';
this.CoverDiv = coverDiv;
document.body.appendChild(coverDiv);
}
if (this.Handle.addEventListener)
{
this.Handle.addEventListener("mousedown", function(element)
{
return function(event)
{
element.StartDragging(event);
if (element.CoverDiv)
element.CoverDiv.style.display = "";
if (event.preventDefault)
event.preventDefault();
}
} (this), true);
this.Handle.addEventListener("dblclick", function(element)
{
return function(event)
{
element.Close(event);
if (element.CoverDiv)
element.CoverDiv.style.display = "none";
ondblClick(element);
}
} (this), true);
}
else
{
this.Handle.attachEvent("onmousedown", function(element)
{
return function(event)
{
element.StartDragging(event);
if (element.CoverDiv)
element.CoverDiv.style.display = "";
if (event.preventDefault)
event.preventDefault();
}
} (this));
this.Handle.attachEvent("ondblclick", function(element)
{
return function(event)
{
element.Close(event);
if (element.CoverDiv)
element.CoverDiv.style.display = "none";
ondblClick(element);
}
} (this), true);
}
}
WidenHandle.prototype.StartDragging = function(event)
{
this.IsDragging = true;
if (this.CoverDiv)
this.CoverDiv.style.display = "none";
this.ClearAttachedEvents();
this.LastX = this.GetX(event);
// ** attach mouse move and mouse up events to document ** //
this.AttachedDragFunction = function(element)
{
return function(event)
{
element.OnDragging(event);
}
} (this);
this.AttachedDropFunction = function(element)
{
return function(event)
{
element.OnDropping(event);
}
} (this);
if (window.attachEvent) // ie
{
document.attachEvent('onmousemove', this.AttachedDragFunction);
document.attachEvent('onmouseup', this.AttachedDropFunction);
}
else // ff
{
document.onmousemove = this.AttachedDragFunction;
document.onmouseup = this.AttachedDropFunction;
}
}
// ** for repositioning popup while dragging ** //
WidenHandle.prototype.OnDragging = function(event)
{
clearHtmlSelection();
this.WidenCell(event);
}
// ** for release popup movement when dropping ** //
WidenHandle.prototype.OnDropping = function(event)
{
this.IsDragging = false;
if (this.CoverDiv)
this.CoverDiv.style.display = "none";
this.ClearAttachedEvents();
if (this.OnDrop)
this.OnDrop();
}
WidenHandle.prototype.ClearAttachedEvents = function()
{
// ** detach events from document ** //
if (window.attachEvent) // ie
{
document.detachEvent('onmousemove', this.AttachedDragFunction);
document.detachEvent('onmouseup', this.AttachedDropFunction);
}
else // ff
{
document.onmousemove = null;
document.onmouseup = null;
}
}
WidenHandle.prototype.GetX = function(event)
{
// ** return x position of mouse ** //
var posx = 0;
if (!event) event = window.event;
if (event.pageX)
{
posx = event.pageX;
}
else if (event.clientX)
{
posx = event.clientX;
}
return posx;
}
WidenHandle.prototype.WidenCell = function(event)
{
if (!this.Element.style.width)
this.Element.style.width = this.Element.offsetWidth - 9 + "px";
var width = parseInt(this.Element.style.width) + (this.GetX(event) - this.LastX);
if (width > 13)
this.Element.style.width = width + "px";
// ** remember last mouse position ** //
this.LastX = this.GetX(event);
}
WidenHandle.prototype.Close = function(event)
{
var width = parseInt(this.Element.style.width);
if (width < 30)
{
this.IsClosed = false;
this.Element.style.width = "";
return;
// width = this.StartWidth;
}
else
{
width = 14;
this.IsClosed = true;
}
this.Element.style.width = width + "px";
}
function clearHtmlSelection()
{
var sel;
if (document.selection && document.selection.empty)
{
document.selection.empty();
}
else if (window.getSelection)
{
sel = window.getSelection();
if (sel && sel.removeAllRanges) sel.removeAllRanges();
}
}

Pushing mouse click location to an array in Javascript

I'm trying to push the coordinates of a mouse click on a particular element to the end of an array. This is what I have:
IN THE HEAD:
var seatsArray = [];
IN THE BODY:
var coordinates = document.getElementById("image");
coordinates.onclick = function(event) {
seatsArray.push(offsetX, offsetY);
}
document.write("Seats array contains: " + seatsArray + ".");
Probably something simple, but I'm new to javascript, so I'd appreciate any help as to why it isn't working!
Thanks
Two things I see, alter your on click event to this:
coordinates.onclick = function(event) {
event = event || window.event;
if (!window.event) { // thanks firefox
event.offsetX = event.layerX;
event.offsetY = event.layerY;
}
seatsArray.push(event.offsetX, event.offsetY);
}
Firefox offsetX/Y is layerX/Y, and ie have a global event object.
But if you wnt global cordinates try this:
coordinates.onclick = function(e) {
e = e || window.event;
if (e && e.pageX && e.pageY) {
e.posX = e.pageX;
e.posY = e.pageY;
} else if (e && e.clientX && e.clientY) {
var scr = {x:0,y:0},
object = e.srcElement || e.target;
//legendary get scrolled
for (;object.parentNode;object = object.parentNode) {
scr['x'] += object.scrollLeft;
scr['y'] += object.scrollTop;
}
e.posX = e.clientX + scr.x;
e.posY = e.clientY + scr.y;
}
seatsArray.push(e.posX, e.posY);
}

Categories

Resources