Skip to content

Commit f5829b8

Browse files
committed
Merge troubleshooting
2 parents ea9de09 + 75ac8af commit f5829b8

File tree

7 files changed

+333
-213
lines changed

7 files changed

+333
-213
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ edition = "2018"
1616
crate-type = ["cdylib", "rlib"]
1717

1818
[dev-dependencies]
19-
wasm-bindgen-test = "^0.2.29" # NOTE: keep in sync with wasm-bindgen version
19+
wasm-bindgen-test = "^0.2.31" # NOTE: keep in sync with wasm-bindgen version
2020

2121
[dependencies]
22-
wasm-bindgen = {version = "^0.2.29", features = ["serde-serialize"]}
22+
wasm-bindgen = {version = "^0.2.31", features = ["serde-serialize"]}
2323
js-sys = "0.3.6"
2424
console_error_panic_hook = "^0.1.5"
2525
serde = { version = "^1.0.80", features = ['derive'] }

examples/homepage/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
The Seed homepage, also serving as an example. Includes
2-
simple interactions, markdown elements, basic routing, and view markup.
2+
simple interactions, markdown elements, routing, and view markup.
33

44
# [Homepage repo](https://github.com/David-OConnor/seed-homepage)

src/dom_types.rs

Lines changed: 118 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -11,39 +11,6 @@ use wasm_bindgen::{closure::Closure, JsCast};
1111
use crate::vdom::Mailbox;
1212

1313

14-
15-
16-
17-
// pub tag: Tag,
18-
// pub attrs: Attrs,
19-
// pub style: Style,
20-
// pub listeners: Vec<Listener<Ms>>,
21-
// pub text: Option<String>,
22-
// pub children: Vec<El<Ms>>,
23-
//
24-
// // Things that get filled in later, to assist with rendering.
25-
// pub id: Option<u32>, // todo maybe not optional...
26-
// pub nest_level: Option<u32>,
27-
// pub el_ws: Option<web_sys::Element>,
28-
//
29-
// // todo temp?
30-
//// pub key: Option<u32>,
31-
//
32-
// pub raw_html: bool,
33-
// pub namespace: Option<Namespace>,
34-
//
35-
// // static: bool
36-
// // static_to_parent: bool
37-
// // ancestors: Vec<u32> // ids of parent, grandparent etc.
38-
//
39-
// // Lifecycle hooks
40-
// pub did_mount: Option<Box<Fn(&web_sys::Element)>>,
41-
// pub did_update: Option<Box<Fn(&web_sys::Element)>>,
42-
// pub will_unmount: Option<Box<Fn(&web_sys::Element)>>,
43-
//
44-
//
45-
46-
4714
/// Common Namespaces
4815
#[derive(Debug,Clone,PartialEq)]
4916
pub enum Namespace {
@@ -148,6 +115,7 @@ impl<Ms: Clone + 'static> Listener<Ms> {
148115
}
149116
}
150117

118+
// todo deal with duplicates between the main methods and the trait
151119
/// This method is where the processing logic for events happens.
152120
pub fn attach<T>(&mut self, el_ws: &T, mailbox: Mailbox<Ms>)
153121
where T: AsRef<web_sys::EventTarget> {
@@ -181,6 +149,41 @@ impl<Ms: Clone + 'static> Listener<Ms> {
181149
}
182150
}
183151

152+
// todo don't have both method and trait fns for these
153+
impl<Ms: Clone + 'static> crate::vdom::Listener<Ms> for Listener<Ms> {
154+
/// This method is where the processing logic for events happens.
155+
fn attach<T>(&mut self, el_ws: &T, mailbox: Mailbox<Ms>)
156+
where T: AsRef<web_sys::EventTarget> {
157+
// This and detach taken from Draco.
158+
let mut handler = self.handler.take().expect("Can't find old handler");
159+
160+
let closure = Closure::wrap(
161+
Box::new(move |event: web_sys::Event| {
162+
mailbox.send(handler(event))
163+
})
164+
as Box<FnMut(web_sys::Event) + 'static>,
165+
);
166+
167+
(el_ws.as_ref() as &web_sys::EventTarget)
168+
.add_event_listener_with_callback(&self.trigger, closure.as_ref().unchecked_ref())
169+
.expect("problem adding listener to element");
170+
171+
// Store the closure so we can detach it later. Not detaching it when an element
172+
// is removed will trigger a panic.
173+
self.closure = Some(closure);
174+
// self.handler.replace(handler); // todo ?
175+
}
176+
177+
fn detach<T>(&self, el_ws: &T)
178+
where T: AsRef<web_sys::EventTarget> {
179+
// This and attach taken from Draco.
180+
let closure = self.closure.as_ref().unwrap();
181+
(el_ws.as_ref() as &web_sys::EventTarget)
182+
.remove_event_listener_with_callback(&self.trigger, closure.as_ref().unchecked_ref())
183+
.expect("problem removing listener from element");
184+
}
185+
}
186+
184187
impl<Ms: Clone + 'static> PartialEq for Listener<Ms> {
185188
fn eq(&self, other: &Self) -> bool {
186189
// todo we're only checking the trigger - will miss changes if
@@ -347,14 +350,6 @@ impl Attrs {
347350
result
348351
}
349352

350-
/// Create an HTML-compatible string representation
351-
pub fn to_string(&self) -> String {
352-
self.vals.iter()
353-
.map(|(k,v)|format!("{}=\"{}\"", k, v))
354-
.collect::<Vec<_>>()
355-
.join(" ")
356-
}
357-
358353
/// Add a new key, value pair
359354
pub fn add(&mut self, key: &str, val: &str) {
360355
self.vals.insert(key.to_string(), val.to_string());
@@ -377,6 +372,23 @@ impl Attrs {
377372
}
378373
}
379374

375+
// todo temp duplication of trait and main methods for vals
376+
impl crate::vdom::Attrs for Attrs {
377+
fn vals(self) -> HashMap<String, String> {
378+
self.vals
379+
}
380+
}
381+
382+
impl ToString for Attrs {
383+
/// Create an HTML-compatible string representation
384+
fn to_string(&self) -> String {
385+
self.vals.iter()
386+
.map(|(k,v)|format!("{}=\"{}\"", k, v))
387+
.collect::<Vec<_>>()
388+
.join(" ")
389+
}
390+
}
391+
380392
/// Handle Style separately from Attrs, since it commonly involves multiple parts,
381393
/// and has a different semantic meaning.
382394
#[derive(Clone, PartialEq)]
@@ -404,18 +416,6 @@ impl Style {
404416
Self { vals: HashMap::new() }
405417
}
406418

407-
/// Output style as a string, as would be set in the DOM as the attribute value
408-
/// for 'style'. Eg: "display: flex; font-size: 1.5em"
409-
pub fn to_string(&self) -> String {
410-
if self.vals.keys().len() > 0 {
411-
self.vals
412-
.iter()
413-
.map(|(k, v)| format!("{}:{}", k, v))
414-
.collect::<Vec<_>>()
415-
.join(";")
416-
} else { String::new() }
417-
}
418-
419419
pub fn add(&mut self, key: &str, val: &str) {
420420
self.vals.insert(key.to_string(), val.to_string());
421421
}
@@ -430,6 +430,27 @@ impl Style {
430430
}
431431
}
432432

433+
// todo temp duplication of trait and main methods for vals
434+
impl crate::vdom::Style for Style {
435+
fn vals(self) -> HashMap<String, String> {
436+
self.vals
437+
}
438+
}
439+
440+
impl ToString for Style {
441+
/// Output style as a string, as would be set in the DOM as the attribute value
442+
/// for 'style'. Eg: "display: flex; font-size: 1.5em"
443+
fn to_string(&self) -> String {
444+
if self.vals.keys().len() > 0 {
445+
self.vals
446+
.iter()
447+
.map(|(k, v)| format!("{}:{}", k, v))
448+
.collect::<Vec<_>>()
449+
.join(";")
450+
} else { String::new() }
451+
}
452+
}
453+
433454
/// Similar to tag population.
434455
macro_rules! make_events {
435456
// Create shortcut macros for any element; populate these functions in this module.
@@ -527,12 +548,12 @@ macro_rules! make_tags {
527548
)+
528549
}
529550

530-
impl Tag {
531-
pub fn as_str(&self) -> &str {
551+
impl ToString for Tag {
552+
fn to_string(&self) -> String {
532553
match self {
533554
Tag::Custom(name) => &name,
534555
$ (
535-
Tag::$tag_camel => $tag,
556+
Tag::$tag_camel => $tag.to_string(),
536557
) +
537558
}
538559
}
@@ -791,7 +812,7 @@ impl<Ms: Clone + 'static> El<Ms> {
791812
fn _html(&self) -> String {
792813
let text = self.text.clone().unwrap_or_default();
793814

794-
let opening = String::from("<") + self.tag.as_str() + &self.attrs.to_string() +
815+
let opening = String::from("<") + &self.tag.to_string() + &self.attrs.to_string() +
795816
" style=\"" + &self.style.to_string() + ">\n";
796817

797818
let inner = self.children.iter().fold(String::new(), |result, child| result + &child._html());
@@ -860,15 +881,6 @@ impl<Ms: Clone + 'static> Clone for El<Ms> {
860881
}
861882
}
862883

863-
pub type SeedEl<Ms> = crate::vdom::DomEl<
864-
Tag,
865-
Attrs,
866-
Style,
867-
String,
868-
Listener<Ms>,
869-
El<Ms>
870-
>;
871-
872884
impl<Ms: Clone + 'static> PartialEq for El<Ms> {
873885
fn eq(&self, other: &Self) -> bool {
874886
// todo Again, note that the listeners check only checks triggers.
@@ -884,8 +896,16 @@ impl<Ms: Clone + 'static> PartialEq for El<Ms> {
884896
}
885897
}
886898

887-
impl <Ms: Clone + 'static>crate::vdom::DomEl<Tag, Attrs, Style, String,
888-
Listener<Ms>, El<Ms>> for El<Ms> {
899+
// todo consider splitting this up into subcrates.
900+
901+
// todo: Consider moving this out into an outer crate/file
902+
impl <Ms: Clone + 'static>crate::vdom::DomEl<Ms> for El<Ms> {
903+
type Tg = Tag;
904+
type At = Attrs;
905+
type St = Style;
906+
type Ls = Listener<Ms>;
907+
type Tx = String;
908+
889909
fn tag(self) -> Tag {
890910
self.tag
891911
}
@@ -904,13 +924,38 @@ impl <Ms: Clone + 'static>crate::vdom::DomEl<Tag, Attrs, Style, String,
904924
fn children(self) -> Vec<Self> {
905925
self.children
906926
}
907-
927+
fn did_mount(self) -> Option<Box<FnMut(&web_sys::Element)>> {
928+
self.did_mount
929+
}
930+
fn did_update(self) -> Option<Box<FnMut(&web_sys::Element)>> {
931+
self.did_mount
932+
}
933+
fn will_unmount(self) -> Option<Box<FnMut(&web_sys::Element)>> {
934+
self.did_mount
935+
}
908936
fn websys_el(self) -> Option<web_sys::Element> {
909937
self.el_ws
910938
}
911939
fn id(self) -> Option<u32> {
912940
self.id
913941
}
942+
fn raw_html(self) -> bool {
943+
self.raw_html
944+
}
945+
fn namespace(self) -> Option<Namespace> {
946+
self.namespace
947+
}
948+
949+
fn empty(self) -> Self {
950+
self.empty()
951+
}
952+
953+
fn set_id(&mut self, id: Option<u32>) {
954+
self.id = id
955+
}
956+
fn set_websys_el(&mut self, el_ws: Option<web_sys::Element>) {
957+
self.el_ws = el_ws
958+
}
914959

915960
// fn make_websys_el(&mut self, document: &web_sys::Document) -> web_sys::Element {
916961
// crate::websys_bridge::make_websys_el(self, document)
@@ -973,6 +1018,7 @@ pub mod tests {
9731018
let mut el: El<Msg> = div![ "test" ];
9741019
crate::vdom::setup_els(&crate::util::document(), &mut el, 0, 0);
9751020
assert_eq!(expected, el.el_ws.unwrap().outer_html());
1021+
<<<<<<< HEAD
9761022
}
9771023

9781024
#[wasm_bindgen_test]
@@ -997,12 +1043,14 @@ pub mod tests {
9971043
pub fn attrs() {
9981044
let expected = "<section class=\"biochemistry\" src=\"https://seed-rs.org\">ok</section>";
9991045

1000-
let mut el: El<Msg> = div![
1046+
let mut el: El<Msg> = section![
10011047
attrs!{"class" => "biochemistry"; "src" => "https://seed-rs.org"},
10021048
"ok"
10031049
];
10041050

10051051
crate::vdom::setup_els(&crate::util::document(), &mut el, 0, 0);
10061052
assert_eq!(expected, el.el_ws.unwrap().outer_html());
1053+
=======
1054+
>>>>>>> 953d5a04f788c3c06fffc8a82a42c4d0c93ff981
10071055
}
10081056
}

src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ pub use crate::{
2828
websys_bridge::{to_input, to_kbevent, to_mouse_event, to_select, to_textarea, to_html_el},
2929
routing::push_route,
3030
util::{document, window},
31+
<<<<<<< HEAD
3132
vdom::{App, run}
33+
=======
34+
vdom::{App, run},
35+
>>>>>>> 75ac8af8d827a3db6ad6325e70086f31583dfcb8
3236
};
3337

3438
/// Create an element flagged in a way that it will not be rendered. Useful

src/routing.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@ use wasm_bindgen::{closure::Closure, JsCast, JsValue};
44

55
use crate::util;
66

7+
// todo: How coupled should this be to Seed, vdom, and dom_types?
78

89
/// A convenience function to prevent repetitions
910
fn get_path() -> String {
1011
let path = util::window().location().pathname().expect("Can't find pathname");
1112
path[1..path.len()].to_string()
1213
}
1314

14-
pub fn initial<Ms, Mdl>(app: crate::vdom::App<Ms, Mdl>, routes: HashMap<String, Ms>) -> crate::vdom::App<Ms, Mdl>
15-
where Ms: Clone + 'static, Mdl: Clone + 'static
15+
pub fn initial<Ms, Mdl, E>(
16+
app: crate::vdom::App<Ms, Mdl, E>,
17+
routes: HashMap<String, Ms>
18+
) -> crate::vdom::App<Ms, Mdl, E>
19+
where Ms: Clone + 'static, Mdl: Clone + 'static, E: crate::vdom::DomEl<Ms>
1620
{
1721
for (route, route_message) in routes.into_iter() {
1822
if route == get_path() {
@@ -23,8 +27,11 @@ pub fn initial<Ms, Mdl>(app: crate::vdom::App<Ms, Mdl>, routes: HashMap<String,
2327
app
2428
}
2529

26-
pub fn update_popstate_listener<Ms, Mdl>(app: &crate::vdom::App<Ms, Mdl>, routes: HashMap<String, Ms>)
27-
where Ms: Clone +'static, Mdl: Clone + 'static
30+
pub fn update_popstate_listener<Ms, Mdl, E>(
31+
app: &crate::vdom::App<Ms, Mdl, E>,
32+
routes: HashMap<String, Ms>
33+
)
34+
where Ms: Clone + 'static, Mdl: Clone + 'static, E: crate::vdom::DomEl<Ms>
2835
{
2936

3037
let window = util::window();

0 commit comments

Comments
 (0)