aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/virtualmethods.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/virtualmethods.rs')
-rw-r--r--components/script/dom/virtualmethods.rs219
1 files changed, 219 insertions, 0 deletions
diff --git a/components/script/dom/virtualmethods.rs b/components/script/dom/virtualmethods.rs
new file mode 100644
index 00000000000..9ce38c4908b
--- /dev/null
+++ b/components/script/dom/virtualmethods.rs
@@ -0,0 +1,219 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use dom::attr::{AttrValue, StringAttrValue};
+use dom::bindings::codegen::InheritTypes::ElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLAnchorElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLAreaElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLBodyElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLButtonElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLCanvasElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLFieldSetElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLIFrameElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLImageElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLInputElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLLinkElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLObjectElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLOptGroupElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLOptionElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLSelectElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLStyleElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLTextAreaElementCast;
+use dom::bindings::js::JSRef;
+use dom::element::Element;
+use dom::element::ElementTypeId;
+use dom::element::HTMLAnchorElementTypeId;
+use dom::element::HTMLAreaElementTypeId;
+use dom::element::HTMLBodyElementTypeId;
+use dom::element::HTMLButtonElementTypeId;
+use dom::element::HTMLCanvasElementTypeId;
+use dom::element::HTMLFieldSetElementTypeId;
+use dom::element::HTMLIFrameElementTypeId;
+use dom::element::HTMLImageElementTypeId;
+use dom::element::HTMLInputElementTypeId;
+use dom::element::HTMLLinkElementTypeId;
+use dom::element::HTMLObjectElementTypeId;
+use dom::element::HTMLOptGroupElementTypeId;
+use dom::element::HTMLOptionElementTypeId;
+use dom::element::HTMLSelectElementTypeId;
+use dom::element::HTMLStyleElementTypeId;
+use dom::element::HTMLTextAreaElementTypeId;
+use dom::event::Event;
+use dom::htmlanchorelement::HTMLAnchorElement;
+use dom::htmlareaelement::HTMLAreaElement;
+use dom::htmlbodyelement::HTMLBodyElement;
+use dom::htmlbuttonelement::HTMLButtonElement;
+use dom::htmlcanvaselement::HTMLCanvasElement;
+use dom::htmlelement::HTMLElement;
+use dom::htmlfieldsetelement::HTMLFieldSetElement;
+use dom::htmliframeelement::HTMLIFrameElement;
+use dom::htmlimageelement::HTMLImageElement;
+use dom::htmlinputelement::HTMLInputElement;
+use dom::htmllinkelement::HTMLLinkElement;
+use dom::htmlobjectelement::HTMLObjectElement;
+use dom::htmloptgroupelement::HTMLOptGroupElement;
+use dom::htmloptionelement::HTMLOptionElement;
+use dom::htmlselectelement::HTMLSelectElement;
+use dom::htmlstyleelement::HTMLStyleElement;
+use dom::htmltextareaelement::HTMLTextAreaElement;
+use dom::node::{Node, NodeHelpers, ElementNodeTypeId};
+
+use servo_util::atom::Atom;
+use servo_util::str::DOMString;
+
+/// Trait to allow DOM nodes to opt-in to overriding (or adding to) common
+/// behaviours. Replicates the effect of C++ virtual methods.
+pub trait VirtualMethods {
+ /// Returns self as the superclass of the implementation for this trait,
+ /// if any.
+ fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods>;
+
+ /// Called when changing or adding attributes, after the attribute's value
+ /// has been updated.
+ fn after_set_attr(&self, name: &Atom, value: DOMString) {
+ match self.super_type() {
+ Some(ref s) => s.after_set_attr(name, value),
+ _ => (),
+ }
+ }
+
+ /// Called when changing or removing attributes, before any modification
+ /// has taken place.
+ fn before_remove_attr(&self, name: &Atom, value: DOMString) {
+ match self.super_type() {
+ Some(ref s) => s.before_remove_attr(name, value),
+ _ => (),
+ }
+ }
+
+ /// Returns the right AttrValue variant for the attribute with name `name`
+ /// on this element.
+ fn parse_plain_attribute(&self, name: &str, value: DOMString) -> AttrValue {
+ match self.super_type() {
+ Some(ref s) => s.parse_plain_attribute(name, value),
+ _ => StringAttrValue(value),
+ }
+ }
+
+ /// Called when a Node is appended to a tree, where 'tree_in_doc' indicates
+ /// whether the tree is part of a Document.
+ fn bind_to_tree(&self, tree_in_doc: bool) {
+ match self.super_type() {
+ Some(ref s) => s.bind_to_tree(tree_in_doc),
+ _ => (),
+ }
+ }
+
+ /// Called when a Node is removed from a tree, where 'tree_in_doc'
+ /// indicates whether the tree is part of a Document.
+ fn unbind_from_tree(&self, tree_in_doc: bool) {
+ match self.super_type() {
+ Some(ref s) => s.unbind_from_tree(tree_in_doc),
+ _ => (),
+ }
+ }
+
+ /// Called on the parent when a node is added to its child list.
+ fn child_inserted(&self, child: &JSRef<Node>) {
+ match self.super_type() {
+ Some(ref s) => s.child_inserted(child),
+ _ => (),
+ }
+ }
+
+ /// Called during event dispatch after the bubbling phase completes.
+ fn handle_event(&self, event: &JSRef<Event>) {
+ match self.super_type() {
+ Some(s) => {
+ s.handle_event(event);
+ }
+ _ => (),
+ }
+ }
+}
+
+/// Obtain a VirtualMethods instance for a given Node-derived object. Any
+/// method call on the trait object will invoke the corresponding method on the
+/// concrete type, propagating up the parent hierarchy unless otherwise
+/// interrupted.
+pub fn vtable_for<'a>(node: &'a JSRef<Node>) -> &'a VirtualMethods {
+ match node.type_id() {
+ ElementNodeTypeId(HTMLAnchorElementTypeId) => {
+ let element: &JSRef<HTMLAnchorElement> = HTMLAnchorElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ ElementNodeTypeId(HTMLAreaElementTypeId) => {
+ let element: &JSRef<HTMLAreaElement> = HTMLAreaElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ ElementNodeTypeId(HTMLBodyElementTypeId) => {
+ let element: &JSRef<HTMLBodyElement> = HTMLBodyElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ ElementNodeTypeId(HTMLButtonElementTypeId) => {
+ let element: &JSRef<HTMLButtonElement> = HTMLButtonElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ ElementNodeTypeId(HTMLCanvasElementTypeId) => {
+ let element: &JSRef<HTMLCanvasElement> = HTMLCanvasElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ ElementNodeTypeId(HTMLFieldSetElementTypeId) => {
+ let element: &JSRef<HTMLFieldSetElement> = HTMLFieldSetElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ ElementNodeTypeId(HTMLImageElementTypeId) => {
+ let element: &JSRef<HTMLImageElement> = HTMLImageElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ ElementNodeTypeId(HTMLIFrameElementTypeId) => {
+ let element: &JSRef<HTMLIFrameElement> = HTMLIFrameElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ ElementNodeTypeId(HTMLInputElementTypeId) => {
+ let element: &JSRef<HTMLInputElement> = HTMLInputElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ ElementNodeTypeId(HTMLLinkElementTypeId) => {
+ let element: &JSRef<HTMLLinkElement> = HTMLLinkElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ ElementNodeTypeId(HTMLObjectElementTypeId) => {
+ let element: &JSRef<HTMLObjectElement> = HTMLObjectElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ ElementNodeTypeId(HTMLOptGroupElementTypeId) => {
+ let element: &JSRef<HTMLOptGroupElement> = HTMLOptGroupElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ ElementNodeTypeId(HTMLOptionElementTypeId) => {
+ let element: &JSRef<HTMLOptionElement> = HTMLOptionElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ ElementNodeTypeId(HTMLSelectElementTypeId) => {
+ let element: &JSRef<HTMLSelectElement> = HTMLSelectElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ ElementNodeTypeId(HTMLStyleElementTypeId) => {
+ let element: &JSRef<HTMLStyleElement> = HTMLStyleElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ ElementNodeTypeId(HTMLTextAreaElementTypeId) => {
+ let element: &JSRef<HTMLTextAreaElement> = HTMLTextAreaElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ ElementNodeTypeId(ElementTypeId) => {
+ let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ ElementNodeTypeId(_) => {
+ let element: &JSRef<HTMLElement> = HTMLElementCast::to_ref(node).unwrap();
+ element as &VirtualMethods
+ }
+ _ => {
+ node as &VirtualMethods
+ }
+ }
+}