Package org.itsnat.impl.core.mut.client

Source Code of org.itsnat.impl.core.mut.client.ClientMutationEventListenerHTMLBlackBerryOldImpl

/*
  ItsNat Java Web Application Framework
  Copyright (C) 2007-2011 Jose Maria Arranz Santamaria, Spanish citizen

  This software is free software; you can redistribute it and/or modify it
  under the terms of the GNU Lesser General Public License as
  published by the Free Software Foundation; either version 3 of
  the License, or (at your option) any later version.
  This software is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  Lesser General Public License for more details. You should have received
  a copy of the GNU Lesser General Public License along with this program.
  If not, see <http://www.gnu.org/licenses/>.
*/

package org.itsnat.impl.core.mut.client;

import java.util.Map;
import org.itsnat.impl.core.browser.BrowserBlackBerryOld;
import org.itsnat.impl.core.clientdoc.ClientDocumentStfulImpl;
import org.itsnat.impl.core.domutil.DOMUtilHTML;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.events.MutationEvent;
import org.w3c.dom.html.HTMLInputElement;
import org.w3c.dom.html.HTMLSelectElement;

/**
*
* @author jmarranz
*/
public class ClientMutationEventListenerHTMLBlackBerryOldImpl extends ClientMutationEventListenerHTMLImpl
{
    public ClientMutationEventListenerHTMLBlackBerryOldImpl(ClientDocumentStfulImpl clientDoc)
    {
        super(clientDoc);
    }

    @Override
    public void postRenderAndSendMutationCode(MutationEvent mutEvent)
    {
        super.postRenderAndSendMutationCode(mutEvent);

        BrowserBlackBerryOld browser = (BrowserBlackBerryOld)clientDoc.getBrowser();
        String type = mutEvent.getType();

        if (browser.isHTMLInputFileValueBuggy() && type.equals("DOMNodeInserted"))
        {
            Node node = (Node)mutEvent.getTarget(); // node es el nodo nuevo
            fixTreeHTMLInputFileValue(node);
        }

        if (browser.isHTMLSelectMultipleOrWithSizeBuggy() &&
            (type.equals("DOMNodeInserted")||type.equals("DOMNodeRemoved")))
        {
            Node node = (Node)mutEvent.getTarget(); // node es el nodo nuevo o el que se va a eliminar
            if (DOMUtilHTML.isHTMLOptionOfSelectMultipleOrWithSize(node)) // node es un option
            {
                HTMLSelectElement select = (HTMLSelectElement)node.getParentNode();
                fixHTMLSelectMultipleOrWithSize(select);
            }
        }

    }

    private void fixHTMLSelectMultipleOrWithSize(HTMLSelectElement select)
    {
        // Este m�todo soluciona un problema complejo de la BlackBerry JDE 4.6 y 4.7 (Bold y Storm)
        // Consiste en que los <select> con atributos "multiple" o "size" (o ambos)
        // se "corrompen" visualmente cuando se a�ade o elimina un <option> (no cuando
        // se selecciona o cambia el valor de una opci�n) aunque el DOM es correcto.
        // El problema ocurre cuando el elemento ya est� renderizado y se modifica por la inserci�n/eliminaci�n de options.
        // He probado mil trucos y ninguno funciona salvo estos trucos:
        // 1) Clonar el elemento y usar el nuevo, a costa de actualizar referencias en el cliente
        //   los option pueden ser los originales, el problema lo tiene el elemento SELECT
        // 2) Cambiar a combo box, tocar con el cursor el componente y volverlo a cambiar
        // a multiple (o poner de nuevo el size). El problema es que �como pedimos al
        // usuario "que toque" el componente? es una chapuza.
        // 3) Dejar que se visualice mal y usar un timer que haga display = "none", dejar renderizar
        // y de nuevo lanzar otro timer que lo vuelva a visualizar.

        // La soluci�n 3) se aplic� con �xito relativo, la 1) es la que funciona siempre aunque suponga crear un nuevo elemento.

        StringBuilder code = new StringBuilder();
        String methodName = "blackBerryOldFixHTMLSelect";
        if (!clientDoc.isClientMethodBounded(methodName))
            code.append(bindFixHTMLSelectMethod(methodName));

        code.append("itsNatDoc." + methodName + "(" + clientDoc.getNodeReference(select,true,true) + ");\n");

        clientDoc.addCodeToSend(code.toString());
    }


    private String bindFixHTMLSelectMethod(String methodName)
    {
        StringBuilder code = new StringBuilder();

        code.append( "var func = function (elem)" );
        code.append( "{" );
        code.append( "    var newElem = elem.cloneNode(false);" );
        code.append( "    while(elem.firstChild != null) newElem.appendChild(elem.firstChild);" );
        code.append( "    elem.parentNode.replaceChild(newElem,elem);" );

        code.append( "    function updateListeners(map,elem,newElem)" );
        code.append( "    {" );
        code.append( "      map.doForAll(function (id,listener) {" );
        code.append( "            if (listener.currentTarget != elem) return;" );
        code.append( "            listener.currentTarget = newElem;" );
        code.append( "            if (listener.isUseCapture) " ); // es listener DOM
        code.append( "              newElem.addEventListener(listener.getType(),listener.w3cHander,listener.isUseCapture());" );
        code.append( "          }" );
        code.append( "      );" );
        code.append( "    }" );

        code.append( "    updateListeners(this.domListeners,elem,newElem);" );
        code.append( "    updateListeners(this.timerListeners,elem,newElem);" );
        code.append( "    updateListeners(this.userListenersById,elem,newElem);" );
        code.append( "    if (elem.itsNatCacheId) " ); // esta cacheado
        code.append( "    {" );
        code.append( "        newElem.itsNatCacheId = elem.itsNatCacheId;" );
        code.append( "        this.nodeCacheById.put(newElem.itsNatCacheId,newElem);" );
        code.append( "    }" );
        code.append( "    return newElem;" ); // No se usa este retorno pero por si en un futuro...
        code.append( "};" );

        code.append( "itsNatDoc." + methodName + " = func;\n" );

        clientDoc.bindClientMethod(methodName);

        return code.toString();
    }

    private void fixTreeHTMLInputFileValue(Node node)
    {
        StringBuilder code = fixTreeHTMLInputFileValue(node,null);

        if ((code != null) && (code.length() > 0))
            clientDoc.addCodeToSend(code.toString());
    }

    private StringBuilder fixTreeHTMLInputFileValue(Node node,StringBuilder code)
    {
        if (node.getNodeType() != Node.ELEMENT_NODE) return code;

        Element elem = (Element)node;

        if (DOMUtilHTML.isHTMLInputFileWithValueAttr(elem))
        {
            return fixHTMLInputFileValue((HTMLInputElement)elem,code);
        }
        else
        {
            Node child = elem.getFirstChild();
            while (child != null)
            {
                code = fixTreeHTMLInputFileValue(child,code);
                child = child.getNextSibling();
            }
        }

        return code;
    }

    private StringBuilder fixHTMLInputFileValue(HTMLInputElement elem,StringBuilder code)
    {
        // Solucionamos el problema de que la sola presencia del atributo
        // "value" en un <input type="file"> provoca una excepci�n.
        // Dicha excepci�n ocurre cuando BlackBerry *renderiza* el DOM
        // modificado, por lo que tras la renderizaci�n de la inserci�n (que pudo ser via innerHTML o DOM)
        // tenemos la oportunidad de eliminar el atributo value antes de que
        // BlackBerry muestre el control.

        if (code == null) code = new StringBuilder();

        String jsRef = clientDoc.getNodeReference(elem,true,true);

        code.append(jsRef + ".removeAttribute(\"value\");\n");

        return code;
    }

}
TOP

Related Classes of org.itsnat.impl.core.mut.client.ClientMutationEventListenerHTMLBlackBerryOldImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.