0

I created a custom directive, chess-board, showing a chess position. With Ionic framework, I generate a list of chess-board, and would like to thumbnail chess-board on the left. Though I followed documentation, but using svg instead, as my directive generate svg, I can't get the desired layout.

Here is my JsBin (don't worry for missing pictures).

Here is index.html :

<!DOCTYPE html>
<html>
<head>    
<script src="//code.ionicframework.com/1.0.0-beta.13/js/ionic.bundle.min.js"></script>
<link href="//code.ionicframework.com/1.0.0-beta.13/css/ionic.min.css" rel="stylesheet" type="text/css" />
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js">    </script>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body ng-app="static-board">

    <ion-pane>
      <ion-header-bar class="bar-dark">
        <h1 class="title">Chess Positions Archiver</h1>
      </ion-header-bar>
      <ion-content>
        <div class="list">
          <a class="item item-thumbnail-left" href="#">
            <chess-board cells-size="30" fen="3rr1k1/pb5p/1qp3pB/1pn1Q3/8/7P/PPP3P1/R3KR2 b - - 0 1" show-coords>    </chess-board>
            <h3>Exercise 1</h3>
          </a>

          <a class="item item-thumbnail-left" href="#">
            <chess-board cells-size="30" show-coords></chess-board>
            <h3>Exercise 2</h3>
          </a>
        </div>

      </ion-content>
    </ion-pane>
  </body>
</html>

Here is my script

(function(){
  var chessPieces = {
    'P': 'wp',
    'N': 'wn',
    'B': 'wb',
    'R': 'wr',
    'Q': 'wq',
    'K': 'wk',

    'b': 'bb',
    'p': 'bp',
    'n': 'bn',
    'r': 'br',
    'q': 'bq',
    'k': 'bk'
  };

  angular.module('static-board', ['ionic'])
  .factory('chessPictures', [function(){
    return {
      getPicture: function(pieceFen){
        return chessPieces[pieceFen];
      }
    }
  }])
  .directive('chessBoard', [function(){

    function getBoardHtml(cellsSize, positionFen, showCoords){

      // taken from http://stackoverflow.com/questions/610406/javascript-equivalent-to-printf-string-format
      function sprintf() {
        var args = arguments,
        string = args[0],
        i = 1;
        return string.replace(/%((%)|s|d)/g, function (m) {
          // m is the matched format, e.g. %s, %d
          var val = null;
          if (m[2]) {
            val = m[2];
          } else {
            val = args[i];
            // A switch statement so that the formatter can be extended. Default is %s
            switch (m) {
              case '%d':
                val = parseFloat(val);
                if (isNaN(val)) {
                  val = 0;
                }
                break;
              }
              i++;
            }
            return val;
          });
        }

      function fenToPosition(){
        function getSingleLine(lineFen){
          var result = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '];
          var column = 0;
          for (var index in lineFen){
            var currElem = lineFen[index];
            var isDigit = !isNaN(parseInt(currElem));
            if (isDigit){
              column += parseInt(currElem);
            }
            else {
              result[column] = currElem;
              column++;
            }
          }
          return result;
        }

        var result = [];
        var parts = positionFen.split(" ")[0].split("/");
        for (var partIndex in parts){
          var currPart = parts[partIndex];
          result.push(getSingleLine(currPart));
        }
        return result;
      }

      function getBackground(size){
        return sprintf("<rect x='0' y='0' width='%d' height='%d' fill='#BAA' />", size, size);
      };

      function getCells(){
        function getSingleCell(cellX, cellY){
          var x = cellX*cellsSize + cellsSize/2;
          var y = cellY*cellsSize + cellsSize/2;
          var color = (cellX+cellY)%2 === 0 ? "#E9E637" : "#7C4116";
          return sprintf("<rect x='%d' y='%d' width='%d', height='%d' fill='%s' />",
            x,y, cellsSize, cellsSize, color);
        }

        var result = "";
        for (var line = 0; line < 8; line++){
          for (var col = 0; col < 8; col++){
            result += getSingleCell(col, line)+'\n';
          }
        }

        return result;
      }

      function getPieces(positionPieces){
        function getSinglePiece(cellX, cellY){
          var x = cellX*cellsSize + cellsSize/2;
          var y = cellY*cellsSize + cellsSize/2;
          var pieceFen = positionPieces[cellY][cellX];
          var piecePictureRef = chessPieces[pieceFen];
          var path = sprintf("../img/chess_pieces/%s.svg", piecePictureRef);
          return piecePictureRef ? sprintf("<image x='%d' y='%d' width='%d' height='%d' xlink:href='%s' />",
            x, y, cellsSize, cellsSize, path
          ) : undefined;
        }

        var result = "";
        for (var rank = 0; rank < 8; rank++){
          for (var file = 0; file < 8; file++){
            var line = getSinglePiece(file, rank);
            if (line) {
              result += line+'\n';
            }
          }
        }

        return result;
      }

      function getPlayerTurn(){
        var turnStr = positionFen.split(" ")[1];
        var color = turnStr === "w" ? "#FFF" : "#000";
        var location = parseInt(8.5*cellsSize);
        var size = cellsSize / 2;
        return sprintf("<rect x='%d' y='%d' width='%d' height='%d' fill='%s'/>",
          location, location, size, size, color);
      }

      function getCoordinates(){
        result = "";

        var files = "ABCDEFGH";
        for (var index in files){
          var currFile = files[index];
          result += sprintf("<text x='%d' y='%d' fill='#000' font-size='%d'>%s</text>",
          parseInt(cellsSize*index + cellsSize*.8), parseInt(cellsSize*.45),
          parseInt(cellsSize*.4), currFile);
          result += sprintf("<text x='%d' y='%d' fill='#000' font-size='%d'>%s</text>",
            parseInt(cellsSize*index + cellsSize*.8), parseInt(cellsSize*8.9),
            parseInt(cellsSize*.4), currFile);
        }

        var ranks = "87654321";
        for (var index in ranks){
          var currRank = ranks[index];
          result += sprintf("<text x='%d' y='%d' fill='#000' font-size='%d'>%s</text>",
            parseInt(cellsSize*.1),     parseInt(cellsSize*1.25+cellsSize*index),
            parseInt(cellsSize*.4), currRank);
            result += sprintf("<text x='%d' y='%d' fill='#000' font-size='%d'>%s</text>",
            parseInt(cellsSize*8.7),     parseInt(cellsSize*1.25+cellsSize*index),
            parseInt(cellsSize*.4), currRank);
        }

        return result;
      }

      var size = 9*cellsSize;
      var result = sprintf("<svg width='%d'     height='%d'>\n%s\n%s\n%s\n%s\n%s\n</svg>",
        size, size, getBackground(size), getCells(),     getPieces(fenToPosition()),
        getPlayerTurn(), showCoords ? getCoordinates() : "");
      return result;
    }

    return {
      restrict: 'E',
      link: {
        post : function(scope, element, attrs){
          var cellsSize = attrs.cellsSize || 20;
          var positionFen = attrs.fen || 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w';
          var showCoords = attrs.showCoords !== undefined ? true : false;

          var newElem = angular.element(getBoardHtml(cellsSize, positionFen, showCoords));
          element.replaceWith(newElem);
        }
      }
    }
  }])
})();

So what's wrong ?

  • Is that the fact that I am using an <svg> instead of an <img> ?
  • Or is it something else ?
loloof64
  • 5,252
  • 12
  • 41
  • 78
  • Looking at my ionic project files, I noticed that generated css from saas defined this feature only for img tags, so I managed to define the same for svg tags. As this is impossible to do in the jsbin, I don't consider this as an answer. Furthermore, I would also need to compile saas at runtime, lazily, but that don't seem to be possible. – loloof64 Apr 03 '15 at 12:25

1 Answers1

1

you will need to do several things:

wrap svg into a div, and give it class item-image

<div class="item-image">
  <chess-board cells-size="30"></chess-board>
</div>

then, when you create the SVG, you will need to set properties like this:

width="100%" height="100%" viewBox="0,0,270,270"

width and hight will tell it how to behave inside it's container, while viewBox property sets the size of canvas, on which the image will be drawn.

this line

var result = sprintf("<svg width='%d' height='%d'>\n%s\n%s\n%s\n%s\n%s\n</svg>", size, size, getBackground(size), getCells(), getPieces(fenToPosition()), getPlayerTurn(), showCoords ? getCoordinates() : "");

should look like this

var result = sprintf("<svg width='100%%' height='100%%' viewBox='0,0,%d,%d'>\n%s\n%s\n%s\n%s\n%s\n</svg>", size, size, getBackground(size), getCells(), getPieces(fenToPosition()), getPlayerTurn(), showCoords ? getCoordinates() : "");

You can see it here http://jsbin.com/basimodufa/1/edit?html,js,output

there is a good resource on SVG sizing/containing here

Vinko Bradvica
  • 466
  • 3
  • 9