Skip to content
This repository has been archived by the owner on Apr 29, 2023. It is now read-only.

Commit

Permalink
Stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
sindreij committed Nov 6, 2018
1 parent 3f1b8d8 commit 803a2cf
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 4 deletions.
20 changes: 19 additions & 1 deletion ded/src/events.rs
@@ -1,8 +1,10 @@
use std::default::Default;
use std::fmt::Debug;
use std::rc::Rc;

use wasm_bindgen::JsCast;

use crate::html::{Attribute, EventToMessage};
use crate::html::{Attribute, EventClosureImpl, EventToMessage, RcEventClosure};

pub fn on_click<Msg: Clone + 'static>(message: Msg) -> Attribute<Msg> {
Attribute::Event {
Expand Down Expand Up @@ -45,6 +47,22 @@ pub fn on_input<Msg: 'static>(message: fn(String) -> Msg) -> Attribute<Msg> {
}
}

// TODO: Ensure that when we start using animationFrame, on_input gets special treatement
pub fn on_input2<Msg: 'static + Debug, Data: Debug + Clone + PartialEq + 'static>(
data: Data,
message: fn(Data, String) -> Msg,
) -> Attribute<Msg> {
Attribute::Event {
type_: "input".to_owned(),
to_message: EventToMessage::InputWithClosure(RcEventClosure(Rc::new(
EventClosureImpl::new(data, message),
))),
stop_propagation: true,
prevent_default: false,
js_closure: Default::default(),
}
}

pub fn on_enter<Msg: Clone + 'static>(message: Msg) -> Attribute<Msg> {
Attribute::Event {
type_: "keydown".to_owned(),
Expand Down
46 changes: 46 additions & 0 deletions ded/src/html.rs
@@ -1,6 +1,7 @@
// TODO: Attributes
// TODO: Are we able to convert Html<A> to Html<B>?

use std::any::Any;
use std::cell::RefCell;
use std::cmp::PartialEq;
use std::fmt::{self, Debug};
Expand Down Expand Up @@ -116,10 +117,55 @@ impl<Msg> Attribute<Msg> {
}
}

pub trait EventClosure<Input, Msg>: Debug {
fn call_ish(&self, input: Input) -> Msg;
fn eq(&self, other: &Rc<EventClosure<Input, Msg>>) -> bool;
}

#[derive(Debug)]
pub struct EventClosureImpl<Input, Data, Msg> {
data: Data,
func: fn(Data, Input) -> Msg,
}

impl<Input, Data, Msg> EventClosureImpl<Input, Data, Msg> {
pub fn new(data: Data, func: fn(Data, Input) -> Msg) -> Self {
Self { data, func }
}
}

impl<Input: Debug + 'static, Data: PartialEq + Debug + Clone + 'static, Msg: Debug + 'static>
EventClosure<Input, Msg> for EventClosureImpl<Input, Data, Msg>
{
fn call_ish(&self, input: Input) -> Msg {
(self.func)(self.data.clone(), input)
}

fn eq(&self, other: &Rc<EventClosure<Input, Msg>>) -> bool {
let other = other as &Any;

if let Some(other_down) = other.downcast_ref::<EventClosureImpl<Input, Data, Msg>>() {
self.data == other_down.data && self.func == other_down.func
} else {
false
}
}
}

#[derive(Clone, Debug)]
pub struct RcEventClosure<Input, Msg>(pub Rc<EventClosure<Input, Msg>>);

impl<Input, Msg> PartialEq for RcEventClosure<Input, Msg> {
fn eq(&self, other: &RcEventClosure<Input, Msg>) -> bool {
self.eq(other)
}
}

#[derive(Clone, Debug, PartialEq)]
pub enum EventToMessage<Msg> {
StaticMsg(Msg),
Input(fn(String) -> Msg),
InputWithClosure(RcEventClosure<String, Msg>),
WithFilter {
msg: Msg,
filter: fn(web_sys::Event) -> bool,
Expand Down
13 changes: 12 additions & 1 deletion ded/src/render.rs
Expand Up @@ -8,7 +8,7 @@ use wasm_bindgen::JsCast;
use web_sys::{self, Document, HtmlElement, Node};

use crate::{
html::{Attribute, EventToMessage, Html, HtmlTag, PropertyValue},
html::{Attribute, EventClosure, EventToMessage, Html, HtmlTag, PropertyValue},
program::Program,
};

Expand Down Expand Up @@ -320,6 +320,17 @@ where
.map(|el| el.value())
.unwrap_or_default(),
)),
EventToMessage::InputWithClosure(closure) => program.dispatch(
&closure.0.call_ish(
event
.target()
.and_then(|target| {
target.dyn_into::<web_sys::HtmlInputElement>().ok()
})
.map(|el| el.value())
.unwrap_or_default(),
),
),
EventToMessage::WithFilter { msg, filter } => {
if filter(event) {
program.dispatch(msg);
Expand Down
4 changes: 2 additions & 2 deletions examples/todomvc/src/app.rs
Expand Up @@ -3,7 +3,7 @@ use ded::{
autofocus, checked, class, class_list, for_, hidden, href, id, name, placeholder, style,
type_, value,
},
events::{on_blur, on_click, on_double_click, on_enter, on_input},
events::{on_blur, on_click, on_double_click, on_enter, on_input, on_input2},
html::{
a, button, div, footer, h1, header, input, label, li, p, section, span, strong, text, ul,
Html,
Expand Down Expand Up @@ -210,7 +210,7 @@ fn view_entry(todo: &Entry) -> Html<Msg> {
value(&todo.description),
name("title"),
id(&format!("todo-{}", todo.id.to_string())),
// on_input(move |val| Msg::UpdateEntry(todo_id, val)),
on_input2(todo_id, |todo_id, val| Msg::UpdateEntry(todo_id, val)),
on_blur(Msg::EditingEntry(todo.id, false)),
on_enter(Msg::EditingEntry(todo.id, false)),
],
Expand Down

0 comments on commit 803a2cf

Please sign in to comment.