//! Event handlers. use crate::OutputType; use htmlescape::encode_attribute; use std::fmt::{Display, Error, Formatter}; /// Trait for event handlers. pub trait EventHandler { /// Build a callback function from this event handler. /// /// Returns `None` is this event handler can't be used to build a callback /// function. This is usually the case if the event handler is a string /// intended for server side rendering. // fn build(self) -> Option>; fn attach(&mut self, target: &mut T::EventTarget) -> T::EventListenerHandle; /// Render this event handler as a string. /// /// Returns `None` if this event handler cannot be rendered. Normally, the /// only event handlers that can be rendered are string values intended for /// server side rendering. fn render(&self) -> Option; } /// Trait for building event handlers from other types. pub trait IntoEventHandler { /// Construct an event handler from an instance of the source type. fn into_event_handler(self) -> Box>; } /// An uninhabited event type for string handlers. pub enum StringEvent {} impl EventHandler for &'static str { fn attach(&mut self, _target: &mut ::EventTarget) { panic!("Silly wabbit, strings as event handlers are only for printing."); } fn render(&self) -> Option { Some(self.to_string()) } } impl IntoEventHandler for &'static str { fn into_event_handler(self) -> Box> { Box::new(self) } } impl EventHandler for String { fn attach(&mut self, _target: &mut ::EventTarget) { panic!("Silly wabbit, strings as event handlers are only for printing."); } fn render(&self) -> Option { Some(self.clone()) } } impl IntoEventHandler for String { fn into_event_handler(self) -> Box> { Box::new(self) } } macro_rules! declare_string_events { ($($name:ident,)*) => { pub struct StringEvents { $( pub $name: Option>>, )* } impl Default for StringEvents { fn default() -> Self { StringEvents { $( $name: None, )* } } } impl Display for StringEvents { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { $( if let Some(ref value) = self.$name { write!(f, " on{}=\"{}\"", stringify!($name), encode_attribute(value.render().unwrap().as_str()))?; } )* Ok(()) } } } } declare_string_events! { abort, autocomplete, autocompleteerror, blur, cancel, canplay, canplaythrough, change, click, close, contextmenu, cuechange, dblclick, drag, dragend, dragenter, dragexit, dragleave, dragover, dragstart, drop, durationchange, emptied, ended, error, focus, input, invalid, keydown, keypress, keyup, load, loadeddata, loadedmetadata, loadstart, mousedown, mouseenter, mouseleave, mousemove, mouseout, mouseover, mouseup, mousewheel, pause, play, playing, progress, ratechange, reset, resize, scroll, seeked, seeking, select, show, sort, stalled, submit, suspend, timeupdate, toggle, volumechange, waiting, }