/* * 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()); } }