jQuery 3 - Using Events
Written by Ian Elliot   
Monday, 01 May 2017
Article Index
jQuery 3 - Using Events
Drag and Drop and Keyboard Events
Form, Browser and Document Events
Immediate Events

Drag and Drop

One of the standard compound gestures you will encounter on the desktop UI is drag and drop. This is far less commonly used in a web page and hardly used on mobiles. For this reason you might want to avoid its use. 

It is a compound gesture because it involves a sequence of events. First we have a mousedown event on the object to be dragged. After this the mousemove is used to track where the object is being dragged to and the object is dropped at that location when a mouseup event occurs. 

The only difficult thing about drag and drop is deciding how to implement it. You can use basic HTML and JavaScript to implement it; you can use jQuery UI, which has a browser independent implementation; or you can use the HTML 5 drag and drop facilities. 

It is interesting to see how drag and drop is implemented in the most basic way. Let's drag and drop a button:

 <button id="button1"> drag me</button>

First we have to make sure that the button's positioning is set to absolute and we need two variables to record if a drag is in progress and which element is being dragged:

var drag = false;
var target;
$("#button1").css("position", "absolute");

When the mouse button goes down on an element all we have to do is remember the target and set drag to true:

$(document).mousedown(function (event) {
 drag = true;
 target = $(event.target);
});

Notice that we save the target as a jQuery object.

The mousemove event handler simply has to update the target's position, but only if drag is true:

$(document).mousemove(function (event) {
 if (drag) {
   target.css("top", event.pageY)
             .css("left", event.pageX);
 }
});

You can modify the mousemove to move a graphic, a bounding rectangle say, that will stand in for a complex element that is too slow to redraw at each move. 

The drop action is implemented as a mouseup event and in this case all it has to do is set drag to false and set the final position of the object:

$(document).mouseup(function (event) {
 if (drag) {
   drag = false;
   target.css("top", event.pageY)
             .css("left", event.pageX);
 }
});

You also need to check that a drag is in progress as there is no point in doing anything unless it is. The drop routine is usually more complicated because of the need to do different things depending on what the drop target is. For example if the button was dropped on a trashcan icon then you might remove it from the DOM. 

If you want some browser independence and more sophistication then you can use the jQuery UI draggable and droppable widgets. Using these is easy, but there are a lot of option and methods not to mention css stylings you can make use of. The simplest example is just to drag a button.

First we need to load jQuery and the latest version of jQuery UI:

<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/
                           smoothness/jquery-ui.css">
<script
  src="https://code.jquery.com/jquery-3.1.1.js"
  integrity=
  "sha256-16cdPddA6VdVInumRGo6IbivbERE8p7CQR3HzTBuELA="
   crossorigin="anonymous">
</script>
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

Assuming we have the same button defined in HTML we can make it draggable using:

$("#button1").draggable({ cancel:false });

After this the user can drag the button and drop it anywhere on the page. The option cancel:false isn't usually needed, but it is for a button because the click event occurs before the drag can begin. 

You can also make any object the target of a drop using the droppable widget. In this case using it is slightly more difficult in that you have to provide at least an event handler for the drop event. For example, if you add another element to the page with id dropTarget then you can handle a drop onto it using:

$( "#dropTarget" ).droppable({
     drop: function() {
     alert( "dropped" );
  }

Now when the button is dropped on it you will see the alert box.

There are lots of options and methods that help you control and customize the drag and drop in jQuery UI but this is the basic mechanism.

Finally we have HTML5 drag and drop. Making something draggable is just a matter of setting the draggable attribute to true:

$("#button1").prop("draggable", "true");

After this the button will be draggable but when the user drops it the result is that it returns to its original position. To make something happen you have to handle the drop event and often one or more of:

  • dragstart
  • drag
  • dragenter
  • dragleave
  • dragover
  • dragend

Not every type of element can be made the target of a drop. For example, to handle the drop of the button onto the document surface we would need to define the drop event and override the dragover and dragenter events to stop the default behaviour:

$(document).on("drop",function(event){
   event.preventDefault();
   alert("drop");
}).on("dragover",function(event){
   event.preventDefault();
}).on("dragenter", function (event) {    
   event.preventDefault();
});;

With these functions defined you can drag and drop the button and produce the alert. 

If you want to actually move the button to its new location then you have to use some complicated techniques. The idea is that with every drag and drop there is some data that is being transferred and this is done using the dataTransfer object. This has set and get methods that allow you to store and retrieve MIME formatted data. For example, to pass the id of the object being dragged you would use:

event.originalEvent.dataTransfer
      .setData("text/plain", event.target.id);

You can arrange for a range of different data types to be dragged and when the drop event occurs the data can be retrieved using getData.

A complete drag and drop event handler set is:

$("#button1").css("position", "absolute");
$("#button1").prop("draggable", "true");

$(document)
  .on("dragstart", function (event) {
      event.originalEvent.dataTransfer
        .setData("text/plain", event.target.id);
     })
 .on("drop", function (event) {
      event.preventDefault();
      var id = event.originalEvent.dataTransfer
         .getData("text");
      $("#" + id).css("top", event.pageY)
        .css("left", event.pageX);
     })
 .on("dragover", function (event) {
      event.preventDefault();
     })
 .on("dragenter", function (event) {
      event.preventDefault();
     });

 

If you try this out then you will be able to drag the button to a new location and drop it there.

In general HTML5 drag and drop is much more designed to allow you to drag data from one element to another.  There are lots of other facilities including the ability to specify a drag icon and customize the behavior in other ways.

So which should you use?

If you already use jQuery UI then using its draggable and droppable widgets is probably the best way to go. Without jQuery UI then it might seem that the best solution is to use HTML5, however there are many differences in the way that browsers have implemented the standard. As time goes on things are getting better, but there is still a place for the direct JavaScript approach to drag and drop using mousedown, mousemove and mouseup.   

Keyboard Events

There are three keyboard events:

  • keypress
  • keydown
  • keyup

We need to look first at keypress.

keypress

keypress is fired when a single key press has been completed and there is a character ready to be processed. Keys that do not create an input character such as Shift do not fire the keypress event. Only the element that has the current focus will receive keypress events. If you want to handle all of the keyboard input on a page attach the event handler to document.

For example:

$(document).keypress(
 function(event){
       console.log(event.which);
 });

The code that which is set to is a character code that corresponds to the character the key produces. That is the code that you get from a particular key depends on how the operating system has configured the keyboard i.e. it depends on the language the keyboard supports. The which property is set to a 16 bit value that corresponds to the UTF-16 code for a character in Plane 0 the Basic Multilingual Plane (BMP). This corresponds to the 65,536 characters that you can type on a keyboard by selecting an appropriate language. 

There are a few lists of symbols in the BMP but the Unicode list is presumably authoritative http://unicode.org/roadmaps/bmp/.

If you would like to convert the UTF-16 code to a string all you need is fromCharCode:

$(document).keypress(function(event){
          console.log(event.which);
          console.log(String.fromCharCode(event.which));
 });

To see this in action try installing a some different country keyboard and try typing the same key with each on selected. In many cases the keycode and character displayed will be different. See Chapter 13 for more information on Unicode and encodings.

keydown and keyup

The most important thing to realize is that keydown and keyup are different from keypress. These two events work with the keys and not the character that the key produces. The keydown event is fired when the user presses any key down including the non-printing or silent keys such as shift and the cursor keys. The keyup even is fired when a key is released. If the operating system auto repeats the key then the keydown and keyup event are fired for each repeat. 

The which property of the even object returns the key code of the key involved in the event. This doesn't change no matter what symbol the key actually produces. The key codes assigned to the keys corresponding to printable characters are generally the UTF-16 code for the character. For example, the A key on the standard PC keyboard returns keycode 65 which is the UTF-16 (and ASCII) code for "A". However this is the code that is returned if you press the shift key at the same time or not or if you configure the keyboard to return some other character.

$(document).keydown(function(event){
 console.log(event.which);  console.log(String.fromCharCode(event.which));
});

There are lists of key codes and most are standard but you need to realize the the range of keys available depends on the device the keyboard is designed to work with. You really should only make use of the most common keys. 

Typically keydown and keyup are used to provide instant input to games. For example the arrow or cursor keys can be used to "steer" a sprite: in this case up is 38, right is 39, left is 37 and down is 40.

 



Last Updated ( Thursday, 05 May 2022 )