• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Implementing the Drag Functionality
2
3ArkWeb provides the functionality of dragging elements on web pages. Users can place an element by holding down the element and dragging it to another element. This functionality meets the HTML5 standard.
4
5## Dragging Web Page Content to Other Applications
6
7The following table lists the data formats supported by ArkWeb. You set data in these formats based on the HTML5 standard to drag content to other applications.
8
9| Data Format     | Description    |
10| ------------- | -------- |
11| text/plain    | Text    |
12| text/uri-list | Link    |
13| text/html     | HTML|
14| Files         | File    |
15
16## Listening for Drag Events
17
18The drag functionality of ArkWeb is different from that of ArkUI. ArkWeb is mainly used to drag web page content. Therefore, only some drag events can be listened for.
19
20| Method   | Description                                                 |
21| ----------- | ----------------------------------------------------- |
22| [onDragStart](../reference/apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#ondragstart)  | This method is not supported and should not be implemented. Otherwise, the drag behavior of the **Web** component will be affected.|
23|  [onDragEnter](../reference/apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#ondragenter) | Called when an element is dragged to the web area.|
24| [onDragMove](../reference/apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#ondragmove)  | Called when an element is moved in the web area. |
25| [onDragLeave](../reference/apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#ondragleave) | Called when the dragged element leaves the web area.         |
26| [onDragEnd](../reference/apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#ondragend10) | Called when the dragging of an element ends.        |
27
28## Implementing the Drag Logic on ArkTS
29
30In most cases, the drag functionality implemented in HTML5 can meet the requirements of an application. If necessary, refer to the following examples to read drag data on ArkTS.
311. [Establishing a data channel between the application and the frontend Page](web-app-page-data-channel.md).
322. In the **onDrop** method, implement simple logic, for example, temporarily storing some key data.
333. To implement time-consuming tasks, add the application processing logic to the message receiving method on ArkTS.
34
35The **onDrop** method on ArkTS is executed earlier than the event processing method ( **droppable.addEventListener('drop')** in the HTML example) in HTML. If page redirection is performed in the **onDrop** method, the **drop** method in HTML5 cannot be executed correctly, and the unexpected result is generated. Therefore, a bidirectional communication mechanism must be established to notify ArkTS to execute the corresponding service logic after the **drop** method in HTML5 is executed.
36
37```ts
38import { webview } from '@kit.ArkWeb'
39import { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData';
40
41@Entry
42@Component
43struct DragDrop {
44  private controller: webview.WebviewController = new webview.WebviewController()
45  @State ports: Array<webview.WebMessagePort> = []
46  @State dragData: Array<unifiedDataChannel.UnifiedRecord> = []
47
48  build() {
49    Column() {
50      Web({
51        src: $rawfile("drag.html"),
52        controller: this.controller,
53      }).onPageEnd((event) => {
54        //Register the message port.
55        this.ports = this.controller.createWebMessagePorts();
56        this.ports[1].onMessageEvent((result: webview.WebMessage) => {
57          //Process the data received from HTML. You can record logs to confirm the message. The message format can be customized as long as it can be uniquely identified.
58          console.log("ETS receive Message: typeof (result) = " + typeof (result) + ";" + result);
59          // Process the message after the message is received in result. You can perform time-consuming tasks.
60        });
61        console.log("ETS postMessage set h5port ");
62        //After the message port is registered, the front end sends a registration completion message to complete bidirectional port binding.
63        this.controller.postMessage('__init_port__', [this.ports[0]], '*');
64      })// Implement simple logic in onDrop, for example, temporarily storing some key data.
65        .onDrop((event) => {
66          console.log("ETS onDrop!")
67          let data: UnifiedData = (event as DragEvent).getData() as UnifiedData;
68          let uriArr: Array<unifiedDataChannel.UnifiedRecord> = data.getRecords();
69          if (!uriArr || uriArr.length <= 0) {
70            return false;
71          }
72          // Traverse records to obtain data for temporary storage or use other methods to temporarily store data.
73          for (let i = 0; i < uriArr.length; ++i) {
74            if (uriArr[i].getType() === uniformTypeDescriptor.UniformDataType.PLAIN_TEXT) {
75              let plainText = uriArr[i] as unifiedDataChannel.PlainText;
76              if (plainText.textContent) {
77                console.info("plainText.textContent: ", plainText.textContent);
78              }
79            }
80          }
81          return true
82        })
83    }
84
85  }
86}
87```
88
89HTML example:
90
91```html
92<html lang="zh-CN">
93<head>
94    <meta charset="UTF-8">
95    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
96    <title>HTML5 Dragging Demo</title>
97</head>
98<style>
99    body {
100      font-family: Arial, sans-serif;
101      padding: 20px;
102    }
103
104    .draggable {
105      width: 100px;
106      height: 100px;
107      background-color: #4CAF50;
108      color: white;
109      text-align: center;
110      line-height: 100px;
111      margin-bottom: 20px;
112      cursor: grab;
113    }
114
115    .droppable {
116      width: 300px;
117      height: 150px;
118      border: 2px dashed #999;
119      background-color: #f0f0f0;
120      text-align: center;
121      line-height: 150px;
122      font-size: 16px;
123    }
124
125    .success {
126      background-color: #4CAF50;
127      color: white;
128    }
129</style>
130<body>
131
132<h2>HTML5 Dragging Demo</h2>
133
134<div id="draggable" class="draggable" draggable="true">Draggable element</div>
135
136<div id="droppable" class="droppable">Please drag the element here</div>
137
138<script>
139    const draggable = document.getElementById('draggable');
140    const droppable = document.getElementById('droppable');
141
142    // Listen for the drag start event.
143    draggable.addEventListener('dragstart', function (e) {
144      e.dataTransfer.setData('text/plain', this.id);
145      this.style.opacity = '0.4';
146    });
147
148    // Listen for the drag end event.
149    draggable.addEventListener('dragend', function (e) {
150      this.style.opacity = '1';
151    });
152
153    // Listen for the event triggered when the element is dragged to the target area.
154    droppable.addEventListener('dragover', function (e) {
155      e.preventDefault(); // This method must be invoked. Otherwise, the drop event cannot be triggered.
156    });
157
158    // Listen for the drop event.
159    droppable.addEventListener('drop', function (e) {
160      e.preventDefault();
161      const data = e.dataTransfer.getData('text/plain');
162      // Transfer the element to ArkTS.
163      PostMsgToArkTS(data);
164      const draggableEl = document.getElementById(data);
165      this.appendChild(draggableEl);
166      this.classList.add('success');
167      this.textContent = "Dropped successfully!";
168    });
169
170    // Set the scriptproxy port on JavaScript.
171    var h5Port;
172    window.addEventListener('message', function (event) {
173    console.log("H5 receive settingPort message");
174        if (event.data == '__init_port__') {
175            if (event.ports[0] != null) {
176                console.log("H5 set h5Port " + event.ports[0]);
177                h5Port = event.ports[0];
178            }
179        }
180    });
181
182    // Send data to ArkTS using scriptproxy.
183    function PostMsgToArkTS(data) {
184        console.log("H5 PostMsgToArkTS, h5Port " + h5Port);
185        if (h5Port) {
186          h5Port.postMessage(data);
187        } else {
188          console.error("h5Port is null, Please initialize first");
189        }
190    }
191</script>
192
193</body>
194</html>
195```
196![web-drag-drop](figures/web-dragdrop.gif)
197Log output:
198![web-drag-log](figures/web-drag-log.png)
199
200## FAQs
201
202### Why is the drag event set in HTML5 not triggered?
203Check whether the CSS resources are properly set. Some web pages set the CSS style only for devices with specific UAs. You can set a custom UA in the **Web** component to solve this problem. For example:
204
205```ts
206import { webview } from '@kit.ArkWeb'
207
208@Entry
209@Component
210struct Index {
211    private webController: webview.WebviewController = new webview.WebviewController()
212    build(){
213      Column() {
214        Web({
215          src: "example.com",
216          controller: this.webController,
217        }).onControllerAttached(() => {
218          // Set a custom UA.
219          let customUA = 'android'
220          this.webController.setCustomUserAgent(this.webController.getUserAgent() + customUA)
221        })
222      }
223    }
224}
225```
226