diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index a2f7b7ca81ed..70462c31cd15 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -10,6 +10,7 @@ use animation; use construct::ConstructionResult; use context::{SharedLayoutContext, SharedLayoutContextWrapper}; +use css::node_style::StyledNode; use display_list_builder::ToGfxColor; use flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils}; use flow_ref::FlowRef; @@ -712,7 +713,10 @@ impl LayoutTask { let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node); let mut iterator = UnioningFragmentBorderBoxIterator::new(requested_node); sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); - rw_data.content_box_response = iterator.rect; + rw_data.content_box_response = match iterator.rect { + Some(rect) => rect, + None => Rect::zero() + }; } fn process_content_boxes_request<'a>(&'a self, @@ -1157,25 +1161,28 @@ impl LayoutRPC for LayoutRPCImpl { struct UnioningFragmentBorderBoxIterator { node_address: OpaqueNode, - rect: Rect, + rect: Option>, } impl UnioningFragmentBorderBoxIterator { fn new(node_address: OpaqueNode) -> UnioningFragmentBorderBoxIterator { UnioningFragmentBorderBoxIterator { node_address: node_address, - rect: Rect::zero(), + rect: None } } } impl FragmentBorderBoxIterator for UnioningFragmentBorderBoxIterator { fn process(&mut self, _: &Fragment, border_box: &Rect) { - self.rect = if self.rect.is_empty() { - *border_box - } else { - self.rect.union(border_box) - } + self.rect = match self.rect { + Some(rect) => { + Some(rect.union(border_box)) + } + None => { + Some(*border_box) + } + }; } fn should_process(&mut self, fragment: &Fragment) -> bool { diff --git a/components/script/dom/activation.rs b/components/script/dom/activation.rs index 46ca27cabb51..c95969729b12 100644 --- a/components/script/dom/activation.rs +++ b/components/script/dom/activation.rs @@ -27,7 +27,7 @@ pub trait Activatable : Copy { fn canceled_activation(&self); // https://html.spec.whatwg.org/multipage/interaction.html#run-post-click-activation-steps - fn activation_behavior(&self); + fn activation_behavior(&self, event: JSRef, target: JSRef); // https://html.spec.whatwg.org/multipage/forms.html#implicit-submission fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool); @@ -60,7 +60,7 @@ pub trait Activatable : Copy { self.canceled_activation(); } else { // post click activation - self.activation_behavior(); + self.activation_behavior(event, target); } // Step 6 diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 4cfa77fdb4b4..d8d5a9ecf93e 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -1637,7 +1637,7 @@ impl<'a> ActivationElementHelpers<'a> for JSRef<'a, Element> { event.fire(target); if !event.DefaultPrevented() { // post click activation - elem.activation_behavior(); + elem.activation_behavior(event, target); } else { elem.canceled_activation(); } diff --git a/components/script/dom/htmlanchorelement.rs b/components/script/dom/htmlanchorelement.rs index 1219692cd9b0..a4da4a148d6e 100644 --- a/components/script/dom/htmlanchorelement.rs +++ b/components/script/dom/htmlanchorelement.rs @@ -2,14 +2,17 @@ * 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::activation::Activatable; use dom::attr::AttrValue; use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use dom::bindings::codegen::Bindings::HTMLAnchorElementBinding; use dom::bindings::codegen::Bindings::HTMLAnchorElementBinding::HTMLAnchorElementMethods; +use dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; -use dom::bindings::codegen::InheritTypes::HTMLAnchorElementDerived; -use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast}; +use dom::bindings::codegen::InheritTypes::{HTMLAnchorElementDerived, HTMLImageElementDerived}; +use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast}; +use dom::bindings::codegen::InheritTypes::{MouseEventCast, NodeCast}; use dom::bindings::js::{MutNullableJS, JSRef, Temporary, OptionalRootable}; use dom::document::{Document, DocumentHelpers}; use dom::domtokenlist::DOMTokenList; @@ -17,10 +20,12 @@ use dom::element::{Element, AttributeHandlers, ElementTypeId}; use dom::event::Event; use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; -use dom::node::{Node, NodeHelpers, NodeTypeId, document_from_node}; +use dom::node::{Node, NodeHelpers, NodeTypeId, document_from_node, window_from_node}; use dom::virtualmethods::VirtualMethods; +use dom::window::WindowHelpers; use std::default::Default; +use std::num::ToPrimitive; use string_cache::Atom; use util::str::DOMString; @@ -112,20 +117,35 @@ impl<'a> Activatable for JSRef<'a, HTMLAnchorElement> { } //https://html.spec.whatwg.org/multipage/semantics.html#the-a-element:activation-behaviour - fn activation_behavior(&self) { + fn activation_behavior(&self, event: JSRef, target: JSRef) { //Step 1. If the node document is not fully active, abort. let doc = document_from_node(*self).root(); if !doc.r().is_fully_active() { return; } //TODO: Step 2. Check if browsing context is specified and act accordingly. - //TODO: Step 3. Handle . - //TODO: Step 4. Download the link is `download` attribute is set. + //Step 3. Handle . let element: JSRef = ElementCast::from_ref(*self); + let mouse_event = MouseEventCast::to_ref(event).unwrap(); + let mut ismap_suffix = None; + if let Some(element) = ElementCast::to_ref(target) { + if target.is_htmlimageelement() && element.has_attribute(&atom!("ismap")) { + + let target_node = NodeCast::to_ref(target).unwrap(); + let rect = window_from_node(target_node).root().r().content_box_query(target_node.to_trusted_node_address()); + ismap_suffix = Some( + format!("?{},{}", mouse_event.ClientX().to_f32().unwrap() - rect.origin.x.to_frac32_px(), + mouse_event.ClientY().to_f32().unwrap() - rect.origin.y.to_frac32_px()) + ) + } + } + + //TODO: Step 4. Download the link is `download` attribute is set. + let attr = element.get_attribute(&ns!(""), &atom!("href")).root(); match attr { Some(ref href) => { - let value = href.r().Value(); + let value = href.r().Value() + ismap_suffix.as_ref().map(|s| &**s).unwrap_or(""); debug!("clicked on link to {}", value); doc.r().load_anchor_href(value); } diff --git a/components/script/dom/htmlbuttonelement.rs b/components/script/dom/htmlbuttonelement.rs index e1d74d7a3a62..7355b1448b11 100644 --- a/components/script/dom/htmlbuttonelement.rs +++ b/components/script/dom/htmlbuttonelement.rs @@ -13,6 +13,7 @@ use dom::bindings::js::{JSRef, Temporary}; use dom::document::Document; use dom::element::{AttributeHandlers, Element, ElementTypeId}; use dom::element::ActivationElementHelpers; +use dom::event::Event; use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; use dom::htmlformelement::{FormSubmitter, FormControl, HTMLFormElementHelpers}; @@ -196,7 +197,7 @@ impl<'a> Activatable for JSRef<'a, HTMLButtonElement> { } // https://html.spec.whatwg.org/multipage/interaction.html#run-post-click-activation-steps - fn activation_behavior(&self) { + fn activation_behavior(&self, _event: JSRef, _target: JSRef) { let ty = self.button_type.get(); match ty { //https://html.spec.whatwg.org/multipage/forms.html#attr-button-type-submit-state diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 9223ac7ad60a..3748ce9bac59 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -750,7 +750,7 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> { } // https://html.spec.whatwg.org/multipage/interaction.html#run-post-click-activation-steps - fn activation_behavior(&self) { + fn activation_behavior(&self, _event: JSRef, _target: JSRef) { let ty = self.input_type.get(); if self.activation_state.borrow().old_type != ty { // Type changed, abandon ship diff --git a/tests/html/test_img_ismap.html b/tests/html/test_img_ismap.html new file mode 100644 index 000000000000..669a941d07d5 --- /dev/null +++ b/tests/html/test_img_ismap.html @@ -0,0 +1,17 @@ + + + + + img element ismap activation test + + +

Click my nose to get the coordinates!

+ + andreas + +

Nothing happends if you click my nose

+ + andreas + + +