2
* BytesJack <https://github.com/EtienneLem/bytesjack>
4
* Dev Etienne Lemay <http://twitter.com/#!/EtienneLem>
5
* Design Tristan L'abbé <http://twitter.com/#!/_Tristan>
7
* Special thanks to rafBM <http://twitter.com/#!/rafbm> for some JS tricks!
10
// Static class hack (auto init)
11
$(document).ready(function(){ window.App = new App() });
14
var App = function() { this.initialize.apply(this, arguments) };
15
App.prototype = (function() { var pro = {};
27
[{deg: 5, top: 0}, {deg: -5, top: 0}],
28
[{deg: 5, top: 15}, {deg: -1, top: 0}, {deg: -5, top: 15}],
29
[{deg: 9, top: 20}, {deg: 4, top: 0}, {deg: -4, top: 0}, {deg: -9, top: 15}],
30
[{deg: 12, top: 50}, {deg: 8, top: 10}, {deg: -4, top: 0}, {deg: -12, top: 15}, {deg: -16, top: 40}],
31
[{deg: 14, top: 40}, {deg: 8, top: 10}, {deg: -2, top: 5}, {deg: -5, top: 15}, {deg: -8, top: 40}, {deg: -14, top: 70}],
32
[{deg: 14, top: 70}, {deg: 8, top: 30}, {deg: 4, top: 10}, {deg: 0, top: 5}, {deg: -4, top: 20}, {deg: -8, top: 40}, {deg: -16, top: 70}]
36
var types = ['clubs', 'diamonds', 'hearts', 'spades'],
42
actionsNav = $('#actions'),
43
doubleBtn = $('#double'),
44
pCardsContainer = $('#player-cards'),
45
dCardsContainer = $('#dealer-cards'),
46
playerTotal = $('#player-total'),
49
dealerTotal = $('#dealer-total'),
53
allChips = $('.chip'),
55
bankroll = $('#bankroll'),
57
currentBet = allChips.first().data('value'),
65
pro.initialize = function(opts) { initialize() };
66
pro.deal = function() { deal() };
67
pro.hit = function() { hit() };
68
pro.stand = function() { stand() };
69
pro.doubledown = function() { doubledown() };
72
var initialize = function()
74
$('a[href="#"]').bind('click', function(e){ e.preventDefault(); });
79
setTimeout(function(){
85
var initResize = function()
87
$(window).bind('resize', onWindowResize);
91
var onWindowResize = function ( e )
93
clearTimeout(resizeTimer);
94
resizeTimer = setTimeout(function(){
100
var initKeyboardKeys = function() {
101
$(document).bind('keydown', onKeyDown);
102
$(document).bind('keyup', onKeyUp);
105
var onKeyDown = function ( e )
107
switch ( e.keyCode ) {
110
? actionsNav.children('li:first-child').children('a').addClass('active')
111
: dealNav.children('a').addClass('active');
113
case KEY_S : actionsNav.children('li:nth-child(2)').children('a').addClass('active'); break;
114
case KEY_D : actionsNav.children('li:nth-child(3)').children('a').addClass('active'); break;
115
case KEY_1 : selectChip(0); break;
116
case KEY_2 : selectChip(1); break;
117
case KEY_3 : selectChip(2); break;
121
var onKeyUp = function ( e )
125
switch ( e.keyCode ) {
129
actionsNav.children('li:first-child').children('a').removeClass('active')
132
dealNav.children('a').removeClass('active');
136
actionsNav.children('li:nth-child(2)').children('a').removeClass('active');
140
actionsNav.children('li:nth-child(3)').children('a').removeClass('active');
142
case KEY_1 : selectChip(0); break;
143
case KEY_2 : selectChip(1); break;
144
case KEY_3 : selectChip(2); break;
148
var selectChip = function ( index )
150
if ( isPlaying || gameEnded ) return;
151
allChips.eq(index).trigger('click');
155
var initDeck = function()
157
for ( var i = 0; i < types.length; i++ ) {
158
for ( var j = 1; j <= 13; j++ ) {
159
var value = ( j > 10 ) ? 10 : j;
160
cards.push({ card:j, value: value, type: types[i] });
167
var addCard = function ( side, player, callback )
169
var cardData = cards[cardsIndex],
170
container = ( player == 'player' ) ? pCardsContainer : dCardsContainer,
171
card = buildCard(cardsIndex, cardData.type, cardData.card, side),
182
container.append(card);
183
zIndex = ( player == 'player' ) ? card.index() : 50-card.index();
184
card.css('z-index', zIndex);
186
setTimeout(function(){
189
'left' : 10 * card.index() + '%'
191
rotateCards(container, (player == 'player'));
194
setTimeout(function(){
195
centerContainer(container);
196
if ( player == 'player' ) addToPlayerTotal(cardData.value);
197
else addToDealerTotal(cardData.value);
200
if ( callback != undefined ) callback.call();
201
}, ANIM_DELAY + 100);
205
var rotateCards = function ( container, isPlayer )
207
var cards = container.children('.card'),
208
numCards = cards.size() - 1,
209
increment = ( isPlayer ) ? -1 : 1,
210
pattern = ( PATTERNS[numCards] ) ? PATTERNS[numCards] : PATTERNS[PATTERNS.length-1];
212
cards.each(function(i){
213
var deg = ( i < pattern.length ) ? pattern[i].deg : pattern[pattern.length-1].deg,
214
offset = ( i < pattern.length ) ? pattern[i].top : pattern[pattern.length-1].top + (20 * (i - pattern.length + 1));
217
'-webkit-transform' : 'rotate('+ deg * increment +'deg)',
218
'-khtml-transform' : 'rotate('+ deg * increment +'deg)',
219
'-moz-transform' : 'rotate('+ deg * increment +'deg)',
220
'-ms-transform' : 'rotate('+ deg * increment +'deg)',
221
'transform' : 'rotate('+ deg * increment +'deg)',
222
'top' : offset * -increment + 'px'
227
var centerContainers = function()
229
centerContainer(pCardsContainer);
230
centerContainer(dCardsContainer);
233
var centerContainer = function ( container )
235
var lastCard = container.children('.card:last-child'),
238
if ( lastCard.size() == 0 ) return;
240
totalWidth = lastCard.position().left + lastCard.width();
241
if ( html.attr('browser') == 'Safari' )
242
container.css('-webkit-transform', 'translate3d('+ -totalWidth / 2 +'px,0,0)');
244
container.css('margin-left', -totalWidth / 2 + 'px');
247
var buildCard = function (id, type, value, side)
250
if ( side == 'back' ) card = $('<div data-id="'+id+'" class="card back"></div>');
252
var cardValue = ( value == 1 ) ? 'A' : ( value == 11 ) ? 'J' : ( value == 12 ) ? 'Q' : ( value == 13 ) ? 'K' : value,
253
cardIcon = ( type == 'hearts' ) ? '♥' : ( type == 'diamonds' ) ? '♦' : ( type == 'spades' ) ? '♠' : '♣',
254
corner = '<div><span>'+cardValue+'</span><span>'+cardIcon+'</span></div>',
258
for ( var i=1, l=value; i <= l; i++ ) {
259
icons += '<span>'+cardIcon+'</span>';
261
} else icons = ( value == 11 ) ? '<span>♝</span>' : ( value == 12 ) ? '<span>♛</span>' : ( value == 13 ) ? '<span>♚</span>' : '';
263
card = $('<div data-id="'+id+'" class="card value'+cardValue+' '+type+'">'+corner+'<div class="icons">'+icons+'</div>'+corner+'</div>');
270
var deal = function()
272
if ( isPlaying || !canDoAction || gameEnded ) return;
277
doubleBtn.removeClass('desactivate');
278
playerTotal.html('');
279
dealerTotal.html('');
289
$('#message').remove();
292
pCardsContainer.html('');
293
dCardsContainer.html('');
303
if ( !isPlaying || !canDoAction || isStanding || gameEnded ) return;
305
doubleBtn.addClass('desactivate');
306
addCard('front', 'player', function(){
307
if ( playerCards.sum() > 21 ) lose('lose-busted');
311
var stand = function()
313
if ( !isPlaying || !canDoAction || isStanding || gameEnded ) return;
318
setTimeout(function(){
319
if ( dealerCards.sum() < 17 ) dealerTurn();
324
var dealerTurn = function()
326
addCard('front', 'dealer', function(){
327
dealerTotal.html(calculateDealerScore());
329
if ( dealerCards.sum() < 17 ) dealerTurn();
334
var doubledown = function()
336
if ( !isPlaying || !canDoAction || isStanding || doubleBtn.hasClass('desactivate') || gameEnded ) return;
340
addCard('front', 'player', function(){
341
if ( playerCards.sum() > 21 ) lose('lose-busted');
346
var push = function ( msg )
349
var increment = ( doubled ) ? 2 : 1;
350
changeBankroll(increment);
354
var win = function ( msg )
357
var increment = ( doubled ) ? 4 : 2;
358
changeBankroll(increment);
362
var lose = function ( msg )
369
var showMessage = function ( status )
371
var msg = document.createElement('div'),
373
message = $('#message');
375
if ( message.size() > 0 ) message.remove();
377
msg.className = status;
381
case 'win': content = 'You win'; break;
382
case 'win-blackjack': content = 'You win<span>Blackjack</span>'; break;
383
case 'win-dealer-busted': content = 'You win<span>Dealer busted</span>'; break;
384
case 'lose': content = 'You lose'; break;
385
case 'lose-blackjack': content = 'You lose<span>Blackjack</span>'; break;
386
case 'lose-busted': content = 'You lose<span>Busted</span>'; break;
387
case 'push': content = 'Push<span>No winner</span>'; break;
388
case 'game-over': content = 'Game over'; break;
389
default: content = '<span>Something broke, don’t know what happened...</span>'; break;
392
msg.innerHTML = content;
393
pCardsContainer.after(msg);
398
var pScore = playerCards.sum(),
399
dScore = dealerCards.sum();
401
if ( dScore > 21 ) win('win-dealer-busted');
402
else if ( dScore > pScore ) lose('lose');
403
else if ( pScore > dScore ) win('win');
404
else if ( pScore == dScore ) push('push');
407
var endGame = function()
409
showMessage('game-over');
412
var overlay = document.createElement('div');
413
overlay.id = 'overlay';
415
$('body').append(overlay);
418
var stopGame = function()
423
chips.removeClass('disabled');
425
allChips.each(function(i){
427
if ( chip.data('value') > bank ) {
428
chip.addClass('desactivate');
430
var chipsAvailable = allChips.removeClass('bet').not('.desactivate');
431
if ( chipsAvailable.size() == 0 ) endGame();
433
var newChip = chipsAvailable.last();
434
newChip.addClass('bet');
435
changeBet(newChip.data('value'));
436
chips.prepend(newChip);
439
} else if ( chip.hasClass('desactivate') ) chip.removeClass('desactivate');
443
var ditributeCards = function()
447
addCard('front', 'player', function(){
448
addCard('front', 'dealer', function(){
449
addCard('front', 'player', function(){
450
addCard('back', 'dealer', function(){
459
chips.addClass('disabled');
462
var checkBlackjack = function()
464
var pScore = playerCards.sum(),
465
dScore = dealerCards.sum();
467
if ( pScore == 21 && dScore == 21 ) push('Push - No winner');
468
else if ( pScore == 21 ) win('win-blackjack');
469
else if ( dScore == 21 ) {
470
lose('lose-blackjack');
476
var addToPlayerTotal = function ( value )
483
playerCards.push(value);
484
playerTotal.html(calculatePlayerScore());
487
var calculatePlayerScore = function()
489
var score = playerCards.sum();
491
if ( score > 21 && playerAces > 0 ) {
492
playerCards.splice(playerCards.indexOf(11), 1, 1);
494
score = calculatePlayerScore();
501
var revealDealerCard = function()
503
var card = $('.back'),
504
id = card.data('id'),
506
newCard = buildCard(id, data.type, data.value, 'front');
509
'left' : 10 * card.index() + '%',
510
'z-index' : 50-card.index()
513
card.after(newCard).remove();
514
dealerTotal.html(calculateDealerScore());
517
var addToDealerTotal = function ( value )
524
dealerCards.push(value);
527
var calculateDealerScore = function()
529
var score = dealerCards.sum();
531
if ( score > 21 && dealerAces > 0 ) {
532
dealerCards.splice(dealerCards.indexOf(11), 1, 1);
534
score = calculateDealerScore();
541
var initBet = function()
543
allChips.bind('click', function(e){
545
if ( isPlaying || chip.hasClass('desactivate') ) return;
547
allChips.removeClass('bet');
548
chip.addClass('bet');
549
changeBet(chip.data('value'));
555
var changeBet = function ( newValue ) {
556
if ( isPlaying ) return;
557
currentBet = newValue;
560
var changeBankroll = function ( increment ) {
561
bank += increment * currentBet;
562
bankroll.html((bank / 10) + 'k');
568
* Array shuffle <http://snipplr.com/view/535>
569
* Array sum <http://snipplr.com/view/533>
571
Array.prototype.shuffle = function() { for(var j, x, i = this.length; i; j = Math.floor(Math.random() * i), x = this[--i], this[i] = this[j], this[j] = x); }
572
Array.prototype.sum = function() { for(var s = 0, i = this.length; i; s += this[--i]); return s; };
575
* Browser Detect <http://teev.io/blog/text/13423292>
577
var BrowserDetect = {
579
this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
580
this.version = this.searchVersion(navigator.userAgent)
581
|| this.searchVersion(navigator.appVersion)
582
|| "an unknown version";
583
this.OS = this.searchString(this.dataOS) || "an unknown OS";
585
var b = document.documentElement;
586
b.setAttribute('browser', this.browser);
587
b.setAttribute('version', this.version );
588
b.setAttribute('os', this.OS);
590
searchString: function (data) {
591
for (var i=0;i<data.length;i++) {
592
var dataString = data[i].string;
593
var dataProp = data[i].prop;
594
this.versionSearchString = data[i].versionSearch || data[i].identity;
596
if (dataString.indexOf(data[i].subString) != -1)
597
return data[i].identity;
600
return data[i].identity;
603
searchVersion: function (dataString) {
604
var index = dataString.indexOf(this.versionSearchString);
605
if (index == -1) return;
606
return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
610
string: navigator.userAgent,
614
{ string: navigator.userAgent,
615
subString: "OmniWeb",
616
versionSearch: "OmniWeb/",
620
string: navigator.vendor,
623
versionSearch: "Version"
628
versionSearch: "Version"
631
string: navigator.vendor,
636
string: navigator.vendor,
638
identity: "Konqueror"
641
string: navigator.userAgent,
642
subString: "Firefox",
646
string: navigator.vendor,
650
{ // for newer Netscapes (6+)
651
string: navigator.userAgent,
652
subString: "Netscape",
656
string: navigator.userAgent,
658
identity: "Explorer",
659
versionSearch: "MSIE"
662
string: navigator.userAgent,
667
{ // for older Netscapes (4-)
668
string: navigator.userAgent,
669
subString: "Mozilla",
670
identity: "Netscape",
671
versionSearch: "Mozilla"
676
string: navigator.platform,
681
string: navigator.platform,
686
string: navigator.userAgent,
688
identity: "iPhone/iPod"
691
string: navigator.platform,
697
BrowserDetect.init();
b'\\ No newline at end of file'