///|
fn Browser::is_draggable_source_id(self : Browser, source_id : String) -> Bool {
if !self.enable_js {
return false
}
let escaped = escape_js_string(source_id)
match
self.execute_inline_js(
"(function(){const target=document.getElementById('" +
escaped +
"');return target&&target.draggable===true?'true':'false';})()",
) {
Some("true") => true
_ => false
}
}
///|
fn Browser::dispatch_drag_event_status_to_source_id(
self : Browser,
source_id : String,
event_type : String,
client_x : Int,
client_y : Int,
related_source_id? : String? = None,
) -> (Bool, Bool) {
let escaped = escape_js_string(source_id)
let related_js = match related_source_id {
Some(id) => "document.getElementById('" + escape_js_string(id) + "')"
None => "null"
}
let source = "(function(){const target=document.getElementById('" +
escaped +
"');if(!target){return 'missing';}const clientX=" +
client_x.to_string() +
";const clientY=" +
client_y.to_string() +
";const relatedTarget=" +
related_js +
";let dataTransfer=globalThis.__craterDragDataTransfer||null;if('" +
escape_js_string(event_type) +
"'==='dragstart'){dataTransfer=new DataTransfer();globalThis.__craterDragDataTransfer=dataTransfer;}const dispatched=target.dispatchEvent(new DragEvent('" +
escape_js_string(event_type) +
"',{bubbles:true,cancelable:true,clientX,clientY,relatedTarget,dataTransfer}));if('" +
escape_js_string(event_type) +
"'==='dragend'){globalThis.__craterDragDataTransfer=null;}return dispatched?'ok':'canceled';})()"
let result = self.execute_inline_js(source)
let _ = self.sync_render_state_from_dom_tree()
match result {
Some("ok") => (true, false)
Some("canceled") => (true, true)
_ => (false, false)
}
}
///|
fn Browser::dispatch_drag_event_to_source_id(
self : Browser,
source_id : String,
event_type : String,
client_x : Int,
client_y : Int,
related_source_id? : String? = None,
) -> Bool {
let (handled, _) = self.dispatch_drag_event_status_to_source_id(
source_id,
event_type,
client_x,
client_y,
related_source_id~,
)
handled
}
///|
fn Browser::is_current_drop_allowed(self : Browser) -> Bool {
match
self.execute_inline_js(
"(function(){const dt=globalThis.__craterDragDataTransfer||null;if(!dt){return 'none/none';}const allowed=String(dt.effectAllowed||'all').toLowerCase();let drop=String(dt.dropEffect||'none').toLowerCase();function fallbackDropEffect(v){switch(v){case 'copy':case 'copylink':case 'copymove':return 'copy';case 'link':case 'linkmove':return 'link';case 'move':return 'move';case 'all':case 'uninitialized':return 'copy';default:return 'none';}}if(drop==='none'){const fallback=fallbackDropEffect(allowed);if(fallback!=='none'){dt.dropEffect=fallback;drop=fallback;}}return allowed + '/' + drop;})()",
) {
Some("none/none") => false
Some(state) => {
let slash = state.find("/")
match slash {
Some(idx) => {
let effect_allowed = state
.unsafe_substring(start=0, end=idx)
.to_lower()
let drop_effect = state
.unsafe_substring(start=idx + 1, end=state.length())
.to_lower()
@interaction_policy.is_drop_effect_compatible(
effect_allowed, drop_effect,
)
}
None => false
}
}
None => false
}
}