Skip to content

Instantly share code, notes, and snippets.

@egorvinogradov
Created June 29, 2014 04:52
Show Gist options
  • Select an option

  • Save egorvinogradov/9328b080e1591624cdd3 to your computer and use it in GitHub Desktop.

Select an option

Save egorvinogradov/9328b080e1591624cdd3 to your computer and use it in GitHub Desktop.
html, body {
padding: 0;
margin: 0;
height: 100%;
}
body {
font-family: Verdana, sans-serif;
}
.container {
display: table;
width: 100%;
height: 100%;
text-align: center;
}
.container__inner {
display: table-cell;
vertical-align: middle;
}
.colors {
margin: 40px 0;
}
.colors__label {
text-transform: uppercase;
display: inline-block;
padding: 0 18px;
font-size: 14px;
color: #555;
}
.table {
background: #eee;
width: 340px;
height: 340px;
margin: 0 auto;
padding: 10px 0 0 10px;
box-sizing: border-box;
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.table__cell {
background: #ccc;
float: left;
width: 100px;
height: 100px;
line-height: 100px;
margin: 0 10px 10px 0;
box-sizing: border-box;
font-size: 42px;
cursor: pointer;
transition: top 700ms, left 700ms, transform 700ms, border-radius 700ms;
-webkit-transition: top 700ms, left 700ms, -webkit-transform 700ms, border-radius 700ms;
-moz-transition: top 700ms, left 700ms, -moz-transform 700ms, border-radius 700ms;
-ms-transition: top 700ms, left 700ms, -ms-transform 700ms, border-radius 700ms;
}
.table__cell_animation {
transform: scale(0.7);
-webkit-transform: scale(0.7);
-moz-transform: scale(0.7);
-ms-transform: scale(0.7);
border-radius: 25px;
}
.table__cell:hover {
border: 1px dashed #000;
line-height: 98px;
}
.buttons {
margin: 20px 0;
}
.buttons__button {
margin: 0 10px;
}
var App = function(params){
if ( !params ) {
throw new Error('Params are not passed');
}
this.container = $(params.container);
this.templates = params.templates;
if ( typeof this.templates !== 'object' ) {
throw new Error('Templates are not provided');
}
if ( !this.container.length ) {
throw new Error('Container is not provided');
}
};
App.prototype = {
selectors: {
colors: '.colors',
colorsRadio: '.colors__radio',
table: '.table',
tableCell: '.table__cell',
reset: '.buttons__reset',
randomize: '.buttons__randomize'
},
classes: {
tableCellAnimation: 'table__cell_animation'
},
animationDuration: 700, // ms
isAnimating: false,
currentColor: null,
defaultColor: null,
colors: {
red: null,
blue: null,
green: null
},
initialize: function(){
this.colorsContainer = $(this.selectors.colors, this.container);
this.tableContainer = $(this.selectors.table, this.container);
this.delegateEvents();
this.render();
this.defineColors();
},
defineColors: function(){
this.defaultColor = this.container
.find(this.selectors.tableCell)
.eq(0)
.css('backgroundColor');
for ( var color in this.colors ) {
var colorElement = $('<i></i>')
.appendTo(this.container)
.css({
backgroundColor: color
});
this.colors[color] = colorElement.css('backgroundColor');
colorElement.remove();
}
},
template: function(string, params){
var match;
var re = /<%\s([^%>]+)?\s%>/g;
while( match = re.exec(string) ) {
string = string.replace(match[0], params[match[1]])
}
return string;
},
render: function(){
var colorsHTML = [];
var tableHTML = [];
for ( var name in this.colors ) {
colorsHTML.push(
this.template(this.templates.colorsLabel, {
color: name
})
);
}
for ( var i = 1; i < 10; i++ ) {
tableHTML.push(
this.template(this.templates.tableCell, {
number: i
})
);
}
this.colorsContainer.html(colorsHTML.join('\n'));
this.tableContainer
.html(tableHTML.join('\n'))
.find(this.selectors.tableCell)
.each(function(i, cell){
var cell = $(cell);
cell.css(cell.position())
});
setTimeout($.proxy(function(){
this.tableContainer
.find(this.selectors.tableCell)
.css({ position: 'absolute' });
}, this), this.animationDuration);
},
delegateEvents: function(){
this.container.delegate(this.selectors.colorsRadio, 'click', $.proxy(function(e){
var target = $(e.currentTarget);
this.currentColor = target.data('color');
}, this));
this.container.delegate(this.selectors.tableCell, 'click', $.proxy(this.onTableCellClick, this));
this.container.delegate(this.selectors.reset, 'click', $.proxy(function(){
this.currentColor = null;
this.render();
}, this));
this.container.delegate(this.selectors.randomize, 'click', $.proxy(this.onRandomizeButtonClick, this));
},
onTableCellClick: function(e){
var target = $(e.currentTarget);
var targetColor;
for ( var name in this.colors ) {
if ( target.css('backgroundColor') === this.colors[name] ) {
targetColor = name;
break;
}
}
if ( targetColor && targetColor !== this.currentColor ) {
alert('Already applied ' + targetColor + ' color.');
}
else {
if ( this.currentColor ) {
target.css({
backgroundColor: this.currentColor
});
}
else {
alert('Please select a color before clicking on boxes.')
}
}
},
onRandomizeButtonClick: function(){
if ( this.isAnimating ) {
return false;
}
this.isAnimating = true;
setTimeout($.proxy(function(){
this.isAnimating = false;
}, this), this.animationDuration * 1.5);
var cells = this.container.find(this.selectors.tableCell);
var positions = [];
cells
.addClass(this.classes.tableCellAnimation)
.each(function(i, cell){
positions.push(
$(cell).position()
)
});
positions = this.shuffleArray(positions);
cells.each(function(i, cell){
$(cell).css(positions[i]);
});
setTimeout($.proxy(function(){
cells.removeClass(this.classes.tableCellAnimation)
}, this), this.animationDuration / 2);
},
shuffleArray: function(array){
// Fisher-Yates shuffle algorithm
var currentIndex = array.length;
var temporaryValue;
var randomIndex;
while (0 !== currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
};
$(function(){
window.app = new App({
container: '.container',
templates: {
colorsLabel: $('#colors-label').html(),
tableCell: $('#table-cell').html()
}
});
app.initialize();
});
<!DOCTYPE html>
<html>
<head>
<title>App</title>
<link rel="stylesheet" href="app.css">
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="app.js"></script>
</head>
<body>
<div class="container">
<div class="container__inner">
<div class="colors"></div>
<div class="table"></div>
<div class="buttons">
<button class="buttons__reset buttons__button">Reset</button>
<button class="buttons__randomize buttons__button">Randomize</button>
</div>
</div>
</div>
<!-- Templates -->
<script type="text/template" id="colors-label">
<label class="colors__label">
<input class="colors__radio" type="radio" name="color" data-color="<% color %>">
<% color %>
</label>
</script>
<script type="text/template" id="table-cell">
<div class="table__cell"><% number %></div>
</script>
<!-- / Templates -->
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment