Browse Source

add chat window

romanmatiasko 10 years ago
parent
commit
ab5610f339

+ 35 - 0
public/images/chat.svg

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+
+<!-- The icon can be used freely in both personal and commercial projects with no attribution required, but always appreciated. 
+You may NOT sub-license, resell, rent, redistribute or otherwise transfer the icon without express written permission from iconmonstr.com -->
+
+
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+
+	 width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+
+<path id="speech-bubble-14-icon" fill="#299cad" d="M440.704,391.771C454.312,375.362,462,354.216,462,332.679c0-35.26-19.864-65.01-49.435-83.766
+
+	c4.186-13.053,6.395-26.594,6.395-40.27c0-90.207-87.645-155.312-184.479-155.312C137.037,53.331,50,118.929,50,208.644
+
+	c0,31.822,11.358,63.066,31.465,87.309c0.849,28.41-15.719,69.156-30.643,98.842c39.998-7.295,96.866-23.416,122.654-39.357
+
+	c15.134,3.717,29.826,6.027,44.007,7.1c17.877,50.588,80.211,89.32,160.944,69.494c17.455,10.789,55.943,21.699,83.016,26.639
+
+	C451.342,438.577,440.129,410.999,440.704,391.771z M172.431,318.04c-34.595,20.203-65.042,28.264-65.042,28.264
+
+	s10.299-27.762,14.588-59.699c-21.101-21.508-36.05-43.32-36.05-77.961c0-65.83,66.641-119.387,148.554-119.387
+
+	c81.912,0,148.554,53.557,148.554,119.387C383.034,276.784,304.718,353.12,172.431,318.04z M418.856,421.499
+
+	c0,0-19.577-5.182-41.82-18.172c-65.705,17.422-110.659-7.877-127.746-40.469c70.42-4.076,124.766-40.012,151.465-87.078
+
+	c19.564,14.066,31.901,34.5,31.901,57.207c0,22.273-9.612,36.297-23.179,50.127C412.234,403.649,418.856,421.499,418.856,421.499z"
+
+	/>
+
+</svg>
+

+ 58 - 3
public/javascripts/play.js

@@ -122,9 +122,6 @@ function movePiece(from, to, promotion, rcvd) {
       else if ($chess.insufficient_material())
       else if ($chess.insufficient_material())
         result = "Draw. (Insufficient Material)";
         result = "Draw. (Insufficient Material)";
       fs.text(result);
       fs.text(result);
-      
-      $('.resign').hide();
-      alert(result);
     }
     }
 
 
     /* Add all moves to the table */
     /* Add all moves to the table */
@@ -147,6 +144,11 @@ function movePiece(from, to, promotion, rcvd) {
         'move': move
         'move': move
       });
       });
     }
     }
+
+    if ($chess.game_over()) {
+      $('.resign').hide();
+      alert(result);
+    }
   }
   }
 }
 }
 
 
@@ -166,6 +168,8 @@ $(document).ready(function () {
       $('.chess_board.white').remove();
       $('.chess_board.white').remove();
       $('.chess_board.black').show();
       $('.chess_board.black').show();
     }
     }
+
+    $('#sendMessage').find('input').addClass($side === 'b' ? 'black' : 'white');
   });
   });
 
 
   $socket.on('move', function (data) {
   $socket.on('move', function (data) {
@@ -186,6 +190,24 @@ $(document).ready(function () {
     alert("This game already has two players. You have to create a new one.");
     alert("This game already has two players. You have to create a new one.");
     window.location = '/';
     window.location = '/';
   });
   });
+
+  $socket.on('receive-message', function (data) {
+    var chat = $('ul#chat');
+    var chat_node = $('ul#chat')[0];
+    var messageSnd = $("#messageSnd")[0];
+
+    chat.append('<li class="' + data.color + ' left" >' + data.message + '</li>');
+
+    if (chat.is(':visible') && chat_node.scrollHeight > 300) {
+      setTimeout(function() { chat_node.scrollTop = chat_node.scrollHeight; }, 50);
+    } else if (!chat.is(':visible') && !$('.new-message').is(':visible')) {
+      $('#bubble').before('<span class="new-message">You have a new message!</span>');
+    }
+
+    if ($('#sounds').is(':checked')) {
+      messageSnd.play();
+    }
+  });
 });
 });
 
 
 /* gameplay */
 /* gameplay */
@@ -238,4 +260,37 @@ $(document).ready(function () {
     alert('You resigned.');
     alert('You resigned.');
     window.location = '/';
     window.location = '/';
   });
   });
+
+  $('a.chat').click(function (e) {
+    $('#chat-wrapper').toggle();
+    $('.new-message').remove();
+    var chat_node = $('ul#chat')[0];
+    if (chat_node.scrollHeight > 300) {
+      setTimeout(function() { chat_node.scrollTop = chat_node.scrollHeight; }, 50);
+    }
+  });
+
+  $('#chat-wrapper .close').click(function (e) {
+    $('#chat-wrapper').hide();
+  });
+
+  $('#sendMessage').submit(function (e) {
+    e.preventDefault();
+    var input = $(this).find('input');
+    var message = input.val();
+    var color = $side === 'b' ? 'black' : 'white';
+
+    if (!/^\W*$/.test(message)) {
+      input.val('');
+      $('ul#chat').append('<li class="' + color + ' right" >' + message + '</li>');
+
+      var chat_node = $('ul#chat')[0];
+      if (chat_node.scrollHeight > 300) {
+        setTimeout(function() { chat_node.scrollTop = chat_node.scrollHeight; }, 50);
+      }
+
+      $socket.emit('send-message', { 'message': message, 'color': color });
+    }
+  });
+
 });
 });

BIN
public/sounds/message.mp3


+ 108 - 2
public/stylesheets/style.css

@@ -99,10 +99,22 @@ h3 {
 .last-target {
 .last-target {
   background: #77d1df !important; }
   background: #77d1df !important; }
 
 
-.about-in-play {
+.chat {
+  text-decoration: none;
+  color: #248a99;
   margin-right: 1em;
   margin-right: 1em;
   line-height: 50px;
   line-height: 50px;
-  float: right !important; }
+  float: right !important;
+  cursor: pointer;
+  font-weight: 600; }
+  .chat:hover {
+    color: #299cad; }
+    .chat:hover .new-message {
+      color: #d12521; }
+  .chat img {
+    vertical-align: middle; }
+  .chat .new-message {
+    color: #d12521; }
 
 
 .fork {
 .fork {
   float: left;
   float: left;
@@ -258,6 +270,100 @@ footer {
   margin: 0px 0px 5px 0px;
   margin: 0px 0px 5px 0px;
   float: left; }
   float: left; }
 
 
+/* Chat */
+#chat-wrapper {
+  display: none;
+  position: absolute;
+  width: 270px;
+  right: 10px;
+  top: 99px;
+  border: 4px solid #fff;
+  background: #e6e3e0; }
+  #chat-wrapper h4 {
+    font-family: 'Cherry Swash';
+    font-size: 1.225rem;
+    height: 3em;
+    line-height: 3em;
+    margin: 5px 5%;
+    text-align: center;
+    color: #423443; }
+  #chat-wrapper a.close {
+    position: absolute;
+    top: 0;
+    right: 0;
+    background: #423443;
+    color: #fff;
+    font-size: 1.125rem;
+    padding: 0 7px;
+    text-decoration: none;
+    font-weight: 600;
+    margin: 1em 5%;
+    cursor: pointer; }
+    #chat-wrapper a.close:hover {
+      text-decoration: none;
+      background: #503f51; }
+  #chat-wrapper > span {
+    font-size: .9rem;
+    margin: 5px 5%;
+    display: block; }
+
+ul#chat {
+  position: relative;
+  top: 0;
+  max-height: 300px;
+  width: 100%;
+  overflow-y: scroll;
+  list-style-type: none; }
+  ul#chat li {
+    font-size: .9rem;
+    padding: 10px;
+    margin: 5px auto;
+    width: 90%;
+    border-radius: 5px;
+    position: relative; }
+    ul#chat li:before {
+      position: absolute;
+      content: '';
+      top: 10px; }
+  ul#chat li.black {
+    background: #444;
+    color: #fff; }
+  ul#chat li.white {
+    background: #fff;
+    color: #444; }
+  ul#chat li.left:before {
+    left: 0;
+    margin-left: -7px;
+    border-bottom: 7px solid transparent;
+    border-top: 7px solid transparent; }
+  ul#chat li.black.left:before {
+    border-right: 7px solid #444; }
+  ul#chat li.white.left:before {
+    border-right: 7px solid #fff; }
+  ul#chat li.right:before {
+    right: 0;
+    margin-right: -7px;
+    border-bottom: 7px solid transparent;
+    border-top: 7px solid transparent; }
+  ul#chat li.black.right:before {
+    border-left: 7px solid #444; }
+  ul#chat li.white.right:before {
+    border-left: 7px solid #fff; }
+
+#sendMessage input {
+  width: 100%;
+  padding: 15px 10px;
+  border: none;
+  outline: none;
+  font-size: .9rem;
+  border: 4px solid #e6e3e0; }
+#sendMessage input.black {
+  background: #444;
+  color: #fff; }
+#sendMessage input.white {
+  background: #fff;
+  color: #444; }
+
 /* Chessboard */
 /* Chessboard */
 #board_moves_wrapper {
 #board_moves_wrapper {
   width: 100%;
   width: 100%;

+ 138 - 1
public/stylesheets/style.scss

@@ -2,6 +2,7 @@ $dark-purple: #423443;
 $blue: #2eafc2;
 $blue: #2eafc2;
 $red: #d12521;
 $red: #d12521;
 $grey: #dad7d2;
 $grey: #dad7d2;
+$dark-grey: #261e26;
 
 
 @mixin all-transition{
 @mixin all-transition{
   -moz-transition: all 0.2s ease-in-out;
   -moz-transition: all 0.2s ease-in-out;
@@ -104,10 +105,26 @@ h3 {
 .last-target{
 .last-target{
   background: lighten($blue, 20%) !important;
   background: lighten($blue, 20%) !important;
 }
 }
-.about-in-play {
+.chat{
+  text-decoration: none;
+  color: darken($blue, 10%);
   margin-right: 1em;
   margin-right: 1em;
   line-height: 50px;
   line-height: 50px;
   float: right !important;
   float: right !important;
+  cursor: pointer;
+  font-weight: 600;
+  &:hover{
+    color: darken($blue, 5%);
+    .new-message{
+      color: $red;
+    }
+  }
+  img{
+    vertical-align: middle;
+  }
+  .new-message{
+    color: $red;
+  }
 }
 }
 .fork{
 .fork{
   float: left;
   float: left;
@@ -270,6 +287,126 @@ footer {
   float: left;
   float: left;
 }
 }
 
 
+/* Chat */
+#chat-wrapper{
+  display: none;
+  position: absolute;
+  width: 270px;
+  right: 10px;
+  top: 99px;
+  border: 4px solid #fff;
+  background: lighten($grey, 5%);
+
+  h4{
+    font-family: 'Cherry Swash';
+    font-size: 1.225rem;
+    height: 3em;
+    line-height: 3em;
+    margin: 5px 5%;
+    text-align: center;
+    color: $dark-purple;
+  }
+
+  a.close{
+    position: absolute;
+    top: 0;
+    right: 0;
+    background: $dark-purple;
+    color: #fff;
+    font-size: 1.125rem;
+    padding: 0 7px;
+    text-decoration: none;
+    font-weight: 600;
+    margin: 1em 5%;
+    cursor: pointer;
+
+    &:hover{
+      text-decoration: none;
+      background: lighten($dark-purple, 5%);
+    }
+  }
+
+  > span{
+    font-size: .9rem;
+    margin: 5px 5%;
+    display: block;
+  }
+}
+
+ul#chat{
+  position: relative;
+  top: 0;
+  max-height: 300px;
+  width: 100%;
+  overflow-y: scroll;
+  list-style-type: none;
+
+  li{
+    font-size: .9rem;
+    padding: 10px;
+    margin: 5px auto;
+    width: 90%;
+    border-radius: 5px;
+    position: relative;
+
+    &:before{
+      position: absolute;
+      content: '';
+      top: 10px;
+    }
+  }
+  li.black{
+    background: #444;
+    color: #fff;
+  }
+  li.white{
+    background: #fff;
+    color: #444;
+  }
+  li.left:before{
+    left: 0;
+    margin-left: -7px;
+    border-bottom: 7px solid transparent;
+    border-top: 7px solid transparent;
+  }
+  li.black.left:before{
+    border-right: 7px solid #444;
+  }
+  li.white.left:before{
+    border-right: 7px solid #fff;
+  }
+  li.right:before{
+    right: 0;
+    margin-right: -7px;
+    border-bottom: 7px solid transparent;
+    border-top: 7px solid transparent;
+  }
+  li.black.right:before{
+    border-left: 7px solid #444;
+  }
+  li.white.right:before{
+    border-left: 7px solid #fff;
+  }
+}
+#sendMessage{
+  input{
+    width: 100%;
+    padding: 15px 10px;
+    border: none;
+    outline: none;
+    font-size: .9rem;
+    border: 4px solid lighten($grey, 5%);
+  }
+  input.black{
+    background: #444;
+    color: #fff;
+  }
+  input.white{
+    background: #fff;
+    color: #444;
+  }
+}
+
 /* Chessboard */
 /* Chessboard */
 
 
 #board_moves_wrapper {
 #board_moves_wrapper {

+ 23 - 4
server.js

@@ -131,16 +131,21 @@ io.sockets.on('connection', function (socket) {
     });
     });
   });
   });
 
 
-  socket.on('resign', function(data) {
+  socket.on('resign', function (data) {
     cancelGame('opponent-resigned', socket);
     cancelGame('opponent-resigned', socket);
   });
   });
 
 
-  socket.on('disconnect', function () {
+  socket.on('disconnect', function (data) {
     cancelGame('opponent-disconnected', socket);
     cancelGame('opponent-disconnected', socket);
   });
   });
+
+  socket.on('send-message', function (data) {
+    var opponent = getOpponent(socket);
+    opponent.socket.emit('receive-message', data);
+  });
 });
 });
 
 
-function cancelGame(event, socket) {
+function getOpponent(socket) {
   for (var token in games) {
   for (var token in games) {
     var game = games[token];
     var game = games[token];
 
 
@@ -149,10 +154,24 @@ function cancelGame(event, socket) {
 
 
       if (player.socket == socket) {
       if (player.socket == socket) {
         var opponent = game.players[Math.abs(j - 1)];
         var opponent = game.players[Math.abs(j - 1)];
+        return opponent;
+      }
+    }
+  }
+}
 
 
+function cancelGame(event, socket) {
+  for (var token in games) {
+    var game = games[token];
+
+    for (var j in game.players) {
+      var player = game.players[j];
+
+      if (player.socket == socket) {
+        var opponent = game.players[Math.abs(j - 1)];
         delete games[token];
         delete games[token];
         opponent.socket.emit(event);
         opponent.socket.emit(event);
       }
       }
     }
     }
   }
   }
-}
+}

+ 2 - 5
views/about.jade

@@ -14,13 +14,10 @@ block content
     a(href='http://socket.io/') Socket.IO
     a(href='http://socket.io/') Socket.IO
     |  . Reti Chess also uses 
     |  . Reti Chess also uses 
     a(href='https://github.com/jhlywa/chess.js') chess.js
     a(href='https://github.com/jhlywa/chess.js') chess.js
-    |  for move validation and check/mate/draw detection. 
-  
-  h3 Why another online chess?
-  p The project may be useful resource for poeple willing to learn Node.js and Socket.IO. Read the source code, fork it, add more functionality and learn something. Besides programming, playing chess is also fun!
+    |  for move validation and check/mate/draw detection.
 
 
   h3 Why Reti?
   h3 Why Reti?
-  p The project is named after famous Czechoslovakian chess player Richard Réti. After him is also named a chess opening which begins with the move: 1. Nf3.
+  p The project is named after famous Czechoslovakian chess player Richard Réti. After him is also named a chess opening which begins with the moves: 1. Nf3 d5, 2. d4.
 
 
   h3 What features chess supports?
   h3 What features chess supports?
   p This is a very lightweight version of chess. You can only play real-time against the human, an AI is not available. Reti Chess doesn't have any timer, the time for a move is unlimited. Although, if you reload the window or disconnect from the game, the game will be cancelled.
   p This is a very lightweight version of chess. You can only play real-time against the human, an AI is not available. Reti Chess doesn't have any timer, the time for a move is unlimited. Although, if you reload the window or disconnect from the game, the game will be cancelled.

+ 0 - 3
views/index.jade

@@ -1,8 +1,5 @@
 extends layout
 extends layout
 
 
-block ribbon
-  a(href='https://github.com/romanmatiasko/reti-chess', class='fork clearfix')
-
 block content
 block content
   script(type='text/javascript', src='/javascripts/start.js')
   script(type='text/javascript', src='/javascripts/start.js')
   h1.knight
   h1.knight

+ 3 - 4
views/layout.jade

@@ -21,7 +21,6 @@ html
     //if IE
     //if IE
       script(src='http://html5shiv.googlecode.com/svn/trunk/html5.js')
       script(src='http://html5shiv.googlecode.com/svn/trunk/html5.js')
   body
   body
-    block ribbon
     
     
     #container_wrapper.clearfix
     #container_wrapper.clearfix
       #container.clearfix
       #container.clearfix
@@ -29,8 +28,8 @@ html
         
         
     footer
     footer
       #footer.clearfix
       #footer.clearfix
-        p.center 2013. Reti Chess is available under 
-          a(href='http://opensource.org/licenses/MIT') the MIT License (MIT)
+        p.center 2013 - 2014. Reti Chess is available under 
+          a(href='http://opensource.org/licenses/MIT')  the MIT License (MIT)
           . Fork me on 
           . Fork me on 
-          a(href='http://github.com/romanmatiasko/reti-chess') Github
+          a(href='http://github.com/romanmatiasko/reti-chess')  Github
           .
           .

+ 13 - 1
views/play.jade

@@ -4,7 +4,9 @@ block content
   header.clearfix
   header.clearfix
     a.button(href='/') New game
     a.button(href='/') New game
     a.button.resign Resign
     a.button.resign Resign
-    a.about-in-play(href='/about/') About Reti Chess
+    a.chat
+      img#bubble(src='/images/chat.svg', width='50', height='50')
+      | Chat
 
 
   script(type='text/javascript')
   script(type='text/javascript')
     $token = '#{token}';
     $token = '#{token}';
@@ -12,6 +14,16 @@ block content
   audio(id='moveSnd', preload='auto')
   audio(id='moveSnd', preload='auto')
     source(src='/sounds/move.mp3')
     source(src='/sounds/move.mp3')
     source(src='/sounds/move.ogg')
     source(src='/sounds/move.ogg')
+  audio(id='messageSnd', preload='auto')
+    source(src='/sounds/message.mp3')
+
+  #chat-wrapper
+    h4 Chat
+    a.close x
+    ul#chat
+    span Write your message:
+    form#sendMessage
+      input
 
 
   #board_moves_wrapper.clearfix
   #board_moves_wrapper.clearfix
     label(id='sounds_label')
     label(id='sounds_label')