1 use webcore::value::{Reference, Value}; 2 use webcore::try_from::TryInto; 3 use 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))] 16 pub struct HashChangeEvent( Reference ); 17 18 impl IEvent for HashChangeEvent {} 19 20 impl 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] old_url( &self ) -> String26 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] new_url( &self ) -> String37 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))] 65 pub struct PopStateEvent(Reference); 66 67 impl 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] state(&self) -> Value78 pub fn state(&self) -> Value { 79 js!(return @{self}.state;) 80 } 81 } 82 83 impl IEvent for PopStateEvent {} 84 85 #[cfg(all(test, feature = "web_test"))] 86 mod tests { 87 use super::*; 88 use webapi::event::ConcreteEvent; 89 90 #[test] test_hash_change_event()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] test_pop_state_event()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 } 132