View Javadoc
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>&lt;link rel="stylesheet" type="text/css" href="..." /&gt;</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>&lt;link rel="stylesheet" type="text/css" href="..." /&gt;</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 }