/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* 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 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",
"input",
"textarea",
"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:
* <p>
* <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]")
* <p>
* <li>A global default list of tag exclusions for click events (i.e.
* clicking on select element shouldn't cause a lock since the selection
* will later cause a change event) and a DOM attribute to override this
* default behavior for click events (data-uf-lock-on-click="[true|false]")
* <ul>
* @param event the DOM event
* @return true, if a lock is required, otherwise false.
*/
public boolean isLockRequired(final Event event) {
final Element target = Element.as(event.getEventTarget());
final String lockAttribute = findLockAttribute("data-uf-lock",
target);
if (lockAttribute != null && !lockAttribute.isEmpty()) {
return Boolean.parseBoolean(lockAttribute);
}
final boolean click = (event.getTypeInt() == Event.ONCLICK);
if (click) {
final String lockOnClickAttribute = findLockAttribute("data-uf-lock-on-click",
target);
if (lockOnClickAttribute != null && !lockOnClickAttribute.isEmpty()) {
return Boolean.parseBoolean(lockOnClickAttribute);
} else {
return !TAG_CLICK_LOCK_EXCLUSIONS.contains(target.getTagName().toLowerCase());
}
}
return true;
}
/**
* 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 | Event.ONPASTE;
}
private String findLockAttribute(final String attributeName,
final Element element) {
if (element == null) {
return null;
}
final String lockAttribute = element.getAttribute(attributeName);
if (lockAttribute != null && !lockAttribute.isEmpty()) {
return lockAttribute;
}
return findLockAttribute(attributeName,
element.getParentElement());
}
}