Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

web_sys cfg conversion #862

Merged
merged 6 commits into from
Jan 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ travis-ci = { repository = "yewstack/yew" }
[dependencies]
anymap = "0.12"
bincode = { version = "~1.2.1", optional = true }
cfg-if = "0.1"
cfg-match = "0.2"
console_error_panic_hook = { version = "0.1", optional = true }
failure = "0.1"
gloo = { version = "0.2", optional = true }
Expand Down
12 changes: 8 additions & 4 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@

use crate::html::{Component, NodeRef, Scope};
use crate::utils::document;
#[cfg(feature = "std_web")]
use stdweb::web::{Element, INode, IParentNode};
#[cfg(feature = "web_sys")]
use web_sys::Element;
use cfg_if::cfg_if;
cfg_if! {
if #[cfg(feature = "std_web")] {
use stdweb::web::{Element, INode, IParentNode};
} else if #[cfg(feature = "web_sys")] {
use web_sys::Element;
}
}

/// An application instance.
#[derive(Debug)]
Expand Down
9 changes: 5 additions & 4 deletions src/components/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
use crate::callback::Callback;
use crate::html::{ChangeData, Component, ComponentLink, Html, ShouldRender};
use crate::macros::{html, Properties};
use cfg_match::cfg_match;

/// `Select` component.
#[derive(Debug)]
Expand Down Expand Up @@ -122,10 +123,10 @@ where
self.link.callback(|event| match event {
ChangeData::Select(elem) => {
let value = elem.selected_index();
#[cfg(feature = "std_web")]
let value = value.map(|x| x as usize);
#[cfg(feature = "web_sys")]
let value = Some(value as usize);
let value = cfg_match! {
feature = "std_web" => value.map(|x| x as usize),
feature = "web_sys" => Some(value as usize),
};
Msg::Selected(value)
}
_ => {
Expand Down
31 changes: 15 additions & 16 deletions src/html/listener/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,22 @@ macro_rules! impl_action {
($($action:ident(name: $name:literal, event: $type:ident) -> $ret:ty => $convert:expr)*) => {$(
/// An abstract implementation of a listener.
pub mod $action {
use cfg_if::cfg_if;
use cfg_match::cfg_match;
use crate::callback::Callback;
#[allow(unused_imports)]
use crate::html::listener::*;
use crate::virtual_dom::Listener;
#[cfg(feature = "std_web")]
use stdweb::web::{
event::{$type, IEvent},
Element, IEventTarget,
};
#[cfg(feature = "web_sys")]
use ::{
gloo::events::EventListener,
wasm_bindgen::JsValue,
web_sys::{$type as WebSysType, Element, EventTarget},
};
cfg_if! {
if #[cfg(feature = "std_web")] {
use stdweb::web::event::{$type, IEvent};
use stdweb::web::{Element, IEventTarget};
} else if #[cfg(feature = "web_sys")] {
use gloo::events::EventListener;
use wasm_bindgen::JsValue;
use web_sys::{$type as WebSysType, Element, EventTarget};
}
}

/// A wrapper for a callback which attaches event listeners to elements.
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -55,12 +56,10 @@ macro_rules! impl_action {
let event: WebSysType = JsValue::from(event).into();
callback.emit($convert(&this, event));
};
#[cfg(feature = "std_web")]
{
EventListener(Some(element.add_event_listener(listener)))
cfg_match! {
feature = "std_web" => EventListener(Some(element.add_event_listener(listener))),
feature = "web_sys" => EventListener::new(&EventTarget::from(element.clone()), $name, listener),
}
#[cfg(feature = "web_sys")]
EventListener::new(&EventTarget::from(element.clone()), $name, listener)
}
}
}
Expand Down
126 changes: 65 additions & 61 deletions src/html/listener/mod.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
#[macro_use]
mod macros;
#[cfg(feature = "std_web")]
mod listener_stdweb;
#[cfg(feature = "web_sys")]
mod listener_web_sys;

#[cfg(feature = "std_web")]
pub use listener_stdweb::*;
#[cfg(feature = "web_sys")]
pub use listener_web_sys::*;
#[cfg(feature = "std_web")]
use stdweb::{
js,
unstable::TryInto,
web::{
html_element::{InputElement, SelectElement, TextAreaElement},
Element, EventListenerHandle, FileList, IElement, INode,
},
};
#[cfg(feature = "web_sys")]
use ::{
wasm_bindgen::JsCast,
web_sys::{
Element, FileList, HtmlInputElement as InputElement, HtmlSelectElement as SelectElement,
HtmlTextAreaElement as TextAreaElement,
},
};
use cfg_if::cfg_if;
use cfg_match::cfg_match;

cfg_if! {
if #[cfg(feature = "std_web")] {
mod listener_stdweb;

use stdweb::js;
use stdweb::unstable::{TryFrom, TryInto};
use stdweb::web::html_element::{InputElement, SelectElement, TextAreaElement};
use stdweb::web::{Element, EventListenerHandle, FileList, IElement, INode};

pub use listener_stdweb::*;
} else if #[cfg(feature = "web_sys")] {
mod listener_web_sys;

use wasm_bindgen::JsCast;
use web_sys::{
Element, FileList, HtmlInputElement as InputElement, HtmlSelectElement as SelectElement,
HtmlTextAreaElement as TextAreaElement,
};

pub use listener_web_sys::*;
}
}

/// A type representing data from `oninput` event.
#[derive(Debug)]
Expand Down Expand Up @@ -60,22 +60,26 @@ fn oninput_handler(this: &Element) -> InputData {
// practice though any element with `contenteditable=true` may generate such events,
// therefore here we fall back to just returning the text content of the node.
// See https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event.
#[cfg(feature = "std_web")]
let (v1, v2) = (
this.clone()
.try_into()
.map(|input: InputElement| input.raw_value())
.ok(),
this.clone()
.try_into()
.map(|input: TextAreaElement| input.value())
.ok(),
);
#[cfg(feature = "web_sys")]
let (v1, v2) = (
this.dyn_ref().map(|input: &InputElement| input.value()),
this.dyn_ref().map(|input: &TextAreaElement| input.value()),
);
let (v1, v2) = cfg_match! {
feature = "std_web" => ({
(
this.clone()
.try_into()
.map(|input: InputElement| input.raw_value())
.ok(),
this.clone()
.try_into()
.map(|input: TextAreaElement| input.value())
.ok(),
)
}),
feature = "web_sys" => ({
(
this.dyn_ref().map(|input: &InputElement| input.value()),
this.dyn_ref().map(|input: &TextAreaElement| input.value()),
)
}),
};
let v3 = this.text_content();
let value = v1.or(v2).or(v3)
.expect("only an InputElement or TextAreaElement or an element with contenteditable=true can have an oninput event listener");
Expand All @@ -85,39 +89,39 @@ fn oninput_handler(this: &Element) -> InputData {
fn onchange_handler(this: &Element) -> ChangeData {
match this.node_name().as_ref() {
"INPUT" => {
#[cfg(feature = "std_web")]
let input: InputElement = this.clone().try_into().unwrap();
#[cfg(feature = "web_sys")]
let input: &InputElement = this.dyn_ref().unwrap();
let input = cfg_match! {
feature = "std_web" => InputElement::try_from(this.clone()).unwrap(),
feature = "web_sys" => this.dyn_ref::<InputElement>().unwrap(),
};
let is_file = input
.get_attribute("type")
.map(|value| value.eq_ignore_ascii_case("file"))
.unwrap_or(false);
if is_file {
#[cfg(feature = "std_web")]
let files: FileList = js!( return @{input}.files; ).try_into().unwrap();
#[cfg(feature = "web_sys")]
let files: FileList = input.files().unwrap();
let files: FileList = cfg_match! {
feature = "std_web" => js!( return @{input}.files; ).try_into().unwrap(),
feature = "web_sys" => input.files().unwrap(),
};
ChangeData::Files(files)
} else {
#[cfg(feature = "std_web")]
return ChangeData::Value(input.raw_value());
#[cfg(feature = "web_sys")]
ChangeData::Value(input.value())
cfg_match! {
feature = "std_web" => ChangeData::Value(input.raw_value()),
feature = "web_sys" => ChangeData::Value(input.value()),
}
}
}
"TEXTAREA" => {
#[cfg(feature = "std_web")]
let tae: TextAreaElement = this.clone().try_into().unwrap();
#[cfg(feature = "web_sys")]
let tae: &TextAreaElement = this.dyn_ref().unwrap();
let tae = cfg_match! {
feature = "std_web" => TextAreaElement::try_from(this.clone()).unwrap(),
feature = "web_sys" => this.dyn_ref::<TextAreaElement>().unwrap(),
};
ChangeData::Value(tae.value())
}
"SELECT" => {
#[cfg(feature = "std_web")]
let se: SelectElement = this.clone().try_into().unwrap();
#[cfg(feature = "web_sys")]
let se = this.dyn_ref::<SelectElement>().unwrap().clone();
let se = cfg_match! {
feature = "std_web" => SelectElement::try_from(this.clone()).unwrap(),
feature = "web_sys" => this.dyn_ref::<SelectElement>().unwrap().clone(),
};
ChangeData::Select(se)
}
_ => {
Expand Down
23 changes: 14 additions & 9 deletions src/html/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,21 @@ pub use scope::{Scope, ScopeHolder};

use crate::callback::Callback;
use crate::virtual_dom::{VChild, VList, VNode};
use cfg_if::cfg_if;
use cfg_match::cfg_match;
use std::any::TypeId;
use std::cell::RefCell;
use std::fmt;
use std::rc::Rc;
#[cfg(feature = "std_web")]
use stdweb::{unstable::TryFrom, web::Node};
#[cfg(feature = "web_sys")]
use ::{wasm_bindgen::JsValue, web_sys::Node};
cfg_if! {
if #[cfg(feature = "std_web")] {
use stdweb::unstable::TryFrom;
use stdweb::web::Node;
} else if #[cfg(feature = "web_sys")] {
use wasm_bindgen::JsValue;
use web_sys::Node;
}
}

/// This type indicates that component should be rendered again.
pub type ShouldRender = bool;
Expand Down Expand Up @@ -324,12 +331,10 @@ impl NodeRef {
&self,
) -> Option<INTO> {
let node = self.get();
#[cfg(feature = "std_web")]
{
node.and_then(|node| INTO::try_from(node).ok())
cfg_match! {
feature = "std_web" => node.and_then(|node| INTO::try_from(node).ok()),
feature = "web_sys" => node.map(Into::into).map(INTO::from),
}
#[cfg(feature = "web_sys")]
node.map(Into::into).map(INTO::from)
}

/// Place a Node in a reference for later use
Expand Down
12 changes: 8 additions & 4 deletions src/html/scope.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
use super::*;
use crate::scheduler::{scheduler, Runnable, Shared};
use crate::virtual_dom::{VDiff, VNode};
use cfg_if::cfg_if;
use std::cell::RefCell;
use std::fmt;
use std::rc::Rc;
#[cfg(feature = "std_web")]
use stdweb::web::Element;
#[cfg(feature = "web_sys")]
use web_sys::Element;
cfg_if! {
if #[cfg(feature = "std_web")] {
use stdweb::web::Element;
} else if #[cfg(feature = "web_sys")] {
use web_sys::Element;
}
}

/// Updates for a `Component` instance. Used by scope sender.
pub(crate) enum ComponentUpdate<COMP: Component> {
Expand Down
47 changes: 27 additions & 20 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,32 +99,39 @@ pub mod services;

/// The module that contains all events available in the framework.
pub mod events {
use cfg_if::cfg_if;

pub use crate::html::{ChangeData, InputData};

#[cfg(feature = "std_web")]
pub use stdweb::web::event::{
BlurEvent, ClickEvent, ContextMenuEvent, DoubleClickEvent, DragDropEvent, DragEndEvent,
DragEnterEvent, DragEvent, DragExitEvent, DragLeaveEvent, DragOverEvent, DragStartEvent,
FocusEvent, GotPointerCaptureEvent, IKeyboardEvent, IMouseEvent, IPointerEvent,
KeyDownEvent, KeyPressEvent, KeyUpEvent, LostPointerCaptureEvent, MouseDownEvent,
MouseEnterEvent, MouseLeaveEvent, MouseMoveEvent, MouseOutEvent, MouseOverEvent,
MouseUpEvent, MouseWheelEvent, PointerCancelEvent, PointerDownEvent, PointerEnterEvent,
PointerLeaveEvent, PointerMoveEvent, PointerOutEvent, PointerOverEvent, PointerUpEvent,
ScrollEvent, SubmitEvent, TouchCancel, TouchEnd, TouchEnter, TouchMove, TouchStart,
};
#[cfg(feature = "web_sys")]
pub use web_sys::{
DragEvent, Event, FocusEvent, KeyboardEvent, MouseEvent, PointerEvent, TouchEvent, UiEvent,
WheelEvent,
};
cfg_if! {
if #[cfg(feature = "std_web")] {
pub use stdweb::web::event::{
BlurEvent, ClickEvent, ContextMenuEvent, DoubleClickEvent, DragDropEvent, DragEndEvent,
DragEnterEvent, DragEvent, DragExitEvent, DragLeaveEvent, DragOverEvent, DragStartEvent,
FocusEvent, GotPointerCaptureEvent, IKeyboardEvent, IMouseEvent, IPointerEvent,
KeyDownEvent, KeyPressEvent, KeyUpEvent, LostPointerCaptureEvent, MouseDownEvent,
MouseEnterEvent, MouseLeaveEvent, MouseMoveEvent, MouseOutEvent, MouseOverEvent,
MouseUpEvent, MouseWheelEvent, PointerCancelEvent, PointerDownEvent, PointerEnterEvent,
PointerLeaveEvent, PointerMoveEvent, PointerOutEvent, PointerOverEvent, PointerUpEvent,
ScrollEvent, SubmitEvent, TouchCancel, TouchEnd, TouchEnter, TouchMove, TouchStart,
};
} else if #[cfg(feature = "web_sys")] {
pub use web_sys::{
DragEvent, Event, FocusEvent, KeyboardEvent, MouseEvent, PointerEvent, TouchEvent, UiEvent,
WheelEvent,
};
}
}
}

use cfg_match::cfg_match;

/// Initializes yew framework. It should be called first.
pub fn initialize() {
#[cfg(feature = "std_web")]
stdweb::initialize();
#[cfg(feature = "web_sys")]
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
cfg_match! {
feature = "std_web" => stdweb::initialize(),
feature = "web_sys" => std::panic::set_hook(Box::new(console_error_panic_hook::hook)),
};
}

/// Starts event loop.
Expand Down
Loading