General issues and theory of Drag and Drop technology. Drag and Drop technology in Android See what “Drag-and-drop” is in other dictionaries

182

In this example, we select a div element and make it movable by calling the draggable() method on it. As shown in the figure below, in the opened document the element takes its usual position, but after that it can be moved using the mouse pointer to any place in the browser window:

The ability to drag and drop elements is useful on its own, but it's even more useful when used in conjunction with the Droppable interaction, which is described next.

Draggable interaction is achieved solely through the use of specific HTML markup and CSS styles. This means that this functionality will work in almost any browser, but the elements endowed with it will not be able to work with similar native drag-and-drop tools operating systems.

Drag-and-drop operations defined by the HTML5 specification are typically implemented using native operating system mechanisms. If you are using the jQuery UI Drag-and-drop mechanism, then it is better to disable the equivalent HTML5 features to avoid conflicts. To do this, set the draggable attribute of the body element of the document to false.

Setting up the Draggable interaction

There are many customization options for Draggable interactions. The most important properties, which are discussed in the following sections, are shown in the table below:

Draggable interaction properties Property Description
axis Limits the ability to move in certain directions. The default value is false, which means no constraint, but you can also specify a value of "x" (move along the X axis only) or "y" (move along the Y axis only)
containment Limits the location of the element being moved to a specific area of ​​the screen. The types of supported values ​​are described in the table below, using the corresponding example. The default value is false, which means no restrictions
delay Specifies how long an element must be dragged before it moves. The default value is 0, which means no delay
distance Defines the distance the user must drag an element from its starting position before it actually moves. Default value is 1 pixel
grid Forces the snapping of the moved element to the grid cells. The default value is false, which means no binding
Limiting movement directions

There are several ways you can restrict an element's movement to certain directions. The first is to use the axis option, which allows you to restrict the direction of movement to the X or Y axis. An example of this is shown below:

... div.dragElement (font-size: large; border: thin solid black; padding:16px; width: 8em; text-align: center; background-color: lightgray; margin: 4px ) $(function() ( $ (".dragElement").draggable(( axis: "x")).filter("#dragV").draggable("option", "axis", "y"); )); Drag vertically Drag horizontally Run example

In this example, we define two div elements, select them using jQuery, and call the draggable() method. As an argument to this method, we pass an object that initially restricts the movement of both div elements to the direction along the X axis. By then using the jQuery filter() method, we are able to select the dragV element without jQuery searching the entire document again and set it to a different allowed movement direction - along the Y axis. Thus, we get a document in which one div element can only be dragged in the vertical direction, and the other - only in the horizontal direction. The result is shown in the figure:

Limiting the allowable area of ​​element movement

You can also limit the area of ​​the screen where you can drag an item. To do this, use the containment option. The value formats that can be specified in this option are described in the table below:

An example of using the containment option is given below:

... div.dragElement (font-size: large; border: thin solid black; padding:16px; width: 8em; text-align: center; background-color: lightgray; margin: 4px ) #container ( border: medium double black; width: 700px; height: 450px) $(function() ( $(".dragElement").draggable(( containment: "parent" )).filter("#dragH").draggable("option", " axis", "x"); )); Drag horizontally Drag inside parent Run example

In this example, both elements are limited in their ability to move so that they can only be dragged within their parent element, which is a fixed-size div. One of the divs being floated has the additional constraint of being floated using the axis option in that it can only move horizontally within its parent. The result is illustrated in the figure:

Limiting the ability to move an element to grid cells

The grid option allows you to set the binding of the moved element to grid cells. This option takes as a value an array of two elements specifying the width and height of the grid cells in pixels. An example of using the grid option is given below:

... #draggable (font-size: x-large; border: thin solid black; width: 5em; text-align: center; padding:10px) $(function() ( $("#draggable").draggable( ( grid: )); )); Drag me Run example

This example specifies a grid with cells 100 pixels wide and 50 pixels high. When you drag an element, it "jumps" from one (invisible) cell to another. The snapping effect is a great example of how interaction functionality can be used, but it's difficult to convey using screenshots.

You can create a snap effect for only one direction by setting the free movement axis to 1. For example, if you set the grid option to , the element will snap to 100 pixel wide grid cells when moved horizontally, but will move freely vertically.

Move delay

There are two options that allow you to delay the dragging of a moving element. The delay option allows you to specify the amount of time, in milliseconds, that the user must drag the mouse pointer before the element is actually moved. Another kind of delay is provided by the distance option, which specifies the distance in pixels that the user must drag the mouse pointer before it is followed by an element.

An example of using both settings is given below:

... #time, #distance (font-size: large; border: thin solid black; padding: 10px; width: 120px; text-align: center; background-color: lightgray; margin: 4px; ) $(function( ) ( $("#time").draggable(( delay: 1000 )) $("#distance").draggable(( distance: 150 )) )); Block with time delay Block with minimum distance Run example

In this example there are two moveable elements, one of which is delayed using the delay option, and the other is delayed using the distance option.

In the case of a delay, specified by the delay option, the user must drag for a specified amount of time before it actually moves the element. In this example, the duration of this period is 1000 ms. It is not necessary to move the mouse at this time, but throughout the entire delay period the mouse button must remain pressed, after which the element can be moved by moving the mouse. After the delay time has elapsed, the element being moved will snap to the mouse pointer location, subject to the constraints imposed by the grid, region, and axis options discussed earlier.

The distance option has a similar effect, but in this case the user must drag the mouse pointer at least a specified number of pixels in any direction from the element's starting location. The element being moved will then jump to the current pointer location.

If you apply both settings to the same element, the moved element will not move until both delay criteria are met, i.e. until an attempt to drag an element lasts for a specified amount of time and until the mouse pointer moves a specified number of pixels.

Using Draggable interaction methods

All of the methods defined for Draggable interaction are part of the set of base methods you've already seen when looking at widgets. There are no methods specific to Draggable interaction, so we won't cover them in detail. The list of available methods is given in the table below:

Using Draggable Interaction Events

Interaction Draggable supports a simple set of events that notify you when an element is dragged. These events are described in the table below:

As with widget events, these events can also be responded to. An example of handling the start and stop events is given below:

... #draggable (font-size: x-large; border: thin solid black; width: 190px; text-align: center; padding:10px) $(function() ( $("#draggable").draggable( ( start: function() ( $("#draggable").text("Drag me..."), stop: function() ( $("#draggable").text("Drag me") ) )) ; )); Drag me Run example

This example uses the start and stop events to change the text content of an element as it is dragged. This advantage is due to the fact that Draggable's interaction is implemented entirely using HTML and CSS: you can use jQuery to change the state of a draggable element even as it moves across the screen.

Using Droppable Interaction

Dragging an element alone may be sufficient in some situations, but it is most useful when used in conjunction with the Droppable interaction.

Elements to which the Droppable interaction has been applied (receiving elements) gain the ability to accept movable elements created using the Draggable interaction.

Receiving elements are created using the droppable() method, but to get useful functionality you will need to create event handlers from among those defined for this type of interaction. Available events are shown in the table below:

Droppable interaction events Event Description
create Occurs when a Droppable interaction is applied to an element
activate Occurs when the user begins to drag the element being moved
deactivate Occurs when the user stops dragging the element being moved
over Occurs when the user drags a floatable element over a receiving element (provided the mouse button has not yet been released)
out Occurs when the user drags the element being moved outside of the receiving element
drop Occurs when the user leaves the element being moved on the receiving element

An example of creating a simple receiving element for which a single drop event handler is defined is given below:

... #draggable, #droppable (font-size: large; border: thin solid black; padding: 10px; width: 100px; text-align: center; background-color: lightgray; margin: 4px;) #droppable (padding : 20px; position: absolute; right: 5px;) $(function() ( $("#draggable").draggable(); $("#droppable").droppable(( drop: function() ( $(" #draggable").text("Left") ) )); )); Leave me here Drag me Run example

This example adds a div element to the document whose text content is represented by the string "Leave here." We select this element using jQuery and call the droppable() method, passing it a settings object that defines a handler for the drop event. The response to this event is to change the text of the element being moved using the text() method.

The Drag-and-drop interaction created in this example is a simple one, but it provides a useful context for explaining how the Draggable and Droppable interactions work together. The various stages of the process of dragging elements are illustrated in the figure:

It all looks very simple. We drag the element being moved until it is above the receiving element and release it. The element that is dropped remains where it was left, and its text content changes in response to the drop event. The following sections show how to use other Droppable interaction events to improve the user experience.

Illumination of target receiving object

Using the activate and deactivate events, you can highlight the target receiving object when the user begins the process of dragging an element. In many situations, this idea is very fruitful because it provides the user with reliable guidance as to which elements are part of the drag-and-drop model. A corresponding example is given below:

... $(function() ( $("#draggable").draggable(); $("#droppable").droppable(( drop: function() ( $("#draggable").text("Left ") ), activate: function() ( $("#droppable").css(( border: "medium double green", backgroundColor: "lightGreen" )); ), deactivate: function() ( $("#droppable ").css("border", "").css("background-color", ""); ) )); )); ...Run example

As soon as the user starts dragging an element, the activate event associated with our receiving element is fired, and the handler function uses the css() method to change the border and background-color CSS properties of that element. As a result, the target receiving element is highlighted, indicating to the user that there is a connection between it and the element being moved.

The deactivate event is used to remove CSS property values ​​from the receiving element and return it to the initial state, as soon as the user releases the mouse button. (This event occurs whenever dragging an element stops, regardless of whether the element being dragged is left on the receiving element or not.) This process is illustrated in the figure:

Handling overlapping elements

Drag-and-drop technology can be improved by adding over and out event handling. The over event occurs when 50% of the element being moved is over any part of the receiving element. The out event occurs when previously overlapping elements no longer overlap. An example of the response to these events is given below:

$(function() ( $("#draggable").draggable(); $("#droppable").droppable(( drop: function() ( $("#draggable").text("Left") ) , activate: function() ( $("#droppable").css(( border: "medium double green", backgroundColor: "lightGreen" )); ), deactivate: function() ( $("#droppable"). css("border", "").css("background-color", ""); ), over: function() ( $("#droppable").css(( border: "medium double red", backgroundColor : "red" )); ), out: function() ( $("#droppable").css("border", "").css("background-color", ""); ) )); ) ); Run example

The same handler functions are used here as in the previous example, but in this case they are associated with the over and out events. When the receiving element overlaps at least 50% of the element being moved, it is enclosed in a frame and its background color changes, as shown in the figure:

This 50% limit is called the overlap threshold (tolerance), the value of which can be set when creating the receiving element, as will be shown later.

Setting up Droppable interaction

The Droppable interaction has a number of properties that you can change to customize its behavior. These properties are listed in the table below:

Droppable Interaction Properties Property Description
disabled If this option is true, then the Droppable interaction functionality is initially disabled. Default value is false
accept Narrows down the set of movable elements that the receiving element will respond to. The default value is *, which matches any element
activeClass Defines a class that will be assigned in response to the activate event and removed in response to the deactivate event
hoverClass Defines a class that will be assigned in response to an over event and removed in response to an out event
tolerance Defines the minimum degree of overlap at which an over event occurs
Limiting the allowed elements to be moved

You can limit the set of droppable elements that will be accepted by an element with Droppable interoperability functionality by using the accept option. The value of the accept option should be set to a selector. As a result, Droppable interaction events will only occur if the element being moved matches the specified selector. A corresponding example is given below:

... .draggable, #droppable (font-size: large; border: thin solid black; padding: 10px; width: 100px; text-align: center; background-color: lightgray; margin: 4px;) #droppable (padding : 20px; position: absolute; right: 5px;) $(function() ( $(".draggable").draggable(); $("#droppable").droppable(( drop: function(event, ui) ( ui.draggable.text("Left") ), activate: function() ( $("#droppable").css(( border: "medium double green", backgroundColor: "lightGreen" )); ), deactivate: function () ( $("#droppable").css("border", "").css("background-color", ""); ), accept: "#drag1" )); )); Leave here Element 1 Element 2 Run example

In this example there are two draggable elements with IDs drag1 and drag2. When creating a receiving element, we use the accept option, with which we indicate that only the drag1 element will be an acceptable element to be moved.

When you drag the drag1 element, you will see the same effect as in the previous examples. At appropriate times, the activate, deactivate, over, and out events will be fired for the receiving element. At the same time, if you drag a drag2 element that does not match the selector specified in the accept parameter, then these events will not be fired. This element can be moved freely, but it will not be perceived by the receiving element.

Notice the change in how we select an acceptable floatable element on which to call the text() method. When there was only one moving element in the document, the id attribute was enough for this:

Drop: function() ( $("#draggable").text("Left") ),

In this example, there are two floatable elements, and selecting by id attribute will not produce the desired result, since the text in this case will always change in the same floatable element, regardless of which one is acceptable for the receiving element.

The solution is to use the ui object, which jQuery UI provides as an additional argument to each event handler. The draggable property of a ui object returns a jQuery object containing the element that the user drags or tries to drop on the target element, allowing the desired element to be selected like this:

Drop: function(event, ui) ( ui.draggable.text("Left") ),

Changing the overlap threshold

By default, the over event only occurs when at least 50% of the element being moved overlaps the receiving element. The amount of this threshold overlap can be changed using the tolerance option, which can take the values ​​shown in the table below:

The two values ​​I use most often are fit and touch because they make the most sense to users. I use fit when the dragged element needs to remain in the area of ​​the receiving element it was moved to, and touch when the dragged element needs to return to its original position (an example will be given below). An example of using the fit and touch parameters is given below:

The clone value tells jQuery UI to create a copy of the element being moved, along with all its contents, and use the resulting result as a helper element. The result is shown in the figure:

The helper element is removed when the user releases the mouse button over the element being moved, leaving the element being moved and the receiving element in their original positions.

As shown in the figure, the original element being moved remains in place and only the auxiliary element moves around the screen following the mouse pointer. If the size of the moved element is large, as in our example, then it covers the rest of the document elements, so that it will be difficult for the user to even track the position of the receiving element. This problem can be dealt with by providing the function as the value of the helper option, as shown in the example below:

... $(function() ( $("div.draggable")..png"/>") ) )); $("#basket").droppable(( activeClass: "active", hoverClass: "hover" )); )); ...Run example

When the user starts dragging an element, jQuery UI calls the function specified by the helper parameter and uses the returned element as the object to be dragged. In this case, I'm using jQuery to create the img element. The result is shown in the figure:

A small image acts as a proxy for the element being moved, making it much easier to keep track of other elements in the document.

The ui object that jQuery UI passes to Droppable interaction events contains a helper property, and this property can be used to manipulate the helper as it is being dragged. An example of using this property in conjunction with the over and out events is given below:

... $(function() ( $("div.draggable")..png"/>") ) )); $("#basket").droppable(( activeClass: "active", hoverClass: "hover", over: function(event, ui) ( ui.helper.css("border", "thick solid #27e6ed") ) , out: function(event, ui) ( ui.helper.css("border", "") ) )); )); ...

Here the over and out events and the ui.helper property are used to display a border around the helper element when it overlaps the receiving element. The result is shown in the figure:

Snap to element edges

Using the snap option, you can ensure that the moved element is “attracted” to the edges of the elements next to which it passes. This option accepts a selector as a value. The element being moved will snap to the edges of any element matching the specified selector. An example of using the snap option is given below:

Run jQuery UI example #snapper, .draggable, .droppable (font-size: large; border: medium solid black; padding: 4px; width: 150px; text-align: center; background-color: lightgray; margin-bottom: 10px ;).droppable (margin-right: 5px; height: 50px; width: 120px) #dropContainer (position: absolute; right: 5px;) div span (position: relative; top: 25%) .droppable.active (border: medium solid green) .droppable.hover (background-color: lightgreen) #snapper (position: absolute; left: 35%; border: medium solid black; width: 180px; height: 50px) $(function() ( $(" div.draggable").draggable(( snap: "#snapper, .droppable", snapMode: "both", snapTolerance: 50 )); $("#basket").droppable(( activeClass: "active", hoverClass: "hover" )); )); Cart Snap here Drag me

When a moving element approaches one of the suitable elements, it is, as it were, “attracted” to it in such a way that their adjacent edges touch. For such a binding, you can select any element, not just the receiving one. In this example, I added a div element and set the snap option to a value that selects that element as well as the receiving element in the document.

There are a couple of helper options that allow you to more precisely customize the anchoring behavior of elements. One of them is the snapMode option. With its help you can specify the type of binding. The following values ​​are allowed: inner(snap to the inner edges of elements), outer(snap to the outer edges of elements) and both(snap to all edges; default).

The snapTolerance option allows you to specify how far the floated element must approach the edge of the target element before snapping occurs. The default value is 20, which means 20 pixels. The example uses a value of 50, which corresponds to a snap at a larger distance. It is very important to choose the correct value for this option. If the snapTolerance value is too low, the user may not notice the snapping effect, and if it is too high, the element being moved will begin to make unexpected jumps, snapping to distant elements.

Use of technology drag and drop(drag and drop) allows the user to move various objects from one to another, for example, elements of one list to another. To do this, you need to use two controls: sink and source. The receiver is the object that will receive the source object (the object being moved).

Events that occur during the movement of objects are listed below in the order in which they occur.

OnStartDrag(type TStartDragEvent) - at the beginning of the operation, generated by the source object. Parameters that are passed to the event handler: DragObject receiver object (TDragObject type), Source object (TObject type).

OnDragOver(type TDragOverEvent) - creates a receiver object when a dragged object is over it. Parameters that are passed to the event handler: receiver object Sender (type TObject), source object Source (type TObject), movement state State (type TDragState), X and Y (type integer) - current coordinates of the mouse pointer, Accept (type boolean ) sign of confirmation of the move operation. The movement state makes it clear whether the object being moved is in the receiver area, is moving in it, or has left it. The passed parameters enable the destination object to accept or reject the source object. The Accept parameter is set to Trye if the move operation is accepted, otherwise it is set to False.

onDragDrop (type TDragDropEvent) - generated by the receiver object when the dragged object is dropped on it. The event handler is passed the current coordinates of the mouse pointer, the Sender receiver object (TObject type), and the original movement object Source (TObject type).

onEndDrag (EndDragEvent type) - Raised when a drag operation completes. The X and Y coordinates of the point where the source Sender object and the receiver Target object are passed to the event handler.

To create a drag and drop, it is enough to implement two events: OnDragDrop and OnDragOver with the DragMode property set to dmAutomatic. Otherwise, the start of the drag operation, the BeginDrag method, must be coded by the programmer.

To consolidate the material, we will create the following application. Place the Panel component on the form. Set the DragMode property of the Object Inspector to dmAutomatic. Let's select the form object and use the Object Inspector to create the following events:

Procedure TForm1.FormDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin if Source = Panel1 then Accept:= True else Accept:= False; end; procedure TForm1.FormDragDrop(Sender, Source: TObject; X, Y: Integer); begin Panel1.Left:= X; Panel1.Top:= Y; end;

Now by launching the application and clicking the mouse button above the panel, we can move the panel object throughout the form.

Bottom line: we got acquainted with the technology drag and drop(drag and drop) and used it in practice.

Drag and drop techniques have evolved over many years. It's no surprise that with the increasing number of programmers developing open source plugins (such as jQuery), old methods are being revived. The JavaScript library is highly responsive and offers many improvements in this era of web technology.

In this tutorial we will make a script that you can use to create dynamic drag and drop rectangles on your website. The process is managed by jQuery. Such scripts save time by providing ready-made functionality! And the drag-and-drop library can be used in other projects.

Preparing content

First of all, let's prepare a small website for the project. In the project folder you need to create two directories with the notable names "js" and "css" and an empty file index.html. The code will be very simple, so that there is a clear idea of ​​the work, and there is a point for further development.

Below is the code for our HTML file. In chapter head we include 3 scripts. The main jQuery script will be loaded from the Google Code server. our style file style.css is also included, which contains the main properties for forming appearance our document.

Drag me Yes, yes. Exactly me. You can drag me too ( zIndex: 200, opacity: .9 )

P.S.: you can leave me anywhere!

Inside section body only two blocks are placed div, which contain both rectangles. The code is quite simple and understandable. Inside each rectangle there are headers with the classes handler and handler2 . This is important because each rectangle behaves differently as you drag.


Installing CSS

The HTML code is very simple. If you understand the basic markup, then the CSS styles won't be difficult either. Mainly defined margins, paddings and colors.

Body,html ( font-family:Calibri, sans-serif; background:#eaf3fb; font-size:12px; height:1000px; line-height:18px; ) p ( height:30px; )

Selectors body,html are used only for the demo page. And all the content is placed in two draggable rectangles.

Dv1 ( width:200px; background-color:#eff7ff; border:1px solid #96c2f1; position:absolute; left:100px; top:100px; ) .dv1 h2 ( background-color:#b2d3f5; padding:5px; font- family:Georgia, "Times New Roman", Times, serif; font-size:1.0em; text-transform:uppercase; font-weight:bold; color:#3a424a; margin:1px; cursor:move; ) .dv1 div ( padding:5px; margin-bottom:10px; ) .dv2 ( background-color:#f6ebfb; border:1px solid #a36fde; width:550px; position:absolute; cursor:move; left:400px; top:230px; ) .dv2 h2 ( background-color:#eacfe9; letter-spacing:-0.09em; font-size:1.8em; font-weight: bold; padding:15px; margin:1px; color:#241f24; cursor:move; ) .dv2 .content2 ( padding:5px; margin-bottom:10px; )

For both classes .dv1 and .dv2 we use absolute positioning. This is not necessary and probably not the most The best way to position draggable rectangles. However, for our example, this positioning makes sense, since each time the page is refreshed, the rectangles are installed in certain places.

Also the fonts and colors are different for the rectangles to make it easier to see the difference.

Otherwise, the headings and content of the blocks are almost identical. If you will be copying styles into your project, change the names before starting. In some cases, it makes more sense to use IDs instead of classes, such as when using the drag-and-drop technique for one specific block.

Parsing JavaScript

Two JavaScript files contain all the code needed to make it work. We will omit the details of working with jQuery, as this is beyond the scope of the lesson. Let's pay attention to the jquery.dragndrop.js file.

Line 22 defines the Drags function.

$.fn.Drags = function(opts) ( var ps = $.extend(( zIndex: 20, opacity: .7, handler: null, onMove: function() ( ), onDrop: function() ( ) ), opts );

This sets the return variable and initialization data for Drags. This method is very commonly used when working with jQuery to pass options to other functions. Internally we set variables for all the available options for the rectangles being dragged.


The next piece of code includes event handlers for the dragndrop variable. Both events drag And drop call functions passing event parameters to them. These events occur when you press the mouse button to drag an object and then release it.

Var dragndrop = ( drag: function(e) ( var dragData = e.data.dragData; dragData.target.css(( left: dragData.left + e.pageX - dragData.offLeft, top: dragData.top + e.pageY - dragData.offTop )); dragData.handler.css(( cursor: "move" )); dragData.target.css (( cursor: "move" )); dragData.onMove(e); ), drop: function( e) ( var dragData = e.data.dragData; dragData.target.css(dragData.oldCss); //.css(( "opacity": "" )); dragData.handler.css("cursor", dragData. oldCss.cursor); dragData.onDrop(e); $().unbind("mousemove", dragndrop.drag) .unbind("mouseup", dragndrop.drop); ) )

Our functions manipulate the CSS positioning of each object. Changing the absolute positioning of your objects will not affect how your code works, since every JavaScript function changes whatever style is defined for the object.

The rest of the code checks the handler and makes cosmetic changes to other styles. Here you can add changes to transparency, font and font color, or add new paragraphs.

Drag/Drop functions

The second fn.js file contains very simple code. We are waiting full load document, after which we call our functions. Two instances of the function are defined Drags, which was discussed earlier.

We have two movable blocks with classes .dv1 and .dv2 . If you need to leave one moveable block, then you just need to remove the second part of the code. Adding another moveable block is also easy. You just need to add a new function in this file.

The first step is to set the options when calling the function. Be sure to set the handler name. With it, we tell jQuery which handler to use when the mouse button is pressed in a certain area of ​​the document. The handler name can be a class or an ID attribute.

Our first function has two event handlers onMove and onDrop. Both call new functions that are passed to the current event as variables. This is where the HTML code in the rectangle is manipulated to update with each movement. This is a great effect for demonstrating how you can control a process using simple jQuery events.

In the second function we use the z-Index and opacity parameters. Can you add other CSS properties? but this will require reworking the JavaScript code so that settings are checked. For example, you can pass a different font style or values ​​for the height and width of a moving rectangle - a very interesting trick!

Conclusion

With a little bit of work, we now have a great drag-and-drop interface at our disposal. jQuery provides huge benefits for developers who are eager to use old methods in their projects.

As a result, we not only have event handler functions, but we can also pass new variables to draggable blocks. This opens up new possibilities for creativity. The demonstration for the lesson contains only a sketch of what can be done using such code.

So check out the jQuery documentation to use the library functions.

For the VCL library, Borland has implemented its own version of the Drag&Drop interface (translated as “drag and drop”). This interface is internal - you can send and receive any Delphi controls inside the form (except for the form itself). It is implemented without using the corresponding Windows API functions - they must be used when organizing communication with other tasks by dragging and dropping.

By clicking the left mouse button over a control, we can “drag” it onto any other element. From a programmer's point of view, this means that at the moments of dragging and releasing a key, certain events are generated, which transmit all the necessary information - a pointer to the dragged object, the current coordinates of the cursor, etc. The recipient of the events is the element on which the cursor is currently located. The event handler for such an event must tell the system whether the control receives the send or not. When the button above the receiving control is released, one or two more events are generated, depending on the readiness of the receiver.

CancelDrag Cancels the current drag-and-drop or drag-and-dock operation.

Function FindDragTarget (const Pos: TPoint ; AllowDisabled: Boolean ): TControl ;

The function returns an object of the base class TControl, which refers to the position of the screen with the coordinates defined by the Pos parameter. This function is used to determine the potential recipient of a drag-and-drop or drag-and-dock operation. If no window control exists for the specified position, then the function returns nil . The AllowDisabled parameter determines whether disabled objects will be taken into account.

Function IsDragObject(Sender: TObject): Boolean;

The function determines whether the object specified in the Sender parameter is a descendant of the TDragObject class. This function can be used as the Source parameter in the OnDragOver and OnDockOver event handlers to determine whether the dragged object will be accepted. The IsDragObject function can also be used as the Source parameter in the OnDragDrop and OnDockDrop event handlers in order to correctly interpret the dragged object.

Properties DragMode, DragCursor, methods BeginDrag, OnDragOver, OnDragDrop, OnEndDrag, OnStartDrag, Accept parameter

The process of dragging information from one object to another using the mouse is widely used in Windows. You can move files between folders, move the folders themselves, etc.

All properties, methods and events associated with the drag-and-drop process are defined in the TControl class, which is the progenitor of all Delphi visual components. Therefore they are common to all components.

The start of dragging is determined by the DragMode property, which can be set at design time or programmatically equal to dmManual or dmAutomatic. The dmAutomatic value specifies whether the dragging process will automatically begin when the user presses a mouse button over a component. However, in this case, the OnMouseDown event associated with the user clicking the mouse button does not occur at all for this component.

The interface for transferring and receiving components appeared quite a long time ago. It allows two controls to interact while the application is running. In this case, any necessary operations can be performed. Despite the ease of implementation and long-standing development, many programmers (especially beginners) consider this mechanism obscure and exotic. However, using Drag-and-Drop can be very useful and easy to implement. Now we will make sure of this.

In order for the mechanism to work, two controls need to be configured accordingly. One should be a source (Source), the second should be a receiver (Target). In this case, the source does not move anywhere, but is only registered as such in the mechanism.

Believe me, it’s enough to simply convert the X,Y coordinates passed in the parameters of the OnDragOver and OnDragDrop events into form coordinates.

Work with the Left and Top properties of the component the cursor is moving over. Let me give you a simple example. Place a Memo component on the form and set the Align property to alTop. Place a panel on the form, also set the Align property to alTop and set the Height property to a small value, say 6 or 7 pixels. Set DragMode to dmAutomatica and DragCursor to crVSplit. Place another Memo component and set Align to alClient. Simultaneously select both Memo components, the panel and create a common OnDragOver event handler as shown below:

Recently I had an idea to start developing a game for Android. To begin with, I decided to write chess. It seemed to me that the Drag and Drop technology would be perfect for implementing the mechanism for moving figures. For the uninitiated, I note that the drag and drop method is the ability to drag one graphic object onto another and perform one or another action after releasing it. The simplest example is deleting a shortcut from the desktop of your PC by dragging it to the trash. By “throwing” the label into the trash, we tell the system that we want to force these two objects to interact. The system receives our signal and decides what action it should take. Drag and drop has become widespread due to its intuitive clarity. This approach is backed by our experience interacting with real-world objects and works great in a virtual environment. As for chess, using drag and drop it is technologically easier to determine the cell where the user dragged the piece, since there is no need to calculate the cell number from the coordinates of the release point. This work will be taken over by the virtual machine.

Purposes of using Drag n Drop technology

Using drag and drop technology allows me to solve three problems with little effort:

  • Progress visualization. When the user touches a shape and begins to move it around the screen, the shape is replaced with a smaller design. Thus, the user understands that the figure is captured.
  • I limited the area of ​​movement of the figure to the size of the board.
  • If the user releases a piece in the wrong place, it should return to its original position.
  • The tasks have been outlined, let's begin to implement them.

    ImageView substitution on touch

    All my shapes are ImageView objects. Unfortunately, it turned out that the implementation of Drag & Drop in Android does not allow “straight out of the box” to replace the image of an object when it is touched. However, this task can be completely solved using the API. We will need to perform a number of simple steps:

  • Create a DragShadowBuilder object.
  • Call the startDrag method.
  • Hide our ImageView, which displays the shape, by calling the setVisibility method with the View.INVISIBLE parameter. As a result, only the DragShadowBuilder object will remain on the screen, which will signal to the user that the shape has been captured.
  • These actions must be implemented in the OnTouchListner handler of the ImageView object. To do this, let's override the onTouch method:

    @ Override public boolean onTouch(View view, MotionEvent motionEvent) ( if (motionEvent. getAction() == MotionEvent. ACTION_DOWN) ( ClipData clipData= ClipData. newPlainText("" , "" ) ; View. DragShadowBuilder dsb= new View. DragShadowBuilder (view) ; view. startDrag(clipData, dsb, view, 0 ) ; view. setVisibility(View. INVISIBLE) ; return true ; ) else ( return false ; ) )

    Everything is very simple. So, we’ve sorted out the image substitution, let’s move on to the next task.

    Limiting the drag area for the drag drop function

    There's a problem with limiting the drag area. The point is that if you release a piece outside the board, the drop event will not occur, since the user released the object in an empty space, and there is nothing for the object to interact with. As a result, the figure will not return to its original state and will remain hidden forever. I spent a lot of time reading the documentation, but I still couldn't find a way to limit the drag-and-drop area of ​​objects. The insight came suddenly. I don't need to limit the area at all, I need to know whether the user released the shape correctly or not.

    Determining Correct Release
    I found answers to my questions in the "handling drag end events" section on the Android Developers website. Here are a few key points:

  • When the user completes dragging, the ACTION_DRAG_ENDED event is generated in the DragListeners handler.
  • In DragListener you can get more detailed information about the drag operation by calling the DragEvent.getResult() method.
  • If the DragListener returns true in response to the ACTION_DROP event, the call to getResult will also return true, otherwise it will return false.
  • So I need to intercept the ACTION_DRAG_ENDED event and call the getResult method. If it returns false, then the user has dragged the piece off the board and I need to set the ImageView to visible mode.

    @ Override public boolean onDrag(View view, DragEvent dragEvent) ( int dragAction= dragEvent. getAction() ; View dragView= (View) dragEvent. getLocalState() ; if (dragAction== DragEvent. ACTION_DRAG_EXITED) ( containsDragable= false ; ) else if (dragAction== DragEvent. ACTION_DRAG_ENTERED) ( containsDragable= true ; ) else if (dragAction== DragEvent. ACTION_DRAG_ENDED) ( if (dropEventNotHandled(dragEvent) ) ( dragView. setVisibility(View. VISIBLE) ; ) ) else if (dragAction= = DragEvent. ACTION_DROP& amp;& amp; containsDragable) ( checkForValidMove((ChessBoardSquareLayoutView) view, dragView) ; dragView. setVisibility(View. VISIBLE) ; ) return true ; ) private boolean dropEventNotHandled(DragEvent dragEvent) ( return ! dragEvent. getResult( ) ; )

    Now the user can release the figure anywhere, and nothing bad will happen.

    Definition of valid moves

    The last part of the article is devoted to checking the validity of the move that the user is trying to make. Before discussing this topic in detail, I will make a short note explaining the structure of my application. The chessboard is represented as a TableLayout, and each cell is a child of a LinearLayout and has an OnDragListener.

    In addition, each OnDragListener refers to a "mediator" object, which takes care of the interaction of game objects and remembers the position of the current cell.

    When the user drags a piece over a cell, the following actions are possible:

  • Using the ACTION_DRAG_ENTERED event to set the 'containsDraggable' variable to true.
  • Using the ACTION_DRAG_EXITED event to set the 'containsDraggable' variable to false.
  • Using the ACTION_DROP event to ask the mediator whether it is acceptable to place a piece in this cell.
  • Below is the code that implements the described logic

    @ Override public boolean onDrag(View view, DragEvent dragEvent) ( int dragAction= dragEvent. getAction() ; View dragView= (View) dragEvent. getLocalState() ; if (dragAction== DragEvent. ACTION_DRAG_EXITED) ( containsDragable= false ; ) else if (dragAction== DragEvent. ACTION_DRAG_ENTERED) ( containsDragable= true ; ) else if (dragAction== DragEvent. ACTION_DRAG_ENDED) ( if (dropEventNotHandled(dragEvent) ) ( dragView. setVisibility(View. VISIBLE) ; ) ) else if (dragAction= = DragEvent.ACTION_DROP& amp;& amp; containsDragable) ( checkForValidMove((ChessBoardSquareLayoutView) view, dragView) ; dragView. setVisibility(View. VISIBLE) ; ) return true ; )

    As you can see, regardless of whether the move is valid or not, the ImageView is transferred to the visible state. I wanted the user to see the shape move. I mentioned earlier that a cell is a child of LayoutView. This is done to make it easier to move the ImageView from cell to cell. Below is the code for the checkForValidMove method, which shows how the ImageView moves.

    private void checkForValidMove(ChessBoardSquareLayoutView view, View dragView) ( if (mediator. isValidMove(view) ) ( ViewGroup owner= (ViewGroup) dragView. getParent() ; owner. removeView(dragView) ; view. addView(dragView) ; view. setGravity (Gravity. CENTER) ; view. showAsLanded() ; mediator. handleMove(view) ; ) )

    I hope this article will help you when developing your own projects.

    
    Top