001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.bean.html5;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020
021import org.apache.juneau.marshall.*;
022
023/**
024 * DTO for an HTML <a class="doclink" href="https://www.w3.org/TR/html5/forms.html#the-select-element">&lt;select&gt;</a>
025 * element.
026 *
027 * <p>
028 * The select element represents a control that provides a menu of options. It creates a dropdown
029 * list that allows users to select one or more options from a list. The select element contains
030 * option elements that define the available choices, and can be organized into groups using
031 * optgroup elements.
032 *
033 * <h5 class='section'>Examples:</h5>
034 * <p class='bcode w800'>
035 *    <jk>import static</jk> org.apache.juneau.bean.html5.HtmlBuilder.*;
036 *
037 *    <jc>// Simple select dropdown</jc>
038 *    Select <jv>select1</jv> = <jsm>select</jsm>(<js>"color"</js>,
039 *       <jsm>option</jsm>(<js>"red"</js>, <js>"Red"</js>),
040 *       <jsm>option</jsm>(<js>"green"</js>, <js>"Green"</js>),
041 *       <jsm>option</jsm>(<js>"blue"</js>, <js>"Blue"</js>)
042 *    );
043 *
044 *    <jc>// Multiple selection</jc>
045 *    Select <jv>select2</jv> = <jsm>select</jsm>(<js>"hobbies"</js>,
046 *       <jsm>option</jsm>(<js>"reading"</js>, <js>"Reading"</js>),
047 *       <jsm>option</jsm>(<js>"gaming"</js>, <js>"Gaming"</js>),
048 *       <jsm>option</jsm>(<js>"sports"</js>, <js>"Sports"</js>)
049 *    ).multiple(<jk>true</jk>).size(4);
050 *
051 *    <jc>// Select with option groups</jc>
052 *    Select <jv>select3</jv> = <jsm>select</jsm>(<js>"food"</js>,
053 *       <jsm>optgroup</jsm>(<js>"Fruits"</js>,
054 *          <jsm>option</jsm>(<js>"apple"</js>, <js>"Apple"</js>),
055 *          <jsm>option</jsm>(<js>"banana"</js>, <js>"Banana"</js>)
056 *       ),
057 *       <jsm>optgroup</jsm>(<js>"Vegetables"</js>,
058 *          <jsm>option</jsm>(<js>"carrot"</js>, <js>"Carrot"</js>),
059 *          <jsm>option</jsm>(<js>"broccoli"</js>, <js>"Broccoli"</js>)
060 *       )
061 *    );
062 *
063 *    <jc>// Disabled select</jc>
064 *    Select <jv>select4</jv> = <jsm>select</jsm>(<js>"disabled"</js>)
065 *       .disabled(<jk>true</jk>)
066 *       .children(
067 *          option().value("option1").text("Option 1")
068 *       );
069 * </p>
070 *
071 * <p>
072 * The following convenience methods are provided for constructing instances of this bean:
073 * <ul class='javatree'>
074 *    <li class='jc'>{@link HtmlBuilder}
075 *    <ul class='javatree'>
076 *       <li class='jm'>{@link HtmlBuilder#select() select()}
077 *       <li class='jm'>{@link HtmlBuilder#select(String, Object...) select(String, Object...)}
078 *    </ul>
079 * </ul>
080 * </p>
081 *
082 * <h5 class='section'>See Also:</h5><ul>
083 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanHtml5">juneau-bean-html5</a>
084 * </ul>
085 */
086@Marshalled(typeName = "select")
087public class Select extends HtmlElementContainer<Select> {
088
089   /**
090    * Creates an empty {@link Select} element.
091    */
092   public Select() {}
093
094   /**
095    * Creates a {@link Select} element with the specified {@link Select#name(String)} attribute and child nodes.
096    *
097    * @param name The {@link Select#name(String)} attribute. Can be <jk>null</jk> to unset the attribute.
098    * @param children The child nodes. Must not be <jk>null</jk>.
099    */
100   public Select(String name, Object...children) {
101      name(name).children(children);
102   }
103
104   /**
105    * <a class="doclink" href="https://www.w3.org/TR/html5/forms.html#attr-fe-autofocus">autofocus</a> attribute.
106    *
107    * <p>
108    * Automatically focus the form control when the page is loaded.
109    *
110    * @param value
111    *    The new value for this attribute.
112    *    Typically a {@link Boolean} or {@link String}.
113    *    Can be <jk>null</jk> to unset the attribute.
114    * @return This object.
115    */
116   public Select autofocus(Object value) {
117      attr("autofocus", value);
118      return this;
119   }
120
121   /**
122    * Convenience method for selecting a child {@link Option} after the options have already been populated.
123    *
124    * @param optionValue The option value. Can be <jk>null</jk> (no-op; no option is selected).
125    * @return This object.
126    */
127   public Select choose(Object optionValue) {
128      if (nn(optionValue)) {
129         getChildren().forEach(x -> {
130            if (x instanceof Option o && eq(optionValue.toString(), o.getAttr(String.class, "value")))
131               o.selected(true);
132         });
133      }
134      return this;
135   }
136
137   /**
138    * <a class="doclink" href="https://www.w3.org/TR/html5/forms.html#attr-fe-disabled">disabled</a> attribute.
139    *
140    * <p>
141    * Whether the form control is disabled.
142    *
143    * <p>
144    * This attribute uses deminimized values:
145    * <ul>
146    *    <li><jk>false</jk> - Attribute is not added</li>
147    *    <li><jk>true</jk> - Attribute is added as <js>"disabled"</js></li>
148    *    <li>Other values - Passed through as-is</li>
149    * </ul>
150    *
151    * @param value
152    *    The new value for this attribute.
153    *    Typically a {@link Boolean} or {@link String}.
154    *    Can be <jk>null</jk> to unset the attribute.
155    * @return This object.
156    */
157   public Select disabled(Object value) {
158      attr("disabled", deminimize(value, "disabled"));
159      return this;
160   }
161
162   /**
163    * <a class="doclink" href="https://www.w3.org/TR/html5/forms.html#attr-fae-form">form</a> attribute.
164    *
165    * <p>
166    * Associates the select element with a form element by specifying the form's ID. This allows the select
167    * to be placed outside the form element while still being part of the form.
168    *
169    * <p>
170    * The value should match the ID of a form element in the same document.
171    *
172    * @param value The ID of the form element to associate with this select. Can be <jk>null</jk> to unset the attribute.
173    * @return This object.
174    */
175   public Select form(String value) {
176      attr("form", value);
177      return this;
178   }
179
180   /**
181    * <a class="doclink" href="https://www.w3.org/TR/html5/forms.html#attr-select-multiple">multiple</a> attribute.
182    *
183    * <p>
184    * Whether to allow multiple values.
185    *
186    * <p>
187    * This attribute uses deminimized values:
188    * <ul>
189    *    <li><jk>false</jk> - Attribute is not added</li>
190    *    <li><jk>true</jk> - Attribute is added as <js>"multiple"</js></li>
191    *    <li>Other values - Passed through as-is</li>
192    * </ul>
193    *
194    * @param value
195    *    The new value for this attribute.
196    *    Typically a {@link Boolean} or {@link String}.
197    *    Can be <jk>null</jk> to unset the attribute.
198    * @return This object.
199    */
200   public Select multiple(Object value) {
201      attr("multiple", deminimize(value, "multiple"));
202      return this;
203   }
204
205   /**
206    * <a class="doclink" href="https://www.w3.org/TR/html5/forms.html#attr-fe-name">name</a> attribute.
207    *
208    * <p>
209    * Specifies the name of the select element. This name is used when the form is submitted and
210    * can be used to access the element via the form.elements API.
211    *
212    * <p>
213    * The name should be unique within the form and should not contain spaces or special characters.
214    *
215    * @param value The name of the select element for submission and API access. Can be <jk>null</jk> to unset the attribute.
216    * @return This object.
217    */
218   public Select name(String value) {
219      attr("name", value);
220      return this;
221   }
222
223   /**
224    * <a class="doclink" href="https://www.w3.org/TR/html5/forms.html#attr-select-required">required</a> attribute.
225    *
226    * <p>
227    * Whether the control is required for form submission.
228    *
229    * @param value
230    *    The new value for this attribute.
231    *    Typically a {@link Boolean} or {@link String}.
232    *    Can be <jk>null</jk> to unset the attribute.
233    * @return This object.
234    */
235   public Select required(Object value) {
236      attr("required", value);
237      return this;
238   }
239
240   /**
241    * <a class="doclink" href="https://www.w3.org/TR/html5/forms.html#attr-select-size">size</a> attribute.
242    *
243    * <p>
244    * Specifies the number of visible options in a select element. If greater than 1,
245    * the select becomes a scrollable list instead of a dropdown.
246    *
247    * @param value The number of visible options (1 for dropdown, >1 for list). Can be <jk>null</jk> to unset the attribute.
248    * @return This object.
249    */
250   public Select size(Object value) {
251      attr("size", value);
252      return this;
253   }
254
255}