001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.dto.html5;
014
015import static org.apache.juneau.xml.annotation.XmlFormat.*;
016import static org.apache.juneau.html.annotation.HtmlFormat.*;
017
018import java.net.*;
019import java.net.URI;
020import java.util.*;
021import java.util.Map.*;
022
023import org.apache.juneau.*;
024import org.apache.juneau.annotation.*;
025import org.apache.juneau.html.*;
026import org.apache.juneau.internal.*;
027import org.apache.juneau.xml.annotation.*;
028
029/**
030 * Superclass for all HTML elements.
031 *
032 * <p>
033 * These are beans that when serialized using {@link HtmlSerializer} generate valid HTML5 elements.
034 *
035 * <h5 class='section'>See Also:</h5>
036 * <ul class='doctree'>
037 *    <li class='link'>{@doc juneau-dto.HTML5}
038 * </ul>
039 */
040@org.apache.juneau.html.annotation.Html(format=XML)
041public abstract class HtmlElement {
042
043   private LinkedHashMap<String,Object> attrs;
044
045   /**
046    * The attributes of this element.
047    *
048    * @return The attributes of this element.
049    */
050   @Xml(format=ATTRS)
051   @BeanProperty("a")
052   public LinkedHashMap<String,Object> getAttrs() {
053      return attrs;
054   }
055
056   /**
057    * Sets the attributes for this element.
058    *
059    * @param attrs The new attributes for this element.
060    * @return This object (for method chaining).
061    */
062   @BeanProperty("a")
063   public HtmlElement setAttrs(LinkedHashMap<String,Object> attrs) {
064      for (Entry<String,Object> e : attrs.entrySet()) {
065         String key = e.getKey();
066         if ("url".equals(key) || "href".equals(key) || key.endsWith("action"))
067            e.setValue(StringUtils.toURI(e.getValue()));
068      }
069      this.attrs = attrs;
070      return this;
071   }
072
073   /**
074    * Adds an arbitrary attribute to this element.
075    *
076    * @param key The attribute name.
077    * @param val The attribute value.
078    * @return This object (for method chaining).
079    */
080   public HtmlElement attr(String key, Object val) {
081      if (this.attrs == null)
082         this.attrs = new LinkedHashMap<>();
083      if (val == null)
084         this.attrs.remove(key);
085      else {
086         if ("url".equals(key) || "href".equals(key) || key.endsWith("action"))
087            val = StringUtils.toURI(val);
088         this.attrs.put(key, val);
089      }
090      return this;
091   }
092
093   /**
094    * Adds an arbitrary URI attribute to this element.
095    *
096    * <p>
097    * Same as {@link #attr(String, Object)}, except if the value is a string that appears to be a URI
098    * (e.g. <js>"servlet:/xxx"</js>).
099    *
100    * <p>
101    * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}.
102    * Strings must be valid URIs.
103    *
104    * <p>
105    * URIs defined by {@link UriResolver} can be used for values.
106    *
107    * @param key The attribute name.
108    * @param val The attribute value.
109    * @return This object (for method chaining).
110    */
111   public HtmlElement attrUri(String key, Object val) {
112      if (this.attrs == null)
113         this.attrs = new LinkedHashMap<>();
114      this.attrs.put(key, StringUtils.toURI(val));
115      return this;
116   }
117
118   /**
119    * Returns the attribute with the specified name.
120    *
121    * @param key The attribute name.
122    * @return The attribute value, or <jk>null</jk> if the named attribute does not exist.
123    */
124   public String getAttr(String key) {
125      return getAttr(String.class, key);
126   }
127
128   /**
129    * Returns the attribute with the specified name converted to the specified class type.
130    *
131    * @param type
132    *    The class type to convert this class to.
133    *    See {@link ObjectUtils} for a list of supported conversion types.
134    * @param key The attribute name.
135    * @return The attribute value, or <jk>null</jk> if the named attribute does not exist.
136    */
137   public <T> T getAttr(Class<T> type, String key) {
138      return attrs == null ? null : ObjectUtils.toType(attrs.get(key), type);
139   }
140
141   /**
142    * {@doc HTML5.editing#the-accesskey-attribute accesskey}
143    * attribute.
144    *
145    * @param accesskey The new value for this attribute.
146    * @return This object (for method chaining).
147    */
148   public HtmlElement accesskey(String accesskey) {
149      attr("accesskey", accesskey);
150      return this;
151   }
152
153   /**
154    * {@doc HTML5.dom#classes class} attribute.
155    *
156    * @param _class The new value for this attribute.
157    * @return This object (for method chaining).
158    */
159   public HtmlElement _class(String _class) {
160      attr("class", _class);
161      return this;
162   }
163
164   /**
165    * {@doc HTML5.editing#attr-contenteditable contenteditable}
166    * attribute.
167    *
168    * @param contenteditable The new value for this attribute.
169    * Typically a {@link Boolean} or {@link String}.
170    * @return This object (for method chaining).
171    */
172   public HtmlElement contenteditable(Object contenteditable) {
173      attr("contenteditable", contenteditable);
174      return this;
175   }
176
177   /**
178    * {@doc HTML5.dom#the-dir-attribute dir} attribute.
179    *
180    * @param dir The new value for this attribute.
181    * @return This object (for method chaining).
182    */
183   public HtmlElement dir(String dir) {
184      attr("dir", dir);
185      return this;
186   }
187
188   /**
189    * {@doc HTML5.editing#the-hidden-attribute hidden} attribute.
190    *
191    * @param hidden
192    *    The new value for this attribute.
193    *    Typically a {@link Boolean} or {@link String}.
194    * @return This object (for method chaining).
195    */
196   public HtmlElement hidden(Object hidden) {
197      attr("hidden", deminimize(hidden, "hidden"));
198      return this;
199   }
200
201   /**
202    * {@doc HTML5.dom#the-id-attribute id} attribute.
203    *
204    * @param id The new value for this attribute.
205    * @return This object (for method chaining).
206    */
207   public HtmlElement id(String id) {
208      attr("id", id);
209      return this;
210   }
211
212   /**
213    * {@doc HTML5.dom#attr-lang lang} attribute.
214    *
215    * @param lang The new value for this attribute.
216    * @return This object (for method chaining).
217    */
218   public HtmlElement lang(String lang) {
219      attr("lang", lang);
220      return this;
221   }
222
223   /**
224    * {@doc HTML5.webappapis#handler-onabort onabort} attribute.
225    *
226    * @param onabort The new value for this attribute.
227    * @return This object (for method chaining).
228    */
229   public HtmlElement onabort(String onabort) {
230      attr("onabort", onabort);
231      return this;
232   }
233
234   /**
235    * {@doc HTML5.webappapis#handler-onblur onblur} attribute.
236    *
237    * @param onblur The new value for this attribute.
238    * @return This object (for method chaining).
239    */
240   public HtmlElement onblur(String onblur) {
241      attr("onblur", onblur);
242      return this;
243   }
244
245   /**
246    * {@doc HTML5.webappapis#handler-oncancel oncancel} attribute.
247    *
248    * @param oncancel The new value for this attribute.
249    * @return This object (for method chaining).
250    */
251   public HtmlElement oncancel(String oncancel) {
252      attr("oncancel", oncancel);
253      return this;
254   }
255
256   /**
257    * {@doc HTML5.webappapis#handler-oncanplay oncanplay} attribute.
258    *
259    * @param oncanplay The new value for this attribute.
260    * @return This object (for method chaining).
261    */
262   public HtmlElement oncanplay(String oncanplay) {
263      attr("oncanplay", oncanplay);
264      return this;
265   }
266
267   /**
268    * {@doc HTML5.webappapis#handler-oncanplaythrough oncanplaythrough}
269    * attribute.
270    *
271    * @param oncanplaythrough The new value for this attribute.
272    * @return This object (for method chaining).
273    */
274   public HtmlElement oncanplaythrough(String oncanplaythrough) {
275      attr("oncanplaythrough", oncanplaythrough);
276      return this;
277   }
278
279   /**
280    * {@doc HTML5.webappapis#handler-onchange onchange} attribute.
281    *
282    * @param onchange The new value for this attribute.
283    * @return This object (for method chaining).
284    */
285   public HtmlElement onchange(String onchange) {
286      attr("onchange", onchange);
287      return this;
288   }
289
290   /**
291    * {@doc HTML5.webappapis#handler-onclick onclick} attribute.
292    *
293    * @param onclick The new value for this attribute.
294    * @return This object (for method chaining).
295    */
296   public HtmlElement onclick(String onclick) {
297      attr("onclick", onclick);
298      return this;
299   }
300
301   /**
302    * {@doc HTML5.webappapis#handler-oncuechange oncuechange}
303    * attribute.
304    *
305    * @param oncuechange The new value for this attribute.
306    * @return This object (for method chaining).
307    */
308   public HtmlElement oncuechange(String oncuechange) {
309      attr("oncuechange", oncuechange);
310      return this;
311   }
312
313   /**
314    * {@doc HTML5.webappapis#handler-ondblclick ondblclick} attribute.
315    *
316    * @param ondblclick The new value for this attribute.
317    * @return This object (for method chaining).
318    */
319   public HtmlElement ondblclick(String ondblclick) {
320      attr("ondblclick", ondblclick);
321      return this;
322   }
323
324   /**
325    * {@doc HTML5.webappapis#handler-ondurationchange ondurationchange}
326    * attribute.
327    *
328    * @param ondurationchange The new value for this attribute.
329    * @return This object (for method chaining).
330    */
331   public HtmlElement ondurationchange(String ondurationchange) {
332      attr("ondurationchange", ondurationchange);
333      return this;
334   }
335
336   /**
337    * {@doc HTML5.webappapis#handler-onemptied onemptied} attribute.
338    *
339    * @param onemptied The new value for this attribute.
340    * @return This object (for method chaining).
341    */
342   public HtmlElement onemptied(String onemptied) {
343      attr("onemptied", onemptied);
344      return this;
345   }
346
347   /**
348    * {@doc HTML5.webappapis#handler-onended onended} attribute.
349    *
350    * @param onended The new value for this attribute.
351    * @return This object (for method chaining).
352    */
353   public HtmlElement onended(String onended) {
354      attr("onended", onended);
355      return this;
356   }
357
358   /**
359    * {@doc HTML5.webappapis#handler-onerror onerror} attribute.
360    *
361    * @param onerror The new value for this attribute.
362    * @return This object (for method chaining).
363    */
364   public HtmlElement onerror(String onerror) {
365      attr("onerror", onerror);
366      return this;
367   }
368
369   /**
370    * {@doc HTML5.webappapis#handler-onfocus onfocus} attribute.
371    *
372    * @param onfocus The new value for this attribute.
373    * @return This object (for method chaining).
374    */
375   public HtmlElement onfocus(String onfocus) {
376      attr("onfocus", onfocus);
377      return this;
378   }
379
380   /**
381    * {@doc HTML5.webappapis#handler-oninput oninput} attribute.
382    *
383    * @param oninput The new value for this attribute.
384    * @return This object (for method chaining).
385    */
386   public HtmlElement oninput(String oninput) {
387      attr("oninput", oninput);
388      return this;
389   }
390
391   /**
392    * {@doc HTML5.webappapis#handler-oninvalid oninvalid} attribute.
393    *
394    * @param oninvalid The new value for this attribute.
395    * @return This object (for method chaining).
396    */
397   public HtmlElement oninvalid(String oninvalid) {
398      attr("oninvalid", oninvalid);
399      return this;
400   }
401
402   /**
403    * {@doc HTML5.webappapis#handler-onkeydown onkeydown} attribute.
404    *
405    * @param onkeydown The new value for this attribute.
406    * @return This object (for method chaining).
407    */
408   public HtmlElement onkeydown(String onkeydown) {
409      attr("onkeydown", onkeydown);
410      return this;
411   }
412
413   /**
414    * {@doc HTML5.webappapis#handler-onkeypress onkeypress} attribute.
415    *
416    * @param onkeypress The new value for this attribute.
417    * @return This object (for method chaining).
418    */
419   public HtmlElement onkeypress(String onkeypress) {
420      attr("onkeypress", onkeypress);
421      return this;
422   }
423
424   /**
425    * {@doc HTML5.webappapis#handler-onkeyup onkeyup} attribute.
426    *
427    * @param onkeyup The new value for this attribute.
428    * @return This object (for method chaining).
429    */
430   public HtmlElement onkeyup(String onkeyup) {
431      attr("onkeyup", onkeyup);
432      return this;
433   }
434
435   /**
436    * {@doc HTML5.webappapis#handler-onload onload} attribute.
437    *
438    * @param onload The new value for this attribute.
439    * @return This object (for method chaining).
440    */
441   public HtmlElement onload(String onload) {
442      attr("onload", onload);
443      return this;
444   }
445
446   /**
447    * {@doc HTML5.webappapis#handler-onloadeddata onloadeddata}
448    * attribute.
449    *
450    * @param onloadeddata The new value for this attribute.
451    * @return This object (for method chaining).
452    */
453   public HtmlElement onloadeddata(String onloadeddata) {
454      attr("onloadeddata", onloadeddata);
455      return this;
456   }
457
458   /**
459    * {@doc HTML5.webappapis#handler-onloadedmetadata onloadedmetadata}
460    * attribute.
461    *
462    * @param onloadedmetadata The new value for this attribute.
463    * @return This object (for method chaining).
464    */
465   public HtmlElement onloadedmetadata(String onloadedmetadata) {
466      attr("onloadedmetadata", onloadedmetadata);
467      return this;
468   }
469
470   /**
471    * {@doc HTML5.webappapis#handler-onloadstart onloadstart}
472    * attribute.
473    *
474    * @param onloadstart The new value for this attribute.
475    * @return This object (for method chaining).
476    */
477   public HtmlElement onloadstart(String onloadstart) {
478      attr("onloadstart", onloadstart);
479      return this;
480   }
481
482   /**
483    * {@doc HTML5.webappapis#handler-onmousedown onmousedown}
484    * attribute.
485    *
486    * @param onmousedown The new value for this attribute.
487    * @return This object (for method chaining).
488    */
489   public HtmlElement onmousedown(String onmousedown) {
490      attr("onmousedown", onmousedown);
491      return this;
492   }
493
494   /**
495    * {@doc HTML5.webappapis#handler-onmouseenter onmouseenter} attribute.
496    *
497    * @param onmouseenter The new value for this attribute.
498    * @return This object (for method chaining).
499    */
500   public HtmlElement onmouseenter(String onmouseenter) {
501      attr("onmouseenter", onmouseenter);
502      return this;
503   }
504
505   /**
506    * {@doc HTML5.webappapis#handler-onmouseleave onmouseleave}
507    * attribute.
508    *
509    * @param onmouseleave The new value for this attribute.
510    * @return This object (for method chaining).
511    */
512   public HtmlElement onmouseleave(String onmouseleave) {
513      attr("onmouseleave", onmouseleave);
514      return this;
515   }
516
517   /**
518    * {@doc HTML5.webappapis#handler-onmousemove onmousemove}
519    * attribute.
520    *
521    * @param onmousemove The new value for this attribute.
522    * @return This object (for method chaining).
523    */
524   public HtmlElement onmousemove(String onmousemove) {
525      attr("onmousemove", onmousemove);
526      return this;
527   }
528
529   /**
530    * {@doc HTML5.webappapis#handler-onmouseout onmouseout} attribute.
531    *
532    * @param onmouseout The new value for this attribute.
533    * @return This object (for method chaining).
534    */
535   public HtmlElement onmouseout(String onmouseout) {
536      attr("onmouseout", onmouseout);
537      return this;
538   }
539
540   /**
541    * {@doc HTML5.webappapis#handler-onmouseover onmouseover}
542    * attribute.
543    *
544    * @param onmouseover The new value for this attribute.
545    * @return This object (for method chaining).
546    */
547   public HtmlElement onmouseover(String onmouseover) {
548      attr("onmouseover", onmouseover);
549      return this;
550   }
551
552   /**
553    * {@doc HTML5.webappapis#handler-onmouseup onmouseup} attribute.
554    *
555    * @param onmouseup The new value for this attribute.
556    * @return This object (for method chaining).
557    */
558   public HtmlElement onmouseup(String onmouseup) {
559      attr("onmouseup", onmouseup);
560      return this;
561   }
562
563   /**
564    * {@doc HTML5.webappapis#handler-onmousewheel onmousewheel}
565    * attribute.
566    *
567    * @param onmousewheel The new value for this attribute.
568    * @return This object (for method chaining).
569    */
570   public HtmlElement onmousewheel(String onmousewheel) {
571      attr("onmousewheel", onmousewheel);
572      return this;
573   }
574
575   /**
576    * {@doc HTML5.webappapis#handler-onpause onpause} attribute.
577    *
578    * @param onpause The new value for this attribute.
579    * @return This object (for method chaining).
580    */
581   public HtmlElement onpause(String onpause) {
582      attr("onpause", onpause);
583      return this;
584   }
585
586   /**
587    * {@doc HTML5.webappapis#handler-onplay onplay} attribute.
588    *
589    * @param onplay The new value for this attribute.
590    * @return This object (for method chaining).
591    */
592   public HtmlElement onplay(String onplay) {
593      attr("onplay", onplay);
594      return this;
595   }
596
597   /**
598    * {@doc HTML5.webappapis#handler-onplaying onplaying} attribute.
599    *
600    * @param onplaying The new value for this attribute.
601    * @return This object (for method chaining).
602    */
603   public HtmlElement onplaying(String onplaying) {
604      attr("onplaying", onplaying);
605      return this;
606   }
607
608   /**
609    * {@doc HTML5.webappapis#handler-onprogress onprogress} attribute.
610    *
611    * @param onprogress The new value for this attribute.
612    * @return This object (for method chaining).
613    */
614   public HtmlElement onprogress(String onprogress) {
615      attr("onprogress", onprogress);
616      return this;
617   }
618
619   /**
620    * {@doc HTML5.webappapis#handler-onratechange onratechange}
621    * attribute.
622    *
623    * @param onratechange The new value for this attribute.
624    * @return This object (for method chaining).
625    */
626   public HtmlElement onratechange(String onratechange) {
627      attr("onratechange", onratechange);
628      return this;
629   }
630
631   /**
632    * {@doc HTML5.webappapis#handler-onreset onreset} attribute.
633    *
634    * @param onreset The new value for this attribute.
635    * @return This object (for method chaining).
636    */
637   public HtmlElement onreset(String onreset) {
638      attr("onreset", onreset);
639      return this;
640   }
641
642   /**
643    * {@doc HTML5.webappapis#handler-onresize onresize} attribute.
644    *
645    * @param onresize The new value for this attribute.
646    * @return This object (for method chaining).
647    */
648   public HtmlElement onresize(String onresize) {
649      attr("onresize", onresize);
650      return this;
651   }
652
653   /**
654    * {@doc HTML5.webappapis#handler-onscroll onscroll} attribute.
655    *
656    * @param onscroll The new value for this attribute.
657    * @return This object (for method chaining).
658    */
659   public HtmlElement onscroll(String onscroll) {
660      attr("onscroll", onscroll);
661      return this;
662   }
663
664   /**
665    * {@doc HTML5.webappapis#handler-onseeked onseeked} attribute.
666    *
667    * @param onseeked The new value for this attribute.
668    * @return This object (for method chaining).
669    */
670   public HtmlElement onseeked(String onseeked) {
671      attr("onseeked", onseeked);
672      return this;
673   }
674
675   /**
676    * {@doc HTML5.webappapis#handler-onseeking onseeking} attribute.
677    *
678    * @param onseeking The new value for this attribute.
679    * @return This object (for method chaining).
680    */
681   public HtmlElement onseeking(String onseeking) {
682      attr("onseeking", onseeking);
683      return this;
684   }
685
686   /**
687    * {@doc HTML5.webappapis#handler-onselect onselect} attribute.
688    *
689    * @param onselect The new value for this attribute.
690    * @return This object (for method chaining).
691    */
692   public HtmlElement onselect(String onselect) {
693      attr("onselect", onselect);
694      return this;
695   }
696
697   /**
698    * {@doc HTML5.webappapis#handler-onshow onshow} attribute.
699    *
700    * @param onshow The new value for this attribute.
701    * @return This object (for method chaining).
702    */
703   public HtmlElement onshow(String onshow) {
704      attr("onshow", onshow);
705      return this;
706   }
707
708   /**
709    * {@doc HTML5.webappapis#handler-onstalled onstalled} attribute.
710    *
711    * @param onstalled The new value for this attribute.
712    * @return This object (for method chaining).
713    */
714   public HtmlElement onstalled(String onstalled) {
715      attr("onstalled", onstalled);
716      return this;
717   }
718
719   /**
720    * {@doc HTML5.webappapis#handler-onsubmit onsubmit} attribute.
721    *
722    * @param onsubmit The new value for this attribute.
723    * @return This object (for method chaining).
724    */
725   public HtmlElement onsubmit(String onsubmit) {
726      attr("onsubmit", onsubmit);
727      return this;
728   }
729
730   /**
731    * {@doc HTML5.webappapis#handler-onsuspend onsuspend} attribute.
732    *
733    * @param onsuspend The new value for this attribute.
734    * @return This object (for method chaining).
735    */
736   public HtmlElement onsuspend(String onsuspend) {
737      attr("onsuspend", onsuspend);
738      return this;
739   }
740
741   /**
742    * {@doc HTML5.webappapis#handler-ontimeupdate ontimeupdate}
743    * attribute.
744    *
745    * @param ontimeupdate The new value for this attribute.
746    * @return This object (for method chaining).
747    */
748   public HtmlElement ontimeupdate(String ontimeupdate) {
749      attr("ontimeupdate", ontimeupdate);
750      return this;
751   }
752
753   /**
754    * {@doc HTML5.webappapis#handler-ontoggle ontoggle} attribute.
755    *
756    * @param ontoggle The new value for this attribute.
757    * @return This object (for method chaining).
758    */
759   public HtmlElement ontoggle(String ontoggle) {
760      attr("ontoggle", ontoggle);
761      return this;
762   }
763
764   /**
765    * {@doc HTML5.webappapis#handler-onvolumechange onvolumechange}
766    * attribute.
767    *
768    * @param onvolumechange The new value for this attribute.
769    * @return This object (for method chaining).
770    */
771   public HtmlElement onvolumechange(String onvolumechange) {
772      attr("onvolumechange", onvolumechange);
773      return this;
774   }
775
776   /**
777    * {@doc HTML5.webappapis#handler-onwaiting onwaiting} attribute.
778    *
779    * @param onwaiting The new value for this attribute.
780    * @return This object (for method chaining).
781    */
782   public HtmlElement onwaiting(String onwaiting) {
783      attr("onwaiting", onwaiting);
784      return this;
785   }
786
787   /**
788    * {@doc HTML5.editing#attr-spellcheck spellcheck} attribute.
789    *
790    * @param spellcheck
791    *    The new value for this attribute.
792    *    Typically a {@link Boolean} or {@link String}.
793    * @return This object (for method chaining).
794    */
795   public HtmlElement spellcheck(Object spellcheck) {
796      attr("spellcheck", spellcheck);
797      return this;
798   }
799
800   /**
801    * {@doc HTML5.dom#the-style-attribute style} attribute.
802    *
803    * @param style The new value for this attribute.
804    * @return This object (for method chaining).
805    */
806   public HtmlElement style(String style) {
807      attr("style", style);
808      return this;
809   }
810
811   /**
812    * {@doc HTML5.editing#attr-tabindex tabindex} attribute.
813    *
814    * @param tabindex
815    *    The new value for this attribute.
816    *    Typically a {@link Number} or {@link String}.
817    * @return This object (for method chaining).
818    */
819   public HtmlElement tabindex(Object tabindex) {
820      attr("tabindex", tabindex);
821      return this;
822   }
823
824   /**
825    * {@doc HTML5.dom#attr-title title} attribute.
826    *
827    * @param title The new value for this attribute.
828    * @return This object (for method chaining).
829    */
830   public HtmlElement title(String title) {
831      attr("title", title);
832      return this;
833   }
834
835   /**
836    * {@doc HTML5.dom#attr-translate translate} attribute.
837    *
838    * @param translate
839    *    The new value for this attribute.
840    *    Typically a {@link Number} or {@link String}.
841    * @return This object (for method chaining).
842    */
843   public HtmlElement translate(Object translate) {
844      attr("translate", translate);
845      return this;
846   }
847
848   /**
849    * If the specified attribute is a boolean, it gets converted to the attribute name if <jk>true</jk> or <jk>null</jk> if <jk>false</jk>.
850    *
851    * @param value The attribute value.
852    * @param attr The attribute name.
853    * @return The deminimized value, or the same value if the value wasn't a boolean.
854    */
855   protected Object deminimize(Object value, String attr) {
856      if (value instanceof Boolean) {
857         if ((Boolean)value)
858            return attr;
859         return null;
860      }
861      return value;
862   }
863
864   @Override /* Object */
865   public String toString() {
866      return HtmlSerializer.DEFAULT_SQ.toString(this);
867   }
868}