001package org.gwtbootstrap3.extras.select.client.ui; 002 003/* 004 * #%L 005 * GwtBootstrap3 006 * %% 007 * Copyright (C) 2013 - 2016 GwtBootstrap3 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.ACTIONS_BOX; 023import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.DESELECT_ALL_TEXT; 024import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.MAX_OPTIONS; 025import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.MULTIPLE_SEPARATOR; 026import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.NONE_SELECTED_TEXT; 027import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.SELECTED_TEXT_FORMAT; 028import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.SELECT_ALL_TEXT; 029 030import java.util.ArrayList; 031import java.util.List; 032import java.util.Map.Entry; 033 034import org.gwtbootstrap3.extras.select.client.ui.constants.SelectedTextFormat; 035 036import com.google.gwt.core.client.JavaScriptObject; 037import com.google.gwt.core.client.JsArrayString; 038import com.google.gwt.dom.client.Element; 039import com.google.gwt.dom.client.OptionElement; 040 041/** 042 * Multiple select box. 043 * 044 * @author Xiaodong Sun 045 */ 046public class MultipleSelect extends SelectBase<List<String>> { 047 048 private static final String MULTIPLE = "multiple"; 049 050 public MultipleSelect() { 051 attrMixin.setAttribute(MULTIPLE, ""); 052 } 053 054 @Override 055 public final boolean isMultiple() { 056 return true; 057 } 058 059 /** 060 * When set to <code>true</code>, adds two buttons to the top of 061 * the drop-down menu (<b>Select All</b> & <b>Deselect All</b>).<br> 062 * <br> 063 * Defaults to <code>false</code>. 064 * 065 * @param showActionsBox 066 */ 067 public void setShowActionsBox(final boolean showActionsBox) { 068 if (showActionsBox) 069 attrMixin.setAttribute(ACTIONS_BOX, Boolean.toString(true)); 070 else 071 attrMixin.removeAttribute(ACTIONS_BOX); 072 } 073 074 /** 075 * The text on the button that deselects all options when 076 * <b>actionsBox</> is enabled.<br> 077 * <br> 078 * Defaults to <code>Deselect All</code>. 079 * 080 * @param deselectAllText 081 */ 082 public void setDeselectAllText(final String deselectAllText) { 083 if (deselectAllText != null) 084 attrMixin.setAttribute(DESELECT_ALL_TEXT, deselectAllText); 085 else 086 attrMixin.removeAttribute(DESELECT_ALL_TEXT); 087 } 088 089 /** 090 * The text on the button that selects all options when 091 * <b>actionsBox</> is enabled.<br> 092 * <br> 093 * Defaults to <code>Select All</code>. 094 * 095 * @param selectAllText 096 */ 097 public void setSelectAllText(final String selectAllText) { 098 if (selectAllText != null) 099 attrMixin.setAttribute(SELECT_ALL_TEXT, selectAllText); 100 else 101 attrMixin.removeAttribute(SELECT_ALL_TEXT); 102 } 103 104 /** 105 * When set to a positive value and in a multi-select, the 106 * number of selected options cannot exceed the given value. 107 * When set to a strict negative value (less than zero), this 108 * options will be deactivated. 109 * 110 * @param maxOptions 111 */ 112 public void setMaxOptions(final int maxOptions) { 113 attrMixin.setAttribute(MAX_OPTIONS, Integer.toString(maxOptions)); 114 } 115 116 /** 117 * Sets the handler to get texts displayed when {@link SelectOptions#MAX_OPTIONS} 118 * is enabled and the maximum number of options within the entire select or an 119 * option group have been selected. 120 * 121 * @param handler 122 * @see #setMaxOptions(int) 123 */ 124 public void setMaxOptionsTextHandler(final MaxOptionsTextHandler handler) { 125 options.setMaxOptionsTextHandler(handler); 126 } 127 128 /** 129 * Sets the character displayed in the button that separates 130 * selected options.<br> 131 * <br> 132 * Defaults to <code>, </code>. 133 * 134 * @param multipleSeparator 135 */ 136 public void setMultipleSeparator(final String multipleSeparator) { 137 if (multipleSeparator != null) 138 attrMixin.setAttribute(MULTIPLE_SEPARATOR, multipleSeparator); 139 else 140 attrMixin.removeAttribute(MULTIPLE_SEPARATOR); 141 } 142 143 /** 144 * Sets the text that is displayed when a multiple select 145 * has no selected options.<br> 146 * <br> 147 * Defaults to <code>Nothing Selected</code>. 148 * 149 * @param noneSelectedText 150 */ 151 public void setNoneSelectedText(final String noneSelectedText) { 152 if (noneSelectedText != null) 153 attrMixin.setAttribute(NONE_SELECTED_TEXT, noneSelectedText); 154 else 155 attrMixin.removeAttribute(NONE_SELECTED_TEXT); 156 } 157 158 /** 159 * Specifies how the selection is displayed with a multiple select.<br> 160 * <br> 161 * Defaults to {@link SelectedTextFormat#VALUES}. 162 * 163 * @param format 164 * @see SelectedTextFormat 165 */ 166 public void setSelectedTextFormat(final SelectedTextFormat format) { 167 if (format != null) 168 attrMixin.setAttribute(SELECTED_TEXT_FORMAT, format.getFormat()); 169 else 170 attrMixin.removeAttribute(SELECTED_TEXT_FORMAT); 171 } 172 173 /** 174 * Specifies the minimum count of the <code>count > #</code> selection 175 * format with a multiple select. 176 * 177 * @param minCount 178 * @see SelectedTextFormat#getFormat(int) 179 */ 180 public void setCountSelectedTextFormat(final int minCount) { 181 attrMixin.setAttribute(SELECTED_TEXT_FORMAT, SelectedTextFormat.COUNT.getFormat(minCount)); 182 } 183 184 @Override 185 public List<String> getValue() { 186 if (isAttached()) { 187 JsArrayString arr = getValue(getElement()); 188 List<String> result = new ArrayList<>(arr.length()); 189 for (int i = 0; i < arr.length(); i++) { 190 result.add(arr.get(i)); 191 } 192 return result; 193 } 194 return getSelectedValues(); 195 } 196 197 private List<String> getSelectedValues() { 198 final List<String> allSelected = new ArrayList<>(0); 199 for (Entry<OptionElement, Option> entry : itemMap.entrySet()) { 200 Option opt = entry.getValue(); 201 if (opt.isSelected()) 202 allSelected.add(opt.getValue()); 203 } 204 return allSelected; 205 } 206 207 @Override 208 protected void setSelectedValue(List<String> value) { 209 if (isAttached()) { 210 final JsArrayString arr = JavaScriptObject.createArray().cast(); 211 for (final String val : value) { 212 arr.push(val); 213 } 214 setValue(getElement(), arr); 215 } else { 216 for (Entry<OptionElement, Option> entry : itemMap.entrySet()) { 217 Option opt = entry.getValue(); 218 boolean selected = value.contains(opt.getValue()); 219 opt.setSelected(selected); 220 } 221 } 222 } 223 224 /** 225 * Returns the selected items list. If no item is selected, this method 226 * returns an empty list. 227 * 228 * @return the selected items list 229 */ 230 public List<Option> getSelectedItems() { 231 final List<Option> items = new ArrayList<>(0); 232 for (Entry<OptionElement, Option> entry : itemMap.entrySet()) { 233 Option opt = entry.getValue(); 234 if (opt.isSelected()) 235 items.add(opt); 236 } 237 return items; 238 } 239 240 /** 241 * Select all items in a multi-select. 242 */ 243 public void selectAll() { 244 setSelectAll(true); 245 } 246 247 /** 248 * Deselect all items in a multi-select. 249 */ 250 public void deselectAll() { 251 setSelectAll(false); 252 } 253 254 private void setSelectAll(boolean selected) { 255 if (isAttached()) { 256 String cmd = selected ? SelectCommand.SELECT_ALL : SelectCommand.DESELECT_ALL; 257 command(getElement(), cmd); 258 } else { 259 for (Entry<OptionElement, Option> entry : itemMap.entrySet()) { 260 entry.getValue().setSelected(selected); 261 } 262 } 263 } 264 265 private native JsArrayString getValue(Element e) /*-{ 266 var value = $wnd.jQuery(e).selectpicker('val'); 267 return value || []; 268 }-*/; 269 270 private native void setValue(Element e, JsArrayString value) /*-{ 271 $wnd.jQuery(e).selectpicker('val', value); 272 }-*/; 273 274}