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

org.omnifaces.component.script.OnloadScript Maven / Gradle / Ivy

There is a newer version: 4.5.1
Show newest version
/*
 * Copyright OmniFaces
 *
 * 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
 *
 *     https://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.omnifaces.component.script;

import static org.omnifaces.util.Ajax.oncomplete;
import static org.omnifaces.util.Events.subscribeToViewEvent;
import static org.omnifaces.util.FacesLocal.isAjaxRequestWithPartialRendering;

import java.io.IOException;
import java.io.StringWriter;

import jakarta.faces.FacesException;
import jakarta.faces.component.FacesComponent;
import jakarta.faces.component.UIViewRoot;
import jakarta.faces.context.FacesContext;
import jakarta.faces.context.ResponseWriter;
import jakarta.faces.context.ResponseWriterWrapper;
import jakarta.faces.event.ComponentSystemEvent;
import jakarta.faces.event.ListenerFor;
import jakarta.faces.event.PostAddToViewEvent;
import jakarta.faces.event.PostRestoreStateEvent;
import jakarta.faces.event.PreRenderViewEvent;
import jakarta.faces.event.SystemEvent;
import jakarta.faces.event.SystemEventListener;

import org.omnifaces.util.Ajax;

/**
 * 

* The <o:onloadScript is a component that extends the standard <h:outputScript> * which will be executed in the end of the HTML body (thus when all HTML elements are initialized in the HTML DOM tree) * and will re-execute its script body on every ajax request. This is particularly useful if you want to re-execute a * specific helper script to manipulate the HTML DOM tree, such as (re-)adding fancy tooltips, performing highlights, * etcetera, also after changes in the HTML DOM tree on ajax responses. *

* You can put it anywhere in the view, it will always be relocated to the end of body. *

 * <o:onloadScript>alert('OnloadScript is invoked!');</o:onloadScript>
 * 
*

* The <o:onloadScript> is implicitly relocated to the end of the <body>, * exactly like as <h:outputScript target="body"> does. So it's always executed when the entire * <body> is finished populating and thus you don't need a window.onload or a * $(document).ready() in there. Again, the difference with <h:outputScript target="body"> * is that the <o:onloadScript> is also executed on every ajax request. * * @author Bauke Scholtz * @see ScriptFamily */ @FacesComponent(OnloadScript.COMPONENT_TYPE) @ListenerFor(systemEventClass=PostAddToViewEvent.class) @ListenerFor(systemEventClass=PostRestoreStateEvent.class) public class OnloadScript extends ScriptFamily implements SystemEventListener { // Public constants ----------------------------------------------------------------------------------------------- /** The component type, which is {@value org.omnifaces.component.script.OnloadScript#COMPONENT_TYPE}. */ public static final String COMPONENT_TYPE = "org.omnifaces.component.script.OnloadScript"; // Actions -------------------------------------------------------------------------------------------------------- /** * Move this component to body using {@link #moveToBody(ComponentSystemEvent)}, and if the event is a * {@link PostRestoreStateEvent}, then subscribe this component to {@link PreRenderViewEvent}, which will invoke * {@link #processEvent(SystemEvent)}. */ @Override public void processEvent(ComponentSystemEvent event) { moveToBody(event); if (event instanceof PostRestoreStateEvent) { subscribeToViewEvent(PreRenderViewEvent.class, this); } } /** * Returns true if the given source is an instance of {@link OnloadScript} or {@link UIViewRoot}. */ @Override public boolean isListenerForSource(Object source) { return source instanceof OnloadScript || source instanceof UIViewRoot; } /** * If the event is a {@link PreRenderViewEvent}, and this component is rendered, and the current request is an ajax * request with partial rendering, then encode the children as {@link Ajax#oncomplete(String...)}. */ @Override public void processEvent(SystemEvent event) { if (!(event instanceof PreRenderViewEvent) || !isRendered()) { return; } FacesContext context = getFacesContext(); if (!isAjaxRequestWithPartialRendering(context)) { return; } pushComponentToEL(context, this); StringWriter buffer = new StringWriter(); ResponseWriter originalResponseWriter = context.getResponseWriter(); String encoding = context.getExternalContext().getRequestCharacterEncoding(); context.getExternalContext().setResponseCharacterEncoding(encoding); ResponseWriter writer = context.getRenderKit().createResponseWriter(buffer, null, encoding); context.setResponseWriter(new ResponseWriterWrapper(writer) { @Override public void writeText(Object text, String property) throws IOException { getWrapped().write(text.toString()); // So, don't escape HTML. } }); try { encodeChildren(context); } catch (IOException e) { throw new FacesException(e); } finally { popComponentFromEL(context); if (originalResponseWriter != null) { context.setResponseWriter(originalResponseWriter); } } String script = buffer.toString().trim(); if (!script.isEmpty()) { oncomplete(script); } } /** * If the current request is not an ajax request with partial rendering, then encode begin. */ @Override public void encodeBegin(FacesContext context) throws IOException { if (!isAjaxRequestWithPartialRendering(context)) { super.encodeBegin(context); } } /** * If the current request is not an ajax request with partial rendering, then encode end. */ @Override public void encodeEnd(FacesContext context) throws IOException { if (!isAjaxRequestWithPartialRendering(context)) { super.encodeEnd(context); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy