Auto merge of #9030 - askobara:refactoring-add-htmlformelement-fire_event, r=Manishearth

Add helper method HTMLFormElement::fire_event

Fixes #8777

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/9030)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-12-22 22:38:19 +05:30
commit dafdc856ac
8 changed files with 61 additions and 71 deletions

View file

@ -558,12 +558,8 @@ impl Document {
self.ready_state.set(state); self.ready_state.set(state);
let event = Event::new(GlobalRef::Window(&self.window), self.upcast::<EventTarget>().fire_simple_event("readystatechange",
atom!("readystatechange"), GlobalRef::Window(&self.window));
EventBubbles::DoesNotBubble,
EventCancelable::NotCancelable);
let target = self.upcast::<EventTarget>();
let _ = event.fire(target);
} }
/// Return whether scripting is enabled or not /// Return whether scripting is enabled or not

View file

@ -11,12 +11,12 @@ use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener;
use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods; use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods;
use dom::bindings::codegen::UnionTypes::EventOrString; use dom::bindings::codegen::UnionTypes::EventOrString;
use dom::bindings::error::{Error, Fallible, report_pending_exception}; use dom::bindings::error::{Error, Fallible, report_pending_exception};
use dom::bindings::global::global_root_from_reflector; use dom::bindings::global::{GlobalRef, global_root_from_reflector};
use dom::bindings::inheritance::{Castable, EventTargetTypeId}; use dom::bindings::inheritance::{Castable, EventTargetTypeId};
use dom::bindings::js::Root; use dom::bindings::js::Root;
use dom::bindings::reflector::{Reflectable, Reflector}; use dom::bindings::reflector::{Reflectable, Reflector};
use dom::errorevent::ErrorEvent; use dom::errorevent::ErrorEvent;
use dom::event::Event; use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventdispatcher::dispatch_event; use dom::eventdispatcher::dispatch_event;
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use dom::window::Window; use dom::window::Window;
@ -329,6 +329,24 @@ impl EventTarget {
pub fn has_handlers(&self) -> bool { pub fn has_handlers(&self) -> bool {
!self.handlers.borrow().is_empty() !self.handlers.borrow().is_empty()
} }
/// Implements https://html.spec.whatwg.org/multipage/#fire-a-simple-event
pub fn fire_simple_event(&self, name: &str, win: GlobalRef) -> Root<Event> {
self.fire_simple_event_params(name, EventBubbles::DoesNotBubble,
EventCancelable::NotCancelable, win)
}
/// Implements more customizable variant of EventTarget::fire_simple_event.
pub fn fire_simple_event_params(&self, name: &str,
bubbles: EventBubbles,
cancelable: EventCancelable,
win: GlobalRef) -> Root<Event> {
let event = Event::new(win, Atom::from(name), bubbles, cancelable);
event.fire(self);
event
}
} }
impl EventTargetMethods for EventTarget { impl EventTargetMethods for EventTarget {

View file

@ -16,7 +16,7 @@ use dom::bindings::js::{Root};
use dom::bindings::reflector::Reflectable; use dom::bindings::reflector::Reflectable;
use dom::document::Document; use dom::document::Document;
use dom::element::Element; use dom::element::Element;
use dom::event::{Event, EventBubbles, EventCancelable}; use dom::event::{EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget; use dom::eventtarget::EventTarget;
use dom::htmlbuttonelement::HTMLButtonElement; use dom::htmlbuttonelement::HTMLButtonElement;
use dom::htmldatalistelement::HTMLDataListElement; use dom::htmldatalistelement::HTMLDataListElement;
@ -169,23 +169,18 @@ impl HTMLFormElement {
{ {
if self.interactive_validation().is_err() { if self.interactive_validation().is_err() {
// TODO: Implement event handlers on all form control elements // TODO: Implement event handlers on all form control elements
// XXXKiChjang: We're also calling the following two statements quite often, self.upcast::<EventTarget>()
// we should refactor it into a function .fire_simple_event("invalid", GlobalRef::Window(win.r()));
let event = Event::new(GlobalRef::Window(win.r()),
atom!("invalid"),
EventBubbles::DoesNotBubble,
EventCancelable::NotCancelable);
event.fire(self.upcast());
return; return;
} }
} }
// Step 5 // Step 5
if submit_method_flag == SubmittedFrom::NotFromFormSubmitMethod { if submit_method_flag == SubmittedFrom::NotFromFormSubmitMethod {
let event = Event::new(GlobalRef::Window(win.r()), let event = self.upcast::<EventTarget>()
atom!("submit"), .fire_simple_event_params("submit",
EventBubbles::Bubbles, EventBubbles::Bubbles,
EventCancelable::Cancelable); EventCancelable::Cancelable,
event.fire(self.upcast()); GlobalRef::Window(win.r()));
if event.DefaultPrevented() { if event.DefaultPrevented() {
return; return;
} }
@ -280,11 +275,11 @@ impl HTMLFormElement {
// Step 5-6 // Step 5-6
let win = window_from_node(self); let win = window_from_node(self);
let unhandled_invalid_controls = invalid_controls.into_iter().filter_map(|field| { let unhandled_invalid_controls = invalid_controls.into_iter().filter_map(|field| {
let event = Event::new(GlobalRef::Window(win.r()), let event = field.as_event_target()
atom!("invalid"), .fire_simple_event_params("invalid",
EventBubbles::DoesNotBubble, EventBubbles::DoesNotBubble,
EventCancelable::Cancelable); EventCancelable::Cancelable,
event.fire(field.as_event_target()); GlobalRef::Window(win.r()));
if !event.DefaultPrevented() { return Some(field); } if !event.DefaultPrevented() { return Some(field); }
None None
}).collect::<Vec<FormSubmittableElement>>(); }).collect::<Vec<FormSubmittableElement>>();
@ -393,11 +388,11 @@ impl HTMLFormElement {
} }
let win = window_from_node(self); let win = window_from_node(self);
let event = Event::new(GlobalRef::Window(win.r()), let event = self.upcast::<EventTarget>()
atom!("reset"), .fire_simple_event_params("reset",
EventBubbles::Bubbles, EventBubbles::Bubbles,
EventCancelable::Cancelable); EventCancelable::Cancelable,
event.fire(self.upcast()); GlobalRef::Window(win.r()));
if event.DefaultPrevented() { if event.DefaultPrevented() {
return; return;
} }
@ -430,6 +425,7 @@ impl HTMLFormElement {
}; };
self.marked_for_reset.set(false); self.marked_for_reset.set(false);
} }
} }
// TODO: add file support // TODO: add file support

View file

@ -17,7 +17,8 @@ use dom::bindings::reflector::Reflectable;
use dom::customevent::CustomEvent; use dom::customevent::CustomEvent;
use dom::document::Document; use dom::document::Document;
use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers}; use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers};
use dom::event::{Event, EventBubbles, EventCancelable}; use dom::event::Event;
use dom::eventtarget::EventTarget;
use dom::htmlelement::HTMLElement; use dom::htmlelement::HTMLElement;
use dom::node::{Node, window_from_node}; use dom::node::{Node, window_from_node};
use dom::urlhelper::UrlHelper; use dom::urlhelper::UrlHelper;
@ -208,12 +209,7 @@ impl HTMLIFrameElement {
// Step 4 // Step 4
let window = window_from_node(self); let window = window_from_node(self);
let event = Event::new(GlobalRef::Window(window.r()), self.upcast::<EventTarget>().fire_simple_event("load", GlobalRef::Window(window.r()));
atom!("load"),
EventBubbles::DoesNotBubble,
EventCancelable::NotCancelable);
event.fire(self.upcast());
// TODO Step 5 - unset child document `mut iframe load` flag // TODO Step 5 - unset child document `mut iframe load` flag
} }
} }

View file

@ -15,7 +15,7 @@ use dom::bindings::js::{LayoutJS, Root};
use dom::bindings::refcounted::Trusted; use dom::bindings::refcounted::Trusted;
use dom::document::Document; use dom::document::Document;
use dom::element::AttributeMutation; use dom::element::AttributeMutation;
use dom::event::{Event, EventBubbles, EventCancelable}; use dom::eventtarget::EventTarget;
use dom::htmlelement::HTMLElement; use dom::htmlelement::HTMLElement;
use dom::node::{Node, NodeDamage, document_from_node, window_from_node}; use dom::node::{Node, NodeDamage, document_from_node, window_from_node};
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
@ -77,12 +77,7 @@ impl Runnable for ImageResponseHandlerRunnable {
// Fire image.onload // Fire image.onload
let window = window_from_node(document.r()); let window = window_from_node(document.r());
let event = Event::new(GlobalRef::Window(window.r()), element.upcast::<EventTarget>().fire_simple_event("load", GlobalRef::Window(window.r()));
atom!("load"),
EventBubbles::DoesNotBubble,
EventCancelable::NotCancelable);
event.fire(element.upcast());
// Trigger reflow // Trigger reflow
window.add_pending_reflow(); window.add_pending_reflow();
} }

View file

@ -858,19 +858,16 @@ impl Activatable for HTMLInputElement {
// https://html.spec.whatwg.org/multipage/#radio-button-state-(type=radio):activation-behavior // https://html.spec.whatwg.org/multipage/#radio-button-state-(type=radio):activation-behavior
if self.mutable() { if self.mutable() {
let win = window_from_node(self); let win = window_from_node(self);
let target = self.upcast(); let target = self.upcast::<EventTarget>();
let event = Event::new(GlobalRef::Window(win.r()), target.fire_simple_event_params("input",
atom!("input"), EventBubbles::Bubbles,
EventBubbles::Bubbles, EventCancelable::NotCancelable,
EventCancelable::NotCancelable); GlobalRef::Window(win.r()));
event.fire(target); target.fire_simple_event_params("change",
EventBubbles::Bubbles,
let event = Event::new(GlobalRef::Window(win.r()), EventCancelable::NotCancelable,
atom!("change"), GlobalRef::Window(win.r()));
EventBubbles::Bubbles,
EventCancelable::NotCancelable);
event.fire(target);
} }
}, },
_ => () _ => ()

View file

@ -498,10 +498,7 @@ impl Runnable for ConnectionEstablishedTask {
// Step 5: Cookies. // Step 5: Cookies.
// Step 6. // Step 6.
let event = Event::new(global.r(), atom!("open"), ws.upcast().fire_simple_event("open", global.r());
EventBubbles::DoesNotBubble,
EventCancelable::NotCancelable);
event.fire(ws.upcast());
} }
} }
@ -539,11 +536,10 @@ impl Runnable for CloseTask {
ws.full.set(false); ws.full.set(false);
//A Bad close //A Bad close
ws.clean_close.set(false); ws.clean_close.set(false);
let event = Event::new(global.r(), ws.upcast().fire_simple_event_params("error",
atom!("error"), EventBubbles::DoesNotBubble,
EventBubbles::DoesNotBubble, EventCancelable::Cancelable,
EventCancelable::Cancelable); global.r());
event.fire(ws.upcast());
} }
let reason = ws.reason.borrow().clone(); let reason = ws.reason.borrow().clone();
/*In addition, we also have to fire a close even if error event fired /*In addition, we also have to fire a close even if error event fired

View file

@ -126,11 +126,7 @@ impl Worker {
pub fn dispatch_simple_error(address: TrustedWorkerAddress) { pub fn dispatch_simple_error(address: TrustedWorkerAddress) {
let worker = address.root(); let worker = address.root();
let global = worker.r().global.root(); let global = worker.r().global.root();
let event = Event::new(global.r(), worker.upcast().fire_simple_event("error", global.r());
atom!("error"),
EventBubbles::DoesNotBubble,
EventCancelable::NotCancelable);
event.fire(worker.upcast());
} }
pub fn handle_error_message(address: TrustedWorkerAddress, message: DOMString, pub fn handle_error_message(address: TrustedWorkerAddress, message: DOMString,