stdweb/webapi/events/history.rs
1use webcore::value::{Reference, Value};
2use webcore::try_from::TryInto;
3use webapi::event::{IEvent, Event};
4
5/// The `HashChangeEvent` is fired when the fragment
6/// identifier of the URL has changed (the part of the URL
7/// that follows the # symbol, including the # symbol).
8///
9/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/hashchange)
10// https://html.spec.whatwg.org/#event-hashchange
11// https://html.spec.whatwg.org/#hashchangeevent
12#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
13#[reference(instance_of = "HashChangeEvent")]
14#[reference(event = "hashchange")]
15#[reference(subclass_of(Event))]
16pub struct HashChangeEvent( Reference );
17
18impl IEvent for HashChangeEvent {}
19
20impl HashChangeEvent {
21 /// The previous URL from which the window was navigated.
22 ///
23 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HashChangeEvent)
24 // https://html.spec.whatwg.org/#the-hashchangeevent-interface:dom-hashchangeevent-oldurl
25 #[inline]
26 pub fn old_url( &self ) -> String {
27 js!(
28 return @{self.as_ref()}.oldURL;
29 ).try_into().unwrap()
30 }
31
32 /// The new URL to which the window was navigated.
33 ///
34 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HashChangeEvent)
35 // https://html.spec.whatwg.org/#the-hashchangeevent-interface:dom-hashchangeevent-newurl
36 #[inline]
37 pub fn new_url( &self ) -> String {
38 js!(
39 return @{self.as_ref()}.newURL;
40 ).try_into().unwrap()
41 }
42}
43
44/// A `PopStateEvent` is dispatched to the window every time the active history entry changes
45/// between two history entries for the same document. If the history entry being activated was
46/// created by a call to `history.push_state()` or was affected by a call to
47/// `history.replace_state()`, the `PopStateEvent`'s state property contains a copy of the history
48/// entry's state object.
49///
50/// Note that just calling `history.push_state()` or `history.replace_state()` won't trigger a
51/// `PopStateEvent`. The `PopStateEvent` is only triggered by doing a browser action such as a
52/// clicking on the back button (or calling `history.back()`). And the event is only
53/// triggered when the user navigates between two history entries for the same document.
54///
55/// Browsers tend to handle the `PopStateEvent` differently on page load. Chrome and Safari always
56/// emit a `PopStateEvent` on page load, but Firefox doesn't.
57///
58/// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PopStateEvent)
59// https://html.spec.whatwg.org/#event-popstate
60// https://html.spec.whatwg.org/#popstateevent
61#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
62#[reference(instance_of = "Event")]
63#[reference(event = "popstate")]
64#[reference(subclass_of(Event))]
65pub struct PopStateEvent(Reference);
66
67impl PopStateEvent {
68 /// The state object associated to the new history entry, if that entry was created with
69 /// push_state or affected by replace_state.
70 ///
71 /// Example usage:
72 ///
73 /// ```rust,ignore
74 /// let state: Option<MyStruct> = event.state().try_into().ok();
75 /// ```
76 // https://html.spec.whatwg.org/#dom-popstateevent-state
77 #[inline]
78 pub fn state(&self) -> Value {
79 js!(return @{self}.state;)
80 }
81}
82
83impl IEvent for PopStateEvent {}
84
85#[cfg(all(test, feature = "web_test"))]
86mod tests {
87 use super::*;
88 use webapi::event::ConcreteEvent;
89
90 #[test]
91 fn test_hash_change_event() {
92 let event: HashChangeEvent = js!(
93 return new HashChangeEvent(
94 @{HashChangeEvent::EVENT_TYPE},
95 {
96 oldURL: "http://test.com#foo",
97 newURL: "http://test.com#bar"
98 }
99 );
100 ).try_into().unwrap();
101 assert_eq!( event.event_type(), HashChangeEvent::EVENT_TYPE );
102 assert_eq!( event.old_url(), "http://test.com#foo" );
103 assert_eq!( event.new_url(), "http://test.com#bar" );
104 }
105
106 #[test]
107 fn test_pop_state_event() {
108 let event: PopStateEvent = js!(
109 return new PopStateEvent(
110 @{PopStateEvent::EVENT_TYPE},
111 {
112 state: {
113 color: "tomato"
114 }
115 }
116 );
117 ).try_into().unwrap();
118
119 assert_eq!(event.event_type(), PopStateEvent::EVENT_TYPE);
120
121 let state_value: Value = event.state();
122 let state: std::collections::BTreeMap<String, Value> = state_value
123 .as_object()
124 .unwrap()
125 .into();
126 let mut expected = std::collections::BTreeMap::new();
127 expected.insert("color".to_string(), "tomato".into());
128
129 assert_eq!(state, expected);
130 }
131}