javascriptjqueryvaadinjquery-eventsvaadin7

Vaadin and independent JavaScript Events


I develop strength password indicator using ProgressBar and PasswordField. The problem is that I can't use jQuery events handlers like e.g. onkeydown or native JavaScript's addEventListener because It works only one time then Vaadin somehow override it. I don't want to remove it permanently and completely, it should work only for jQuery object. Any ideas or better solution will be welcome.


Solution

  • Any ideas or better solution will be welcome.

    That's how batman would do it (code first, explanation later):

    @SuppressWarnings("serial")
    @Theme("so5")
    @JavaScript("batman.js")
    public class So5UI extends UI {
    
        @WebServlet(value = "/*", asyncSupported = true)
        @VaadinServletConfiguration(productionMode = false, ui = So5UI.class)
        public static class Servlet extends VaadinServlet {
        }
    
        @Override
        protected void init(VaadinRequest request) {
            VerticalLayout layout = new VerticalLayout();
            TextField field = new TextField();
            field.setId("batmanField");
            layout.addComponent(field);
            setContent(layout);
        }
    }
    

    And batman.js located in the same package as So5UI class.

    alert('Script loaded');
    var i = setInterval(batmanFunction, 300);
    
    function batmanFunction()
    {
        var element = document.getElementById("batmanField");
        if(element != null)
        {
            element.addEventListener("mouseover", batmanScript);
            clearInterval(i);
        }
    }
    function batmanScript()
    {
        alert('I am batman');
    }
    

    This code works and every time you mouse over your textfield an alert with "I am batman" text appears. I would like to point out some most important stuff:

    1. I've added an Id to the field so we can find it by getElementById()
    2. I run batmanFunction which register a listener to the field in intervals. That's because we have no control over execution time of JavaScript and DOM creation. We need to register listener after DOM creation.
    3. While working with JavaScript and Vaadin be sure to disable js caching in your browser because sometimes it leads to confusion ("This script should work" while browser still use cached script). Here is how to do it on Firefox.

    The code has been tested on Firefox 34, Vaadin 7.3, Tomcat 7.0. If you still having troubles please provide more details.

    EDIT: tested and works for keydown too

    EDIT2 I believe I figured out why it might only works "once" for you. Since Vaadin removes and adds div's automatically via Ajax, you must add event listener to the component every time it's added to the DOM. In example: if you click on button which removes the field from layout, and later you will click on button which adds the same field to the layout the event will no longer be generated. You must find those places and execute given script once again. You can check that with following code:

        @Override
        protected void init(VaadinRequest request) {
        VerticalLayout layout = new VerticalLayout();
        TextField field = new TextField();
        field.setId("batmanField");
        layout.addComponent(field);
        Button button = new Button("remove");
        button.addClickListener(new ClickListener()
        {
    
            @Override
            public void buttonClick(ClickEvent event)
            {
                layout.removeComponent(field);
            }
        });
        layout.addComponent(button);
        Button button2 = new Button("add");
        button2.addClickListener(new ClickListener()
        {
    
            @Override
            public void buttonClick(ClickEvent event)
            {
                layout.addComponent(field);
                com.vaadin.ui.JavaScript.eval("setInterval(batmanFunction, 300)");
            }
        });
        layout.addComponent(button2);
        setContent(layout);
    }