Java tutorial
package org.gwtbootstrap3.extras.select.client.ui; /* * #%L * GwtBootstrap3 * %% * Copyright (C) 2016 GwtBootstrap3 * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.DROP_AUTO; import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.HEADER; import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.HIDE_DISABLED; import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.LIVE_SEARCH; import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.LIVE_SEARCH_PLACEHOLDER; import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.MOBILE; import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.SELECT_ON_TAB; import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.SHOW_CONTENT; import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.SHOW_ICON; import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.SHOW_SUBTEXT; import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.SIZE; import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.STYLE; import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.WIDTH; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.gwtbootstrap3.client.ui.base.ComplexWidget; import org.gwtbootstrap3.client.ui.base.HasSize; import org.gwtbootstrap3.client.ui.base.HasType; import org.gwtbootstrap3.client.ui.base.mixin.AttributeMixin; import org.gwtbootstrap3.client.ui.base.mixin.EnabledMixin; import org.gwtbootstrap3.client.ui.constants.ButtonSize; import org.gwtbootstrap3.client.ui.constants.ButtonType; import org.gwtbootstrap3.client.ui.constants.Styles; import org.gwtbootstrap3.extras.select.client.ui.constants.MenuSize; import org.gwtbootstrap3.extras.select.client.ui.constants.SelectStyles; import org.gwtbootstrap3.extras.select.client.ui.constants.SelectWidth; import org.gwtbootstrap3.extras.select.client.ui.event.HasAllSelectHandlers; import org.gwtbootstrap3.extras.select.client.ui.event.HiddenEvent; import org.gwtbootstrap3.extras.select.client.ui.event.HiddenHandler; import org.gwtbootstrap3.extras.select.client.ui.event.HideEvent; import org.gwtbootstrap3.extras.select.client.ui.event.HideHandler; import org.gwtbootstrap3.extras.select.client.ui.event.LoadedEvent; import org.gwtbootstrap3.extras.select.client.ui.event.LoadedHandler; import org.gwtbootstrap3.extras.select.client.ui.event.RefreshedEvent; import org.gwtbootstrap3.extras.select.client.ui.event.RefreshedHandler; import org.gwtbootstrap3.extras.select.client.ui.event.RenderedEvent; import org.gwtbootstrap3.extras.select.client.ui.event.RenderedHandler; import org.gwtbootstrap3.extras.select.client.ui.event.ShowEvent; import org.gwtbootstrap3.extras.select.client.ui.event.ShowHandler; import org.gwtbootstrap3.extras.select.client.ui.event.ShownEvent; import org.gwtbootstrap3.extras.select.client.ui.event.ShownHandler; import com.google.gwt.core.client.ScriptInjector; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.NodeList; import com.google.gwt.dom.client.OptionElement; import com.google.gwt.dom.client.SelectElement; import com.google.gwt.editor.client.IsEditor; import com.google.gwt.editor.client.LeafValueEditor; import com.google.gwt.editor.client.adapters.TakesValueEditor; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.ui.Focusable; import com.google.gwt.user.client.ui.HasEnabled; import com.google.gwt.user.client.ui.HasValue; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.client.ui.impl.FocusImpl; /** * Bootstrap select widget base * * @param <T> select value type * * @see http://silviomoreto.github.io/bootstrap-select/ * @author Xiaodong Sun */ public abstract class SelectBase<T> extends ComplexWidget implements HasValue<T>, HasEnabled, Focusable, HasType<ButtonType>, HasSize<ButtonSize>, IsEditor<LeafValueEditor<T>>, HasAllSelectHandlers<T> { private LeafValueEditor<T> editor; private ButtonType type; private ButtonSize size; /** * Default language: {@link SelectLanguage#EN} */ private static final SelectLanguage DEFAULT_LANGUAGE = SelectLanguage.EN; /** * Language; defaults to {@value #DEFAULT_LANGUAGE} */ private SelectLanguage language = DEFAULT_LANGUAGE; protected final SelectElement selectElement; protected final Map<OptionElement, Option> itemMap = new HashMap<>(0); protected final AttributeMixin<SelectBase<T>> attrMixin = new AttributeMixin<>(this); private final EnabledMixin<SelectBase<T>> enabledMixin = new EnabledMixin<>(this); private final FocusImpl focusImpl = FocusImpl.getFocusImplForWidget(); /** * Initialize options */ private SelectOptions options = SelectOptions.newOptions(); protected SelectBase() { this.selectElement = Document.get().createSelectElement(); setElement(selectElement); setStyleName(SelectStyles.SELECT_PICKER); addStyleName(Styles.FORM_CONTROL); } /** * Returns <code>true</code> if multiple selection is allowed. * * @return <code>true</code> if multiple selection is allowed */ public abstract boolean isMultiple(); @Override protected void onLoad() { super.onLoad(); // Inject the language JS is necessary if (language.getJs() != null) { ScriptInjector.fromString(language.getJs().getText()).setWindow(ScriptInjector.TOP_WINDOW).inject(); } initialize(getElement(), options); bindSelectEvents(getElement()); } @Override protected void onUnload() { super.onUnload(); unbindSelectEvents(getElement()); command(getElement(), SelectCommand.DESTROY); } @Override public void add(Widget child) { super.add(child); updateItemMap(child, true); } @Override public void insert(Widget child, int beforeIndex) { super.insert(child, beforeIndex); updateItemMap(child, true); } @Override public boolean remove(Widget w) { boolean removed = super.remove(w); if (removed) { updateItemMap(w, false); } return removed; } void updateItemMap(Widget widget, boolean toAdd) { // Option ==> update with this option if (widget instanceof Option) { Option option = (Option) widget; if (toAdd) itemMap.put(option.getSelectElement(), option); else itemMap.remove(option.getSelectElement()); } else if (widget instanceof OptGroup) { // OptGroup ==> update with all optGroup options OptGroup optGroup = (OptGroup) widget; if (toAdd) itemMap.putAll(optGroup.getItemMap()); else for (Entry<OptionElement, Option> entry : optGroup.getItemMap().entrySet()) { OptionElement optElem = entry.getKey(); itemMap.remove(optElem); } } } /** * Set the select language. * * @param language */ public void setLanguage(final SelectLanguage language) { this.language = (language == null) ? DEFAULT_LANGUAGE : language; } /** * Returns the select language. * * @return */ public SelectLanguage getLanguage() { return language; } /** * Sets the handler to get the text displayed when selectedTextFormat * is <code>count</code> or <code>count > #</code>, or <code>null</code> * to use the default text: <code>X of Y selected</code>. * * @param handler */ public void setCoundSelectedTextHandler(final CountSelectedTextHandler handler) { options.setCountSelectedTextHandler(handler); } /** * Checks to see which has more room, above or below. * If the drop-up has enough room to fully open normally, * but there is more room above, the drop-up still opens * normally. Otherwise, it becomes a drop-up. * If dropupAuto is set to <code>false</code>, drop-ups * must be called manually.<br> * <br> * Defaults to <code>true</code>. * * @param dropupAuto */ public void setDropupAuto(final boolean dropupAuto) { if (!dropupAuto) attrMixin.setAttribute(DROP_AUTO, Boolean.toString(false)); else attrMixin.removeAttribute(DROP_AUTO); } /** * If drop-up auto is set to <code>false</code>, force to make * the select a drop-up menu if set to <code>true</code>. * * @param forceDropup * @see #setDropupAuto(boolean) */ public void setForceDropup(final boolean forceDropup) { if (forceDropup) { addStyleName(SelectStyles.DROPUP); } else { removeStyleName(SelectStyles.DROPUP); } } /** * Adds a header to the top of the menu; includes * a close button by default.<br> * <br> * No header by default. * * @param header */ public void setHeader(final String header) { if (header != null) attrMixin.setAttribute(HEADER, header); else attrMixin.removeAttribute(HEADER); } /** * Removes disabled options and optgroups from the menu<br> * <br> * Defaults to <code>false</code>. * * @param hideDisabled */ public void setHideDisabled(final boolean hideDisabled) { if (hideDisabled) attrMixin.setAttribute(HIDE_DISABLED, Boolean.toString(true)); else attrMixin.removeAttribute(HIDE_DISABLED); } /** * When set to <code>true</code>, adds a search box to the * top of the select picker drop-down.<br> * <br> * Defaults to <code>false</code>. * * @param liveSearch */ public void setLiveSearch(final boolean liveSearch) { if (liveSearch) attrMixin.setAttribute(LIVE_SEARCH, Boolean.toString(true)); else attrMixin.removeAttribute(LIVE_SEARCH); } /** * Set a placeholder to the live search input.<br> * <br> * Defaults to <code>null</code>. * * @param liveSearchPlaceholder */ public void setLiveSearchPlaceholder(final String liveSearchPlaceholder) { if (liveSearchPlaceholder != null) attrMixin.setAttribute(LIVE_SEARCH_PLACEHOLDER, liveSearchPlaceholder); else attrMixin.removeAttribute(LIVE_SEARCH_PLACEHOLDER); } /** * When set to <code>true</code>, enables the device's native * menu for select menus.<br> * <br> * Defaults to <code>false</code>. * * @param mobile */ public void setMobile(final boolean mobile) { if (mobile) attrMixin.setAttribute(MOBILE, Boolean.toString(true)); else attrMixin.removeAttribute(MOBILE); } /** * When set to <code>true</code>, treats the tab character like the * <code>enter</code> or <code>Space</code> characters within the * select picker drop-down.<br> * <br> * Defaults to <code>false</code>. * * @param selectOnTab */ public void setSelectOnTab(final boolean selectOnTab) { if (selectOnTab) attrMixin.setAttribute(SELECT_ON_TAB, Boolean.toString(true)); else attrMixin.removeAttribute(SELECT_ON_TAB); } /** * When set to <code>true</code>, display custom HTML associated with * selected option(s) in the button. When set to <code>false</code>, * the option value will be displayed instead.<br> * <br> * Defaults to <code>true</code>. * * @param showContent */ public void setShowContent(final boolean showContent) { if (!showContent) attrMixin.setAttribute(SHOW_CONTENT, Boolean.toString(false)); else attrMixin.removeAttribute(SHOW_CONTENT); } /** * When set to <code>true</code>, display icon(s) associated with * selected option(s) in the button.<br> * <br> * Defaults to <code>true</code>. * * @param showIcon */ public void setShowIcon(final boolean showIcon) { if (!showIcon) attrMixin.setAttribute(SHOW_ICON, Boolean.toString(false)); else attrMixin.removeAttribute(SHOW_ICON); } /** * When set to <code>true</code>, display sub-text associated with a * selected option in the button.<br> * <br> * Defaults to <code>false</code>. * * @param showSubtext */ public void setShowSubtext(final boolean showSubtext) { if (showSubtext) attrMixin.setAttribute(SHOW_SUBTEXT, Boolean.toString(true)); else attrMixin.removeAttribute(SHOW_SUBTEXT); } /** * Specifies the number of visible menu items.<br> * <br> * Defaults to {@link MenuSize#AUTO}. * * @param size * @see MenuSize */ public void setMenuSize(final MenuSize size) { if (size != null) attrMixin.setAttribute(SIZE, size.getValue()); else attrMixin.removeAttribute(SIZE); } /** * The menu will show the given number of items, even if * the drop-down is cut off.<br> * <br> * Defaults to {@link MenuSize#AUTO}. * * @param size */ public void setFixedMenuSize(final int size) { attrMixin.setAttribute(SIZE, Integer.toString(size)); } /** * Sets the {@link ButtonType} of the select.<br> * <br> * <b>IMPORTANT</b>: This method will override the style set by * {@link #setStyle(String)}. */ @Override public void setType(final ButtonType type) { this.type = type; updateStyle(); } /** * Returns the {@link ButtonType} of the select; may be <code>null</code>. * * @return the {@link ButtonType} of the select */ @Override public ButtonType getType() { return type; } /** * Sets the {@link ButtonSize} of the select.<br> * <br> * <b>IMPORTANT</b>: This method will override the style set by * {@link #setStyle(String)}. */ @Override public void setSize(final ButtonSize size) { this.size = size; updateStyle(); } /** * Returns the {@link ButtonSize} of the select; may be <code>null</code>. * * @return the {@link ButtonSize} of the select */ @Override public ButtonSize getSize() { return size; } private void updateStyle() { StringBuilder sb = new StringBuilder(); if (type != null) { sb.append(type.getCssName()); } if (size != null) { if (!sb.toString().isEmpty()) { sb.append(" "); } sb.append(size.getCssName()); } setStyle(sb.toString()); } /** * Set the customized style name to the select.<br> * <br> * Defaults to <code>null</code>.<br> * <br> * <b>IMPORTANT</b>: This method will override the style set by * {@link #setType(ButtonType)} and/or {@link #setSize(ButtonSize)}. * * @param styleName */ public void setStyle(final String styleName) { if (styleName != null) attrMixin.setAttribute(STYLE, styleName); else attrMixin.removeAttribute(STYLE); } /** * Returns the style name applied to the select. * * @return */ public String getStyle() { return attrMixin.getAttribute(STYLE); } /** * Set the default placeholder text when nothing is selected. * This works for both multiple and standard select boxes.<br> * <br> * Defaults to <code>null</code>. * * @param title * @see #setTitle(String) */ public void setPlaceholder(final String placeholder) { setTitle(placeholder); } /** * Set the specified width to the select.<br> * <br> * Defaults to {@link SelectWidth#NONE}. * * @param width * @see #setWidth(String) * @see SelectWidth */ public void setSelectWidth(final SelectWidth width) { setWidth((width != null) ? width.getValue() : null); } /** * Set the select width witch is forced inline to the given value. * * @param cssWidth a CSS width with units, e.g. 100px */ @Override public void setWidth(final String cssWidth) { if (cssWidth != null) attrMixin.setAttribute(WIDTH, cssWidth); else attrMixin.removeAttribute(WIDTH); } /** * Set to <code>true</code> to add the Bootstrap menu arrow. * * @param showMenuArrow */ public void setShowMenuArrow(final boolean showMenuArrow) { if (showMenuArrow) { addStyleName(SelectStyles.SHOW_MENU_ARROW); } else { removeStyleName(SelectStyles.SHOW_MENU_ARROW); } } @Override public LeafValueEditor<T> asEditor() { if (editor == null) { editor = TakesValueEditor.of(this); } return editor; } @Override public void setValue(final T value) { setValue(value, false); } @Override public void setValue(final T value, final boolean fireEvents) { T oldValue = fireEvents ? getValue() : null; setSelectedValue(value); if (fireEvents) { T newValue = getValue(); ValueChangeEvent.fireIfNotEqual(this, oldValue, newValue); } } /** * Fires {@link ValueChangeEvent} with the current value. */ private void onValueChange() { T newValue = getValue(); ValueChangeEvent.fire(this, newValue); } /** * Selects the given value. If the value is <code>null</code> * or does not match any option, no option will be selected. * * @param value */ protected abstract void setSelectedValue(final T value); @Override public void setEnabled(boolean enabled) { enabledMixin.setEnabled(enabled); refresh(); } @Override public boolean isEnabled() { return enabledMixin.isEnabled(); } @Override public int getTabIndex() { return focusImpl.getTabIndex(getFocusElement()); } @Override public void setAccessKey(char key) { focusImpl.setAccessKey(getFocusElement(), key); } @Override public void setFocus(boolean focused) { if (focused) { focusImpl.focus(getFocusElement()); } else { focusImpl.blur(getFocusElement()); } } @Override public void setTabIndex(int index) { focusImpl.setTabIndex(getFocusElement(), index); } private Element getFocusElement() { if (!isAttached()) { return selectElement; } return getElement().getParentElement().getFirstChildElement(); } /** * Returns the number of items present in the select. * * @return the number of items */ public int getItemCount() { return selectElement.getOptions().getLength(); } /** * Returns the item list. * * @return the item list */ public List<Option> getItems() { List<Option> selectedItems = new ArrayList<>(0); NodeList<OptionElement> items = selectElement.getOptions(); for (int i = 0; i < items.getLength(); i++) { OptionElement item = items.getItem(i); Option option = itemMap.get(item); if (option != null) selectedItems.add(option); } return selectedItems; } /** * Returns <code>true</code> if the item at the given index is selected.<br> * <br> * <b>Note</b>: if the item at the given index is a divider, this method * always returns <code>false</code>. * * @param index * @return */ public boolean isItemSelected(final int index) { checkIndex(index); OptionElement item = selectElement.getOptions().getItem(index); Option option = itemMap.get(item); return option != null && option.isSelected(); } /** * Returns the {@link Option} at the given index. * * @param index * @return */ public Option getItem(final int index) { checkIndex(index); OptionElement item = selectElement.getOptions().getItem(index); return itemMap.get(item); } private void checkIndex(final int index) { int max = getItemCount(); if (index < 0 || index >= max) { throw new IndexOutOfBoundsException("Index should be in [0, " + max + "]"); } } @Override public HandlerRegistration addValueChangeHandler(ValueChangeHandler<T> handler) { return addHandler(handler, ValueChangeEvent.getType()); } @Override public HandlerRegistration addLoadedHandler(LoadedHandler handler) { return addHandler(handler, LoadedEvent.getType()); } @Override public HandlerRegistration addShowHandler(ShowHandler handler) { return addHandler(handler, ShowEvent.getType()); } @Override public HandlerRegistration addShownHandler(ShownHandler handler) { return addHandler(handler, ShownEvent.getType()); } @Override public HandlerRegistration addHideHandler(HideHandler handler) { return addHandler(handler, HideEvent.getType()); } @Override public HandlerRegistration addHiddenHandler(HiddenHandler handler) { return addHandler(handler, HiddenEvent.getType()); } @Override public HandlerRegistration addRenderedHandler(RenderedHandler handler) { return addHandler(handler, RenderedEvent.getType()); } @Override public HandlerRegistration addRefreshedHandler(RefreshedHandler handler) { return addHandler(handler, RefreshedEvent.getType()); } /** * Force a re-render of the bootstrap-select UI. This is useful if you programmatically * change any underlying values that affect the layout of the element. */ public void render() { if (isAttached()) command(getElement(), SelectCommand.RENDER); } /** * Toggles the select menu open/closed. */ public void toggle() { if (isAttached()) command(getElement(), SelectCommand.TOGGLE); } /** * Enables the device's native menu for select menus. */ public void mobile() { if (isAttached()) command(getElement(), SelectCommand.MOBILE); } /** * WHEN CHANGING ANY SETTINGS CALL REFRESH AFTER!! */ public void refresh() { if (isAttached()) command(getElement(), SelectCommand.REFRESH); } /** * Shows the select. This only affects the visibility of * the select itself. */ public void show() { if (isAttached()) command(getElement(), SelectCommand.SHOW); else super.setVisible(true); } /** * Hides the select. This only affects the visibility of * the select itself. */ public void hide() { if (isAttached()) command(getElement(), SelectCommand.HIDE); else super.setVisible(false); } @Override public void setVisible(boolean visible) { if (visible) show(); else hide(); } @Override public boolean isVisible() { if (isAttached()) { return isVisible(selectElement.getParentElement()); } return super.isVisible(); } private native void initialize(Element e, SelectOptions options) /*-{ $wnd.jQuery(e).selectpicker(options); }-*/; /** * Binds the select events. * * @param e */ private native void bindSelectEvents(Element e) /*-{ var select = this; $wnd.jQuery(e).on(@org.gwtbootstrap3.extras.select.client.ui.event.HasAllSelectHandlers::LOADED_EVENT, function(event) { @org.gwtbootstrap3.extras.select.client.ui.event.LoadedEvent::fire(Lorg/gwtbootstrap3/extras/select/client/ui/event/HasLoadedHandlers;)(select); }); $wnd.jQuery(e).on(@org.gwtbootstrap3.extras.select.client.ui.event.HasAllSelectHandlers::CHANGED_EVENT, function(event, clickedIndex, newValue, oldValue) { select.@org.gwtbootstrap3.extras.select.client.ui.SelectBase::onValueChange()(); }); $wnd.jQuery(e).on(@org.gwtbootstrap3.extras.select.client.ui.event.HasAllSelectHandlers::SHOW_EVENT, function(event) { @org.gwtbootstrap3.extras.select.client.ui.event.ShowEvent::fire(Lorg/gwtbootstrap3/extras/select/client/ui/event/HasShowHandlers;)(select); }); $wnd.jQuery(e).on(@org.gwtbootstrap3.extras.select.client.ui.event.HasAllSelectHandlers::SHOWN_EVENT, function(event) { @org.gwtbootstrap3.extras.select.client.ui.event.ShownEvent::fire(Lorg/gwtbootstrap3/extras/select/client/ui/event/HasShownHandlers;)(select); }); $wnd.jQuery(e).on(@org.gwtbootstrap3.extras.select.client.ui.event.HasAllSelectHandlers::HIDE_EVENT, function(event) { @org.gwtbootstrap3.extras.select.client.ui.event.HideEvent::fire(Lorg/gwtbootstrap3/extras/select/client/ui/event/HasHideHandlers;)(select); }); $wnd.jQuery(e).on(@org.gwtbootstrap3.extras.select.client.ui.event.HasAllSelectHandlers::HIDDEN_EVENT, function(event) { @org.gwtbootstrap3.extras.select.client.ui.event.HiddenEvent::fire(Lorg/gwtbootstrap3/extras/select/client/ui/event/HasHiddenHandlers;)(select); }); $wnd.jQuery(e).on(@org.gwtbootstrap3.extras.select.client.ui.event.HasAllSelectHandlers::RENDERED_EVENT, function(event) { @org.gwtbootstrap3.extras.select.client.ui.event.RenderedEvent::fire(Lorg/gwtbootstrap3/extras/select/client/ui/event/HasRenderedHandlers;)(select); }); $wnd.jQuery(e).on(@org.gwtbootstrap3.extras.select.client.ui.event.HasAllSelectHandlers::REFRESHED_EVENT, function(event) { @org.gwtbootstrap3.extras.select.client.ui.event.RefreshedEvent::fire(Lorg/gwtbootstrap3/extras/select/client/ui/event/HasRefreshedHandlers;)(select); }); }-*/; /** * Unbinds the select events. * * @param e */ private native void unbindSelectEvents(Element e) /*-{ $wnd.jQuery(e).off(@org.gwtbootstrap3.extras.select.client.ui.event.HasAllSelectHandlers::LOADED_EVENT); $wnd.jQuery(e).off(@org.gwtbootstrap3.extras.select.client.ui.event.HasAllSelectHandlers::CHANGED_EVENT); $wnd.jQuery(e).off(@org.gwtbootstrap3.extras.select.client.ui.event.HasAllSelectHandlers::SHOW_EVENT); $wnd.jQuery(e).off(@org.gwtbootstrap3.extras.select.client.ui.event.HasAllSelectHandlers::SHOWN_EVENT); $wnd.jQuery(e).off(@org.gwtbootstrap3.extras.select.client.ui.event.HasAllSelectHandlers::HIDE_EVENT); $wnd.jQuery(e).off(@org.gwtbootstrap3.extras.select.client.ui.event.HasAllSelectHandlers::HIDDEN_EVENT); $wnd.jQuery(e).off(@org.gwtbootstrap3.extras.select.client.ui.event.HasAllSelectHandlers::RENDERED_EVENT); $wnd.jQuery(e).off(@org.gwtbootstrap3.extras.select.client.ui.event.HasAllSelectHandlers::REFRESHED_EVENT); }-*/; protected native void command(Element e, String command) /*-{ $wnd.jQuery(e).selectpicker(command); }-*/; }