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 hide(); 109 removeDataIfExists(getWidget().getElement(), getDataName()); 110 } 111 112 protected native void removeDataIfExists(Element e, String dataName) /*-{ 113 var element = $wnd.jQuery(e); 114 if(element.data(dataName)) { 115 var data = element.data(dataName); 116 var eventIn, eventOut; 117 if (data.options.trigger != 'manual') { 118 eventIn = data.options.trigger == 'hover' ? 'mouseenter' : 'focus' 119 eventOut = data.options.trigger == 'hover' ? 'mouseleave' : 'blur' 120 data.$element.off(eventIn); 121 data.$element.off(eventOut); 122 } 123 element.removeData(dataName); 124 } 125 }-*/; 126 127 /** 128 * Adds an HTML data attribute to the widget's tag. 129 * 130 * @param e target element 131 * 132 * @param attribute 133 * the name of the attribute without leading <code>"data-"</code> 134 * @param value 135 * the value to be stored 136 */ 137 protected void setDataAttribute(Element e , String attribute, String value) { 138 e.setAttribute("data-" + attribute, value); 139 } 140 141 /** 142 * {@inheritDoc} 143 */ 144 public void setAnimation(boolean animated) { 145 this.animated = animated; 146 } 147 148 /** 149 * Redraws the widget with the currently set options. This must <b>not</b> 150 * be called when a parameter is updated because it would deactivate all 151 * other parameters. No idea why... 152 */ 153 public abstract void reconfigure(); 154 155 /** 156 * {@inheritDoc} 157 */ 158 public boolean getAnimation() { 159 return animated; 160 } 161 162 /** 163 * {@inheritDoc} Relative to its trigger element. 164 */ 165 public void setPlacement(Placement placement) { 166 this.placement = placement; 167 } 168 169 /** 170 * {@inheritDoc} 171 */ 172 public Placement getPlacement() { 173 return placement; 174 } 175 176 /** 177 * {@inheritDoc} 178 */ 179 public void setTrigger(Trigger trigger) { 180 this.trigger = trigger; 181 } 182 183 /** 184 * {@inheritDoc} 185 */ 186 public Trigger getTrigger() { 187 return trigger; 188 } 189 190 /** 191 * {@inheritDoc} 192 */ 193 public void setShowDelay(int delayInMilliseconds) { 194 showDelayInMilliseconds = delayInMilliseconds; 195 } 196 197 /** 198 * {@inheritDoc} 199 */ 200 public int getShowDelay() { 201 return showDelayInMilliseconds; 202 } 203 204 /** 205 * {@inheritDoc} 206 */ 207 public void setHideDelay(int delayInMilliseconds) { 208 hideDelayInMilliseconds = delayInMilliseconds; 209 } 210 211 /** 212 * {@inheritDoc} 213 */ 214 public int getHideDelay() { 215 return hideDelayInMilliseconds; 216 } 217 218 /** 219 * {@inheritDoc} 220 */ 221 public void show() { 222 changeVisibility(VisibilityChange.SHOW); 223 } 224 225 /** 226 * {@inheritDoc} 227 */ 228 public void hide() { 229 changeVisibility(VisibilityChange.HIDE); 230 } 231 232 /** 233 * {@inheritDoc} 234 */ 235 public void toggle() { 236 changeVisibility(VisibilityChange.TOGGLE); 237 } 238 239 /** 240 * Changes the visibility of the widget. 241 * 242 * @param visibilityChange 243 * the action to be performed 244 */ 245 protected abstract void changeVisibility(VisibilityChange visibilityChange); 246 247 /** 248 * Get data name of JS Data API. 249 * @return data name 250 */ 251 protected abstract String getDataName(); 252}