001 
002 /*
003  *  JScripter Standard 1.0 - To Script In Java
004  *  Copyright (C) 2008-2011  J.J.Liu<jianjunliu@126.com> <http://www.jscripter.org>
005  *  
006  *  This program is free software: you can redistribute it and/or modify
007  *  it under the terms of the GNU Affero General Public License as published by
008  *  the Free Software Foundation, either version 3 of the License, or
009  *  (at your option) any later version.
010  *  
011  *  This program is distributed in the hope that it will be useful,
012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014  *  GNU Affero General Public License for more details.
015  *  
016  *  You should have received a copy of the GNU Affero General Public License
017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
018  */
019 
020 package jsx.client;
021 
022 import js.*;
023 import js.core.*;
024 import js.user.*;
025 import jsx.dom.Nodes;
026 
027 /**
028  * <p>A utility class accessing the properties of {@link js.user.JsWindow#document}.</p>
029  * <p>Users are encouraged to use the utilities provided in this class instead of the 
030  * <b>opaque</b> methods of the {@link js.user.JsDocument} class in consideration of the 
031  * reuse benefit for re-compilation results.</p>
032  * 
033  * @author <a href="mailto:jianjunliu@126.com">J.J.Liu (Jianjun Liu)</a> at <a href="http://www.jscripter.org" target="_blank">http://www.jscripter.org</a>
034  */
035 public final class Document extends Disposable
036 {
037     private Document() {}
038 
039     /**
040      * <p>Statically accesses a property of <tt>document</tt> by the name of this field. 
041      * @since 1.0
042      * @see js.user.JsDocument
043      */
044     public final static Var<String> compatMode = new Static<String>(new Field<String>(Win.document, JsDocument.compatMode));
045     /**
046      * <p>Statically accesses a property of <tt>document</tt> by the name of this field. 
047      * @since 1.0
048      * @see js.user.JsDocument
049      */
050     public final static Var<JsHTMLElement> body = new Static<JsHTMLElement>(new Field<JsHTMLElement>(Win.document, JsHTMLDocument.body));
051     /**
052      * <p>Statically accesses a property of <tt>document</tt> by the name of this field. 
053      * @since 1.0
054      * @see js.user.JsDocument
055      */
056     public final static Var<JsHTMLElement> documentElement = new Static<JsHTMLElement>(new Field<JsHTMLElement>(Win.document, JsHTMLDocument.documentElement));
057     /**
058      * <p>Adds an event handler function to the set of event handlers for the current {@link JsWindow#document} object. 
059      * This is a DOM-standard method supported by all modern browsers except IE.</p>
060      * <p>This method adds the specified event <tt>listener</tt> function to the set of 
061      * listeners registered on this node to handle events of the specified <tt>type</tt>. 
062      * If <tt>useCapture</tt> is <tt>true</tt>, the <tt>listener</tt> is registered as 
063      * a capturing event listener. If <tt>useCapture</tt> is <tt>false</tt>, it is 
064      * registered as a normal event listener.</p>
065      * <p>This method may be called multiple times to register multiple event handlers 
066      * for the same type of event on the same node. Note, however, that the DOM 
067      * Specification makes no guarantees about the order in which multiple event handlers 
068      * are invoked.</p>
069      * <p>If the same event listener function is registered twice on the same node with 
070      * the same <tt>type</tt> and <tt>useCapture</tt> arguments, the second registration 
071      * is simply ignored. If a new event listener is registered on this node while an 
072      * event is being handled at this node, the new event listener is not invoked for 
073      * that event.</p>
074      * <p>When a node is duplicated with {@link JsNode#cloneNode(Boolean)} or {@link JsDocument#importNode(JsNode, Boolean)}, 
075      * the event listeners registered for the original node are not copied.</p>
076      * <p>The same method is also defined by, and works analogously on, the {@link JsElement} 
077      * and {@link JsWindow} objects</p>
078      * @param type The type of event for which the event listener is to be invoked.
079      * @param listener The event listener function that is invoked when an event of the 
080      * specified type is dispatched to this node. When invoked, the listener function 
081      * is passed an {@link JsEvent} object and is invoked as a method of the node on 
082      * which it is registered.
083      * @param useCapture If <tt>true</tt>, the specified <tt>listener</tt> is to be 
084      * invoked only during the capturing phase of event propagation. The more common 
085      * value of <tt>false</tt> means that the <tt>listener</tt> is not invoked during 
086      * the capturing phase but instead is invoked when this node is the actual event 
087      * target or when the event bubbles up to this node from its original target.
088      * @since 1.0
089      * @see #attachEvent(String, JsFunction)
090      * @see #removeEventListener(String, JsFunction, Boolean)
091      * @see JsDocument#addEventListener(String, JsFunction, Boolean)
092      * @see Win#addEventListener(String, JsFunction, Boolean)
093      * @see JsWindow#addEventListener(String, JsFunction, Boolean)
094      * @see JsElement#addEventListener(String, JsFunction, Boolean)
095      */
096     public static final void addEventListener(String type, JsFunction<?> listener, Boolean useCapture) {
097         Win.document.var().addEventListener(type, listener, useCapture);
098     }
099     /**
100      * <p>Removes an event handler function from the set of handlers for the current {@link JsWindow#document} object. 
101      * This is a standard DOM method implemented by all modern browsers except IE.</p>
102      * <p>This method removes the specified event <tt>listener</tt> function. The <tt>type</tt> 
103      * and <tt>useCapture</tt> arguments must be the same as they are in the 
104      * corresponding call to {@link #addEventListener(String, JsFunction, Boolean)}. If 
105      * no event listener is found that matches the specified arguments, this method does 
106      * nothing.</p>
107      * <p>Once an event <tt>listener</tt> function has been removed by this method, it 
108      * will no longer be invoked for the specified <tt>type</tt> of event on this node. 
109      * This is true even if the event <tt>listener</tt> is removed by another event 
110      * listener registered for the same type of event on the same node.</p>
111      * <p>The same method is also defined by, and works analogously on, the {@link JsElement} 
112      * and {@link JsWindow} objects</p>
113      * @param type The type of event for which the event listener is to be deleted.
114      * @param listener The event listener function that is to be removed.
115      * @param useCapture <tt>true</tt> if a capturing event listener is to be removed; 
116      * <tt>false</tt> if a normal event listener is to be removed.
117      * @since 1.0
118      * @see #detachEvent(String, JsFunction)
119      * @see #addEventListener(String, JsFunction, Boolean)
120      * @see JsDocument#removeEventListener(String, JsFunction, Boolean)
121      * @see Win#removeEventListener(String, JsFunction, Boolean)
122      * @see JsWindow#removeEventListener(String, JsFunction, Boolean)
123      * @see JsElement#removeEventListener(String, JsFunction, Boolean)
124      */
125     public static final void removeEventListener(String type, JsFunction<?> listener, Boolean useCapture) {
126         Win.document.var().removeEventListener(type, listener, useCapture);
127     }
128     /**
129      * <p>Adds an event handler function to the set of handlers for the current {@link JsWindow#document} object. 
130      * This is the IE-specific alternative to {@link #addEventListener(String, JsFunction, Boolean)}.</p>
131      * <p>This method is an IE-specific event registration method. It serves the same 
132      * purpose as the standard {@link #addEventListener(String, JsFunction, Boolean)} 
133      * method, which IE does not support, but is different from that function in several 
134      * important ways:
135      * <ul>
136      * <li>Since the IE event model does not support event capturing, this method and 
137      * {@link #detachEvent(String, JsFunction)} expect only two arguments: the event 
138      * type and the handler function.</li>
139      * <li>The event handler names passed to the IE methods should include the "on" 
140      * prefix.</li>
141      * <li>Functions registered with this method are invoked with no {@link JsEvent} 
142      * object argument. Instead, they must read the {@link JsWindow#event} property of 
143      * the {@link JsWindow#window} object.</li>
144      * <li>Functions registered with this method are invoked as global functions, rather 
145      * than as methods of the node on which the event occurred. That is, when an event 
146      * handler registered with this method executes, the <tt>this</tt> keyword refers to 
147      * the {@link JsWindow#window} object, not to the event's target node.</li>
148      * <li>This method allows the same event handler function to be registered more than 
149      * once. When an event of the specified type occurs, the registered function is 
150      * invoked as many times as it is registered.</li>
151      * </ul>
152      * </p>
153      * <p>The same method is also defined by, and works analogously on, the {@link JsElement} 
154      * and {@link JsWindow} objects</p>
155      * @param type The type of event for which the event listener is to be invoked, with 
156      * a leading "on" prefix.
157      * @param listener The event listener function that is invoked when an event of the 
158      * specified type is dispatched to this node. This function is not passed any 
159      * arguments but can obtain the {@link JsEvent} object from the {@link JsWindow#event} 
160      * property of the {@link JsWindow} object.
161      * @since 1.0
162      * @see #addEventListener(String, JsFunction, Boolean)
163      * @see #detachEvent(String, JsFunction)
164      * @see JsDocument#attachEvent(String, JsFunction)
165      * @see Win#attachEvent(String, JsFunction)
166      * @see JsWindow#attachEvent(String, JsFunction)
167      * @see JsElement#attachEvent(String, JsFunction)
168      */
169     public static final void attachEvent(String type, JsFunction<?> listener) {
170         Win.document.var().attachEvent(type, listener);
171     }
172     /**
173      * <p>Removes an event handler function from the current {@link JsWindow#document} object. This is the IE-specific 
174      * alternative to the standard {@link #removeEventListener(String, JsFunction, Boolean)} 
175      * method.</p>
176      * <p>This method undoes the event handler function registration performed by the 
177      * {@link #attachEvent(String, JsFunction)} method. It is the IE-specific analog to 
178      * the standard {@link #removeEventListener(String, JsFunction, Boolean)}. To remove 
179      * an event handler function for a node, simply invoke this method with the same 
180      * arguments you originally passed to {@link #attachEvent(String, JsFunction)}.</p>
181      * <p>The same method is also defined by, and works analogously on, the {@link JsElement} 
182      * and {@link JsWindow} objects</p>
183      * @param type The type of event for which the event listener is to be invoked, with 
184      * a leading "on" prefix.
185      * @param listener The event listener function that is to be removed.
186      * @since 1.0
187      * @see #removeEventListener(String, JsFunction, Boolean)
188      * @see #attachEvent(String, JsFunction)
189      * @see JsDocument#detachEvent(String, JsFunction)
190      * @see Win#detachEvent(String, JsFunction)
191      * @see JsWindow#detachEvent(String, JsFunction)
192      * @see JsElement#detachEvent(String, JsFunction)
193      */
194     public static final void detachEvent(String type, JsFunction<?> listener) {
195         Win.document.var().detachEvent(type, listener);
196     }
197     /**
198      * <p>Creates a new {@link JsElement} node with the specified tag name.</p>
199      * @param tagName The tag name of the {@link JsElement} node being created. Since 
200      * HTML tags are case-insensitive, you may use any capitalization for HTML tag names. 
201      * XML tag names are case-sensitive. 
202      * @return A newly created {@link JsElement} node with the specified tag name. 
203      * @throws RuntimeException JavaScript throws a {@link JsDOMException} object with 
204      * the {@link JsDOMException#code} property of the value {@link JsDOMException#INVALID_CHARACTER_ERR} 
205      * if <tt>tagName</tt> contains an illegal character. See {@link Js#err(Object)} 
206      * for JS Simulation.
207      * @since 1.0
208      * @see #createElement(StringLike)
209      * @see JsDocument#createElement(String)
210      */
211     public static final JsElement createElement(String tagName) {
212         return Win.document.var().createElement(tagName);
213     }
214     /**
215      * <p>Creates a new {@link JsElement} node with the specified tag name.</p>
216      * @param tagName The tag name of the {@link JsElement} node being created. Since 
217      * HTML tags are case-insensitive, you may use any capitalization for HTML tag names. 
218      * XML tag names are case-sensitive. 
219      * @return A newly created {@link JsElement} node with the specified tag name. 
220      * @throws RuntimeException JavaScript throws a {@link JsDOMException} object with 
221      * the {@link JsDOMException#code} property of the value {@link JsDOMException#INVALID_CHARACTER_ERR} 
222      * if <tt>tagName</tt> contains an illegal character. See {@link Js#err(Object)} 
223      * for JS Simulation.
224      * @since 1.0
225      * @see #createElement(String)
226      * @see JsDocument#createElement(StringLike)
227      */
228     public static final JsElement createElement(StringLike tagName) {
229         return Win.document.var().createElement(tagName);
230     }
231     /**
232      * <p>Creates a style sheet for the current document.</p>
233      * <p>This method is IE specific.</p>
234      * @param url Specifies how to add the style sheet to the document. If a file name is 
235      * specified for the argument, the style information will be added as a {@link JsHTMLLinkElement} 
236      * object. If the argument contains style information, this information will be added 
237      * to the style object.
238      * @param index Specifies the index that indicates where the new style sheet is inserted 
239      * in the {@link JsDocument#styleSheets} collection. The default is to insert the new style sheet 
240      * at the end of the collection.
241      * @return A newly created {@link JsCSSStyleSheet} object. 
242      * @since 1.0
243      * @see #createStyleSheet(String)
244      * @see JsDocument#createStyleSheet(String, int)
245      */
246     public static final JsCSSStyleSheet createStyleSheet(String url, int index) {
247         return Win.document.var().createStyleSheet(url, index);
248     }
249     /**
250      * <p>Creates a style sheet for the current document.</p>
251      * <p>This method is IE specific.</p>
252      * @param url Specifies how to add the style sheet to the document. If a file name is 
253      * specified for the argument, the style information will be added as a {@link JsHTMLLinkElement} 
254      * object. If the argument contains style information, this information will be added 
255      * to the style object.
256      * @return A newly created {@link JsCSSStyleSheet} object. 
257      * @since 1.0
258      * @see #createStyleSheet(String, int)
259      * @see JsDocument#createStyleSheet(String)
260      */
261     public static final JsCSSStyleSheet createStyleSheet(String url) {
262         return Win.document.var().createStyleSheet(url);
263     }
264     /**
265      * <p>Gets the {@link JsHTMLHeadElement} of the current document.</p>
266      * @return The {@link JsHTMLHeadElement} of the current document. 
267      * @since 1.0
268      * @see JsDocument#getElementsByTagName(String)
269      * @see Nodes#getElementsByTagName(JsNode, String)
270      */
271     public static final JsHTMLHeadElement head() {
272         return new JsHTMLHeadElement(Nodes.getElementsByTagName(Win.document.var(), "head").get(0));
273     }
274     /**
275      * <p>Gets the {@link JsHTMLBodyElement} of the current document.</p>
276      * @return The {@link JsHTMLBodyElement} of the current document. 
277      * @since 1.0
278      * @see JsDocument#getElementsByTagName(String)
279      * @see Nodes#getElementsByTagName(JsNode, String)
280      */
281     public static final JsHTMLBodyElement body() {
282         return new JsHTMLBodyElement(Nodes.getElementsByTagName(Win.document.var(), "body").get(0));
283     }
284 
285     /**
286      * <p>Determines whether the current document is in a {@link #compatMode}.</p>
287      * @see Browser
288      * @since 1.0
289      */
290     public static final boolean isStrict = Js.eq(compatMode.var(), "");
291 }