Drag-n-drop version of HGM's chess variant

Discussion of anything and everything relating to chess playing software and machines.

Moderators: hgm, Rebel, chrisw

User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Drag-n-drop version of HGM's chess variant

Post by maksimKorzh »

Mr. Muller

I've made the implementation of drag-n-drop for your chess variant we were discussing in this thread:
http://talkchess.com/forum3/viewtopic.php?f=2&t=75963

Live demo:
https://maksimkorzh.github.io/chessboard/hgm/hgm.html

Video tutorial (really doubt you'll be interested, it's more likely for my subscribers):


Source code:
https://github.com/maksimKorzh/chessboa ... gm/game.js

All I done is altered 2 lines of code:
1. Commented line 494
2. Changed line 495 to:

Code: Select all

document.getElementById(cell).innerHTML = '<img ondragstart="event.target.style.opacity=0.0;" ' + image.replace('url(', 'src=').replace(')', '>');
On drag start I make piece transparent on source square and convert your image string from "url(...)" to src="..."

I didn't face cell resizing issues you've pointed out, please let me know how I can reproduce them on my side.
Does it now work exactly the way you intended it to work?

P.S. Months of work with your MicroMax code let me orient in your code instantly) I've learnt so much from you!
User avatar
hgm
Posts: 27787
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Drag-n-drop version of HGM's chess variant

Post by hgm »

It doesn't quite work for me (FireFox on Windows 7). The piece on the from-square indeed disappears as soon as I start dragging. But the mouse cursor doesn't change into the piece. It stays an arrow, but with a small greyish rectangle at the bottom right. (Which is apparently supposed to indicate that I am now dragging an image.)

Strange thing is that when I drag other images (like the forum avatars) a semi-transparent copy of them actually does move with the cursor, with a small black circle and a diagonal line through it printed on top of them (probably indicating that I cannot drop them in that place). I am not sure why the behavior is different. Perhaps the diagram does some preventDefault stuff.
User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Re: Drag-n-drop version of HGM's chess variant

Post by maksimKorzh »

hgm wrote: Thu Dec 03, 2020 8:55 pm It doesn't quite work for me (FireFox on Windows 7). The piece on the from-square indeed disappears as soon as I start dragging. But the mouse cursor doesn't change into the piece. It stays an arrow, but with a small greyish rectangle at the bottom right. (Which is apparently supposed to indicate that I am now dragging an image.)

Strange thing is that when I drag other images (like the forum avatars) a semi-transparent copy of them actually does move with the cursor, with a small black circle and a diagonal line through it printed on top of them (probably indicating that I cannot drop them in that place). I am not sure why the behavior is different. Perhaps the diagram does some preventDefault stuff.
I see... Well, this is weird - I just never tested my code in other browser but Chrome.
It works in chrome. But my library doesn't seem to work in firefox at all - firefox opens piece image in tab on drop believe it or not!
Did you actually see my library working properly in your firefox or you watched the example in video?

I need to figure out why the technique that works in chrome doesn't work in firefox.
I will let you know if find the solution.
User avatar
hgm
Posts: 27787
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Drag-n-drop version of HGM's chess variant

Post by hgm »

You are right, on Chrome it works. I also see the same small gey rectangle at the bottom right of the cursor arrow, like I see in FireFox. It seems like FireFox also applies the opacity=0 to the image it drags.

I hate those differences between browsers... :evil:
User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Re: Drag-n-drop version of HGM's chess variant

Post by maksimKorzh »

hgm wrote: Thu Dec 03, 2020 9:28 pm You are right, on Chrome it works. I also see the same small gey rectangle at the bottom right of the cursor arrow, like I see in FireFox. It seems like FireFox also applies the opacity=0 to the image it drags.

I hate those differences between browsers... :evil:
Oh.. so do I...
But I swear it's possible, see this example:
https://www.w3schools.com/HTML/html5_draganddrop.asp
It works in firefox nicely.
I've partially fixed my library and drawing the image should work as well.
Just gimme some time - I'll research it deeper and hopefully find a solution.
This is a very standard stuff, it SHOULD work.

I'll get back to you when fins solution.
User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Re: Drag-n-drop version of HGM's chess variant

Post by maksimKorzh »

hgm wrote: Thu Dec 03, 2020 9:28 pm You are right, on Chrome it works. I also see the same small gey rectangle at the bottom right of the cursor arrow, like I see in FireFox. It seems like FireFox also applies the opacity=0 to the image it drags.

I hate those differences between browsers... :evil:
Setting opacity to 0.5 draws the dragged piece but also piece remains on source square half transparent (((
So in Chrome dragged piece is temp element created by browser automatically while in firefox image's style used during drag-n-drop.
I just need to find a unified solution.
User avatar
hgm
Posts: 27787
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Drag-n-drop version of HGM's chess variant

Post by hgm »

I found this description of a fairly simple program that moves an image with the cursor.

If I understand it correctly I could keep a dummy image in the <div> that contains the diagram (e.g. just above the <table> that is the board), and dynamically change its location to follow the mouse pointer, so that it overlaps other stuff in the same <div>. The mousedown on the from-square could change the src of that image to the piece in the square, and make the image fully transparent when it is no longer needed.
User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Re: Drag-n-drop version of HGM's chess variant

Post by maksimKorzh »

hgm wrote: Thu Dec 03, 2020 10:08 pm I found this description of a fairly simple program that moves an image with the cursor.

If I understand it correctly I could keep a dummy image in the <div> that contains the diagram (e.g. just above the <table> that is the board), and dynamically change its location to follow the mouse pointer, so that it overlaps other stuff in the same <div>. The mousedown on the from-square could change the src of that image to the piece in the square, and make the image fully transparent when it is no longer needed.
Here's what I've managed to do eventually:
https://maksimkorzh.github.io/chessboard/hgm/hgm.html

Source update:

Code: Select all

var source_cell;

function image_dragover(event) {
  if (source_cell == event.target.parentElement.id)
    event.target.src = 'empty.png';
}

function image_dragstart(event) {
  event.target.style.opacity=1.0;
  source_cell = event.target.parentElement.id
}
All it does - replaces image at source square by transparent png if dragged piece is within source cell.
Works for me in both chrome and firefox.
Limitation: if drag piece too fast it doesn't get erased, but if after overlap it again by dragged piece it will disappear.
The reason why this is happening is simple - ondragenter event does not fire on time.
If drag-n-drop not very fast it works fine because ondragenter event has enough time to fire.
Weird image in bottom right of cursor doesn't show anymore, well at least on my side.

I've also fixed firefox bugs in my library.
User avatar
hgm
Posts: 27787
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Drag-n-drop version of HGM's chess variant

Post by hgm »

So it seems that you can (both in FireFox and Chrome) replace or change the properties of the image during dragover without affecting what is dragged, but that you cannot do that during dragstart. I suppose this is because the user dragstart handler is executed before the default handler. (Otherwise preventDefault could not work in the user handler.) Another work-around for this could be to set a timeout with 0 delay in the dragstart handler for removing the image, instead of relying on dragover to do that.

Another problem with the current implementation is that it uses the pieces as foreground image. As I mentioned, this caused the row expansion/contraction, at least on FireFox). In the Interactive Diagram we tested on this is probably not visible, because it already used an unnecessary large square size of 36x36 for the 33x33 images.

But there also is a second reason why this is problematic: in addition to highlighting the piece moves through a background color, the Diagram also has a mode where it uses marker symbols (dots, squares, triangles or stars) to indicate the various types of move. These symbols are then used as foreground image (i.e. cell content), displayed on top of the pieces (e.g. when indicating a possible capture). This mode is necessary to make the Diagram work on monochrome devices (like e-readers), where one cannot distinguish the colors. Below I posted a Diagram where I switched that on. (On monochrome devices it would get enabled by default.)

The problem is that it is the foreground image that will be dragged. But I suppose it must be possible to have the dragstart handler copy the backgroundImage URL of the clicked square, wrap it in an <img> tag and put it in the cell, and that this would still be in time for the browser default action to grab that image and start dragging it. The dragover (or timeout) handler could then remove the image again (possibly even put back the old cell content, if there was any).
theme=MV firstRank=1 useMarkers=1
squareSize=33
promoChoice=CL
Pawn::::a2-h2,,a7,h7
Lance::C::a1,h1,,a8,h8
Cannon::mRcpR:Canon:c1,f1,,c8,f8
Lion:N::::1,1
King::::e1,,e8
User avatar
hgm
Posts: 27787
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Drag-n-drop version of HGM's chess variant

Post by hgm »

I think I have something now that works purely with background images, and doesn't rely on browser default behavior for dragging. It works by explicitly setting the style.cursor attribute of the board <table> element to the dragged piece, by copying the cell's back-ground image there (plus some coordinates for shifting the center of the image to the pointer location, rather than the upper-left corner), and then deleting that background.

The tricky thing is to undo that when the drag ends. Problem is that not every mousedown can be a drag start. (And I cannot use ondragstart, because when the pieces are background, there is nothing in the cells to drag. So it must happen on mousedown.) In click-click moving some clicks are 'to-clicks'. And this cannot be determined in advance, because the Diagram supports re-selection: if you have selected a piece, but then click another piece that is not a highlighted destination, it assumes that you want to move (and thus drag) that piece instead. So a 'from-click' is not guaranteed to be followed by a 'to-click', it can be a new 'from-click' as well.

And if every click prepares dragging, you would have to undo it on the mouseup of a to-click as well. That is OK for the cursor (which can always be the default if no button is pressed), but when you put back the piece you deleted, it would overwrite the piece that moved there in case of a to-click. I solved that by testing at the end of the mousdown handler whether the click left a piece selected; clicks that finish a move wouldn't do that, and handling the move would in that case have put the correct piece in that square. In other cases undoing the drag start is left to the mouseup handler, when in occurs on the same square as the mousedown.

I have the following code now (working in the diagram above):

Code: Select all

var downX;
var downY;
var noMouse = 0;
var down = 0;
var drag, draggedPiece;

function Down(bnr, x, y, ev) {
  if(noMouse) return;
  SwitchDiag(bnr);
  if(ev.button == 2) {
    ev.preventDefault();
    RightClick(x, y);
    return;
  }
  downX = x; downY = y; down = 1;
  var off = sqrSize >> 1;
  drag = document.getElementById(bnr + 'y' + y + 'y' + x);
  draggedPiece = drag.style.backgroundImage;
  curCell = "";
  Click(x, y);
  if(xx < 0) drag = null; else { // attach piece to cursor if this click didn't finish move
    document.getElementById('board' + bnr).style.cursor = draggedPiece + ' ' + off + ' ' + off +', auto';
    drag.style.backgroundImage = '';
  }
}

function Up(bnr, x, y) { // catches up-click on empty square
  if(noMouse) return;
  SwitchDiag(bnr);
  if(drag) {
    document.getElementById('board' + bnr).style.cursor = 'default';
    if(down && x == downX && y == downY) drag.style.backgroundImage = draggedPiece;
    drag = null;
  }
  if(x == downX && y == downY) return; // ignore up on static click
  Click(x, y); // on other square up counts as new click event
}
It is still a bit troublesome on promotions, where the to-click does not finish the move, but where you have to select the promotion piece from the table first.