1 /*
2 * Copyright (c) 2002-2026 Gargoyle Software Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 * https://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 package org.htmlunit.javascript.host.html;
16
17 import java.net.MalformedURLException;
18
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21 import org.htmlunit.css.CssStyleSheet;
22 import org.htmlunit.html.HtmlLink;
23 import org.htmlunit.html.HtmlPage;
24 import org.htmlunit.javascript.JavaScriptEngine;
25 import org.htmlunit.javascript.configuration.JsxClass;
26 import org.htmlunit.javascript.configuration.JsxConstructor;
27 import org.htmlunit.javascript.configuration.JsxGetter;
28 import org.htmlunit.javascript.configuration.JsxSetter;
29 import org.htmlunit.javascript.host.css.CSSStyleSheet;
30 import org.htmlunit.javascript.host.dom.DOMTokenList;
31
32 /**
33 * The JavaScript object {@code HTMLLinkElement}.
34 *
35 * @author Ahmed Ashour
36 * @author Ronald Brill
37 * @author Sven Strickroth
38 *
39 * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLLinkElement">MDN Documentation</a>
40 */
41 @JsxClass(domClass = HtmlLink.class)
42 public class HTMLLinkElement extends HTMLElement {
43
44 private static final Log LOG = LogFactory.getLog(HTMLLinkElement.class);
45
46 /**
47 * The associated style sheet (only valid for links of type
48 * <code><link rel="stylesheet" type="text/css" href="..." /></code>).
49 */
50 private CSSStyleSheet sheet_;
51
52 /**
53 * JavaScript constructor.
54 */
55 @Override
56 @JsxConstructor
57 public void jsConstructor() {
58 super.jsConstructor();
59 }
60
61 /**
62 * {@inheritDoc}
63 */
64 @Override
65 public HtmlLink getDomNodeOrDie() {
66 return (HtmlLink) super.getDomNodeOrDie();
67 }
68
69 /**
70 * Sets the {@code href} property.
71 * @param href the {@code href} property value
72 */
73 @JsxSetter
74 public void setHref(final String href) {
75 getDomNodeOrDie().setAttribute("href", href);
76 }
77
78 /**
79 * Returns the value of the {@code href} property.
80 * @return the value of the {@code href} property
81 */
82 @JsxGetter
83 public String getHref() {
84 final HtmlLink link = getDomNodeOrDie();
85 final String href = link.getHrefAttribute();
86 if (href.isEmpty()) {
87 return href;
88 }
89 try {
90 return ((HtmlPage) link.getPage()).getFullyQualifiedUrl(href).toString();
91 }
92 catch (final MalformedURLException e) {
93 return href;
94 }
95 }
96
97 /**
98 * Sets the {@code rel} property.
99 * @param rel the {@code rel} property value
100 */
101 @JsxSetter
102 public void setRel(final String rel) {
103 getDomNodeOrDie().setAttribute("rel", rel);
104 }
105
106 /**
107 * Returns the value of the {@code rel} property.
108 * @return the value of the {@code rel} property
109 */
110 @JsxGetter
111 public String getRel() {
112 return getDomNodeOrDie().getRelAttribute();
113 }
114
115 /**
116 * Sets the {@code rev} property.
117 * @param rel the {@code rev} property value
118 */
119 @JsxSetter
120 public void setRev(final String rel) {
121 getDomNodeOrDie().setAttribute("rev", rel);
122 }
123
124 /**
125 * Returns the value of the {@code rev} property.
126 * @return the value of the {@code rev} property
127 */
128 @JsxGetter
129 public String getRev() {
130 return getDomNodeOrDie().getRevAttribute();
131 }
132
133 /**
134 * Sets the {@code type} property.
135 * @param type the {@code type} property value
136 */
137 @JsxSetter
138 public void setType(final String type) {
139 getDomNodeOrDie().setAttribute("type", type);
140 }
141
142 /**
143 * Returns the value of the {@code type} property.
144 * @return the value of the {@code type} property
145 */
146 @JsxGetter
147 public String getType() {
148 return getDomNodeOrDie().getTypeAttribute();
149 }
150
151 /**
152 * Returns the associated style sheet (only valid for links of type
153 * <code><link rel="stylesheet" type="text/css" href="..." /></code>).
154 * @return the associated style sheet
155 */
156 public CSSStyleSheet getSheet() {
157 if (sheet_ == null) {
158 try {
159 final CssStyleSheet sheet = getDomNodeOrDie().getSheet();
160 sheet_ = new CSSStyleSheet(this, getTopLevelScope(getParentScope()), sheet);
161 }
162 catch (final RuntimeException e) {
163 // Got something unexpected; we can throw an exception in this case.
164 LOG.error("RuntimeException loading stylesheet", e);
165 throw JavaScriptEngine.reportRuntimeError("Exception: " + e);
166 }
167 catch (final Exception e) {
168 // Got something unexpected; we can throw an exception in this case.
169 LOG.error("Exception loading stylesheet", e);
170 throw JavaScriptEngine.reportRuntimeError("Exception: " + e);
171 }
172 }
173 return sheet_;
174 }
175
176 /**
177 * {@inheritDoc}
178 */
179 @Override
180 protected boolean isEndTagForbidden() {
181 return true;
182 }
183
184 /**
185 * Returns the {@code relList} attribute.
186 * @return the {@code relList} attribute
187 */
188 @JsxGetter
189 public DOMTokenList getRelList() {
190 return new DOMTokenList(this, "rel");
191 }
192
193 /**
194 * Sets the {@code relList} attribute.
195 * @param rel the {@code relList} attribute value
196 */
197 @JsxSetter
198 public void setRelList(final Object rel) {
199 if (JavaScriptEngine.isUndefined(rel)) {
200 setRel("undefined");
201 return;
202 }
203 setRel(JavaScriptEngine.toString(rel));
204 }
205
206 /**
207 * {@inheritDoc} Overridden to modify browser configurations.
208 */
209 @Override
210 @JsxGetter
211 public boolean isDisabled() {
212 return super.isDisabled();
213 }
214
215 /**
216 * {@inheritDoc} Overridden to modify browser configurations.
217 */
218 @Override
219 @JsxSetter
220 public void setDisabled(final boolean disabled) {
221 super.setDisabled(disabled);
222 }
223 }