package org.uberfire.client.mvp;

import java.util.Arrays;
import java.util.List;

import javax.enterprise.context.Dependent;

import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.Event;

@Dependent
public class LockDemandDetector {

    private static final List<String> TAG_CLICK_LOCK_EXCLUSIONS = Arrays.asList( "a",
                                                                                 "select",
                                                                                 "table",
                                                                                 "tbody",
                                                                                 "tfoot",
                                                                                 "td",
                                                                                 "tr" );

    /**
     * Determines whether or not the provided event indicates a change and
     * therefore demands a lock. The decision is based on:
     * 
     * <ul>
     * <li>An optional custom DOM attribute which can be placed on the target
     * element or any of its parent elements (data-uf-lock="[true|false]")
     * 
     * <li>A global default list of tag exclusion for click events (i.e.
     * clicking on select element should cause a lock since the selection will
     * later cause a change event)
     * <ul>
     * 
     * @param event
     *            the DOM event
     * @return true, if a lock is required, otherwise false.
     */
    public boolean isLockRequired( Event event ) {
        final Element target = Element.as( event.getEventTarget() );
        final String lockAttribute = findLockAttribute( target );
        if ( lockAttribute != null && !lockAttribute.isEmpty() ) {
            return Boolean.parseBoolean( lockAttribute );
        }

        boolean eventExcluded = (event.getTypeInt() == Event.ONCLICK &&
                TAG_CLICK_LOCK_EXCLUSIONS.contains( target.getTagName().toLowerCase() ));

        return !eventExcluded;
    }

    /**
     * Returns the bitmask of all events that can potentially indicate a lock
     * demand. The actually event should be passed to
     * {@link #isLockRequired(Event)} to account for fine-tuning (i.e. via
     * custom configuration).
     */
    public int getLockDemandEventTypes() {
        return Event.KEYEVENTS | Event.ONCHANGE | Event.ONCLICK;
    }

    private String findLockAttribute( final Element element ) {
        if ( element == null ) {
            return null;
        }

        final String lockAttribute = element.getAttribute( "data-uf-lock" );
        if ( lockAttribute != null && !lockAttribute.isEmpty() ) {
            return lockAttribute;
        }

        return findLockAttribute( element.getParentElement() );
    }
}
@@ -423,24 +423,114 @@
   %22select%22,%0A
+                                                                                 %22input%22,%0A
             
@@ -1336,16 +1336,17 @@
 xclusion
+s
  for cli
@@ -1401,16 +1401,19 @@
 t should
+n't
  cause a
@@ -1442,19 +1442,20 @@
 ion 
-will
 %0A     *
+ will
  lat
@@ -1478,16 +1478,133 @@
 e event)
+ and a DOM attribute to override this%0A     * default behavior for click events (data-uf-lock-on-click=%22%5Btrue%7Cfalse%5D%22)
 %0A     * 
@@ -1771,16 +1771,22 @@
 equired(
+ final
  Event e
@@ -1918,16 +1918,32 @@
 tribute(
+ %22data-uf-lock%22,
  target 
@@ -2089,24 +2089,30 @@
         
+final 
 boolean 
 eventExc
@@ -2103,29 +2103,21 @@
 boolean 
-eventExcluded
+click
  = (even
@@ -2151,28 +2151,340 @@
 LICK
- &&%0A                
+);%0A        %0A        if (click) %7B%0A            final String lockOnClickAttribute = findLockAttribute( %22data-uf-lock-on-click%22, target );%0A            if ( lockOnClickAttribute != null && !lockOnClickAttribute.isEmpty() ) %7B%0A               return Boolean.parseBoolean( lockOnClickAttribute );%0A            %7D else %7B%0A               return !
 TAG_
@@ -2550,19 +2550,51 @@
 Case() )
-);%0A
+; %0A            %7D%0A        %7D%0A        
 %0A       
@@ -2605,22 +2605,12 @@
 urn 
-!eventExcluded
+true
 ;%0A  
@@ -3019,16 +3019,44 @@
 tribute(
+ final String attributeName,
  final E
@@ -3202,30 +3202,29 @@
 ribute( 
-%22data-uf-lock%22
+attributeName
  );%0A    
@@ -3364,16 +3364,31 @@
 tribute(
+ attributeName,
  element

Support fine-tuning of lock demand for click events