add icons and chatbox
|
@ -19,17 +19,11 @@ class Message(models.Model):
|
||||||
body = models.TextField(verbose_name=_('body of comment'), max_length=8192)
|
body = models.TextField(verbose_name=_('body of comment'), max_length=8192)
|
||||||
|
|
||||||
def notify_ws_clients(self):
|
def notify_ws_clients(self):
|
||||||
# inform client that there is a new message
|
|
||||||
notification = {
|
notification = {
|
||||||
'type': 'recieve_group_message',
|
'type': 'recieve_group_message',
|
||||||
'message': '{}'.format(self.id)
|
'message': '{}'.format(self.id)
|
||||||
}
|
}
|
||||||
channel_layer = get_channel_layer()
|
channel_layer = get_channel_layer()
|
||||||
# print("user.id {}".format(self.user.id))
|
|
||||||
# print("user.id {}".format(self.recipient.id))
|
|
||||||
|
|
||||||
async_to_sync(channel_layer.group_send)("{}".format(self.user.id), notification)
|
|
||||||
async_to_sync(channel_layer.group_send)("{}".format(self.recipient.id), notification)
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
new_message = self.id
|
new_message = self.id
|
||||||
|
|
|
@ -1,11 +1,31 @@
|
||||||
from django.shortcuts import render
|
from django.http import HttpResponseRedirect
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django.views.generic import ListView
|
from django.views.generic import ListView
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
|
|
||||||
from .models import Message
|
from .models import Message
|
||||||
|
|
||||||
|
|
||||||
class ChatView(ListView):
|
class ChatView(ListView):
|
||||||
model = Message
|
model = Message
|
||||||
title = _('Chat Box')
|
context_object_name = 'messages'
|
||||||
template_name = 'chat/chat.html'
|
template_name = 'chat/chat.html'
|
||||||
|
title = _('Chat Box')
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(ChatView, self).get_context_data(**kwargs)
|
||||||
|
context['title'] = self.title
|
||||||
|
return context
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def send(request):
|
||||||
|
new_message = Message(body=request.POST['message'],
|
||||||
|
author=request.profile,
|
||||||
|
time=timezone.now())
|
||||||
|
new_message.save()
|
||||||
|
return HttpResponseRedirect(reverse('chat'))
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from chat_box.views import ChatView
|
from chat_box.views import ChatView, send
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls import include, url
|
from django.conf.urls import include, url
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
@ -367,7 +367,10 @@ urlpatterns = [
|
||||||
|
|
||||||
url(r'^custom_checker_sample/', about.custom_checker_sample, name='custom_checker_sample'),
|
url(r'^custom_checker_sample/', about.custom_checker_sample, name='custom_checker_sample'),
|
||||||
|
|
||||||
url(r'^chat/', ChatView.as_view(), name='chat'),
|
url(r'^chat/', include([
|
||||||
|
url(r'^$', ChatView.as_view(), name='chat'),
|
||||||
|
url(r'send$', send, name='send_message')
|
||||||
|
])),
|
||||||
]
|
]
|
||||||
|
|
||||||
favicon_paths = ['apple-touch-icon-180x180.png', 'apple-touch-icon-114x114.png', 'android-chrome-72x72.png',
|
favicon_paths = ['apple-touch-icon-180x180.png', 'apple-touch-icon-114x114.png', 'android-chrome-72x72.png',
|
||||||
|
|
58
resources/chatbox.scss
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
#chat-log {
|
||||||
|
padding: 0;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 4px;
|
||||||
|
height: 20em;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-log li {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.4em;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-submit {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-pic {
|
||||||
|
height: 2.6em;
|
||||||
|
width: 2.6em;
|
||||||
|
border-radius: 0.3em;
|
||||||
|
margin-top: 0.1em;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body-message {
|
||||||
|
padding-left: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-time {
|
||||||
|
margin-bottom: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
margin-left: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
.message {
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 797 B After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 14 KiB |
BIN
resources/icons/apple-touch-icon-114x114-precomposed.png
Normal file
After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 14 KiB |
BIN
resources/icons/apple-touch-icon-120x120-precomposed.png
Normal file
After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 15 KiB |
BIN
resources/icons/apple-touch-icon-144x144-precomposed.png
Normal file
After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 21 KiB |
BIN
resources/icons/apple-touch-icon-152x152-precomposed.png
Normal file
After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 23 KiB |
BIN
resources/icons/apple-touch-icon-180x180-precomposed.png
Normal file
After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 31 KiB |
BIN
resources/icons/apple-touch-icon-57x57-precomposed.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 4.4 KiB |
BIN
resources/icons/apple-touch-icon-60x60-precomposed.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 4.8 KiB |
BIN
resources/icons/apple-touch-icon-72x72-precomposed.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 6.4 KiB |
BIN
resources/icons/apple-touch-icon-76x76-precomposed.png
Normal file
After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 7 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 28 KiB |
|
@ -5,8 +5,7 @@
|
||||||
<square70x70logo src="/mstile-70x70.png"/>
|
<square70x70logo src="/mstile-70x70.png"/>
|
||||||
<square150x150logo src="/mstile-150x150.png"/>
|
<square150x150logo src="/mstile-150x150.png"/>
|
||||||
<square310x310logo src="/mstile-310x310.png"/>
|
<square310x310logo src="/mstile-310x310.png"/>
|
||||||
<wide310x150logo src="/mstile-310x150.png"/>
|
<TileColor>#da532c</TileColor>
|
||||||
<TileColor>#00aba9</TileColor>
|
|
||||||
</tile>
|
</tile>
|
||||||
</msapplication>
|
</msapplication>
|
||||||
</browserconfig>
|
</browserconfig>
|
||||||
|
|
Before Width: | Height: | Size: 830 B After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "DMOJ",
|
"name": "LQDOJ",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "\/android-chrome-36x36.png",
|
"src": "\/android-chrome-36x36.png",
|
||||||
|
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 14 KiB |
|
@ -2,18 +2,57 @@
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
width="960.000000pt" height="960.000000pt" viewBox="0 0 960.000000 960.000000"
|
width="223.000000pt" height="223.000000pt" viewBox="0 0 223.000000 223.000000"
|
||||||
preserveAspectRatio="xMidYMid meet">
|
preserveAspectRatio="xMidYMid meet">
|
||||||
<metadata>
|
<metadata>
|
||||||
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
||||||
</metadata>
|
</metadata>
|
||||||
<g transform="translate(0.000000,960.000000) scale(0.100000,-0.100000)"
|
<g transform="translate(0.000000,223.000000) scale(0.100000,-0.100000)"
|
||||||
fill="#000000" stroke="none">
|
fill="#000000" stroke="none">
|
||||||
<path d="M4430 9579 c-1066 -77 -2049 -478 -2810 -1146 -900 -791 -1457 -1877
|
<path d="M1101 2183 c0 -7 -1 -15 -1 -18 0 -3 -7 -19 -15 -35 -8 -16 -15 -32
|
||||||
-1597 -3115 -25 -218 -25 -828 0 -1048 126 -1122 585 -2089 1362 -2865 773
|
-15 -35 0 -3 0 -6 -1 -7 0 -2 -2 -10 -4 -18 -2 -8 -18 -67 -35 -130 -17 -63
|
||||||
-774 1763 -1251 2865 -1381 183 -21 681 -30 891 -15 951 68 1836 397 2584 961
|
-34 -125 -37 -137 -4 -18 -9 -20 -30 -12 -18 7 -22 6 -17 -4 5 -8 2 -8 -9 2
|
||||||
181 137 295 236 474 413 538 531 923 1151 1161 1867 129 386 200 739 231 1150
|
-13 11 -17 11 -17 1 0 -8 -3 -10 -7 -7 -3 4 -12 2 -20 -4 -7 -6 -13 -8 -13 -4
|
||||||
15 201 6 734 -16 929 -126 1130 -590 2116 -1355 2881 -763 763 -1738 1226
|
0 4 -7 2 -15 -5 -8 -7 -15 -10 -15 -7 0 3 -15 1 -32 -4 -18 -6 -42 -12 -53
|
||||||
-2855 1355 -166 20 -744 28 -935 14z"/>
|
-14 -11 -3 -32 -7 -47 -11 -16 -3 -28 -10 -28 -15 0 -5 -3 -8 -7 -8 -23 4 -43
|
||||||
|
-2 -38 -11 3 -5 1 -10 -5 -10 -6 0 -8 -5 -4 -12 5 -7 2 -9 -7 -6 -11 4 -14 -5
|
||||||
|
-15 -36 -4 -92 -9 -116 -26 -122 -10 -3 -18 -10 -18 -16 0 -6 -3 -8 -6 -5 -4
|
||||||
|
4 -19 -2 -33 -12 -22 -15 -46 -27 -71 -36 -32 -11 -86 -40 -97 -51 -8 -8 -19
|
||||||
|
-12 -24 -9 -5 4 -9 -6 -10 -22 -1 -38 -7 -126 -12 -193 -3 -30 -8 -107 -12
|
||||||
|
-170 -11 -168 -14 -181 -46 -175 -10 2 -19 -1 -19 -7 0 -6 -11 -8 -25 -6 -13
|
||||||
|
3 -24 2 -23 -1 2 -20 -3 -31 -12 -26 -6 4 -7 -1 -3 -11 4 -12 3 -15 -5 -10 -8
|
||||||
|
5 -10 2 -6 -9 4 -9 13 -14 20 -11 7 3 16 0 20 -6 4 -7 3 -8 -4 -4 -8 5 -12 0
|
||||||
|
-12 -13 0 -12 5 -21 12 -21 9 0 9 -3 0 -12 -7 -7 -12 -17 -12 -22 0 -6 5 -4
|
||||||
|
11 4 8 12 10 9 6 -13 -3 -18 0 -30 8 -34 8 -2 16 -12 19 -20 6 -14 4 -14 -10
|
||||||
|
-2 -16 13 -16 12 -4 -11 7 -14 18 -28 24 -32 8 -6 6 -11 -4 -18 -9 -6 -10 -10
|
||||||
|
-3 -10 6 0 13 -10 15 -22 2 -15 13 -24 35 -30 23 -6 37 -19 52 -51 33 -67 199
|
||||||
|
-247 228 -247 7 0 16 -6 20 -13 4 -7 26 -21 48 -32 22 -11 42 -22 45 -25 7 -7
|
||||||
|
53 -27 64 -28 5 0 12 -5 15 -11 4 -5 19 -12 35 -15 15 -3 34 -10 41 -16 10 -8
|
||||||
|
14 -7 18 2 4 10 6 10 6 1 1 -7 6 -13 12 -13 5 0 7 6 3 12 -5 9 -2 9 9 -1 9 -7
|
||||||
|
17 -10 17 -5 0 5 5 2 10 -6 7 -11 10 -11 10 -2 0 7 5 10 10 7 6 -4 8 -11 5
|
||||||
|
-16 -4 -5 -1 -9 4 -9 6 0 11 7 11 16 0 8 4 13 10 9 5 -3 7 -13 4 -23 -4 -10
|
||||||
|
-3 -13 3 -6 8 11 52 12 69 1 5 -3 16 -2 24 3 8 5 22 5 32 -1 12 -6 18 -6 18 1
|
||||||
|
0 5 5 10 11 10 5 0 7 -6 3 -12 -5 -9 -2 -9 9 1 13 10 17 10 17 1 0 -9 4 -9 17
|
||||||
|
1 15 12 16 12 8 -1 -7 -13 -6 -13 7 -2 13 10 17 10 21 0 4 -10 6 -10 6 0 1 6
|
||||||
|
9 12 19 12 10 0 24 6 31 12 11 11 12 10 6 -2 -8 -13 -7 -13 8 -1 9 7 17 11 17
|
||||||
|
7 0 -3 16 0 35 8 19 8 35 12 35 9 0 -3 7 0 15 7 8 7 15 10 15 6 0 -3 32 10 70
|
||||||
|
30 39 21 70 41 70 45 0 4 9 11 21 14 24 8 52 29 82 62 11 12 25 19 31 16 6 -3
|
||||||
|
8 -3 4 2 -4 4 9 22 28 40 18 18 34 37 34 44 0 6 4 11 10 11 5 0 24 25 41 55
|
||||||
|
17 30 35 55 41 55 5 0 7 4 4 9 -3 5 1 14 9 21 8 7 12 16 9 21 -3 5 -2 9 3 8
|
||||||
|
24 -4 43 2 37 13 -4 7 -3 8 5 4 12 -8 44 18 34 28 -4 3 -1 6 5 6 6 0 9 7 6 15
|
||||||
|
-4 8 1 17 10 21 14 5 14 9 4 22 -7 9 -8 13 -2 9 12 -7 38 39 29 53 -3 4 5 10
|
||||||
|
18 14 18 5 19 8 7 15 -12 9 -12 11 3 17 9 3 14 10 11 15 -3 5 0 9 5 9 6 0 11
|
||||||
|
6 11 14 0 8 6 17 13 19 7 4 6 6 -4 6 -9 1 -20 8 -23 17 -4 9 -13 14 -21 10 -8
|
||||||
|
-3 -15 -1 -15 4 0 6 -6 10 -14 10 -17 0 -41 28 -41 49 0 9 -4 22 -8 29 -5 6
|
||||||
|
-4 12 1 12 5 0 6 17 2 40 -5 25 -4 40 3 40 6 0 6 5 0 13 -5 6 -9 56 -9 109 1
|
||||||
|
54 -3 98 -7 98 -5 0 -5 5 -1 12 4 7 6 35 5 62 -2 28 -4 64 -5 80 -1 16 -7 31
|
||||||
|
-14 34 -7 2 -10 8 -7 13 4 5 -1 6 -10 3 -8 -4 -25 0 -38 8 -12 8 -41 20 -64
|
||||||
|
28 -24 7 -43 17 -43 22 0 4 -3 8 -7 7 -16 -2 -53 14 -53 22 0 5 -3 8 -7 7 -10
|
||||||
|
-4 -73 23 -74 31 -2 9 -7 42 -14 86 -3 22 -8 51 -11 65 -4 14 -7 44 -8 67 0
|
||||||
|
22 -4 39 -8 36 -5 -2 -8 0 -8 6 0 10 -93 57 -130 65 -3 1 -15 7 -27 14 -13 7
|
||||||
|
-23 9 -23 5 0 -4 -4 -3 -8 2 -11 16 -102 56 -113 50 -5 -4 -12 1 -15 10 -5 13
|
||||||
|
-9 14 -14 4 -7 -10 -11 -9 -22 2 -8 8 -15 17 -16 22 -1 4 -3 9 -3 12 -1 3 -3
|
||||||
|
10 -4 15 -1 6 -4 12 -5 15 -1 3 -3 8 -4 13 -18 83 -32 132 -37 132 -4 0 -10 8
|
||||||
|
-12 18 -3 9 -5 11 -6 5z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 933 B After Width: | Height: | Size: 3.8 KiB |
|
@ -12,3 +12,4 @@
|
||||||
@import "submission";
|
@import "submission";
|
||||||
@import "contest";
|
@import "contest";
|
||||||
@import "misc";
|
@import "misc";
|
||||||
|
@import "chatbox";
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
{% if request.user.is_authenticated %}
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block js_media %}
|
{% block js_media %}
|
||||||
|
@ -9,34 +10,127 @@
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(function() {
|
$(function() {
|
||||||
chatSocket.onmessage = function(e) {
|
chatSocket.onmessage = function(e) {
|
||||||
var data = JSON.parse(e.data);
|
let data = JSON.parse(e.data)
|
||||||
var message = data['message'];
|
data = data['message']
|
||||||
$('#chat-log').append(message + '\n');
|
console.log(data)
|
||||||
|
loadMessage(data['content'],
|
||||||
|
data['sender'],
|
||||||
|
data['time'],
|
||||||
|
data['image'])
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function loadMessage(content, user, time, image) {
|
||||||
|
li = `<li>
|
||||||
|
<img src="${image}" class="profile-pic">
|
||||||
|
<div class="body-message">
|
||||||
|
<div class="user-time">
|
||||||
|
<a href="#" class="user">
|
||||||
|
${user}
|
||||||
|
</a>
|
||||||
|
<span class="time">${time}</span>
|
||||||
|
</div>
|
||||||
|
<span class="message">
|
||||||
|
<span>${content}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="clear"></div>
|
||||||
|
</li>`
|
||||||
|
ul = $('#chat-log')
|
||||||
|
ul.append(li)
|
||||||
|
$('#chat-log').scrollTop($('#chat-log')[0].scrollHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$("#chat-submit").click(function() {
|
||||||
|
if ($("#chat-input").val().trim()) {
|
||||||
|
let content = $('#chat-input').val().trim();
|
||||||
|
let img = '{{ gravatar(request.user, 32) }}'
|
||||||
|
|
||||||
|
message = {
|
||||||
|
'content': content,
|
||||||
|
'image': img,
|
||||||
|
'time': calcTime(6), // HCM City
|
||||||
|
'sender': '{{ request.user }}'
|
||||||
|
}
|
||||||
|
|
||||||
|
chatSocket.send(JSON.stringify({
|
||||||
|
'message': message,
|
||||||
|
}))
|
||||||
|
// $.post('/chat/send', message)
|
||||||
|
|
||||||
|
$('#chat-input').val('').focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function calcTime(offset) {
|
||||||
|
utc = new Date().getTime()
|
||||||
|
nd = new Date(utc + (3600000*offset));
|
||||||
|
return nd.toLocaleString();
|
||||||
|
}
|
||||||
|
|
||||||
chatSocket.onclose = function(e) {
|
chatSocket.onclose = function(e) {
|
||||||
console.error('Chat socket closed unexpectedly');
|
console.error('Chat socket closed unexpectedly');
|
||||||
};
|
};
|
||||||
$('#chat-message-input').focus();
|
|
||||||
$('#chat-message-input').keyup(function(e) {
|
$("#chat-log").change(function() {
|
||||||
if (e.keyCode === 13) { // enter, return
|
$('#chat-log').scrollTop($('#chat-log')[0].scrollHeight);
|
||||||
$('#chat-message-submit').click();
|
});
|
||||||
|
|
||||||
|
$('#chat-input').focus();
|
||||||
|
|
||||||
|
$('#chat-input').keydown(function(e) {
|
||||||
|
if (e.keyCode === 13) {
|
||||||
|
if (e.ctrlKey || e.shiftKey) {
|
||||||
|
var val = this.value;
|
||||||
|
if (typeof this.selectionStart == "number" && typeof this.selectionEnd == "number") {
|
||||||
|
var start = this.selectionStart;
|
||||||
|
this.value = val.slice(0, start) + "\n" + val.slice(this.selectionEnd);
|
||||||
|
this.selectionStart = this.selectionEnd = start + 1;
|
||||||
|
} else if (document.selection && document.selection.createRange) {
|
||||||
|
this.focus();
|
||||||
|
var range = document.selection.createRange();
|
||||||
|
range.text = "\r\n";
|
||||||
|
range.collapse(false);
|
||||||
|
range.select();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
e.preventDefault();
|
||||||
|
$('#chat-submit').click();
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
});
|
});
|
||||||
$("#chat-message-submit").click(function() {
|
|
||||||
var message = "{{ request.user }}: " + $('input#chat-message-input').val();
|
|
||||||
chatSocket.send(JSON.stringify({
|
|
||||||
'message': message,
|
|
||||||
}));
|
|
||||||
$('input#chat-message-input').val('');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock js_media %}
|
{% endblock js_media %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div>
|
{% csrf_token %}
|
||||||
<textarea disabled id="chat-log" rows="20" style="width: 100%"></textarea><br/>
|
<div id="chat-area">
|
||||||
<input id="chat-message-input" type="text" style="width: 100%"/><br/>
|
<ul id="chat-log">
|
||||||
|
<li>
|
||||||
|
<img src="https://via.placeholder.com/150" class="profile-pic">
|
||||||
|
<div class="body-message">
|
||||||
|
<div class="user-time">
|
||||||
|
<a href="#" class="user">
|
||||||
|
cuom1999
|
||||||
|
</a>
|
||||||
|
<span class="time">12:00:00</span>
|
||||||
</div>
|
</div>
|
||||||
<button id="chat-message-submit" style="margin-top: 1em"> Send </button>
|
<span class="message">
|
||||||
|
<span>It’s possible that a request can come in via POST with an empty POST dictionary – if, say, a form is requested via the POST HTTP method but does not include form data. Therefore, you shouldn’t use if request.POST to check for use of the POST method; instead, use if request.method == "POST" (see HttpRequest.method).</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="clear"></div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{{_('Your message')}}
|
||||||
|
|
||||||
|
<textarea rows="6" id="chat-input"></textarea>
|
||||||
|
</div>
|
||||||
|
<button id="chat-submit"> Send </button>
|
||||||
{% endblock body %}
|
{% endblock body %}
|
||||||
|
{% endif %}
|
||||||
|
|