Browse Source

add few react components for gameplay

romanmatiasko 9 years ago
parent
commit
15987900fd

+ 32 - 30
gulpfile.js

@@ -32,38 +32,40 @@ var dependencies = [
 
 var browserifyTask = function() {
 
-  var appBundler = browserify({
-    entries: './src/js/index.js',
-    transform: [babelify],
-    debug: IS_DEVELOPMENT,
-    // required by watchify
-    cache: {}, packageCache: {}, fullPaths: IS_DEVELOPMENT
-  });
-    
-  (IS_DEVELOPMENT ? dependencies : []).forEach(function(dep) {
-    appBundler.external(dep);
-  });
+  ['index.js', 'play.js'].forEach(function(bundle) {
+    var appBundler = browserify({
+      entries: './src/js/' + bundle,
+      transform: [babelify],
+      debug: IS_DEVELOPMENT,
+      // required by watchify
+      cache: {}, packageCache: {}, fullPaths: IS_DEVELOPMENT
+    });
+      
+    (IS_DEVELOPMENT ? dependencies : []).forEach(function(dep) {
+      appBundler.external(dep);
+    });
 
-  var rebundle = function() {
-    var start = Date.now();
-    console.log('Building BROWSERIFY bundle');
-    appBundler.bundle()
-      .on('error', gutil.log)
-      .pipe(source('index.js'))
-      .pipe(gulpif(!IS_DEVELOPMENT, streamify(uglify())))
-      .pipe(gulp.dest(IS_DEVELOPMENT ? './build/js/' : './dist/js/'))
-      .pipe(notify(function() {
-        gutil.log(gutil.colors.green('BROWSERIFY bundle built in ' +
-          (Date.now() - start) + 'ms'));
-      }));
-  };
+    var rebundle = function() {
+      var start = Date.now();
+      console.log('Building BROWSERIFY(' + bundle + ') bundle');
+      appBundler.bundle()
+        .on('error', gutil.log)
+        .pipe(source(bundle))
+        .pipe(gulpif(!IS_DEVELOPMENT, streamify(uglify())))
+        .pipe(gulp.dest(IS_DEVELOPMENT ? './build/js/' : './dist/js/'))
+        .pipe(notify(function() {
+          gutil.log(gutil.colors.green('BROWSERIFY(' + bundle +
+            ') bundle built in ' + (Date.now() - start) + 'ms'));
+        }));
+    };
 
-  if (IS_DEVELOPMENT) {
-    appBundler = watchify(appBundler);
-    appBundler.on('update', rebundle);
-  }
-  
-  rebundle();
+    if (IS_DEVELOPMENT) {
+      appBundler = watchify(appBundler);
+      appBundler.on('update', rebundle);
+    }
+    
+    rebundle();
+  });
   
   if (IS_DEVELOPMENT) {
     var vendorBundler = browserify({

+ 1 - 0
package.json

@@ -22,6 +22,7 @@
   "devDependencies": {
     "babelify": "^5.0.3",
     "browserify": "^9.0.3",
+    "chess.js": "^0.1.0",
     "gulp": "^3.8.11",
     "gulp-autoprefixer": "^2.1.0",
     "gulp-cssmin": "^0.1.6",

+ 37 - 37
public/javascripts/play.js

@@ -377,30 +377,30 @@ $(function() {
     }
   });
 
-  $socket.on('countdown', function (data) {
-    var color = data.color;
-    var opp_color = color === 'black' ? 'white' : 'black';
-    var min = Math.floor(data.time / 60);
-    var sec = data.time % 60;
-    if (sec.toString().length === 1) {
-      sec = '0' + sec;
-    }
+  // $socket.on('countdown', function (data) {
+  //   var color = data.color;
+  //   var opp_color = color === 'black' ? 'white' : 'black';
+  //   var min = Math.floor(data.time / 60);
+  //   var sec = data.time % 60;
+  //   if (sec.toString().length === 1) {
+  //     sec = '0' + sec;
+  //   }
     
-    $('#clock li.' + color).text(min + ':' + sec);
-  });
-
-  $socket.on('countdown-gameover', function (data) {
-    $gameOver = true;
-    unbindMoveHandlers();
-    var loser = data.color === 'black' ? 'Black' : 'White';
-    var winner = data.color === 'black' ? 'White' : 'Black';
-    var message = loser + "'s time is out. " + winner + " wins.";
-    $('.resign').hide();
-    $('.rematch').show();
-    showModal(message);
-    $('.feedback-move').text('');
-    $('.feedback-status').text(message);
-  });
+  //   $('#clock li.' + color).text(min + ':' + sec);
+  // });
+
+  // $socket.on('countdown-gameover', function (data) {
+  //   $gameOver = true;
+  //   unbindMoveHandlers();
+  //   var loser = data.color === 'black' ? 'Black' : 'White';
+  //   var winner = data.color === 'black' ? 'White' : 'Black';
+  //   var message = loser + "'s time is out. " + winner + " wins.";
+  //   $('.resign').hide();
+  //   $('.rematch').show();
+  //   showModal(message);
+  //   $('.feedback-move').text('');
+  //   $('.feedback-status').text(message);
+  // });
 
   $socket.on('rematch-offered', function (data) {
     hideModal();
@@ -549,23 +549,23 @@ $(function() {
     e.stopPropagation();
   });
 
-  $('.resign').click(function (e) {
-    e.preventDefault();
+  // $('.resign').click(function (e) {
+  //   e.preventDefault();
 
-    $socket.emit('resign', {
-      'token': $token,
-      'color': $side
-    });
-  });
+  //   $socket.emit('resign', {
+  //     'token': $token,
+  //     'color': $side
+  //   });
+  // });
 
-  $('.rematch').click(function (e) {
-    e.preventDefault();
-    showModal('Your offer has been sent.');
+  // $('.rematch').click(function (e) {
+  //   e.preventDefault();
+  //   showModal('Your offer has been sent.');
 
-    $socket.emit('rematch-offer', {
-      'token': $token
-    });
-  })
+  //   $socket.emit('rematch-offer', {
+  //     'token': $token
+  //   });
+  // })
 
   $('a.chat').click(function (e) {
     $('#chat-wrapper').toggle();

+ 5 - 4
routes/routes.js

@@ -5,6 +5,7 @@ const path = require('path');
 const fs = require('fs');
 const React = require('react');
 const Index = require('../src/js/components/Index');
+const GameInterface = require('../src/js/components/GameInterface');
 let router = express.Router();
 
 router.get('/', (req, res) => {
@@ -17,11 +18,11 @@ router.get('/about', (req, res) => {
   res.render('about');
 });
 
-router.get('/play/:token/:time/:increment', (req, res) => {
+router.get('/play/:token/:time/:inc', (req, res) => {
+  let params = [req.params.token, req.params.time, req.params.inc];
+
   res.render('play', {
-    'token': req.params.token,
-    'time': req.params.time,
-    'increment': req.params.increment
+    content: React.renderToString(<GameInterface params={params} />)
   });
 });
 

+ 4 - 0
src/css/_base.scss

@@ -36,6 +36,10 @@ article, aside, figure, footer, header, nav, section {
   display: block;
 }
 
+pre {
+  font-size: 12px;
+}
+
 audio, canvas, video {
   display: inline-block; *display: inline; *zoom: 1;
 }

+ 1 - 1
src/css/_chat.scss

@@ -119,7 +119,7 @@ ul#chat {
   }
 }
 
-.chat {
+#chat-icon {
   text-decoration: none;
   color: darken($blue, 10%);
   margin-right: 1em;

+ 1 - 2
src/css/_game.scss

@@ -56,8 +56,7 @@ span#game-type {
   height: 30px;
   line-height: 30px;
   display: block;
-  margin: 0px 0px 5px 0px;
-  float: left;
+  margin: .5em auto;
 }
 
 #captured-pieces {

+ 4 - 4
src/css/_layout.scss

@@ -25,7 +25,7 @@ input, button {
   font-family: 'Open Sans';
 }
 
-.button {
+.btn {
   width: 15%;
   height: 50px;
   display: block;
@@ -52,7 +52,7 @@ input, button {
   }
 }
 
-a.button {
+a.btn {
   width: 120px;
   line-height: 46px;
   text-align: center;
@@ -63,7 +63,7 @@ a.button {
   }
 }
 
-.button--red {
+.btn--red {
   background: $red;
   border-color: darken($red, 5%);
   box-shadow: inset 0 -2px darken($red, 5%);
@@ -138,7 +138,7 @@ footer {
     text-align: center;
     padding: 1.5em;
   }
-  .button {
+  .btn {
     position: absolute;
     bottom: 1em;
 

+ 1 - 1
src/css/main.scss

@@ -55,7 +55,7 @@
   html {
     font-size: 14px;
   }
-  #form {
+  #create-game > form {
     fieldset {
       width: 100%;
       text-align: center;

+ 60 - 0
src/js/components/Clock.js

@@ -0,0 +1,60 @@
+'use strict';
+
+const React = require('react/addons');
+const PureRenderMixin = React.addons.PureRenderMixin;
+
+const Clock = React.createClass({
+  
+  propTypes: {
+    io: React.PropTypes.object,
+    params: React.PropTypes.array.isRequired
+  },
+  mixins: [PureRenderMixin],
+
+  getInitialState() {
+    let [_, time, inc] = this.props.params;
+    
+    return {
+      white: time * 60,
+      black: time * 60,
+      inc: inc
+    };
+  },
+  componentDidMount() {
+    let io = this.props.io;
+
+    io.on('countdown', data => this.setState({
+      [data.color]: data.time
+    }));
+
+    io.on('countdown-gameover', data => {
+      // GameStore.gameOver({
+      //   timeout: true,
+      //   winner: data.color === 'black' ? 'White' : 'Black'
+      // });
+    });
+  },
+  render() {
+    return (
+      <ul id="clock">
+        <Timer color="white" time={this.state.white} />
+        <Timer color="black" time={this.state.black} />
+      </ul>
+    );
+  }
+});
+
+const Timer = React.createClass({
+
+  mixins: [PureRenderMixin],
+
+  render() {
+    let min = Math.floor(this.props.time / 60);
+    let sec = this.props.time % 60;
+    let timeLeft = `${min}:${sec < 10 ? '0' + sec : sec}`;
+
+    return <li className={this.props.color}>{timeLeft}</li>;
+  }
+});
+
+module.exports = Clock;

+ 1 - 1
src/js/components/CreateGameForm.js

@@ -46,7 +46,7 @@ const CreateGameForm = React.createClass({
           value={this.props.link || 'Game link will be generated here.'}
           onClick={e => e.target.select()}
           readOnly />
-        <button type="submit" className="button">Play</button>
+        <button type="submit" className="btn">Play</button>
       </form>
     );
   }

+ 79 - 0
src/js/components/GameHeader.js

@@ -0,0 +1,79 @@
+'use strict';
+
+const React = require('react/addons');
+const Clock = require('./Clock');
+
+const GameHeader = React.createClass({
+  
+  propTypes: {
+    io: React.PropTypes.object,
+    params: React.PropTypes.array.isRequired,
+    color: React.PropTypes.string,
+    toggleModal: React.PropTypes.func.isRequired
+  },
+  mixins: [React.addons.PureRenderMixin],
+
+  render() {
+    let [_, time, inc] = this.props.params;
+
+    return (
+      <header className="clearfix">
+
+        <Clock
+          io={this.props.io}
+          params={this.props.params} />
+
+        <span id="game-type">
+          {`${time}|${inc}`}
+        </span>
+
+        <a className="btn" href="/">New game</a>
+
+        <button type="button"
+                className="btn btn--red resign"
+                onClick={this._onResign}>
+          Resign
+        </button>
+
+        <button type="button"
+                className="btn btn--red rematch"
+                onClick={this._onRematch}>
+          Rematch
+        </button>
+
+        <a id="chat-icon"
+           onClick={this._toggleChat}>
+          <img id="bubble"
+               src="/img/chat.svg"
+               width="50"
+               height="50" />
+          Chat
+        </a>
+      </header>
+    );
+  },
+  _onResign(e) {
+    let {io, params, color} = this.props;
+
+    io.emit('resign', {
+      token: params[0],
+      color: color
+    });
+    e.preventDefault();
+  },
+  _onRematch(e) {
+    let {io, params, toggleModal} = this.props;
+
+    io.emit('rematch-offer', {
+      token: params[0]
+    });
+    toggleModal(true, 'Your offer has been sent.');
+    e.preventDefault();
+  },
+  _toggleChat(e) {
+    // ChatStore.toggleChat();
+    e.preventDefault();
+  }
+});
+
+module.exports = GameHeader;

+ 56 - 0
src/js/components/GameInterface.js

@@ -0,0 +1,56 @@
+'use strict';
+
+const React = require('react/addons');
+const GameHeader = require('./GameHeader');
+const Immutable = require('immutable');
+const {Map} = Immutable;
+const Chess = require('chess.js');
+
+const GameInterface = React.createClass({
+  
+  propTypes: {
+    io: React.PropTypes.object,
+    params: React.PropTypes.array.isRequired
+  },
+
+  getInitialState() {
+    return {
+      modal: Map({open: false, message: ''}),
+      soundsEnabled: false
+    };
+  },
+  render() {
+    return (
+      <div>
+        <GameHeader
+          io={this.props.io}
+          params={this.props.params}
+          toggleModal={this._toggleModal} />
+
+        <audio preload="auto" ref="moveSnd">
+          <source src="/snd/move.mp3" />
+          <source src="/snd/move.ogg" />
+        </audio>
+        <label id="sounds-label">
+          <input type="checkbox"
+                 checked={this.state.soundsEnabled}
+                 onChange={this._toggleSounds} />
+          <span> Enable sounds</span>
+        </label>
+
+      </div>
+    );
+  },
+  _toggleModal(open, message) {
+    this.setState({
+      modal: Map({open: open, message: message})
+    });
+  },
+  _toggleSounds() {
+    this.setState({
+      soundsEnabled: !this.state.soundsEnabled
+    });
+  }
+});
+
+module.exports = GameInterface;

+ 11 - 0
src/js/play.js

@@ -0,0 +1,11 @@
+'use strict';
+
+const React = require('react');
+const io = require('./io');
+const GameInterface = require('./components/GameInterface');
+const params = window.location.pathname.replace('/play/', '').split('/');
+
+React.render(
+  <GameInterface io={io} params={params} />,
+  document.getElementById('container')
+);

+ 3 - 4
views/layout.jade

@@ -12,7 +12,6 @@ html(lang='en')
     meta(name='viewport', content='width=device-width, initial-scale=1')
     link(rel='shortcut icon', href='/img/logo.png')
     link(rel='stylesheet', href='/css/main.css')
-    block head
     link(href='http://fonts.googleapis.com/css?family=Cherry+Swash|Open+Sans:400,600', rel='stylesheet', type='text/css')
 
   body
@@ -25,7 +24,7 @@ html(lang='en')
         |  OK
       #modal-window.modal
         p#modal-message Message.
-        a#modal-ok.button(href='#', style='left: 50%; margin-left: -60px;') OK
+        a#modal-ok.btn(href='#', style='left: 50%; margin-left: -60px;') OK
     #offer-mask.modal-mask
       p
         strong Esc: 
@@ -35,8 +34,8 @@ html(lang='en')
         |  Accept
       #offer-window.modal
         p#offer-message Offer.
-        a#offer-accept.button(href='#') Accept
-        a#offer-decline.button.button--red(href='#') Decline
+        a#offer-accept.btn(href='#') Accept
+        a#offer-decline.btn.btn--red(href='#') Decline
 
     #container-wrapper.clearfix
         block content

+ 2 - 269
views/play.jade

@@ -1,274 +1,7 @@
 extends layout
 
-block head
-  script(type='text/javascript')
-    $token = '#{token}';
-    $time = #{time};
-    $increment = #{increment};
-
 block content
-  header.clearfix
-    ul#clock
-      li.white
-      li.black
-    span#game-type
-    a.button(href='/') New game
-    a.button.button--red.resign Resign
-    a.button.button--red.rematch Rematch
-    a.chat
-      img#bubble(src='/img/chat.svg', width='50', height='50')
-      | Chat
-  audio(id='moveSnd', preload='auto')
-    source(src='/sounds/move.mp3')
-    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#send-message
-      input
-
-  #board-moves-wrapper.clearfix
-    label(id='sounds-label')
-      input(type='checkbox', id='sounds')
-      |  Enable sounds
-    #board-wrapper
-      #captured-pieces
-        ul.w
-        ul.b
-      table.chessboard.white
-        tr
-          td.A8(data-id='A8', draggable='true')
-            a.black.rook(draggable='true') &#9820;
-          td.B8(data-id='B8', draggable='true')
-            a.black.knight(draggable='true') &#9822;
-          td.C8(data-id='C8', draggable='true')
-            a.black.bishop(draggable='true') &#9821;
-          td.D8(data-id='D8', draggable='true')
-            a.black.queen(draggable='true') &#9819;
-          td.E8(data-id='E8', draggable='true')
-            a.black.king(draggable='true') &#9818;
-          td.F8(data-id='F8', draggable='true')
-            a.black.bishop(draggable='true') &#9821;
-          td.G8(data-id='G8', draggable='true')
-            a.black.knight(draggable='true') &#9822;
-          td.H8(data-id='H8', draggable='true')
-            a.black.rook(draggable='true') &#9820;
-        tr
-          td.A7(data-id='A7', draggable='true')
-            a.black.pawn(draggable='true') &#9823;
-          td.B7(data-id='B7', draggable='true')
-            a.black.pawn(draggable='true') &#9823;
-          td.C7(data-id='C7', draggable='true')
-            a.black.pawn(draggable='true') &#9823;
-          td.D7(data-id='D7', draggable='true')
-            a.black.pawn(draggable='true') &#9823;
-          td.E7(data-id='E7', draggable='true')
-            a.black.pawn(draggable='true') &#9823;
-          td.F7(data-id='F7', draggable='true')
-            a.black.pawn(draggable='true') &#9823;
-          td.G7(data-id='G7', draggable='true')
-            a.black.pawn(draggable='true') &#9823;
-          td.H7(data-id='H7', draggable='true')
-            a.black.pawn(draggable='true') &#9823;
-        tr
-          td.A6(data-id='A6')
-          td.B6(data-id='B6')
-          td.C6(data-id='C6')
-          td.D6(data-id='D6')
-          td.E6(data-id='E6')
-          td.F6(data-id='F6')
-          td.G6(data-id='G6')
-          td.H6(data-id='H6')
-        tr
-          td.A5(data-id='A5')
-          td.B5(data-id='B5')
-          td.C5(data-id='C5')
-          td.D5(data-id='D5')
-          td.E5(data-id='E5')
-          td.F5(data-id='F5')
-          td.G5(data-id='G5')
-          td.H5(data-id='H5')
-        tr
-          td.A4(data-id='A4')
-          td.B4(data-id='B4')
-          td.C4(data-id='C4')
-          td.D4(data-id='D4')
-          td.E4(data-id='E4')
-          td.F4(data-id='F4')
-          td.G4(data-id='G4')
-          td.H4(data-id='H4')
-        tr
-          td.A3(data-id='A3')
-          td.B3(data-id='B3')
-          td.C3(data-id='C3')
-          td.D3(data-id='D3')
-          td.E3(data-id='E3')
-          td.F3(data-id='F3')
-          td.G3(data-id='G3')
-          td.H3(data-id='H3')
-        tr
-          td.A2(data-id='A2', draggable='true')
-            a.white.pawn(draggable='true') &#9817;
-          td.B2(data-id='B2', draggable='true')
-            a.white.pawn(draggable='true') &#9817;
-          td.C2(data-id='C2', draggable='true')
-            a.white.pawn(draggable='true') &#9817;
-          td.D2(data-id='D2', draggable='true')
-            a.white.pawn(draggable='true') &#9817;
-          td.E2(data-id='E2', draggable='true')
-            a.white.pawn(draggable='true') &#9817;
-          td.F2(data-id='F2', draggable='true')
-            a.white.pawn(draggable='true') &#9817;
-          td.G2(data-id='G2', draggable='true')
-            a.white.pawn(draggable='true') &#9817;
-          td.H2(data-id='H2', draggable='true')
-            a.white.pawn(draggable='true') &#9817;
-        tr
-          td.A1(data-id='A1', draggable='true')
-            a.white.rook(draggable='true') &#9814;
-          td.B1(data-id='B1', draggable='true')
-            a.white.knight(draggable='true') &#9816;
-          td.C1(data-id='C1', draggable='true')
-            a.white.bishop(draggable='true') &#9815;
-          td.D1(data-id='D1', draggable='true')
-            a.white.queen(draggable='true') &#9813;
-          td.E1(data-id='E1', draggable='true')
-            a.white.king(draggable='true') &#9812;
-          td.F1(data-id='F1', draggable='true')
-            a.white.bishop(draggable='true') &#9815;
-          td.G1(data-id='G1', draggable='true')
-            a.white.knight(draggable='true') &#9816;
-          td.H1(data-id='H1', draggable='true')
-            a.white.rook(draggable='true') &#9814;
-      table.chessboard.black(style='display: none;')
-        tr
-          td.H1(data-id='H1', draggable='true')
-            a.white.rook(draggable='true') &#9814;
-          td.G1(data-id='G1', draggable='true')
-            a.white.knight(draggable='true') &#9816;
-          td.F1(data-id='F1', draggable='true')
-            a.white.bishop(draggable='true') &#9815;
-          td.E1(data-id='E1', draggable='true')
-            a.white.king(draggable='true') &#9812;
-          td.D1(data-id='D1', draggable='true')
-            a.white.queen(draggable='true') &#9813;
-          td.C1(data-id='C1', draggable='true')
-            a.white.bishop(draggable='true') &#9815;
-          td.B1(data-id='B1', draggable='true')
-            a.white.knight(draggable='true') &#9816;
-          td.A1(data-id='A1', draggable='true')
-            a.white.rook(draggable='true') &#9814;
-        tr
-          td.H2(data-id='H2', draggable='true')
-            a.white.pawn(draggable='true') &#9817;
-          td.G2(data-id='G2', draggable='true')
-            a.white.pawn(draggable='true') &#9817;
-          td.F2(data-id='F2', draggable='true')
-            a.white.pawn(draggable='true') &#9817;
-          td.E2(data-id='E2', draggable='true')
-            a.white.pawn(draggable='true') &#9817;
-          td.D2(data-id='D2', draggable='true')
-            a.white.pawn(draggable='true') &#9817;
-          td.C2(data-id='C2', draggable='true')
-            a.white.pawn(draggable='true') &#9817;
-          td.B2(data-id='B2', draggable='true')
-            a.white.pawn(draggable='true') &#9817;
-          td.A2(data-id='A2', draggable='true')
-            a.white.pawn(draggable='true') &#9817;
-        tr
-          td.H3(data-id='H3')
-          td.G3(data-id='G3')
-          td.F3(data-id='F3')
-          td.E3(data-id='E3')
-          td.D3(data-id='D3')
-          td.C3(data-id='C3')
-          td.B3(data-id='B3')
-          td.A3(data-id='A3')
-        tr
-          td.H4(data-id='H4')
-          td.G4(data-id='G4')
-          td.F4(data-id='F4')
-          td.E4(data-id='E4')
-          td.D4(data-id='D4')
-          td.C4(data-id='C4')
-          td.B4(data-id='B4')
-          td.A4(data-id='A4')
-        tr
-          td.H5(data-id='H5')
-          td.G5(data-id='G5')
-          td.F5(data-id='F5')
-          td.E5(data-id='E5')
-          td.D5(data-id='D5')
-          td.C5(data-id='C5')
-          td.B5(data-id='B5')
-          td.A5(data-id='A5')
-        tr
-          td.H6(data-id='H6')
-          td.G6(data-id='G6')
-          td.F6(data-id='F6')
-          td.E6(data-id='E6')
-          td.D6(data-id='D6')
-          td.C6(data-id='C6')
-          td.B6(data-id='B6')
-          td.A6(data-id='A6')
-        tr
-          td.H7(data-id='H7', draggable='true')
-            a.black.pawn(draggable='true') &#9823;
-          td.G7(data-id='G7', draggable='true')
-            a.black.pawn(draggable='true') &#9823;
-          td.F7(data-id='F7', draggable='true')
-            a.black.pawn(draggable='true') &#9823;
-          td.E7(data-id='E7', draggable='true')
-            a.black.pawn(draggable='true') &#9823;
-          td.D7(data-id='D7', draggable='true')
-            a.black.pawn(draggable='true') &#9823;
-          td.C7(data-id='C7', draggable='true')
-            a.black.pawn(draggable='true') &#9823;
-          td.B7(data-id='B7', draggable='true')
-            a.black.pawn(draggable='true') &#9823;
-          td.A7(data-id='A7', draggable='true')
-            a.black.pawn(draggable='true') &#9823;
-        tr
-          td.H8(data-id='H8', draggable='true')
-            a.black.rook(draggable='true') &#9820;
-          td.G8(data-id='G8', draggable='true')
-            a.black.knight(draggable='true') &#9822;
-          td.F8(data-id='F8', draggable='true')
-            a.black.bishop(draggable='true') &#9821;
-          td.E8(data-id='E8', draggable='true')
-            a.black.king(draggable='true') &#9818;
-          td.D8(data-id='D8', draggable='true')
-            a.black.queen(draggable='true') &#9819;
-          td.C8(data-id='C8', draggable='true')
-            a.black.bishop(draggable='true') &#9821;
-          td.B8(data-id='B8', draggable='true')
-            a.black.knight(draggable='true') &#9822;
-          td.A8(data-id='A8', draggable='true')
-            a.black.rook(draggable='true') &#9820;
-
-    table#moves.clearfix
-      thead
-        tr
-          th Table of moves
-      tbody
-        tr
-    
-    span.promotion
-      label(id='for_promotion') Promotion: 
-        select(id='promotion')
-          option(value='q', selected) Queen
-          option(value='r') Rook
-          option(value='n') Knight
-          option(value='b') Bishop
-
-    span.feedback.whitefeedback
-      span.feedback-move White to move.
-      span.feedback-status
+  #container.clearfix!=content
 
 block scripts
-  script(type='text/javascript', src='/js/play.js')
+  script(src='/js/play.js')