All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.icesoft.faces.context.effects.JavascriptContext Maven / Gradle / Ivy

There is a newer version: 3.3.0
Show newest version
/*
 * Copyright 2004-2012 ICEsoft Technologies Canada Corp.
 *
 * 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 com.icesoft.faces.context.effects;


import com.icesoft.faces.application.StartupTime;
import com.icesoft.util.CoreComponentUtils;
import org.icefaces.util.FocusController;

import javax.faces.component.UIComponent;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * Used to send Javascript to the browser
 */
public class JavascriptContext {
    private static final Random RANDOM = new Random();

    /**
     * Request scope key, used to store javascript code to be sent to the browser
     */
    private static final String REQUEST_KEY =
            "icesoft_javascript_request_key_7698193";
    /**
     * Effects scope key, used to store the fired effects in the request scope
     */
    private static final String EFFECTS_REQUEST_KEY =
            "icesoft_javascript_effects_request_key_9072451";
    /**
     * Request scope key for componenet focus
     */
    private static final String FOCUS_COMP_KEY =
            "icesoft_javascript_focus_comp";
    /**
     * Request Scope Key, storing the focus
     */
    private static final String FOCUS_APP_KEY = "icesoft_javascript_focus_app";
    /**
     * Request Scope Key, indicating that extras needs to be included
     */
    public static final String LIB_KEY =
            "icesoft_javascript_required_libs_897241";
    /**
     * ID of script node used to send Javascript in a dom update
     */
    public static final String DYNAMIC_CODE_ID = "dynamic-code";

    /**
     * URL of the ICE Bridge lib
     */
    public static final String ICE_BRIDGE = "/xmlhttp" + StartupTime.getStartupInc() + "icefaces-d2d.js";

    /**
     * URL of the ICE Extras lib
     */
    public static final String ICE_EXTRAS = "/xmlhttp" + StartupTime.getStartupInc() + "icefaces-compat.js";

    /**
     * Include a script tag in the <head> section of the page with the src
     * attribute set to libname. This will insure that all icefaces pages
     * contain this script for the remainder of the session.
     *
     * @param libname      the source of the javascript file
     * @param facesContext The facescontext this file is needed for
     */
    public static void includeLib(String libname, FacesContext facesContext) {
        if (facesContext == null)
            return;
        ExternalContext externalContext = facesContext.getExternalContext();
        if (externalContext == null)
            return;
        Map sessionMap = externalContext.getSessionMap();
        if (sessionMap == null)
            return;
        List libs = (List) sessionMap.get(LIB_KEY);
        if (libs == null) {
            libs = new ArrayList();
            sessionMap.put(LIB_KEY, libs);
        }
        if (!libs.contains(libname))
            libs.add(libname);
    }

    /**
     * Get the included javascript libraries
     *
     * @param facesContext
     * @return
     */
    public static String[] getIncludedLibs(FacesContext facesContext) {
        List libs = (List) facesContext.getExternalContext().getSessionMap()
                .get(LIB_KEY);
        String[] result = new String[0];
        if (libs != null) {
            result = new String[libs.size()];
            libs.toArray(result);
        }
        return result;
    }

    /**
     * Add a javascript call to be executed on the browser. Code will be
     * executed at the end of the current render cycle.
     * 

* Note: When sending function definitions you must specify the function * name as this['functionName'] = function(){} For example: * helloWorld(name}{ alert('Hello [' + name + ']'); } *

* Would need to be written as this['helloWorld'] = function(name){ * alert('Hello [' + name + ']'); } * * @param facesContext * @param call Javascript code to execute */ public static void addJavascriptCall(FacesContext facesContext, String call) { Map map = facesContext.getExternalContext().getRequestMap(); addJavascriptCall(map, call); } /** * Add a javascript call to the request map * * @param map * @param call */ private static void addJavascriptCall(Map map, String call) { String currentValue = (String) map.get(REQUEST_KEY); if (currentValue == null) { map.put(REQUEST_KEY, call); } else { map.put(REQUEST_KEY, currentValue + call); } } /** * Add a javascript call to this request * * @param facesContext * @return */ public static String getJavascriptCalls(FacesContext facesContext) { Map map = facesContext.getExternalContext().getRequestMap(); return getJavascriptCalls(map); } /** * Get javascript calls from the Request map * * @param map * @return */ public static String getJavascriptCalls(Map map) { addtEffectJavascriptCalls(map); String code = (String) map.get(REQUEST_KEY); map.put(REQUEST_KEY, ""); code = replaceDupes(code == null || "".equals(code) ? "" : code); // Hack so that javascript will be called from both the bridge and the html parser // Remove when we have a better way if ("".equals(code)) { return ""; } else { return code + randomComment(); } } /** * Wrap the effect in a javascript method to be called later. Returns the * method name. Used in local effects. * * @param effect * @param id * @param context * @return The name of the method that wraps the effect */ public static String applyEffect(Effect effect, String id, FacesContext context) { //Get the real ID if a JSF component UIComponent uiComponent = CoreComponentUtils.findComponent(id, context.getViewRoot()); if (uiComponent != null) { id = uiComponent.getClientId(context); } String name = genFunctionName(id, effect); String call = "window['" + name + "'] = function (){" + "id = '" + id + "';" + effect.toString() + "};"; addJavascriptCall(context, call); return name + "();"; } /** * Fire an effect at the end of the current render cycle. Fired from server, non local. * * @param effect * @param id Target element of the effect * @param context */ public static void fireEffect(Effect effect, String id, FacesContext context) { if (effect == null || effect.isFired()) return; effect.setFired(true); Object viewRoot = context.getViewRoot(); try { UIComponent uiComponent = CoreComponentUtils.findComponent(id, context.getViewRoot()); if (uiComponent != null) { id = uiComponent.getClientId(context); } } catch (Exception e) { /*Class clazz = context.getViewRoot().getClass(); Method[] methods =clazz.getMethods(); for(int i = 0; i < methods.length; i++){ Method m = methods[i]; System.err.println("Method [" + m.getName() + "]"); Class[] args = m.getParameterTypes(); for(int a =0; a 64 && c < 91) || (c > 96 && c < 123) || (c > 47 && c < 58)) { sb.append(ca[i]); } else { sb.append('_'); } } sb.append(effect.hashCode()); return sb.toString(); } /** * Remove duplicate semi-colons from a givin string * * @param s * @return */ private static String replaceDupes(String s) { if (s.indexOf(";;") == -1) return s; s = s.replaceAll(";;", ";"); return s; } /** * \ Set focus on an HTML element. * * @param context * @param id */ public static void focus(FacesContext context, String id) { FocusController.setFocus(context, id); } /** * Set the application focus for the current request, overrides and setFocus call. * Generally setFocus is used by components, while setApplicationFocus is used by the application. * * @param id */ public static void applicationFocus(FacesContext facesContext, String id) { FocusController.setFocus(facesContext, id); } /** * Add an effect call for the current request * * @param effect * @param facesContext */ private static void addEffect(Effect effect, FacesContext facesContext) { Map map = facesContext.getExternalContext().getRequestMap(); List list = (ArrayList) map.get(EFFECTS_REQUEST_KEY); if (list == null) { list = new ArrayList(); map.put(EFFECTS_REQUEST_KEY, list); } list.add(effect); } /** * Add fired effects as javascript calls * * @param map */ private static void addtEffectJavascriptCalls(Map map) { List list = (ArrayList) map.get(EFFECTS_REQUEST_KEY); if (list == null) { return; } Map sequencedEffects = new HashMap(); Iterator iter = list.iterator(); while (iter.hasNext()) { Effect effect = (Effect) iter.next(); if (effect.getSequence() == null && !(effect instanceof EffectQueue)) { String call = "id = '" + effect.getId() + "';" + effect.toString(); addJavascriptCall(map, call); } else { extractEffectSequence(effect, sequencedEffects); } } if (sequencedEffects.size() > 0) { iter = sequencedEffects.values().iterator(); int sequence = 0; while (iter.hasNext()) { list = (List) iter.next(); Collections.sort(list, new EffectComparator()); String call = buildSequenceEffectCall(list, sequence); addJavascriptCall(map, call); sequence++; } } map.remove(EFFECTS_REQUEST_KEY); } /** * Build sequence of javascript effect calls * * @param list * @param sequence * @return */ private static String buildSequenceEffectCall(List list, int sequence) { StringBuffer sb = new StringBuffer(); Iterator effectIter = list.iterator(); int effect = 0; String lastCall = null; while (effectIter.hasNext()) { Effect fx = (Effect) effectIter.next(); String var = getVariableName(sequence, effect); lastCall = "var " + var + " = '" + fx.getId() + "';" + fx.toString(var, lastCall); effect++; } return lastCall; } /** * Extra Javascript Effect Sequence from a map of effects * * @param effect * @param sequencedEffects */ private static void extractEffectSequence(Effect effect, Map sequencedEffects) { String seqName = effect.getSequence(); List seq = (List) sequencedEffects.get(seqName); if (seq == null) { seq = new ArrayList(); sequencedEffects.put(seqName, seq); } if (effect instanceof EffectQueue) { List eqList = ((EffectQueue) effect).getEffects(); Iterator eqIter = eqList.iterator(); int seqId = 0; while (eqIter.hasNext()) { Effect fx = (Effect) eqIter.next(); fx.setSequence(seqName); fx.setSequenceId(seqId); fx.setId(effect.getId()); seq.add(fx); seqId++; } } else { seq.add(effect); } } /** * Get variable name for an effect in a sequence * * @param sequence * @param effect * @return */ private static String getVariableName(int sequence, int effect) { return "s" + sequence + "e" + effect; } /** * Generate random Javascript comment to force a diff on the 'script' * elements, thus triggering their evaluation in the browser. */ private static String randomComment() { return "//" + RANDOM.nextInt(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy