import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style;
+import com.vaadin.client.AnimationUtil.AnimationEndListener;
/**
* Utility methods for working with CSS transitions and animations.
var callbackFunc = $entry(function(e) {
listener.@com.vaadin.client.AnimationUtil.AnimationEndListener::onAnimationEnd(Lcom/google/gwt/dom/client/NativeEvent;)(e);
});
+ callbackFunc.listener = listener;
elem.addEventListener(@com.vaadin.client.AnimationUtil::ANIMATION_END_EVENT_NAME, callbackFunc, false);
elem.removeEventListener(@com.vaadin.client.AnimationUtil::ANIMATION_END_EVENT_NAME, listener, false);
}-*/;
+ /**
+ * Removes the given animation listener.
+ *
+ * @param element
+ * the element which has the listener
+ * @param animationEndListener
+ * the listener to remove
+ * @return <code>true</code> if the listener was removed, <code>false</code>
+ * if the listener was not registered to the given element
+ */
+ public static native boolean removeAnimationEndListener(Element elem,
+ AnimationEndListener animationEndListener)
+ /*-{
+ if(elem._vaadin_animationend_callbacks) {
+ var callbacks = elem._vaadin_animationend_callbacks;
+ for(var i=0; i < callbacks.length; i++) {
+ if (callbacks[i].listener == animationEndListener) {
+ elem.removeEventListener(@com.vaadin.client.AnimationUtil::ANIMATION_END_EVENT_NAME, callbacks[i], false);
+ return true;
+ }
+ }
+ return false;
+ }
+ }-*/;
+
/** For internal use only. May be removed or replaced in the future. */
public static native void removeAllAnimationEndListeners(Element elem)
/*-{
'MozAnimation': 'animationend',
'WebkitAnimation': 'webkitAnimationEnd'
}
-
+
for(var a in anims){
if( el.style[a] !== undefined ){
return anims[a];
'mozAnimation',
'webkitAnimation'
]
-
+
for(var i=0; i < anims.length; i++) {
if( el.style[anims[i]] !== undefined ){
return anims[i];
current = null;
}
- private JavaScriptObject animateInListener;
-
private boolean fitInWindow = false;
private boolean maybeShowWithAnimation() {
if (animationName.contains(ADDITIONAL_CLASSNAME_ANIMATE_IN)) {
// Disable GWT PopupPanel animation if used
setAnimationEnabled(false);
- animateInListener = AnimationUtil.addAnimationEndListener(
+ AnimationUtil.addAnimationEndListener(
getElement(), new AnimationEndListener() {
@Override
public void onAnimationEnd(NativeEvent event) {
.getAnimationName(event);
if (animationName
.contains(ADDITIONAL_CLASSNAME_ANIMATE_IN)) {
- AnimationUtil.removeAnimationEndListener(
- getElement(), animateInListener);
+ boolean removed = AnimationUtil.removeAnimationEndListener(getElement(), this);
+ assert removed: "Animation end listener was not removed";
removeStyleDependentName(ADDITIONAL_CLASSNAME_ANIMATE_IN);
if (isShadowEnabled()) {
shadow.removeClassName(CLASSNAME_SHADOW
.getAnimationName(event)
.contains(
ADDITIONAL_CLASSNAME_ANIMATE_IN)) {
+ boolean removed = AnimationUtil.removeAnimationEndListener(getElement(), this);
+ assert removed: "Animation end listener was not removed";
reallyHide(autoClosed);
}
}
.getAnimationName(event);
if (animationName
.contains(ADDITIONAL_CLASSNAME_ANIMATE_OUT)) {
- AnimationUtil
- .removeAllAnimationEndListeners(getElement());
+ boolean removed = AnimationUtil.removeAnimationEndListener(getElement(), this);
+ assert removed: "Animation end listener was not removed";
// Remove both animation styles just in
// case
removeStyleDependentName(ADDITIONAL_CLASSNAME_ANIMATE_IN);
--- /dev/null
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * 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.
+ */
+package com.vaadin.tests.components.combobox;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.ComboBox;
+
+@Theme("valo")
+public class ComboBoxValoDoubleClick extends AbstractTestUI {
+
+ // Quite impossible to autotest reliably as there must be a click to open
+ // the popup and another click during the opening animation to reproduce the
+ // bug. Manually a double click is just about the right timing.
+ @Override
+ protected void setup(VaadinRequest request) {
+ ComboBox cb = new ComboBox("Double-click Me");
+ for (int i = 0; i < 100; i++) {
+ cb.addItem("Item-" + i);
+ }
+ addComponent(cb);
+ }
+
+ @Override
+ public String getTestDescription() {
+ return "ComboBox should remain usable even after double-clicking (affects only Valo theme with $v-overlay-animate-in).";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 17903;
+ }
+
+}