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.dom;
021 
022 import js.ArrayLike;
023 import js.Disposable;
024 import js.Js;
025 import js.user.JsHTMLElement;
026 import js.user.JsNode;
027 import js.user.JsRange;
028 import jsx.Code;
029 import jsx.Template;
030 import jsx.client.Browser;
031 
032 /**
033  * <p>A utility class manipulating DOM in HTML with its static methods.</p>
034  * 
035  * @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>
036  */
037 public final class Markups extends Disposable
038 {
039     private Markups() {}
040 
041     /**
042      * <p>Inserts the given HTML text immediately before the node.</p>
043      * @param node An HTML element node.
044      * @param html A string that specifies the HTML text to insert. The string can be a 
045      * combination of text and HTML tags. This must be well-formed, valid HTML or this 
046      * method will fail.
047      * @return An HTML element node.
048      * @since 1.0
049      */
050     public static final JsHTMLElement insertBeforeBegin(JsNode node, String html) {
051         if (Browser.canInsertHTML) {
052             Nodes.insertAdjacentHTML(node, "BeforeBegin", html);
053         } else {
054             JsRange range = node.var(JsNode.ownerDocument).createRange();
055             range.setStartBefore(node);
056             JsNode n = range.createContextualFragment(html);
057             Nodes.parentNode(node).insertBefore(n, node);
058         }
059         return new JsHTMLElement(Nodes.previousSibling(node));
060     }
061 
062     /**
063      * <p>Inserts the given HTML text immediately after the end of the node.</p>
064      * @param node An HTML element node.
065      * @param html A string that specifies the HTML text to insert. The string can be a 
066      * combination of text and HTML tags. This must be well-formed, valid HTML or this 
067      * method will fail.
068      * @return An HTML element node.
069      * @since 1.0
070      */
071     public static final JsHTMLElement insertAfterEnd(JsNode node, String html) {
072         if (Browser.canInsertHTML) {
073             Nodes.insertAdjacentHTML(node, "AfterEnd", html);
074         } else {
075             JsRange range = node.var(JsNode.ownerDocument).createRange();
076             range.setStartAfter(node);
077             JsNode n = range.createContextualFragment(html);
078             Nodes.parentNode(node).insertBefore(n, Nodes.nextSibling(node));
079         }
080         return new JsHTMLElement(Nodes.nextSibling(node));
081     }
082 
083     /**
084      * <p>Inserts the given HTML text immediately after the start of the node.</p>
085      * @param node An HTML element node.
086      * @param html A string that specifies the HTML text to insert. The string can be a 
087      * combination of text and HTML tags. This must be well-formed, valid HTML or this 
088      * method will fail.
089      * @return An HTML element node.
090      * @since 1.0
091      */
092     public static final JsHTMLElement insertAfterBegin(JsNode node, String html) {
093         if (Browser.canInsertHTML) {
094             Nodes.insertAdjacentHTML(node, "AfterBegin", html);
095         } else {
096             JsNode first = Nodes.firstChild(node);
097             if (Js.be(first)) {
098                 JsRange range = node.var(JsNode.ownerDocument).createRange();
099                 range.setStartBefore(first);
100                 JsNode n = range.createContextualFragment(html);
101                 node.insertBefore(n, first);
102             } else {
103                 Nodes.innerHTML(node, html);
104             }
105         }
106         return new JsHTMLElement(Nodes.firstChild(node));
107     }
108 
109     /**
110      * <p>Inserts the given HTML text immediately before the end of the node.</p>
111      * @param node An HTML element node.
112      * @param html A string that specifies the HTML text to insert. The string can be a 
113      * combination of text and HTML tags. This must be well-formed, valid HTML or this 
114      * method will fail.
115      * @return An HTML element node.
116      * @since 1.0
117      */
118     public static final JsHTMLElement insertBeforeEnd(JsNode node, String html) {
119         if (Browser.canInsertHTML) {
120             Nodes.insertAdjacentHTML(node, "BeforeEnd", html);
121         } else {
122             JsNode last = Nodes.lastChild(node);
123             if (Js.be(last)) {
124                 JsRange range = node.var(JsNode.ownerDocument).createRange();
125                 range.setStartAfter(last);
126                 JsNode n = range.createContextualFragment(html);
127                 node.appendChild(n);
128             } else {
129                 Nodes.innerHTML(node, html);
130             }
131         }
132         return new JsHTMLElement(Nodes.lastChild(node));
133     }
134 
135     /**
136      * <p>Creates HTML text from the given template and template parameters and inserts it
137      * immediately before the node.</p>
138      * <p>The created HTML can be a combination of text and HTML tags. It must be 
139      * well-formed, valid HTML or this method will fail.</p>
140      * @param node An HTML element node.
141      * @param tmplt A template for creating the HTML text.
142      * @param paras An array of template parameter strings.
143      * @return An HTML element node.
144      * @since 1.0
145      */
146     public static final JsHTMLElement insertBeforeBegin(JsNode node, ArrayLike<String> tmplt, ArrayLike<String> paras) {
147         return insertBeforeBegin(node, Template.apply(tmplt, paras));
148     }
149 
150     /**
151      * <p>Creates HTML text from the given template and template parameters and inserts it
152      * immediately after the end of the node.</p>
153      * <p>The created HTML can be a combination of text and HTML tags. It must be 
154      * well-formed, valid HTML or this method will fail.</p>
155      * @param node An HTML element node.
156      * @param tmplt A template for creating the HTML text.
157      * @param paras An array of template parameter strings.
158      * @return An HTML element node.
159      * @since 1.0
160      */
161     public static final JsHTMLElement insertAfterEnd(JsNode node, ArrayLike<String> tmplt, ArrayLike<String> paras) {
162         return insertAfterEnd(node, Template.apply(tmplt, paras));
163     }
164 
165     /**
166      * <p>Creates HTML text from the given template and template parameters and inserts it
167      * immediately after the start of the node.</p>
168      * <p>The created HTML can be a combination of text and HTML tags. It must be 
169      * well-formed, valid HTML or this method will fail.</p>
170      * @param node An HTML element node.
171      * @param tmplt A template for creating the HTML text.
172      * @param paras An array of template parameter strings.
173      * @return An HTML element node.
174      * @since 1.0
175      */
176     public static final JsHTMLElement insertAfterBegin(JsNode node, ArrayLike<String> tmplt, ArrayLike<String> paras) {
177         return insertAfterBegin(node, Template.apply(tmplt, paras));
178     }
179 
180     /**
181      * <p>Creates HTML text from the given template and template parameters and inserts it
182      * immediately before the end of the node.</p>
183      * <p>The created HTML can be a combination of text and HTML tags. It must be 
184      * well-formed, valid HTML or this method will fail.</p>
185      * @param node An HTML element node.
186      * @param tmplt A template for creating the HTML text.
187      * @param paras An array of template parameter strings.
188      * @return An HTML element node.
189      * @since 1.0
190      */
191     public static final JsHTMLElement insertBeforeEnd(JsNode node, ArrayLike<String> tmplt, ArrayLike<String> paras) {
192         return insertBeforeEnd(node, Template.apply(tmplt, paras));
193     }
194 
195     /**
196      * <p>Creates HTML text from the given template and template parameters and replace the
197      * innerHTML of the node with it.</p>
198      * <p>The created HTML can be a combination of text and HTML tags. It must be 
199      * well-formed, valid HTML or this method will fail.</p>
200      * @param node An HTML element node.
201      * @param tmplt A template for creating the HTML text.
202      * @param paras An array of template parameter strings.
203      * @return An HTML element node.
204      * @since 1.0
205      */
206     public static final JsHTMLElement replaceHtml(JsNode node, ArrayLike<String> tmplt, ArrayLike<String> paras) {
207         String html = Template.apply(tmplt, paras);
208         Nodes.innerHTML(node, html);
209         return new JsHTMLElement(Nodes.firstChild(node));
210     }
211 
212     /**
213      * <p>The HTML string of &lt;div&gt;&lt;/div&gt;.</p>
214      * @since 1.0
215      */
216     public final static String DIV   = Template.apply(Template.DIV  );
217     /**
218      * <p>The HTML string of &lt;label&gt;&lt;/label&gt;.</p>
219      * @since 1.0
220      */
221     public final static String LABEL = Template.apply(Template.LABEL);
222     /**
223      * <p>The HTML string of &lt;li&gt;&lt;/li&gt;.</p>
224      * @since 1.0
225      */
226     public final static String LI    = Template.apply(Template.LI   );
227     /**
228      * <p>The HTML string of &lt;ul&gt;&lt;/ul&gt;.</p>
229      * @since 1.0
230      */
231     public final static String UL    = Template.apply(Template.UL   );
232     /**
233      * <p>The HTML string of &lt;span&gt;&lt;/span&gt;.</p>
234      * @since 1.0
235      */
236     public final static String SPAN  = Template.apply(Template.SPAN );
237 
238     /**
239      * <p>Creates a starting HTML tag.</p>
240      * @param tag The tag name.
241      * @return The text of the created HTML tag.
242      * @since 1.0
243      */
244     public static final String start(String tag) {
245         return Template.apply(Template.START, tag);
246     }
247 
248     /**
249      * <p>Creates HTML text for an attribute.</p>
250      * @param attr The attribute name.
251      * @param value The attribute value.
252      * @return The text of the created HTML piece.
253      * @since 1.0
254      */
255     public static final String attr(String attr, String value) {
256         return Template.apply(Template.attr(attr), Code.qt(value));
257     }
258 
259     /**
260      * <p>Creates HTML text for a button element.</p>
261      * @param value The name of the button.
262      * @return The text of the created HTML piece.
263      * @since 1.0
264      */
265     public static final String button(String value) {
266         return Template.apply(Template.BUTTON, value);
267     }
268 
269     /**
270      * <p>Creates HTML text for a button element.</p>
271      * @param value The name of the button.
272      * @param title The title of the button.
273      * @return The text of the created HTML piece.
274      * @since 1.0
275      */
276     public static final String button(String value, String title) {
277         return Template.apply(
278                 Template.element(
279                         Js.add(
280                                 "button",
281                                 Template.apply(
282                                         Template.attr("title"),
283                                         Code.qt(title)
284                                 )
285                         ),
286                         "button"
287                 ),
288                 value
289         );
290     }
291 
292     /**
293      * <p>Creates HTML text for an input element.</p>
294      * @param type The type of the input element to create.
295      * @return The text of the created HTML piece.
296      * @since 1.0
297      */
298     public static final String input(String type) {
299         return start(Js.add("input", attr("type", type)));
300     }
301 
302     /**
303      * <p>Creates an HTML radio element.</p>
304      * @param name The name for the radio element.
305      * @return The text of the created HTML piece.
306      * @since 1.0
307      */
308     public static final String radio(String name) {
309         return start(Code.join("input", attr("type", "radio"), attr("name", name)));
310     }
311 
312     /**
313      * <p>Creates an HTML &lt;span&gt;&lt;/span&gt; element.</p>
314      * @param html The HTML text to span.
315      * @return The text of the created HTML piece.
316      * @since 1.0
317      */
318     public static final String span(String html) {
319         return Template.apply(Template.SPAN, html);
320     }
321 
322     /**
323      * <p>Creates HTML tags for an element with value and title.</p>
324      * @param tag The tag name for the element.
325      * @param value The value for the element.
326      * @param title The text of the title.
327      * @return The text of the created HTML piece.
328      * @since 1.0
329      */
330     public static final String title(String tag, String value, String title) {
331         return Template.apply(
332                 Template.element(
333                         Js.add(
334                                 tag,
335                                 Template.apply(
336                                         Template.attr("title"),
337                                         Code.qt(title)
338                                 )
339                         ),
340                         tag
341                 ),
342                 value
343         );
344     }
345 }