Bejeweled

by David Joseph Guzsik

HTML

<div id="center">
  <div id="grid-wrap-wrap">
    <div id="grid-wrap">
      <div id="grid">
      </div>
    </div>
  </div>
</div>

CSS

body {
  padding: 8px;
  -moz-user-select: none;
  -webkit-user-select: none;
  user-select: none;
}
html, body, #center {
  height: 100%;
  box-sizing: border-box;
}
#center {
  display: flex;
  justify-content: center;
}
#grid-wrap-wrap {
  width: 400px;
  margin: 0 auto;
  align-self: center;
}
#grid-wrap {
  width: 100%;
  padding-top: 100%;
  position: relative;
  background: rgba(100,100,100,.2);
}
#grid {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border: 1px solid black;
  padding: 2px;
  display: flex;
  flex-flow: row wrap;
}
#grid > .cell {
  flex: 1 1 10%;
  margin: 3px;
  position: relative;
  cursor: pointer;
}
#grid > .cell.selected {
  z-index: 1;
}
#grid > .cell.targeted {
  z-index: 2;
}
#grid > .cell.disabled {
  opacity: .5;
  -moz-pointer-events: none;
  -webkit-pointer-events: none;
  pointer-events: none;
}
#grid > .cell > span {
  position: absolute;
  width: 100%;
  height: 100%;
  display: block;
  font-size: 20px;
  border: 1px solid grey;
  background-color: #fff;
  box-sizing: boder-box;
  font-family: "Source Code Pro Semibold", Consolas, monospace;
  text-align: center;
}
#grid > .cell.selected > span {
  border-color: dodgerblue;
  background: #def;
}
#grid > .cell.cell-red {
  color:red;
}
#grid > .cell.cell-green {
  color:green;
}
#grid > .cell.cell-purple {
  color:purple;
}
#grid > .cell.cell-yellow {
  color:#da0;
}

JavaScript

$(function(){
	var $grid = $('#grid'),
  		$cell = $(document.createElement('div')).attr({
      	'class':'cell',
        draggable: 'true',
     	}).append(document.createElement('span')),
  		grid = {},
      moveSpeed = 300,
      types = ['red','green','purple','yellow'];

  function calcDist(a,b){
      return Math.abs(a[0]-b[0])+Math.abs(a[1]-b[1]);
  }
  function calcDistEls($a, $b){
  	var idSelf = $a.attr('id'),
        coordSelf = idToCoords(idSelf),
        idSel = $b.attr('id'),
        coordSel = idToCoords(idSel);
    return calcDist(coordSel,coordSelf);
  }
	function idToCoords(id){
  	return id.split('-').slice(1);
  }
  function nobub(e){
  	e.preventDefault();
    e.stopPropagation();
  }
      
  for (var row = 0; row < 8; row++){
  	grid[row] = {};
  	for (var col = 0; col < 8; col++){
    	grid[row][col] = $cell.clone().attr('id', 'cell-'+row+'-'+col).addClass('cell-'+types[Math.floor(Math.random()*types.length)]).find('span').text(row+';'+col).end();
      $grid.append(grid[row][col]);
    }
  }
  
  function swap($a, $b){
  	var distance = calcDistEls($a, $b);
          
    if (distance > 1){
    	$b.removeClass('selected');
    	return;
    }
      
    $a.addClass('targeted');
      
  	var offsetA = $a.offset(),
    		offsetB = $b.offset(),
        fin = 0,
        finish = function(){
        	if (fin < 1)
          	return fin++;
          
          var $bc = $b.clone(),
          		bid = $b.attr('id'),
              bc = idToCoords(bid),
          		$ac = $a.clone(),
              aid = $a.attr('id'),
              ac = idToCoords(aid);
          $a.replaceWith($bc);
          $b.replaceWith($ac);
          $a = $bc;
          $b = $ac;
          grid[ac[0]][ac[1]] = $a;
          grid[bc[0]][bc[1]] = $b;
          $a.removeClass('selected').attr('id', aid);
          $b.removeClass('targeted').attr('id', bid);
          $b.children().add($a.children()).css({
          	top: '',
            left: '',
          });
        };
   	
  ...