stdweb/webapi/events/drag.rs
1#[cfg(feature = "futures-support")]
2use futures_channel::oneshot;
3use webapi::event::{IEvent, IUiEvent, UiEvent, Event};
4use webapi::events::mouse::{IMouseEvent, MouseEvent};
5use webapi::file::File;
6use webcore::once::Once;
7use webcore::value::{Reference, Value};
8use webcore::try_from::TryInto;
9use webapi::file_list::FileList;
10use webapi::html_elements::ImageElement;
11use webapi::dom_exception::NotSupportedError;
12use webapi::dom_exception::InvalidStateError;
13
14/// The DragEvent interface is a DOM event that represents a drag and drop interaction.
15/// The user initiates a drag by placing a pointer device (such as a mouse) on the touch surface
16/// and then dragging the pointer to a new location (such as another DOM element).
17///
18/// This interface inherits properties from MouseEvent and Event.
19///
20/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DragEvent)
21// https://www.w3.org/TR/html51/editing.html#dragevent-dragevent
22pub trait IDragEvent: IMouseEvent {
23 /// The DataEvent.dataTransfer property holds the drag operation's data (as a DataTransfer object).
24 ///
25 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DragEvent/dataTransfer)
26 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-dragevent-datatransfer-1
27 #[inline]
28 fn data_transfer(&self) -> Option<DataTransfer> {
29 js!(
30 return @{self.as_ref()}.dataTransfer;
31 ).try_into().unwrap()
32 }
33}
34
35/// A reference to a JavaScript object which implements the [IDragEvent](trait.IDragEvent.html)
36/// interface.
37///
38/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DragEvent)
39// https://www.w3.org/TR/html51/editing.html#the-dragevent-interface
40#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
41#[reference(instance_of = "DragEvent")]
42#[reference(subclass_of(Event, UiEvent, MouseEvent))]
43pub struct DragRelatedEvent(Reference);
44
45impl IEvent for DragRelatedEvent {}
46
47impl IUiEvent for DragRelatedEvent {}
48
49impl IMouseEvent for DragRelatedEvent {}
50
51impl IDragEvent for DragRelatedEvent {}
52
53/// The drag event is fired every few hundred milliseconds as an element or text selection is being
54/// dragged by the user.
55///
56/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/drag)
57// https://www.w3.org/TR/html51/editing.html#eventdef-global-drag
58#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
59#[reference(instance_of = "DragEvent")]
60#[reference(event = "drag")]
61#[reference(subclass_of(Event, UiEvent, MouseEvent, DragRelatedEvent))]
62pub struct DragEvent(Reference);
63
64impl IEvent for DragEvent {}
65
66impl IUiEvent for DragEvent {}
67
68impl IMouseEvent for DragEvent {}
69
70impl IDragEvent for DragEvent {}
71
72/// The dragstart event is fired when the user starts dragging an element or text selection.
73///
74/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/dragstart)
75// https://www.w3.org/TR/html51/editing.html#eventdef-global-dragstart
76#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
77#[reference(instance_of = "DragEvent")]
78#[reference(event = "dragstart")]
79#[reference(subclass_of(Event, UiEvent, MouseEvent, DragRelatedEvent))]
80pub struct DragStartEvent(Reference);
81
82impl IEvent for DragStartEvent {}
83
84impl IUiEvent for DragStartEvent {}
85
86impl IMouseEvent for DragStartEvent {}
87
88impl IDragEvent for DragStartEvent {}
89
90/// The dragenter event is fired when a dragged element or text selection enters a valid drop target.
91///
92/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/dragenter)
93// https://www.w3.org/TR/html51/editing.html#eventdef-global-dragenter
94#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
95#[reference(instance_of = "DragEvent")]
96#[reference(event = "dragenter")]
97#[reference(subclass_of(Event, UiEvent, MouseEvent, DragRelatedEvent))]
98pub struct DragEnterEvent(Reference);
99
100impl IEvent for DragEnterEvent {}
101
102impl IUiEvent for DragEnterEvent {}
103
104impl IMouseEvent for DragEnterEvent {}
105
106impl IDragEvent for DragEnterEvent {}
107
108/// The dragexit event is fired when an element is no longer the drag operation's immediate
109/// selection target.
110///
111/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/dragexit)
112// https://www.w3.org/TR/html51/editing.html#eventdef-global-dragexit
113#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
114#[reference(instance_of = "DragEvent")]
115#[reference(event = "dragexit")]
116#[reference(subclass_of(Event, UiEvent, MouseEvent, DragRelatedEvent))]
117pub struct DragExitEvent(Reference);
118
119impl IEvent for DragExitEvent {}
120
121impl IUiEvent for DragExitEvent {}
122
123impl IMouseEvent for DragExitEvent {}
124
125impl IDragEvent for DragExitEvent {}
126
127/// The dragleave event is fired when a dragged element or text selection leaves a valid drop target.
128///
129/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/dragleave)
130// https://www.w3.org/TR/html51/editing.html#eventdef-global-dragleave
131#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
132#[reference(instance_of = "DragEvent")]
133#[reference(event = "dragleave")]
134#[reference(subclass_of(Event, UiEvent, MouseEvent, DragRelatedEvent))]
135pub struct DragLeaveEvent(Reference);
136
137impl IEvent for DragLeaveEvent {}
138
139impl IUiEvent for DragLeaveEvent {}
140
141impl IMouseEvent for DragLeaveEvent {}
142
143impl IDragEvent for DragLeaveEvent {}
144
145/// The dragover event is fired when an element or text selection is being dragged over a valid drop
146/// target (every few hundred milliseconds).
147///
148/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/dragover)
149// https://www.w3.org/TR/html51/editing.html#eventdef-global-dragover
150#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
151#[reference(instance_of = "DragEvent")]
152#[reference(event = "dragover")]
153#[reference(subclass_of(Event, UiEvent, MouseEvent, DragRelatedEvent))]
154pub struct DragOverEvent(Reference);
155
156impl IEvent for DragOverEvent {}
157
158impl IUiEvent for DragOverEvent {}
159
160impl IMouseEvent for DragOverEvent {}
161
162impl IDragEvent for DragOverEvent {}
163
164/// The drop event is fired when an element or text selection is dropped on a valid drop target.
165///
166/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/drop)
167// https://www.w3.org/TR/html51/editing.html#eventdef-global-drop
168#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
169#[reference(instance_of = "DragEvent")]
170#[reference(event = "drop")]
171#[reference(subclass_of(Event, UiEvent, MouseEvent, DragRelatedEvent))]
172pub struct DragDropEvent(Reference);
173
174impl IEvent for DragDropEvent {}
175
176impl IUiEvent for DragDropEvent {}
177
178impl IMouseEvent for DragDropEvent {}
179
180impl IDragEvent for DragDropEvent {}
181
182/// The dragend event is fired when a drag operation is being ended (by releasing a mouse button or
183/// hitting the escape key).
184///
185/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/dragend)
186// https://www.w3.org/TR/html51/editing.html#eventdef-global-dragend
187#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
188#[reference(instance_of = "DragEvent")]
189#[reference(event = "dragend")]
190#[reference(subclass_of(Event, UiEvent, MouseEvent, DragRelatedEvent))]
191pub struct DragEndEvent(Reference);
192
193impl IEvent for DragEndEvent {}
194
195impl IUiEvent for DragEndEvent {}
196
197impl IMouseEvent for DragEndEvent {}
198
199impl IDragEvent for DragEndEvent {}
200
201/// The DataTransfer object is used to hold the data that is being dragged during a drag and drop
202/// operation.
203///
204/// It may hold one or more data items, each of one or more data types.
205/// For more information about drag and drop, see HTML Drag and Drop API.
206///
207/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer)
208// https://www.w3.org/TR/html51/editing.html#datatransfer-datatransfer
209#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
210#[reference(instance_of = "DataTransfer")]
211pub struct DataTransfer( Reference );
212impl DataTransfer {
213 /// Gets the type of drag-and-drop operation currently selected type.
214 /// The value must be none, copy, link or move.
215 ///
216 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/dropEffect)
217 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-dropeffect-2
218 pub fn drop_effect( &self ) -> DropEffect {
219 let v: String = js!(
220 return @{self.as_ref()}.dropEffect;
221 ).try_into().unwrap();
222 match v.as_ref() {
223 "copy" => DropEffect::Copy,
224 "move" => DropEffect::Move,
225 "link" => DropEffect::Link,
226 "none" => DropEffect::None,
227 other => panic!("Expected valid dropEffect value, got {:?}", other),
228 }
229 }
230
231 /// Sets the type of drag-and-drop operation currently selected.
232 /// The value must be none, copy, link or move.
233 ///
234 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/dropEffect)
235 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-dropeffect-2
236 pub fn set_drop_effect( &self, value: DropEffect ) {
237 js! { @(no_return)
238 @{self.as_ref()}.dropEffect = @{match value {
239 DropEffect::Copy => "copy",
240 DropEffect::Move => "move",
241 DropEffect::Link => "link",
242 DropEffect::None => "none",
243 }};
244 }
245 }
246
247 /// Provides all of the types of operations that are possible.
248 /// Must be one of none, copy, copyLink, copyMove, link, linkMove, move, all or uninitialized.
249 ///
250 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/effectAllowed)
251 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-effectallowed-1
252 pub fn effect_allowed( &self ) -> EffectAllowed {
253 let v: String = js!(
254 return @{self.as_ref()}.effectAllowed;
255 ).try_into().unwrap();
256 match v.as_ref() {
257 "none" => EffectAllowed::None,
258 "copy" => EffectAllowed::Copy,
259 "copyLink" => EffectAllowed::CopyLink,
260 "copyMove" => EffectAllowed::CopyMove,
261 "link" => EffectAllowed::Link,
262 "linkMove" => EffectAllowed::LinkMove,
263 "move" => EffectAllowed::Move,
264 "all" => EffectAllowed::All,
265 "uninitialized" => EffectAllowed::Uninitialized,
266 other => panic!("Expected valid effectAllowed value, got {:?}", other),
267 }
268 }
269
270 /// Sets the effect that is allowed for a drag operation.
271 /// Must be one of none, copy, copyLink, copyMove, link, linkMove, move, all or uninitialized.
272 ///
273 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/effectAllowed)
274 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-effectallowed-1
275 pub fn set_effect_allowed( &self, value: EffectAllowed ) {
276 js! { @(no_return)
277 @{self.as_ref()}.effectAllowed = @{match value {
278 EffectAllowed::None => "none",
279 EffectAllowed::Copy => "copy",
280 EffectAllowed::CopyLink => "copyLink",
281 EffectAllowed::CopyMove => "copyMove",
282 EffectAllowed::Link => "link",
283 EffectAllowed::LinkMove => "linkMove",
284 EffectAllowed::Move => "move",
285 EffectAllowed::All => "all",
286 EffectAllowed::Uninitialized => "uninitialized",
287 }};
288 }
289 }
290
291 /// Gives a DataTransferItemList object which is a list of all of the drag data.
292 ///
293 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/items)
294 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-items-1
295 pub fn items( &self ) -> DataTransferItemList {
296 js!(
297 return @{self.as_ref()}.items;
298 ).try_into().unwrap()
299 }
300
301 /// Contains a list of all the local files available on the data transfer.
302 /// If the drag operation doesn't involve dragging files, this property is an empty list.
303 ///
304 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/files)
305 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-files-1
306 pub fn files( &self ) -> FileList {
307 js!(
308 return @{self.as_ref()}.files;
309 ).try_into().unwrap()
310 }
311
312 /// An array of strings giving the formats that were set in the dragstart event.
313 ///
314 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/types)
315 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-types-1
316 pub fn types( &self ) -> Vec<String> {
317 js!(
318 return @{self.as_ref()}.types;
319 ).try_into().unwrap()
320 }
321
322 /// Remove the data associated with a given type. The type argument is optional.
323 /// If the type is empty or not specified, the data associated with all types is removed.
324 /// If data for the specified type does not exist, or the data transfer contains no data,
325 /// this method will have no effect.
326 ///
327 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/clearData)
328 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-cleardata-1
329 pub fn clear_data( &self, format: Option<&str> ) {
330 match format {
331 None => js!(@(no_return) @{self.as_ref()}.clearData()),
332 Some(x) => js!(@(no_return) @{self.as_ref()}.clearData(@{x}))
333 };
334 }
335
336 /// Retrieves the data for a given type, or an empty string if data for that type does not exist
337 /// or the data transfer contains no data.
338 ///
339 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/getData)
340 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-getdata-1
341 pub fn get_data( &self, format: &str ) -> String {
342 js!(
343 return @{self.as_ref()}.getData(@{format});
344 ).try_into().unwrap()
345 }
346
347 /// Set the data for a given type.
348 /// If data for the type does not exist, it is added at the end, such that the last item in the
349 /// types list will be the new format.
350 /// If data for the type already exists, the existing data is replaced in the same position.
351 ///
352 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setData)
353 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-setdata-1
354 pub fn set_data( &self, format: &str, data: &str ) {
355 js!(@(no_return)
356 @{self.as_ref()}.setData(@{format}, @{data});
357 );
358 }
359
360 /// Set the image to be used for dragging if a custom one is desired.
361 ///
362 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setDragImage)
363 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-setdragimage-1
364 pub fn set_drag_image( &self, img: &ImageElement, x_offset: i32, y_offset: i32 ) {
365 js!(@(no_return)
366 @{self.as_ref()}.setDragImage(@{img.as_ref()}, @{x_offset}, @{y_offset});
367 );
368 }
369}
370
371/// A DOMString representing the drag operation effect.
372// https://www.w3.org/TR/html51/editing.html#dom-datatransfer-dropeffect
373#[derive(Clone, Copy, Debug, PartialEq, Eq)]
374pub enum DropEffect {
375 /// A copy of the source item is made at the new location
376 Copy,
377 /// An item is moved to a new location.
378 Move,
379 /// A link is established to the source at the new location.
380 Link,
381 /// The item may not be dropped.
382 None,
383}
384
385/// A DOMString representing the drag operation that is allowed.
386// https://www.w3.org/TR/html51/editing.html#dom-datatransfer-effectallowed
387#[derive(Clone, Copy, Debug, PartialEq, Eq)]
388pub enum EffectAllowed {
389 /// The item may not be dropped.
390 None,
391 /// A copy of the source item may be made at the new location.
392 Copy,
393 /// A copy or link operation is permitted.
394 CopyLink,
395 /// A copy or move operation is permitted.
396 CopyMove,
397 /// A link may be established to the source at the new location.
398 Link,
399 /// A link or move operation is permitted.
400 LinkMove,
401 /// An item may be moved to a new location.
402 Move,
403 /// All operations are permitted.
404 All,
405 /// The default value when the effect has not been set, equivalent to all.
406 Uninitialized,
407}
408
409/// The DataTransferItemList object is a list of DataTransferItem objects representing items being
410/// dragged.
411/// During a drag operation, each DragEvent has a dataTransfer property and that property is a
412/// DataTransferItemList.
413///
414/// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList)
415// https://www.w3.org/TR/html51/editing.html#datatransferitemlist-datatransferitemlist
416#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
417#[reference(instance_of = "DataTransferItemList")]
418pub struct DataTransferItemList( Reference );
419impl DataTransferItemList {
420 /// An unsigned long that is the number of drag items in the list.
421 ///
422 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList/length)
423 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitemlist-length-1
424 pub fn len( &self ) -> u32 {
425 js!(
426 return @{self.as_ref()}.length;
427 ).try_into().unwrap()
428 }
429
430 /// Adds an item of kind "string" to the drag item list and returns
431 /// a DataTransferItem object for the new item.
432 ///
433 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList/add)
434 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitemlist-add-1
435 pub fn add_string( &self, data: &str, ty: &str ) -> Result<Option<DataTransferItem>, NotSupportedError> {
436 js_try!(
437 return @{self.as_ref()}.add(@{data}, @{ty});
438 ).unwrap()
439 }
440
441 /// Adds an item of kind "file" to the drag item list and returns
442 /// a DataTransferItem object for the new item.
443 ///
444 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList/add)
445 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitemlist-add-2
446 pub fn add_file( &self, file: &File ) -> Option<DataTransferItem> {
447 js!(
448 return @{self.as_ref()}.add(@{file});
449 ).try_into().unwrap()
450 }
451
452 /// Removes the drag item from the list at the given index.
453 ///
454 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList/remove)
455 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitemlist-remove-1
456 pub fn remove( &self, index: u32 ) -> Result<(), InvalidStateError> {
457 js_try!(@{self.as_ref()}.remove(@{index})).unwrap()
458 }
459
460 /// Removes all of the drag items from the list.
461 ///
462 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList/clear)
463 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitemlist-clear-1
464 pub fn clear( &self ) {
465 js!(@(no_return) @{self.as_ref()}.clear());
466 }
467
468 /// Getter that returns a DataTransferItem at the given index.
469 ///
470 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList/DataTransferItem)
471 // https://www.w3.org/TR/html51/editing.html#ref-for-datatransferitem-datatransferitem-1
472 pub fn index( &self, index: u32 ) -> Option<DataTransferItem> {
473 let v: Value = js!(
474 return @{self.as_ref()}[@{index}];
475 );
476 match v {
477 Value::Reference(_) => Some(v.try_into().unwrap()),
478 _ => None,
479 }
480 }
481
482 /// Returns an iterator over the list
483 pub fn iter( &self ) -> DataTransferItemIter {
484 DataTransferItemIter {
485 list: self.clone(),
486 index: 0,
487 }
488 }
489}
490
491impl IntoIterator for DataTransferItemList {
492 type Item = DataTransferItem;
493 type IntoIter = DataTransferItemIter;
494
495 #[inline]
496 fn into_iter( self ) -> Self::IntoIter {
497 DataTransferItemIter {
498 list: self,
499 index: 0
500 }
501 }
502}
503
504impl< 'a > IntoIterator for &'a DataTransferItemList {
505 type Item = DataTransferItem;
506 type IntoIter = DataTransferItemIter;
507
508 #[inline]
509 fn into_iter( self ) -> Self::IntoIter {
510 DataTransferItemIter {
511 list: self.clone(),
512 index: 0
513 }
514 }
515}
516
517impl Iterator for DataTransferItemIter {
518 type Item = DataTransferItem;
519
520 fn next( &mut self ) -> Option< Self::Item > {
521 let v = self.list.index(self.index);
522 if v.is_some() {
523 self.index += 1;
524 }
525 v
526 }
527}
528
529#[derive(Debug)]
530pub struct DataTransferItemIter {
531 list: DataTransferItemList,
532 index: u32,
533}
534
535/// The DataTransferItem object represents one drag data item. During a drag operation, each drag
536/// event has a dataTransfer property which contains a list of drag data items. Each item in the
537/// list is a DataTransferItem object.
538///
539/// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem)
540// https://www.w3.org/TR/html51/editing.html#datatransferitem-datatransferitem
541#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
542#[reference(instance_of = "DataTransferItem")]
543pub struct DataTransferItem( Reference );
544
545impl DataTransferItem {
546 /// The kind of drag data item, string or file.
547 ///
548 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/kind)
549 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitem-kind-13
550 pub fn kind( &self ) -> DataTransferItemKind {
551 let kind: String = js!(
552 return @{self.as_ref()}.kind;
553 ).try_into().unwrap();
554 match kind.as_ref() {
555 "string" => DataTransferItemKind::String,
556 "file" => DataTransferItemKind::File,
557 other => DataTransferItemKind::__Other(OtherKind { name: String::from(other) }),
558 }
559 }
560
561 /// The drag data item's type, typically a MIME type.
562 ///
563 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/type)
564 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitem-type-2
565 pub fn ty( &self ) -> String {
566 js!(
567 return @{self.as_ref()}.type;
568 ).try_into().unwrap()
569 }
570
571 /// Returns the File object associated with the drag data item
572 /// (or null if the drag item is not a file)
573 ///
574 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/getAsFile)
575 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitem-getasfile-1
576 pub fn get_as_file( &self ) -> Option<File> {
577 js!(
578 return @{self.as_ref()}.getAsFile();
579 ).try_into().unwrap()
580 }
581
582 /// Invokes the specified callback with the drag data item string as its argument.
583 ///
584 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/getAsString)
585 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitem-getasstring-1
586 pub fn get_as_string<F>( &self, callback: F )
587 where F: FnOnce(String) + 'static {
588 js!(@(no_return)
589 @{self.as_ref()}.getAsString(@{Once(callback)});
590 );
591 }
592
593 /// Invokes the specified callback with the drag data item string as its argument.
594 ///
595 /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/getAsString)
596 // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitem-getasstring-1
597 #[cfg(feature = "futures-support")]
598 pub fn get_as_string_future( &self ) -> oneshot::Receiver<String> {
599 let (sender, receiver) = oneshot::channel();
600 let callback = |s: String| {
601 match sender.send(s) {
602 Ok(_) => {},
603 Err(_) => {},
604 };
605 };
606
607 js!(@(no_return)
608 @{self.as_ref()}.getAsString(@{Once(callback)});
609 );
610
611 receiver
612 }
613}
614
615/// The kind of drag data item, string or file.
616///
617/// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/kind)
618// https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitem-kind-13
619// TODO use #[non_exhaustive] when available
620#[derive(Clone, Debug, PartialEq, Eq)]
621pub enum DataTransferItemKind {
622 /// If the drag data item is a file.
623 File,
624 /// If the kind of drag data item is a plain Unicode string.
625 String,
626 /// If the kind of drag data is something different (e.g. dragging an <img /> tag in Firefox)
627 #[doc(hidden)]
628 __Other(OtherKind),
629}
630
631impl DataTransferItemKind {
632 /// Returns the string representation of this DataTransferItemKind
633 /// Useful in case the browser returns a non-standard kind that you want to special case.
634 pub fn as_str( &self ) -> &str {
635 match *self {
636 DataTransferItemKind::File => "file",
637 DataTransferItemKind::String => "string",
638 DataTransferItemKind::__Other( ref other_kind ) => &other_kind.name
639 }
640 }
641}
642
643#[derive(Clone, Debug, PartialEq, Eq)]
644pub struct OtherKind {
645 name: String,
646}
647
648#[cfg(all(test, feature = "web_test"))]
649mod tests {
650 use super::*;
651 use webapi::event::ConcreteEvent;
652
653 #[test]
654 fn test_drag_event() {
655 let event: DragRelatedEvent = js!(
656 return new DragEvent(
657 @{DragStartEvent::EVENT_TYPE},
658 {
659 dataTransfer: new DataTransfer()
660 }
661 );
662 ).try_into().unwrap();
663
664 // effects
665 assert_eq!(event.event_type(), DragStartEvent::EVENT_TYPE);
666 assert_eq!(event.data_transfer().unwrap().effect_allowed(), EffectAllowed::None);
667 assert_eq!(event.data_transfer().unwrap().drop_effect(), DropEffect::None);
668 event.data_transfer().unwrap().set_effect_allowed(EffectAllowed::CopyMove);
669 event.data_transfer().unwrap().set_drop_effect(DropEffect::Copy);
670 // TODO how to test? can only set these during ondragstart event triggered in browser
671 // assert_eq!(event.data_transfer().effect_allowed(), EffectAllowed::CopyMove);
672 // assert_eq!(event.data_transfer().drop_effect(), DropEffect::Copy);
673
674 // get, set, clear data
675 event.data_transfer().unwrap().set_data("myformat", "mydata");
676 event.data_transfer().unwrap().set_data("myformat2", "mydata2");
677 event.data_transfer().unwrap().clear_data(Some("myformat3"));
678 assert_eq!(event.data_transfer().unwrap().get_data("myformat"), String::from("mydata"));
679 event.data_transfer().unwrap().clear_data(Some("myformat"));
680 assert_eq!(event.data_transfer().unwrap().get_data("myformat"), String::from(""));
681 assert_eq!(event.data_transfer().unwrap().get_data("myformat2"), String::from("mydata2"));
682 event.data_transfer().unwrap().clear_data(None);
683 assert_eq!(event.data_transfer().unwrap().get_data("myformat2"), String::from(""));
684 let img = ImageElement::new();
685 event.data_transfer().unwrap().set_drag_image(&img, 10, 10);
686
687 // types
688 assert_eq!(event.data_transfer().unwrap().types().len(), 0);
689
690 // items
691 assert_eq!(event.data_transfer().unwrap().items().len(), 0);
692 let data = "mydata";
693 let ty = "text/plain";
694 let item = event.data_transfer().unwrap().items().add_string(data, ty).unwrap().unwrap();
695 assert_eq!(item.ty(), ty);
696 assert_eq!(item.kind(), DataTransferItemKind::String);
697 // TODO(https://github.com/koute/stdweb/issues/128) fix when async unit testing is available
698 // item.get_as_string().and_then(|s| {
699 // assert_eq!(data, s);
700 // assert_eq!(1, 1);
701 // assert_eq!(2, 1);
702 // });
703 let filename = "myname";
704 let file = js!(return new File(["content"], @{filename})).try_into().unwrap();
705 event.data_transfer().unwrap().items().add_file(&file).unwrap();
706 assert_eq!(event.data_transfer().unwrap().items().len(), 2);
707 assert_eq!(event.data_transfer().unwrap().items().iter().count(), 2);
708 assert!(event.data_transfer().unwrap().items().index(2).is_none());
709 assert_eq!(event.data_transfer().unwrap().files().len(), 1);
710 let item = event.data_transfer().unwrap().items().index(1).unwrap();
711 assert_eq!(item.kind(), DataTransferItemKind::File);
712 assert_eq!(item.get_as_file().unwrap().name(), filename);
713 let result = event.data_transfer().unwrap().items().remove(0);
714 assert!(result.is_ok());
715 assert_eq!(event.data_transfer().unwrap().items().len(), 1);
716 event.data_transfer().unwrap().items().clear();
717 assert_eq!(event.data_transfer().unwrap().items().len(), 0);
718 }
719}