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