Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement HTMLHyperlinkElementUtils for HTMLAnchorElement #9887

Merged
merged 1 commit into from Mar 25, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
343 changes: 343 additions & 0 deletions components/script/dom/htmlanchorelement.rs
Expand Up @@ -5,13 +5,15 @@

use dom::activation::Activatable;
use dom::attr::AttrValue;
use dom::bindings::cell::DOMRefCell;
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::inheritance::Castable;
use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::str::USVString;
use dom::document::Document;
use dom::domtokenlist::DOMTokenList;
use dom::element::Element;
Expand All @@ -21,16 +23,19 @@ use dom::htmlelement::HTMLElement;
use dom::htmlimageelement::HTMLImageElement;
use dom::mouseevent::MouseEvent;
use dom::node::{Node, document_from_node, window_from_node};
use dom::urlhelper::UrlHelper;
use dom::virtualmethods::VirtualMethods;
use num::ToPrimitive;
use std::default::Default;
use string_cache::Atom;
use url::{Url, UrlParser};
use util::str::DOMString;

#[dom_struct]
pub struct HTMLAnchorElement {
htmlelement: HTMLElement,
rel_list: MutNullableHeap<JS<DOMTokenList>>,
url: DOMRefCell<Option<Url>>,
}

impl HTMLAnchorElement {
Expand All @@ -41,6 +46,7 @@ impl HTMLAnchorElement {
htmlelement:
HTMLElement::new_inherited(localName, prefix, document),
rel_list: Default::default(),
url: DOMRefCell::new(None),
}
}

Expand All @@ -51,6 +57,37 @@ impl HTMLAnchorElement {
let element = HTMLAnchorElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLAnchorElementBinding::Wrap)
}

// https://html.spec.whatwg.org/multipage/#concept-hyperlink-url-set
fn set_url(&self) {
let attribute = self.upcast::<Element>().get_attribute(&ns!(), &atom!("href"));
*self.url.borrow_mut() = attribute.and_then(|attribute| {
let document = document_from_node(self);
let mut parser = UrlParser::new();
parser.base_url(document.url());
parser.parse(&attribute.value()).ok()
});
}

// https://html.spec.whatwg.org/multipage/#reinitialise-url
fn reinitialize_url(&self) {
// Step 1.
match *self.url.borrow() {
None => return,
Some(ref url) if url.scheme == "blob" &&
url.non_relative_scheme_data().is_some() => return,
_ => (),
}

// Step 2.
self.set_url();
}

// https://html.spec.whatwg.org/multipage/#update-href
fn update_href(&self) {
self.upcast::<Element>().set_string_attribute(&atom!("href"),
self.url.borrow().as_ref().unwrap().serialize().into());
}
}

impl VirtualMethods for HTMLAnchorElement {
Expand Down Expand Up @@ -107,6 +144,312 @@ impl HTMLAnchorElementMethods for HTMLAnchorElement {

// https://html.spec.whatwg.org/multipage/#dom-a-shape
make_setter!(SetShape, "shape");

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-hash
fn Hash(&self) -> USVString {
// Step 1.
self.reinitialize_url();

match *self.url.borrow() {
// Step 3.
None => USVString(String::new()),
Some(ref url) => {
// Steps 3-4.
UrlHelper::Hash(url)
}
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-hash
fn SetHash(&self, value: USVString) {
// Step 1.
self.reinitialize_url();

// Step 3.
if let Some(url) = self.url.borrow_mut().as_mut() {
if url.scheme == "javascript" { return; }
// Steps 4-5.
UrlHelper::SetHash(url, value);
// Step 6.
self.update_href();
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-host
fn Host(&self) -> USVString {
// Step 1.
self.reinitialize_url();

match *self.url.borrow() {
// Step 3.
None => USVString(String::new()),
Some(ref url) => {
if url.host().is_none() {
USVString(String::new())
} else {
// Steps 4-5.
UrlHelper::Host(url)
}
}
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-host
fn SetHost(&self, value: USVString) {
// Step 1.
self.reinitialize_url();

// Step 3.
if let Some(url) = self.url.borrow_mut().as_mut() {
if url.non_relative_scheme_data().is_some() {
return;
}
// Step 4.
UrlHelper::SetHost(url, value);
// Step 5.
self.update_href();
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-hostname
fn Hostname(&self) -> USVString {
// Step 1.
self.reinitialize_url();

match *self.url.borrow() {
// Step 3.
None => USVString(String::new()),
Some(ref url) => {
// Step 4.
UrlHelper::Hostname(url)
}
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-hostname
fn SetHostname(&self, value: USVString) {
// Step 1.
self.reinitialize_url();

// Step 3.
if let Some(url) = self.url.borrow_mut().as_mut() {
if url.non_relative_scheme_data().is_some() {
return;
}
// Step 4.
UrlHelper::SetHostname(url, value);
// Step 5.
self.update_href();
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-href
fn Href(&self) -> USVString {
// Step 1.
self.reinitialize_url();

USVString(match *self.url.borrow() {
None => {
match self.upcast::<Element>().get_attribute(&ns!(), &atom!("href")) {
// Step 3.
None => String::new(),
// Step 4.
Some(attribute) => (**attribute.value()).to_owned(),
}
},
// Step 5.
Some(ref url) => url.serialize(),
})
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-href
fn SetHref(&self, value: USVString) {
self.upcast::<Element>().set_string_attribute(&atom!("href"),
DOMString::from_string(value.0));
self.set_url();
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-password
fn Password(&self) -> USVString {
// Step 1.
self.reinitialize_url();

match *self.url.borrow() {
// Step 3.
None => USVString(String::new()),
// Steps 3-4.
Some(ref url) => UrlHelper::Password(url)
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-password
fn SetPassword(&self, value: USVString) {
// Step 1.
self.reinitialize_url();

// Step 3.
if let Some(url) = self.url.borrow_mut().as_mut() {
if url.host().is_none() || url.non_relative_scheme_data().is_some() {
return;
}
// Step 4.
UrlHelper::SetPassword(url, value);
// Step 5.
self.update_href();
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-pathname
fn Pathname(&self) -> USVString {
// Step 1.
self.reinitialize_url();

match *self.url.borrow() {
// Step 3.
None => USVString(String::new()),
// Steps 4-5.
Some(ref url) => UrlHelper::Pathname(url)
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-pathname
fn SetPathname(&self, value: USVString) {
// Step 1.
self.reinitialize_url();

// Step 3.
if let Some(url) = self.url.borrow_mut().as_mut() {
if url.non_relative_scheme_data().is_some() { return; }
// Step 5.
UrlHelper::SetPathname(url, value);
// Step 6.
self.update_href();
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-port
fn Port(&self) -> USVString {
// Step 1.
self.reinitialize_url();

match *self.url.borrow() {
// Step 3.
None => USVString(String::new()),
// Step 4.
Some(ref url) => UrlHelper::Port(url)
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-port
fn SetPort(&self, value: USVString) {
// Step 1.
self.reinitialize_url();

// Step 3.
if let Some(url) = self.url.borrow_mut().as_mut() {
if url.host().is_none() ||
url.non_relative_scheme_data().is_some() ||
url.scheme == "file" {
return;
}
// Step 4.
UrlHelper::SetPort(url, value);
// Step 5.
self.update_href();
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-protocol
fn Protocol(&self) -> USVString {
// Step 1.
self.reinitialize_url();

match *self.url.borrow() {
// Step 2.
None => USVString(":".to_owned()),
// Step 3.
Some(ref url) => UrlHelper::Protocol(url)
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-protocol
fn SetProtocol(&self, value: USVString) {
// Step 1.
self.reinitialize_url();

// Step 2.
if let Some(url) = self.url.borrow_mut().as_mut() {
// Step 3.
UrlHelper::SetProtocol(url, value);
// Step 4.
self.update_href();
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-search
fn Search(&self) -> USVString {
// Step 1.
self.reinitialize_url();

match *self.url.borrow() {
// Step 2.
None => USVString(String::new()),
// Step 3.
Some(ref url) => UrlHelper::Search(url)
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-search
fn SetSearch(&self, value: USVString) {
// Step 1.
self.reinitialize_url();

// Step 3.
if let Some(url) = self.url.borrow_mut().as_mut() {
// Steps 4-5.
// TODO add this element's node document character encoding as
// encoding override (as described in the spec)
UrlHelper::SetSearch(url, value);
// Step 6.
self.update_href();
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-username
fn Username(&self) -> USVString {
// Step 1.
self.reinitialize_url();

match *self.url.borrow() {
// Step 2.
None => USVString(String::new()),
// Step 3.
Some(ref url) => UrlHelper::Username(url)
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-username
fn SetUsername(&self, value: USVString) {
// Step 1.
self.reinitialize_url();

// Step 3.
if let Some(url) = self.url.borrow_mut().as_mut() {
if url.host().is_none() || url.non_relative_scheme_data().is_some() {
return;
}

// Step 4.
UrlHelper::SetUsername(url, value);
// Step 5.
self.update_href();
}
}

// https://html.spec.whatwg.org/multipage/#dom-hyperlink-href
fn Stringifier(&self) -> DOMString {
DOMString::from(self.Href().0)
}
}

impl Activatable for HTMLAnchorElement {
Expand Down