1

FireFox says my method, doSend, is not defined, but it is.
And Chrome says nothing about the websockets...

Here's my code:

<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:p="http://primefaces.org/ui"
  xmlns:c="http://java.sun.com/jsp/jstl/core"
  xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<script type="text/javascript">

    var image;
    var output;
    function init() {
        console.log('CONNECTED to websockets!');
        output = document.getElementById('output');
        testWebSocket();
    }

    //connects websocket to KwetterWebsocketBean
    function testWebSocket() {
        websocket = new WebSocket(wsUri);
        websocket.onopen = function(evt) {
            onOpen(evt);
        };
        websocket.onclose = function(evt) {
            onClose(evt);
        };
        websocket.onmessage = function(evt) {
            onMessage(evt);
        };
        websocket.onerror = function(evt) {
            onError(evt);
        };
    }

    //define event handlers
    function onOpen(evt) {
    }            
    function onWindowClose(evt){
        websocket.close();
    }
    function onClose(evt) {
    }
    function onMessage(evt) {
        //convert json to javascript object
        var message = JSON.parse(evt.data);
        writeToScreen('<span style="color: green;">New tweet by ' + message.username + ': ' + message.text + '</span>');
        console.log(message.text + ' : ' + message.username);
        //write message.text to screen
    }

    function onError(event) {
    }

    function doSend(message) {
        console.log(message);
        websocket.send(message);
    }

    //appends text to #output
    function writeToScreen(text) {
        var pre = document.createElement('p');
        pre.style.wordWrap = 'break-word';
        pre.innerHTML = text;
        output.appendChild(pre);
    }

    //invoke init() on load
    window.addEventListener('load', init, false);

    //enter key clicks #sendButton
    function keyPressed(event){
        if(event.keyCode == 13){
            document.getElementById('sendButton').click();
            document.getElementById('textforws').value='';
        }
    }
</script>
</h:head>
<h:body>
    <ui:composition template="./aTemplate.xhtml">
        <ui:define name="S1">
            <h1>What's happening?</h1>
            <h:form id="formNewestTweet">
                <p:inputText maxlength="140" value="aMessage"/>
                <p:commandButton value="Post Tweet" id="sendButton"                                     
                                 onclick='doSend("aMessage");'/>
            </h:form>
            <div id="output"/>
        </ui:define>
    </ui:composition>
</h:body>
</html>

How should I fix this?

Teysz
  • 741
  • 9
  • 33
  • In future questions, please don't overgeneralize Facelets as XHTML by using `[xhtml]` tag instead of `[facelets]`. Naive HTML/JS developers who overgeneralize XHTML as overhyped HTML don't know *real* XHTML as such. See also http://stackoverflow.com/a/3869174/157882 – BalusC Jul 02 '13 at 12:52
  • Added the script between and . It still does NOT work. – Teysz Jul 02 '13 at 13:22
  • Try **reading** my answer. I said nowhere to put `` and `` around the script. Or if you were referring to someone else's answer, please comment to them instead of to me. – BalusC Jul 02 '13 at 13:23
  • @BalusC The comment was addressed to the other answer, I'm trying yours now. – Teysz Jul 02 '13 at 13:29
  • In the future, post such a comment in other's answer directly, instead of responding to my comment. – BalusC Jul 02 '13 at 13:30

2 Answers2

3

In Facelets, Any content outside <ui:composition> of a template client is ignored. Basically, you need to put the content inside <ui:define> of <ui:composition>.

There are in your particular case several ways to fix this wrong code:

  1. Put it straight in <ui:define>.

    <ui:composition template="./aTemplate.xhtml">
        <ui:define name="S1">
            <script type="text/javascript">
                ...
            </script>
            ...
        </ui:define>
    </ui:composition>
    
  2. The same way, but then using <h:outputScript target="head"> instead of <script>. It'll automatically end up in HTML head (provided that you've a <h:head> instead of <head> in your master template aTemplate.xhtml):

    <ui:composition template="./aTemplate.xhtml">
        <ui:define name="S1">
            <h:outputScript target="head">
                ...
            </h:outputScript>
            ...
        </ui:define>
    </ui:composition>
    
  3. Add a new <ui:insert name="head"> to the bottom of <h:head> of your master template aTemplate.xhtml and declare in there instead:

    <ui:composition template="./aTemplate.xhtml">
        <ui:define name="head">
            <script type="text/javascript">
                ...
            </script>
        </ui:define>
    
        <ui:define name="S1">
            ...
        </ui:define>
    </ui:composition>
    

See also:


Unrelated to the concrete problem, I recommend to put master template files in /WEB-INF folder and use it like so

<ui:composition template="/WEB-INF/aTemplate.xhtml">

otherwise endusers are able to open it individually and see raw (unparsed) source code.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
0

Try to declare methods between

  <head></head>

tag

Because all the script contained in head tag was rendered before the body tag

And the events inside body.

WinHtaikAung
  • 414
  • 2
  • 11