001/* 002 * Copyright 2012 GWT-Bootstrap 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.github.gwtbootstrap.client.ui.base; 017 018import com.github.gwtbootstrap.client.ui.constants.Placement; 019import com.github.gwtbootstrap.client.ui.constants.Trigger; 020import com.github.gwtbootstrap.client.ui.constants.VisibilityChange; 021import com.google.gwt.core.client.Scheduler; 022import com.google.gwt.core.client.Scheduler.ScheduledCommand; 023import com.google.gwt.dom.client.Element; 024import com.google.gwt.event.logical.shared.AttachEvent; 025import com.google.gwt.user.client.ui.HasOneWidget; 026import com.google.gwt.user.client.ui.HasText; 027import com.google.gwt.user.client.ui.HasWidgets; 028import com.google.gwt.user.client.ui.IsWidget; 029import com.google.gwt.user.client.ui.Widget; 030 031//@formatter:off 032/** 033* Base class for widgets that hover above other widgets. 034* 035* @since 2.0.4.0 036* 037* @author Dominik Mayer 038* 039* @see <a href="http://twitter.github.com/bootstrap/javascript.html#popovers">Bootstrap documentation</a> 040*/ 041//@formatter:on 042public abstract class HoverBase extends MarkupWidget implements IsWidget, HasWidgets, HasOneWidget, IsAnimated, HasTrigger, HasPlacement, HasText, HasShowDelay, HasVisibility { 043 044 /** 045 * Whether the widget is animated or not. 046 */ 047 protected boolean animated = true; 048 049 /** 050 * The placement of the widget relative to its trigger element. 051 */ 052 protected Placement placement = Placement.TOP; 053 054 /** 055 * The action that triggers the widget. 056 */ 057 protected Trigger trigger = Trigger.HOVER; 058 059 /** 060 * The delay until the widget is shown. 061 */ 062 protected int showDelayInMilliseconds = 0; 063 064 /** 065 * The delay until the widget is hidden. 066 */ 067 protected int hideDelayInMilliseconds = 0; 068 069 /** 070 * Creates a new widget based on the provided HTML tag. 071 */ 072 public HoverBase() { 073 } 074 075 /** 076 * {@inheritDoc} 077 */ 078 @Override 079 public Widget asWidget() { 080 081 if(getWidget() != null) { 082 Scheduler.get().scheduleDeferred(new ScheduledCommand() { 083 084 @Override 085 public void execute() { 086 removeDataIfExists(); 087 088 reconfigure(); 089 090 getWidget().addAttachHandler(new AttachEvent.Handler() { 091 092 @Override 093 public void onAttachOrDetach(AttachEvent event) { 094 if (!event.isAttached()) { 095 changeVisibility(VisibilityChange.HIDE); 096 } 097 } 098 }); 099 } 100 }); 101 } 102 103 return getWidget(); 104 105 } 106 107 protected void removeDataIfExists() { 108 removeDataIfExists(getWidget().getElement(), getDataName()); 109 } 110 111 protected native void removeDataIfExists(Element e, String dataName) /*-{ 112 if($wnd.jQuery(e).data(dataName)) { 113 var data = $wnd.jQuery(e).data(dataName); 114 var eventIn, eventOut; 115 if (data.options.trigger != 'manual') { 116 eventIn = data.options.trigger == 'hover' ? 'mouseenter' : 'focus' 117 eventOut = data.options.trigger == 'hover' ? 'mouseleave' : 'blur' 118 data.$element.off(eventIn); 119 data.$element.off(eventOut); 120 } 121 $wnd.jQuery(e).removeData(dataName); 122 } 123 }-*/; 124 125 /** 126 * Adds an HTML data attribute to the widget's tag. 127 * 128 * @param e target element 129 * 130 * @param attribute 131 * the name of the attribute without leading <code>"data-"</code> 132 * @param value 133 * the value to be stored 134 */ 135 protected void setDataAttribute(Element e , String attribute, String value) { 136 e.setAttribute("data-" + attribute, value); 137 } 138 139 /** 140 * {@inheritDoc} 141 */ 142 public void setAnimation(boolean animated) { 143 this.animated = animated; 144 } 145 146 /** 147 * Redraws the widget with the currently set options. This must <b>not</b> 148 * be called when a parameter is updated because it would deactivate all 149 * other parameters. No idea why... 150 */ 151 public abstract void reconfigure(); 152 153 /** 154 * {@inheritDoc} 155 */ 156 public boolean getAnimation() { 157 return animated; 158 } 159 160 /** 161 * {@inheritDoc} Relative to its trigger element. 162 */ 163 public void setPlacement(Placement placement) { 164 this.placement = placement; 165 } 166 167 /** 168 * {@inheritDoc} 169 */ 170 public Placement getPlacement() { 171 return placement; 172 } 173 174 /** 175 * {@inheritDoc} 176 */ 177 public void setTrigger(Trigger trigger) { 178 this.trigger = trigger; 179 } 180 181 /** 182 * {@inheritDoc} 183 */ 184 public Trigger getTrigger() { 185 return trigger; 186 } 187 188 /** 189 * {@inheritDoc} 190 */ 191 public void setShowDelay(int delayInMilliseconds) { 192 showDelayInMilliseconds = delayInMilliseconds; 193 } 194 195 /** 196 * {@inheritDoc} 197 */ 198 public int getShowDelay() { 199 return showDelayInMilliseconds; 200 } 201 202 /** 203 * {@inheritDoc} 204 */ 205 public void setHideDelay(int delayInMilliseconds) { 206 hideDelayInMilliseconds = delayInMilliseconds; 207 } 208 209 /** 210 * {@inheritDoc} 211 */ 212 public int getHideDelay() { 213 return hideDelayInMilliseconds; 214 } 215 216 /** 217 * {@inheritDoc} 218 */ 219 public void show() { 220 changeVisibility(VisibilityChange.SHOW); 221 } 222 223 /** 224 * {@inheritDoc} 225 */ 226 public void hide() { 227 changeVisibility(VisibilityChange.HIDE); 228 } 229 230 /** 231 * {@inheritDoc} 232 */ 233 public void toggle() { 234 changeVisibility(VisibilityChange.TOGGLE); 235 } 236 237 /** 238 * Changes the visibility of the widget. 239 * 240 * @param visibilityChange 241 * the action to be performed 242 */ 243 protected abstract void changeVisibility(VisibilityChange visibilityChange); 244 245 /** 246 * Get data name of JS Data API. 247 * @return data name 248 */ 249 protected abstract String getDataName(); 250}