use std::ops::Deref;
use stdweb::{Reference, Value, JsSerialize, Once};
use stdweb::unstable::{TryFrom, TryInto};
use stdweb::web::{IEventTarget, INode, IElement, IHtmlElement, HtmlElement, Node, window, TextNode, EventTarget, Element};
use stdweb::web::event::ConcreteEvent;
use callbacks::Callbacks;
use traits::*;
use operations;
use operations::for_each;
use dom_operations;
use operations::{ValueDiscard, FnDiscard, spawn_future};
use futures_signals::signal::{IntoSignal, Signal};
use futures_signals::signal_vec::IntoSignalVec;
use futures_core::{Never, Async};
use futures_core::task::Context;
use futures_core::future::Future;
use futures_channel::oneshot;
use discard::{Discard, DiscardOnDrop};
pub struct DerefFn {
value: A,
callback: B,
}
impl DerefFn where B: ?Sized, C: Fn(&A) -> &B {
#[inline]
pub fn new(value: A, callback: C) -> Self {
Self { value, callback }
}
}
impl Deref for DerefFn where B: ?Sized, C: Fn(&A) -> &B {
type Target = B;
#[inline]
fn deref(&self) -> &Self::Target {
(self.callback)(&self.value)
}
}
// TODO this should be in stdweb
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "CSSStyleRule")]
pub struct CssStyleRule(Reference);
/// A reference to an SVG Element.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/SVGElement)
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "SVGElement")]
#[reference(subclass_of(EventTarget, Node, Element))]
pub struct SvgElement(Reference);
// https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS#Valid%20Namespace%20URIs
pub const HTML_NAMESPACE: &str = "http://www.w3.org/1999/xhtml";
pub const SVG_NAMESPACE: &str = "http://www.w3.org/2000/svg";
// 32-bit signed int
pub const HIGHEST_ZINDEX: &str = "2147483647";
// TODO this should be in stdweb
// TODO this should return HtmlBodyElement
pub fn body() -> HtmlElement {
js! ( return document.body; ).try_into().unwrap()
}
pub struct DomHandle {
parent: Node,
dom: Dom,
}
impl Discard for DomHandle {
#[inline]
fn discard(self) {
self.parent.remove_child(&self.dom.element).unwrap();
self.dom.callbacks.discard();
}
}
#[inline]
pub fn append_dom(parent: &A, mut dom: Dom) -> DomHandle {
parent.append_child(&dom.element);
dom.callbacks.trigger_after_insert();
// This prevents it from triggering after_remove
dom.callbacks.leak();
DomHandle {
parent: parent.as_node().clone(),
dom
}
}
struct IsWindowLoadedEvent {
callback: Value,
}
impl IsWindowLoadedEvent {
#[inline]
fn new(callback: F) -> Self where F: FnOnce() + 'static {
// TODO use a proper type for the event
let callback = move |_: Value| {
callback();
};
Self {
callback: js!(
var callback = @{Once(callback)};
addEventListener("load", callback, true);
return callback;
),
}
}
}
impl Drop for IsWindowLoadedEvent {
fn drop(&mut self) {
js! { @(no_return)
var callback = @{&self.callback};
removeEventListener("load", callback, true);
callback.drop();
}
}
}
enum IsWindowLoaded {
Initial {},
Pending {
receiver: oneshot::Receiver<()>,
event: IsWindowLoadedEvent,
},
Done {},
}
impl Signal for IsWindowLoaded {
type Item = bool;
fn poll_change(&mut self, cx: &mut Context) -> Async