0

I am using PrimeFaces 7.0 and want to enable a Java Script eventListener for the "copy" event, as described here:

https://developer.mozilla.org/en-US/docs/Web/API/Element/copy_event

When I attach the eventListener to the document, everything works fine:

My Java Script function:

function jsCopyAction(){
    document.addEventListener('copy', (event) => {
        const selection = document.getSelection();
        event.clipboardData.setData('text/plain', selection.toString());
        event.preventDefault();
        document.getElementById("badTransFormId:jsCopyTextId").value=selection.toString();

        var jsfCommandButton = document.getElementById("badTransFormId:jsCopyLinkId");
        jsfCommandButton.click();
    });
};

My facelet page:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">
    <h:head>
    </h:head>
    <h:body>
        <h:outputStylesheet name="primeicons/primeicons.css" library="primefaces"/>
        <h:outputStylesheet library="css" name="styles.css"  />
        <h:outputScript library="primefaces" name="jquery/jquery.js"/>
        <h:outputScript library="js" name="commons.js" />
        <script>
                // we need to execute the js init() function after the page load:
                // @see https://stackoverflow.com/questions/8996316/how-to-execute-javascript-after-page-load
                jQuery(document).ready(function() {
                    jQuery(document).ready(function() {
                        // twice in document.ready to execute after Primefaces callbacks
                        jsCopyAction();
                    });
                });
        </script>
        <h:form id="badTransFormId">
            <div>
                <div>
                    <h:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5" columnClasses="label, value">
                        <h:commandButton style="display:none" id="jsCopyLinkId" action="#{badTransBean2.jsCopyAction}">
                            <f:ajax execute = "badTransFormId:jsCopyTextId" render = "@form"/>
                        </h:commandButton>
                        <input type="hidden" id="badTransFormId:jsCopyTextId" name = "jsCopyText" value="" />
                    </h:panelGrid>
                </div>
            </div>
            <div id="translEntityDiv">
              <h:outputText id= "correspHomeEntityId" value="Alabala alabala tralala" />
            </div>
        </h:form>
    </h:body>
</html>

My Bean:

@ManagedBean(name = "badTransBean2")
@ViewScoped
public class BadTransBean2 implements Serializable {


    public void jsCopyAction() {
        HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext()
                .getRequest();
        String jsCopyText = req.getParameter("jsCopyText");

        if (StringUtils.isEmpty(jsCopyText) || StringUtils.isEmpty(jsCopyText.trim())) {
            return;
        }
        jsCopyText = jsCopyText.trim().toLowerCase();

        System.out.println(jsCopyText);
    }

}

However, when I want to be more specific and want to attach the EventListener to a particular HTML element, this works ONLY the first time the user copies an element after the page is loaded in the browser. When the user copies an element, the Java Script event listener is not fired at all. Tested on Chrome and Mozilla.

My changed JavaScript function:

function jsCopyAction(){

    const source = document.getElementById("badTransFormId:correspHomeEntityId");

    source.addEventListener('copy', (event) => {
        const selection = document.getSelection();
        event.clipboardData.setData('text/plain', selection.toString());
        event.preventDefault();
        document.getElementById("badTransFormId:jsCopyTextId").value=selection.toString();

        var jsfCommandButton = document.getElementById("badTransFormId:jsCopyLinkId");
        jsfCommandButton.click();
    });
};

My pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>seller</groupId>
<artifactId>home.digest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>

<name>home.digest Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://maven.apache.org</url>
<repositories>
    <repository>
        <id>prime-repo</id>
        <name>Prime Repo</name>
        <url>http://repository.primefaces.org</url>
    </repository>
</repositories>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>3.141.59</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpcore</artifactId>
        <version>4.4.10</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.6</version>
    </dependency>
    <dependency>
        <groupId>org.primefaces</groupId>
        <artifactId>primefaces</artifactId>
        <version>7.0</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.logging</groupId>
        <artifactId>jboss-logging</artifactId>
        <version>3.0.1.GA</version>
        <scope>compile</scope>
        <optional>true</optional>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.hibernate.javax.persistence/hibernate-jpa-2.1-api -->
    <dependency>
        <groupId>org.hibernate.javax.persistence</groupId>
        <artifactId>hibernate-jpa-2.1-api</artifactId>
        <version>1.0.2.Final</version>
        <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>4.3.6.Final</version>
         <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.enterprise/cdi-api -->
    <dependency>
        <groupId>javax.enterprise</groupId>
        <artifactId>cdi-api</artifactId>
        <version>2.0.SP1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.as</groupId>
        <artifactId>jboss-as-web</artifactId>
        <version>7.1.1.Final</version>
        <scope>compile</scope>
        <optional>true</optional>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.jboss.spec.javax.ejb/jboss-ejb-api_3.2_spec -->
    <dependency>
        <groupId>org.jboss.spec.javax.ejb</groupId>
        <artifactId>jboss-ejb-api_3.2_spec</artifactId>
        <version>1.0.2.Final</version>
        <scope>provided</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/com.google.cloud/google-cloud-translate -->
    <dependency>
        <groupId>com.google.cloud</groupId>
        <artifactId>google-cloud-translate</artifactId>
        <version>1.79.0</version>
    </dependency>
    <dependency>
        <!-- jsoup HTML parser library @ https://jsoup.org/ -->
        <groupId>org.jsoup</groupId>
        <artifactId>jsoup</artifactId>
        <version>1.11.3</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.8.1</version>
    </dependency>
</dependencies>

<build>
    <finalName>home.digest</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven 
            defaults (may be moved to parent pom) -->
        <plugins>
            <plugin>
                <artifactId>maven-clean-plugin</artifactId>
                <version>3.1.0</version>
            </plugin>
            <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.0.2</version>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
            </plugin>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.1</version>
            </plugin>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.2</version>
            </plugin>
            <plugin>
                <artifactId>maven-install-plugin</artifactId>
                <version>2.5.2</version>
            </plugin>
            <plugin>
                <artifactId>maven-deploy-plugin</artifactId>
                <version>2.8.2</version>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

What might be the reason?

Alex Mi
  • 1,409
  • 2
  • 21
  • 35
  • Besides the outputscript, I don't see anything jsf related here, and certainly not PrimeFaces. [mcve] please – Kukeltje Jul 25 '19 at 08:17
  • Why not use the PFE Clipboard component which has events already and does it the JSF way? https://www.primefaces.org/showcase-ext/sections/clipboard/basicUsage.jsf – Melloware Jul 25 '19 at 18:54
  • @Kukeltje I created a minimal example yesterday, and it functions. So the problem should be in my real example. I am still investigating. Thank you! – Alex Mi Jul 26 '19 at 04:21
  • @Melloware the PFE Clipboard component is not OK for me, beacuase I want to be able to copy separate words from a UI Component (output text): The PFE Clipboard copies the whole content of the UI Comonent ( outputText) and this is not OK for me. – Alex Mi Jul 26 '19 at 04:22
  • Understood. I didn't know your whole use case. – Melloware Jul 26 '19 at 10:51
  • @Kukeltje please help me! I added a minimal wokring example above. Thank you! – Alex Mi Jul 30 '19 at 04:20
  • The reason is here... https://stackoverflow.com/questions/20228634/javascript-jquery-event-listeners-do-not-work-after-jsf-component-is-updated-via – Kukeltje Jul 30 '19 at 07:00

1 Answers1

0

I was not able to identify the reason for the problem. However, I was able to work-around the problem as follows:

1.) My Java Script function:

function jsCopyAction(){

    var source = document.getElementById("badTransFormId:correspHomeEntityId");
    document.addEventListener('copy', (event) => {

    if ( event == null || event.srcElement == null ||  event.srcElement.id == null ){
        return;
    }

    selection = document.getSelection();
    event.clipboardData.setData('text/plain', selection.toString());
    event.preventDefault();
    document.getElementById("badTransFormId:jsCopyTextId").value=selection.toString();

    var jsfCommandButton = null;

    if ( event.srcElement.id == 'badTransFormId:correspHomeEntityId'){
        jsfCommandButton = document.getElementById("badTransFormId:jsCopyCorrespHomeEntityId");
    } else if ( event.srcElement.id == 'badTransFormId:translDescrDetailTxtId'){
        jsfCommandButton = document.getElementById("badTransFormId:jsCopyTranslDescrId");
    }
    if ( jsfCommandButton != null){
        jsfCommandButton.click();
    }
}); };

As you see, the event listener is attached to the document, but in the Java Script function I check the event source, and dependeing on it, I invoke different hidden buttons on the page, which, in turn, invoke different bean methods.

Alex Mi
  • 1,409
  • 2
  • 21
  • 35