Source

django-live / live / templates / live / chat.html

{% extends 'live/base.html' %}
{% load i18n %}

<!--
#
# Copyright 2010 Nicolás Echániz
# All rights reserved.
#
# This file is part of django-live.
#
# Django-Live is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Django-Live 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-->

{% block extra_head %}
{{ block.super }}
    <script src="http://{{ ORBITED_HOST }}:{{ ORBITED_PORT }}/static/Orbited.js"></script>
    <script src="http://{{ ORBITED_HOST }}:{{ ORBITED_PORT }}/static/protocols/stomp/stomp.js">
    </script>
    <script src="http://{{ ORBITED_HOST }}:{{ ORBITED_PORT }}/static/JSON.js"></script>
    <script>
      document.domain = document.domain
      Orbited.settings.port = "{{ ORBITED_PORT }}"
      Orbited.settings.hostname = "{{ORBITED_HOST }}"
      TCPSocket = Orbited.TCPSocket
    </script>

<script>

// ajax boilerplate from Orbited.js
var createXHR = function () {
    try { return new XMLHttpRequest(); } catch(e) {}
    try { return new ActiveXObject('MSXML3.XMLHTTP'); } catch(e) {}
    try { return new ActiveXObject('MSXML2.XMLHTTP.3.0'); } catch(e) {}
    try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {}
    try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}
    throw new Error('Could not find XMLHttpRequest or an alternative.');
};


var participant_link = function (nickname, user_type){
    if (channel_name.indexOf("..")>=0) var is_private = true
    else var is_private = false
    if (nickname!=current_nickname && !is_private){
        return "<li class='participant "+ user_type +"' id='"+ nickname +"'><a onClick='invite(this.text);' href='{% url one_on_one role='host' channel_name=channel_name %}.."+ current_nickname +".."+ nickname +"' target='_blank'>"+ nickname +"</a></li>"
    }
    // this is myself, so we don't link
    else{
        return "<li class='participant myself "+ user_type +"' id='"+ nickname +"'>"+ nickname +"</li>"   
    }
}

Shell = function(output, participants_list){
    var self = this
    self.output = output
    self.participants_list = participants_list
    self.participants = []

    self.rename_participant = function (nickname, new_nickname){
        for(var i = 0; i < self.participants.length; i++){
            if (self.participants[i][0] == nickname){
                self.participants[i][0] = new_nickname
            }
        }
    }

    self.remove_participant = function (nickname){
        var temp = []
        for(var i = 0; i < self.participants.length; i++){
            if (self.participants[i][0] == nickname) continue
            else temp.push(self.participants[i])
        }
        self.participants = temp                           
    }

    self.refresh_participants_list = function (){
        self.participants_list.innerHTML = ''
        for (var i in self.participants){
            self.participants_list.innerHTML += participant_link(self.participants[i][0], self.participants[i][1])
        }
    }

    self.add_participant = function(nickname, user_type){
        self.participants.push([nickname, user_type])
        self.participants = self.participants.sort()
    }

    self.add_participants = function(participants){
        for (i in participants){
            participant = participants[i]
            self.add_participant(participant[0], participant[1])
        }
    }

    self.run_command = function(action, payload, nickname){
        if (action == 'join'){
            var user_type = payload
            // update the participants list
            self.add_participant(nickname, user_type)
            self.refresh_participants_list()
            if (nickname != current_nickname){
                self.print(nickname +' {% trans "has joined this channel." %}')
            }
        }

        else if (action == 'say'){
            self.print(payload, nickname)
        }

        else if (action == 'invite'){
            invited = payload
            if (current_nickname == invited){
                self.safe_print(nickname +" <a href='{% url one_on_one role='guest' channel_name=channel_name %}.."+ nickname +".."+ current_nickname +"' target='_blank'>{% trans 'has invited you to chat'%}</a>")
            }
        }

        else if (action == 'rename'){
            new_nickname = payload
            self.rename_participant(nickname, new_nickname)
            self.participants = self.participants.sort()
            self.refresh_participants_list()
            if (nickname != new_nickname){
                self.print(nickname +' {% trans "is now known as" %} '+ new_nickname +".")
            }
        }

        else if (action == 'failed_rename'){
        // when a user tries to rename to an invalid nickname
        // the server will change the action to 'failed_rename'
            new_nickname = payload
            if (nickname == previous_nickname){
                nickname_input = document.getElementById('nickname')
                nickname_input.value = nickname         
                current_nickname = nickname
                self.print('{% trans "You cannot change name to:" %} '+ new_nickname)
            }
            else {
                self.print(nickname +' {% trans "tried to rename to" %} '+ new_nickname +".")
            }
        }

        else if (action == 'leave'){
            if (nickname == current_nickname){
                container = document.getElementById("chat_container")
                container.innerHTML = '<p>{% trans "You have been disconnected" %}</p>'
                stomp.reset()
            }
            else {
                self.remove_participant(nickname)
                self.refresh_participants_list()
                self.print(nickname +' {% trans "has left this channel." %}')
            }
        }
    }

    self.print = function(s, u) {
        var s = self.format(s)
        if (!u) {
            self.output.innerHTML +=  "<span class='message channel_message'>&rarr; " + s + "</span><br>"
        }
        else {
            self.output.innerHTML += "<span class='sender'>"+ u +"</span>"+
                "<span class='message user_message'>&rarr; " + s + "</span><br>"
        }
        if (chat_scroll){
            self.output.scrollTop = self.output.scrollHeight
        }
    }

    self.safe_print = function(s) {
        self.output.innerHTML +=  "<span class='message channel_message'>&rarr; " + s + "</span><br>"
        if (chat_scroll){
            self.output.scrollTop = self.output.scrollHeight
        }
    }

    self.format = function(expr)
    {
        var s = prettyprint(expr)
        s = htmlescape(s)
        return s
    }

    var htmlescape = function(s) {
        var s = s.replace("&", "&amp;", "g")
        s = s.replace("<", "&lt;", "g")
        s = s.replace(">", "&gt;", "g")
        s = s.replace(" ", "&nbsp;", "g")
        s = s.replace("\n", "<br>", "g")
        return s
    }

    var prettyprint = function(s) {
        var q = "("
        if(typeof(s) == "string")
            return s
        for (var i=0; i<s.length; i++) {
            if (typeof(s[i]) != "object")
                q += s[i]
            else
                q += prettyprint(s[i])
            if (i < s.length -1)
                q += " "
        }
        q += ")"
        return q
    }
}

</script>

<script>

var current_nickname = '{{ nickname }}'
var channel_slug = '{{ channel_slug }}'
var channel_name = '{{ channel_name }}'

var just_entered = true
var previous_nickname = ''
var chat_scroll = true

var manager_channel = "{{ manager_channel }}"
var stomp_port = {{ STOMP_PORT }}

// stomp broker parameters
var send_headers = {exchange:''}
var subscribe_destination = channel_slug
var send_headers = {exchange:''}
var subscribe_headers = {exchange:''};

var change_nickname = function(new_nickname){
    current_nickname = new_nickname
    document.getElementById('input').focus()
    channel_action('rename', new_nickname, previous_nickname)
}

var invite = function(nickname){
    channel_action('invite', nickname, current_nickname)
}

var leave = function() {
    var xhr = createXHR()
    xhr.open('GET', '{% url kickme_from_channel channel_slug=channel_slug %}', false)
    xhr.send()
//    stomp.reset()
}

var channel_action = function (action, payload, nickname){
    if (!nickname) json_msg = JSON.stringify({'message': {'action': action, 'payload': payload}})
    else json_msg = JSON.stringify({'message': {'action': action, 'payload': payload},
                                    'nickname': nickname,})
    stomp.send(json_msg, channel_slug, send_headers)
}

var user_message = function (msg){
    if (!msg) msg = document.getElementById('input').value
    document.getElementById('input').value = ""
    channel_action('say', msg, current_nickname)
}
      
var manager_message = function(nickname, channel, msg){
    json_msg = JSON.stringify({'nickname': nickname, 'channel': channel})
    stomp.send(json_msg, manager_channel, send_headers)
}


onload = function() {
    var output = document.getElementById('output')
    var participants_list = document.getElementById('participants')
    var shell = new Shell(output, participants_list)

    // set up stomp client.
    stomp = new STOMPClient()
    stomp.onopen = function() {
    };

    stomp.onerror = function(error) {
        alert("onerror: " + error)
    };
    stomp.onerrorframe = function(frame) {
        alert("onerrorframe: " + frame.body)
    };
    stomp.onconnectedframe = function() {
        shell.print('{% trans "Connected as"%} ' + current_nickname)
        stomp.subscribe(subscribe_destination, subscribe_headers)
        manager_message(current_nickname, channel_slug)
        // TODO: get initial participants for channel from django through an ajax view
        channel_action('join', '', current_nickname)
        var xhr = createXHR()
        xhr.open('GET', '{% url channel_participants channel_slug=channel_slug %}', true)
        xhr.onreadystatechange = function() {
            if (xhr.readyState==4){
                participants = JSON.parse(xhr.responseText)
                shell.add_participants(participants)
                shell.refresh_participants_list()
            }
        }
        xhr.send(null)
    };

    stomp.onmessageframe = function(frame) {
        var parsed_frame = JSON.parse(frame.body)
        action = parsed_frame.message.action
        if (action){
            payload = parsed_frame.message.payload
            nickname = parsed_frame.nickname
            shell.run_command(action, payload, nickname)
        }
        else{
            shell.print(parsed_frame.message, parsed_frame.nickname);
        }

    };

    window.onunload = function(){leave()}

    stomp.onclose = function(code) {
        shell.print(' {% trans "Transport closed (code:" %} ' + code + ')')
        stomp.reset()
    }

    stomp.connect(document.domain, stomp_port, '{{ username }}', '')
    document.getElementById('input').value = "{% trans 'type your message here and press ENTER to send' %}"
    document.getElementById('input').focus()
}

</script>

{% endblock %}


{% block content %}
<div id="chat_container">
  <div id="channel_name">
    {% if not '..' in channel_name %}{{ channel_name }}
    {% else %} {% trans "Private chat" %}
    {% endif %}
  </div>
    <div id="change_name">
    {% trans "your name" %}: <input id="nickname" value="{{ nickname  }}" onKeyPress="previous_nickname = current_nickname; if(event.keyCode==13) change_nickname(this.value);"/>
    </div>

    <div id="wrapper">
      <div id="output"></div> 
      <div id="participants_box">
        <ul id="participants">
        </ul>
      </div>
      <div id="input_box">
        <input id="input" value="" size="40" 
         onKeyPress="if (just_entered){ this.value=''; just_entered = false}; if(event.keyCode==13) user_message();"/>
    <label for="chat_scroll">{% trans "auto-scroll" %}</label>
        <input id="chat_scroll" type="checkbox" checked="checked"
         onChange="if (chat_scroll) chat_scroll = false; else chat_scroll = true;"/>

      </div>
    </div>

</div>
{% endblock %}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.