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 197Log output: 198 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