javascript game ( 3 in line ) line check logic - javascript

i've been in a battle to sort this problem since yesterday and i fear that i've gotten tunnel vision.
The game:
first player to make a line of 3 of a kind (xxx or 000) wins.
http://jsfiddle.net/brunobliss/YANAW/
The catch:
Only the first horizontal line is working!!! I can make it all work using a lot of IFS but repeating the same code over and over again is often a good indicator that i'm doing somethin wrong
The problem:
bruno.checkWin(); will check if there's a line or not, the guy who presented me this game chalenge told me that it is possible to check the lines with a for loop and that i should use it instead of IFS. I can't solve this without IFS unfortunately...
<!doctype html>
<html>
<head>
<meta charset="iso-8859-1">
<title> </title>
<style>
#jogo {
border: #000 1px solid;
width: 150px;
position: absolute;
left: 50%;
top: 50%;
margin-left: -75px;
margin-top: -75px;
}
#jogo div {
display: inline-block;
vertical-align: top;
width: 28px;
height: 28px;
padding: 10px;
font-size: 20px;
border: #000 1px solid;
border-collapse: collapse;
text-align: center;
}
#reset {
font-family: Verdana;
width: 153px;
height: 30px;
background-color: black;
color: white;
text-align: center;
cursor: pointer;
left: 50%;
top: 50%;
position: absolute;
margin-left: -76px;
margin-top: 100px;
}
</style>
<script> </script>
</head>
<body>
<div id="jogo"> </div>
<div id="reset"> RESET </div>
<script>
var ultimo = "0";
var reset = document.getElementById('reset');
var jogo = document.getElementById('jogo');
var cell = jogo.getElementsByTagName('div');
var bruno = {
init: function () {
var jogo = document.getElementById('jogo');
for ( i = 0 ; i < 9 ; i++ ) {
var cell = document.createElement('div');
cell.onclick = function () {
// variavel publica dentro do obj?
ultimo = (ultimo == "x") ? 0 : "x";
this.innerHTML = ultimo;
bruno.checkWin();
};
jogo.appendChild(cell);
}
},
checkWin: function () {
var jogo = document.getElementById('jogo');
var cell = jogo.getElementsByTagName('div');
// as diagonais nao verificar por loop
for ( i = 0 ; i < cell.length ; i=i+4 ) {
switch(i) {
case 0:
if (cell[0].innerHTML != '') {
bruno.checkFirst();
}
case 4:
if (cell[4].innerHTML != '') {
bruno.checkFirst();
}
case 8:
if (cell[8].innerHTML != '') {
bruno.checkFirst();
}
}
/*
} else
if (i == 4 && cell[4].innerHTML != '') {
bruno.checkCenter();
} else
if (i == 8 && cell[8].innerHTML != '') {
bruno.checkLast();
}*/
}
},
reset: function () {
var jogo = document.getElementById('jogo');
var cell = jogo.getElementsByTagName('div');
for ( j = 0 ; j < cell.length ; j++ ) {
cell[j].innerHTML = "";
}
},
checkFirst: function () {
if (cell[0].innerHTML == cell[1].innerHTML && cell[1].innerHTML == cell[2].innerHTML) {
alert("linha horizontal");
return false;
} else
if (cell[0].innerHTML == cell[3].innerHTML && cell[3].innerHTML == cell[6].innerHTML) {
alert("linha vertical");
return false;
}
},
checkMiddle: function () {
// check vertical and horizontal lines from the center
},
checkLast: function () {
// check last horizontal and right edge vertical
}
};
window.onload = function () {
bruno.init();
};
reset.onclick = function () {
bruno.reset();
};
</script>
</body>
</html>

I came up with a more 'compact' version of your code. No switch statements. Have a look:
http://jsfiddle.net/YANAW/1/
Here's the code, for those who prefer to read it here. Important/updated functions are checkWin() and checkCells().
var bruno = {
init: function () {
var jogo = document.getElementById('jogo');
for ( i = 0 ; i < 9 ; i++ ) {
var cell = document.createElement('div');
cell.onclick = function () {
// variavel publica dentro do obj?
ultimo = (ultimo == "x") ? 0 : "x";
this.innerHTML = ultimo;
bruno.checkWin();
};
jogo.appendChild(cell);
}
},
checkWin: function () {
var jogo = document.getElementById('jogo');
var cells = jogo.getElementsByTagName('div');
// Scan through every cell
var numRows = 3;
var numColumns = 3;
for (var i = 0; i < cells.length; i++)
{
// Determine cell's position
var isHorizontalFirstCell = ((i % numColumns) === 0);
var isVerticalFirstCell = (i < numColumns);
var isTopLeftCorner = (i == 0);
var isTopRightCorner = (i == 2);
// Check for horizontal matches
if (isHorizontalFirstCell
&& bruno.checkCells(
cells, i,
(i + 3), 1))
{
alert('Horizontal');
}
// Check for vertical matches
if (isVerticalFirstCell
&& bruno.checkCells(
cells, i,
(i + 7), 3))
{
alert('Vertical');
}
// Check for diagonal matches
if (isTopLeftCorner
&& bruno.checkCells(
cells, i,
(i + 9), 4))
{
alert('Diagonal');
}
if (isTopRightCorner
&& bruno.checkCells(
cells, i,
(i + 5), 2))
{
alert('Diagonal');
}
}
},
reset: function () {
var jogo = document.getElementById('jogo');
var cell = jogo.getElementsByTagName('div');
for ( j = 0 ; j < cell.length ; j++ ) {
cell[j].innerHTML = "";
}
},
checkCells: function(cells, index, limit, step) {
var sequenceChar = null;
for (var i = index; i < limit; i += step)
{
// Return false immediately if one
// of the cells in the sequence is empty
if (!cells[i].innerHTML)
return false;
// If this is the first cell we're checking,
// store the character(s) it holds.
if (sequenceChar === null)
sequenceChar = cells[i].innerHTML;
// Otherwise, confirm that this cell holds
// the same character(s) as the previous cell(s).
else if (cells[i].innerHTML !== sequenceChar)
return false;
}
// If we reached this point, the entire sequence
// of cells hold the same character(s).
return true;
}
};

Related

How to automatically place "read more" when characters hit X amount

I'm currently using a nice bit of open source code which pulls Google reviews.
Issue is, if a review is very long... it makes my site look weird. I need to set a max amount of characters, but give the user the option to read the full review. I'm not sure if this should be done through jQuery, CSS or what... Looking for some guidance.
See my issue here:
My code is here:
jQuery(document).ready(function( $ ) {
$("#google-reviews").googlePlaces({
placeId: 'place ID' //Find placeID #: https://developers.google.com/places/place-id
, render: ['reviews']
, min_rating: 5
, max_rows:3
});
});
/* https://github.com/peledies/google-places */
(function($) {
$.googlePlaces = function(element, options) {
var defaults = {
placeId: 'place ID' // placeId provided by google api documentation
, render: ['reviews']
, min_rating: 0
, max_rows: 0
, rotateTime: false
};
var plugin = this;
plugin.settings = {}
var $element = $(element),
element = element;
plugin.init = function() {
plugin.settings = $.extend({}, defaults, options);
$element.html("<div id='map-plug'></div>"); // create a plug for google to load data into
initialize_place(function(place){
plugin.place_data = place;
// render specified sections
if(plugin.settings.render.indexOf('reviews') > -1){
renderReviews(plugin.place_data.reviews);
if(!!plugin.settings.rotateTime) {
initRotation();
}
}
});
}
var initialize_place = function(c){
var map = new google.maps.Map(document.getElementById('map-plug'));
var request = {
placeId: plugin.settings.placeId
};
var service = new google.maps.places.PlacesService(map);
service.getDetails(request, function(place, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
c(place);
}
});
}
var sort_by_date = function(ray) {
ray.sort(function(a, b){
var keyA = new Date(a.time),
keyB = new Date(b.time);
// Compare the 2 dates
if(keyA < keyB) return -1;
if(keyA > keyB) return 1;
return 0;
});
return ray;
}
var filter_minimum_rating = function(reviews){
for (var i = reviews.length -1; i >= 0; i--) {
if(reviews[i].rating < plugin.settings.min_rating){
reviews.splice(i,1);
}
}
return reviews;
}
var renderReviews = function(reviews){
reviews = sort_by_date(reviews);
reviews = filter_minimum_rating(reviews);
var html = "";
var row_count = (plugin.settings.max_rows > 0)? plugin.settings.max_rows - 1 : reviews.length - 1;
// make sure the row_count is not greater than available records
row_count = (row_count > reviews.length-1)? reviews.length -1 : row_count;
for (var i = row_count; i >= 0; i--) {
var stars = renderStars(reviews[i].rating);
var date = convertTime(reviews[i].time);
html = html+"<div class='review-item'><div class='review-meta'><span class='review-author'>"+reviews[i].author_name+"</span><span class='review-sep'>, </span><span class='review-date'>"+date+"</span></div>"+stars+"<p class='review-text'>"+reviews[i].text+"</p></div>"
};
$element.append(html);
}
var initRotation = function() {
var $reviewEls = $element.children('.review-item');
var currentIdx = $reviewEls.length > 0 ? 0 : false;
$reviewEls.hide();
if(currentIdx !== false) {
$($reviewEls[currentIdx]).show();
setInterval(function(){
if(++currentIdx >= $reviewEls.length) {
currentIdx = 0;
}
$reviewEls.hide();
$($reviewEls[currentIdx]).fadeIn('slow');
}, plugin.settings.rotateTime);
}
}
var renderStars = function(rating){
var stars = "<div class='review-stars'><ul>";
// fill in gold stars
for (var i = 0; i < rating; i++) {
stars = stars+"<li><i class='star'></i></li>";
};
// fill in empty stars
if(rating < 5){
for (var i = 0; i < (5 - rating); i++) {
stars = stars+"<li><i class='star inactive'></i></li>";
};
}
stars = stars+"</ul></div>";
return stars;
}
var convertTime = function(UNIX_timestamp){
var a = new Date(UNIX_timestamp * 1000);
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var time = months[a.getMonth()] + ' ' + a.getDate() + ', ' + a.getFullYear();
return time;
}
plugin.init();
}
$.fn.googlePlaces = function(options) {
return this.each(function() {
if (undefined == $(this).data('googlePlaces')) {
var plugin = new $.googlePlaces(this, options);
$(this).data('googlePlaces', plugin);
}
});
}
})(jQuery);
#map-plug {display:none;}
#google-reviews {
display:flex;
flex-wrap:wrap;
//display: grid;
//grid-template-columns: repeat( auto-fit, minmax(320px, 1fr));
}
.review-item {
margin:0 auto;
padding:1em;
flex: 1 1 20%;
}
#media ( max-width:1200px) {
.review-item { flex: 1 1 40%; }
}
#media ( max-width:450px) {
.review-item { flex: 1 1 90%; }
}
.review-meta, .review-stars {text-align:center; font-size:115%;}
.review-author { text-transform: capitalize; font-weight:bold; }
.review-date {opacity:.6; display:block;}
.review-text { line-height:1.55; text-align:left; max-width:32em; margin:auto;}
.review-stars ul {
display: inline-block;
list-style: none;
margin:0; padding:0;
}
.review-stars ul li {
float: left;
margin-right: 1px;
line-height:1;
}
.review-stars ul li i {
color: #E4B248;
font-size: 1.4em;
font-style:normal;
}
.review-stars ul li i.inactive { color: #c6c6c6;}
.star:after { content: "\2605"; }
<div id="google-reviews"></div>
The substr method will return the part of a string between the start index and a number of characters after it and will truncate your text.
Ex:
reviews[i].text.substr(0, 100 /* amount of characters */) + " read more..."

Calculate the word amount from an <input>?

The following code converts text into equal paragraphs, based on the users input character amount.
Is it possible for the input box to calculate the amount of words for each paragraph instead of being based on the character amount?
JSFiddle
If an updated fiddle could please be provided, would be much appreciated, as I am still new to coding.
Thank You!
$(function() {
$('select').on('change', function() {
//Lets target the parent element, instead of P. P will inherit it's font size (css)
var targets = $('#content'),
property = this.dataset.property;
targets.css(property, this.value);
sameheight('#content p');
}).prop('selectedIndex', 0);
});
var btn = document.getElementById('go'),
textarea = document.getElementById('textarea1'),
content = document.getElementById('content');
chunkSize = 100;
btn.addEventListener('click', initialDistribute);
content.addEventListener('keyup', handleKey);
content.addEventListener('paste', handlePaste);
function initialDistribute() {
custom = parseInt(document.getElementById("custom").value);
chunkSize = (custom>0)?custom:chunkSize;
var text = textarea.value;
while (content.hasChildNodes()) {
content.removeChild(content.lastChild);
}
rearrange(text);
}
function rearrange(text) {
var chunks = splitText(text, false);
chunks.forEach(function(str, idx) {
para = document.createElement('P');
para.classList.add("Paragraph_CSS");
para.setAttribute('contenteditable', true);
para.textContent = str;
content.appendChild(para);
});
sameheight('#content p');
}
function handleKey(e) {
var para = e.target,
position,
key, fragment, overflow, remainingText;
key = e.which || e.keyCode || 0;
if (para.tagName != 'P') {
return;
}
if (key != 13 && key != 8) {
redistributeAuto(para);
return;
}
position = window.getSelection().getRangeAt(0).startOffset;
if (key == 13) {
fragment = para.lastChild;
overflow = fragment.textContent;
fragment.parentNode.removeChild(fragment);
remainingText = overflow + removeSiblings(para, false);
rearrange(remainingText);
}
if (key == 8 && para.previousElementSibling && position == 0) {
fragment = para.previousElementSibling;
remainingText = removeSiblings(fragment, true);
rearrange(remainingText);
}
}
function handlePaste(e) {
if (e.target.tagName != 'P') {
return;
}
overflow = e.target.textContent + removeSiblings(fragment, true);
rearrange(remainingText);
}
function redistributeAuto(para) {
var text = para.textContent,
fullText;
if (text.length > chunkSize) {
fullText = removeSiblings(para, true);
}
rearrange(fullText);
}
function removeSiblings(elem, includeCurrent) {
var text = '',
next;
if (includeCurrent && !elem.previousElementSibling) {
parent = elem.parentNode;
text = parent.textContent;
while (parent.hasChildNodes()) {
parent.removeChild(parent.lastChild);
}
} else {
elem = includeCurrent ? elem.previousElementSibling : elem;
while (next = elem.nextSibling) {
text += next.textContent;
elem.parentNode.removeChild(next);
}
}
return text;
}
function splitText(text, useRegex) {
var chunks = [],
i, textSize, boundary = 0;
if (useRegex) {
var regex = new RegExp('.{1,' + chunkSize + '}\\b', 'g');
chunks = text.match(regex) || [];
} else {
for (i = 0, textSize = text.length; i < textSize; i = boundary) {
boundary = i + chunkSize;
if (boundary <= textSize && text.charAt(boundary) == ' ') {
chunks.push(text.substring(i, boundary));
} else {
while (boundary <= textSize && text.charAt(boundary) != ' ') {
boundary++;
}
chunks.push(text.substring(i, boundary));
}
}
}
return chunks;
}
#text_land {
border: 1px solid #ccc;
padding: 25px;
margin-bottom: 30px;
}
textarea {
width: 95%;
}
label {
display: block;
width: 50%;
clear: both;
margin: 0 0 .5em;
}
label select {
width: 50%;
float: right;
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
body {
font-family: monospace;
font-size: 1em;
}
h3 {
margin: 1.2em 0;
}
div {
margin: 1.2em;
}
textarea {
width: 100%;
}
button {
padding: .5em;
}
p {
/*Here the sliles for OTHER paragraphs*/
}
#content p {
font-size: inherit;
/*So it gets the font size set on the #content div*/
padding: 1.2em .5em;
margin: 1.4em 0;
border: 1px dashed #aaa;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<h3>Import Text below, then press the button</h3>
<textarea id="textarea1" placeholder="Type text here, then press the button below." rows="5">
</textarea>
<input style="width:200px;" id="custom" placeholder="Custom Characters per box">
<br>
<button style="width:200px;" id="go">Divide Text into Paragraphs</button>
</div>
<div>
<h3 align="right">Divided Text Will Appear Below:</h3>
<hr>
<div id="content"></div>
</div>
How about this? It uses jQuery, but as you used the library in your original submission, I hope that won't be an issue:
HTML
<textarea id="input"></textarea>
<br/>
<button id='divide'>Divide</button>
<div id="paras"></div>
CSS
#input {
resize: none;
height: 200px;
width: 100%;
}
JS
$(function() {
$("#divide").click(function() {
var text = $("#input").val();
var wpp = 10 // words per paragraph
var words = text.split(" ");
var paras = [];
for (i = 0; i < words.length; i += wpp) {
paras.push(words.slice(i, i + wpp).join(" "));
}
$.each(paras, function(i, para) {
$("#paras").append("<p>" + para + "</p>");
});
});
})
JSFiddle

javascript:window.print() not showing barcode for printing

I am making Mean Stack App in which I need to print barcode, I am using an angular js directive for generating code 128 barcode, and it is generating well, but when I click print button (javascript:window.print()) it is not showing the barcode in printing window neither in PDF,
Here is my directive,
.directive('barcodeGenerator', [function() {
var Barcode = (function () {
var barcode = {
settings: {
barWidth: 1,
barHeight: 50,
moduleSize: 5,
showHRI: false,
addQuietZone: true,
marginHRI: 5,
bgColor: "#FFFFFF",
color: "#000000",
fontSize: 10,
posX: 0,
posY: 0
},
intval: function(val) {
var type = typeof(val);
if ( type == 'string' ) {
val = val.replace(/[^0-9-.]/g, "");
val = parseInt(val * 1, 10);
return isNaN(val) || !isFinite(val)? 0: val;
}
return type == 'number' && isFinite(val)? Math.floor(val): 0;
},
code128: {
encoding:[
"11011001100", "11001101100", "11001100110", "10010011000",
"10010001100", "10001001100", "10011001000", "10011000100",
"10001100100", "11001001000", "11001000100", "11000100100",
"10110011100", "10011011100", "10011001110", "10111001100",
"10011101100", "10011100110", "11001110010", "11001011100",
"11001001110", "11011100100", "11001110100", "11101101110",
"11101001100", "11100101100", "11100100110", "11101100100",
"11100110100", "11100110010", "11011011000", "11011000110",
"11000110110", "10100011000", "10001011000", "10001000110",
"10110001000", "10001101000", "10001100010", "11010001000",
"11000101000", "11000100010", "10110111000", "10110001110",
"10001101110", "10111011000", "10111000110", "10001110110",
"11101110110", "11010001110", "11000101110", "11011101000",
"11011100010", "11011101110", "11101011000", "11101000110",
"11100010110", "11101101000", "11101100010", "11100011010",
"11101111010", "11001000010", "11110001010", "10100110000",
"10100001100", "10010110000", "10010000110", "10000101100",
"10000100110", "10110010000", "10110000100", "10011010000",
"10011000010", "10000110100", "10000110010", "11000010010",
"11001010000", "11110111010", "11000010100", "10001111010",
"10100111100", "10010111100", "10010011110", "10111100100",
"10011110100", "10011110010", "11110100100", "11110010100",
"11110010010", "11011011110", "11011110110", "11110110110",
"10101111000", "10100011110", "10001011110", "10111101000",
"10111100010", "11110101000", "11110100010", "10111011110",
"10111101110", "11101011110", "11110101110", "11010000100",
"11010010000", "11010011100", "11000111010"
],
getDigit: function(code) {
var tableB = " !\"#$%&'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
var result = "";
var sum = 0;
var isum = 0;
var i = 0;
var j = 0;
var value = 0;
// check each characters
for(i=0; i<code.length; i++){
if (tableB.indexOf(code.charAt(i)) == -1){
return("");
}
}
// check firsts characters : start with C table only if enought numeric
var tableCActivated = code.length > 1;
var c = '';
for (i=0; i<3 && i<code.length; i++) {
c = code.charAt(i);
tableCActivated &= c >= '0' && c <= '9';
}
sum = tableCActivated ? 105 : 104;
// start : [105] : C table or [104] : B table
result = this.encoding[ sum ];
i = 0;
while ( i < code.length ) {
if ( !tableCActivated) {
j = 0;
// check next character to activate C table if interresting
while ( (i + j < code.length) && (code.charAt(i+j) >= '0') && (code.charAt(i+j) <= '9') ) {
j++;
}
// 6 min everywhere or 4 mini at the end
tableCActivated = (j > 5) || ((i + j - 1 == code.length) && (j > 3));
if ( tableCActivated ){
result += this.encoding[ 99 ]; // C table
sum += ++isum * 99;
} // 2 min for table C so need table B
} else if ( (i == code.length) || (code.charAt(i) < '0') || (code.charAt(i) > '9') || (code.charAt(i+1) < '0') || (code.charAt(i+1) > '9') ) {
tableCActivated = false;
result += this.encoding[ 100 ]; // B table
sum += ++isum * 100;
}
if ( tableCActivated ) {
value = barcode.intval(code.charAt(i) + code.charAt(i+1)); // Add two characters (numeric)
i += 2;
} else {
value = tableB.indexOf( code.charAt(i) ); // Add one character
i += 1;
}
result += this.encoding[ value ];
sum += ++isum * value;
}
result += this.encoding[sum % 103];// Add CRC
result += this.encoding[106];// Stop
result += "11";// Termination bar
return(result);
}
},
bitStringTo2DArray: function( digit) {//convert a bit string to an array of array of bit char
var d = [];
d[0] = [];
for ( var i=0; i<digit.length; i++) {
d[0][i] = digit.charAt(i);
}
return(d);
},
digitToCssRenderer: function( $container, settings, digit, hri, mw, mh, type) {// css barcode renderer
var lines = digit.length;
var columns = digit[0].length;
var content = "";
var len, current;
var bar0 = "<div class='w w%s' ></div>";
var bar1 = "<div class='b b%s' ></div>";
for ( var y=0, x; y<lines; y++) {
len = 0;
current = digit[y][0];
for ( x=0; x<columns; x++){
if ( current == digit[y][x] ) {
len++;
} else {
content += (current == '0'? bar0: bar1).replace("%s", len * mw);
current = digit[y][x];
len=1;
}
}
if ( len > 0) {
content += (current == '0'? bar0: bar1).replace("%s", len * mw);
}
}
if ( settings.showHRI) {
content += "<div style=\"clear:both; width: 100%; background-color: " + settings.bgColor + "; color: " + settings.color + "; text-align: center; font-size: " + settings.fontSize + "px; margin-top: " + settings.marginHRI + "px;\">"+hri+"</div>";
}
var div = document.createElement('DIV');
div.innerHTML = content;
div.className = 'barcode '+ type +' clearfix-child';
return div;
},
digitToCss: function($container, settings, digit, hri, type) {// css 1D barcode renderer
var w = barcode.intval(settings.barWidth);
var h = barcode.intval(settings.barHeight);
return this.digitToCssRenderer($container, settings, this.bitStringTo2DArray(digit), hri, w, h, type);
}
};
var generate = function(datas, type, settings) {
var
digit = "",
hri = "",
code = "",
crc = true,
rect = false,
b2d = false
;
if ( typeof(datas) == "string") {
code = datas;
} else if (typeof(datas) == "object") {
code = typeof(datas.code) == "string" ? datas.code : "";
crc = typeof(datas.crc) != "undefined" ? datas.crc : true;
rect = typeof(datas.rect) != "undefined" ? datas.rect : false;
}
if (code == "") {
return(false);
}
if (typeof(settings) == "undefined") {
settings = [];
}
for( var name in barcode.settings) {
if ( settings[name] == undefined) {
settings[name] = barcode.settings[name];
}
}
switch (type) {
case "std25":
case "int25": {
digit = barcode.i25.getDigit(code, crc, type);
hri = barcode.i25.compute(code, crc, type);
break;
}
case "ean8":
case "ean13": {
digit = barcode.ean.getDigit(code, type);
hri = barcode.ean.compute(code, type);
break;
}
case "upc": {
digit = barcode.upc.getDigit(code);
hri = barcode.upc.compute(code);
break;
}
case "code11": {
digit = barcode.code11.getDigit(code);
hri = code;
break;
}
case "code39": {
digit = barcode.code39.getDigit(code);
hri = code;
break;
}
case "code93": {
digit = barcode.code93.getDigit(code, crc);
hri = code;
break;
}
case "code128": {
digit = barcode.code128.getDigit(code);
hri = code;
break;
}
case "codabar": {
digit = barcode.codabar.getDigit(code);
hri = code;
break;
}
case "msi": {
digit = barcode.msi.getDigit(code, crc);
hri = barcode.msi.compute(code, crc);
break;
}
case "datamatrix": {
digit = barcode.datamatrix.getDigit(code, rect);
hri = code;
b2d = true;
break;
}
}
if ( digit.length == 0) {
return this;
}
if ( !b2d && settings.addQuietZone) {
digit = "0000000000" + digit + "0000000000";
}
var fname = 'digitToCss' + (b2d ? '2D' : '');
return barcode[fname](this, settings, digit, hri, type);
};
return generate;
}());
return {
link: function(scope, element, attrs) {
attrs.$observe('barcodeGenerator', function(value){
var code = Barcode(value, "code128",{barWidth:2}),
code_wrapper = angular.element("<div class='barcode code128'></div>")
code_wrapper.append(code);
angular.element(element).html('').append(code_wrapper);
});
}
}
And here is barcode generating code,
<div ng-model='myInput' barcode-generator="{{myInput}}" style="height:208px;">
</div>
Here are the screenshots
It shows barcode on the page
But not shows up while printing
It's because some browsers has turned off rendering background-color in print mode by default. You won't force all users to mess up with browser settings, but you can replace background-color with border-width like this:
<style type="text/css" media="print">
.barcode.code128 > div.b {
border-style: solid !important;
border-color: #000000 !important;
}
.barcode.code128 .b1 {
width: 0px !important;
border-width: 0px 0px 0px 1px !important;
}
.barcode.code128 .b2 {
width: 0px !important;
border-width: 0px 0px 0px 2px !important;
}
.barcode.code128 .b3 {
width: 0px !important;
border-width: 0px 0px 0px 3px !important;
}
.barcode.code128 .b4 {
width: 0px !important;
border-width: 0px 0px 0px 4px !important;
}
.barcode.code128 .b5 {
width: 0px !important;
border-width: 0px 0px 0px 5px !important;
}
.barcode.code128 .b6 {
width: 0px !important;
border-width: 0px 0px 0px 6px !important;
}
.barcode.code128 .b7 {
width: 0px !important;
border-width: 0px 0px 0px 7px !important;
}
.barcode.code128 .b8 {
width: 0px !important;
border-width: 0px 0px 0px 8px !important;
}
.barcode.code128 .b9 {
width: 0px !important;
border-width: 0px 0px 0px 9px !important;
}
.barcode.code128 .b10 {
width: 0px !important;
border-width: 0px 0px 0px 10px !important;
}

Javascript end game when click on image

Hey this is my first time on Stackoverflow!
I am building a small javascript html5 game where you click on objects kind of like whack-a-mole.. The goal is to kill as many "gem green" and " gem blue" as possible in 10 seconds, and when you click on the "gem red".. the game ends and plays a sound.
I got most things to work, except I can't find a way to make the game end when clicking on "gem red".. I have tried lots of functions and listeners.. but to no avail.. can anyone help me figure this out?
Here is the code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>HTML 5 Gem Game</title>
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1">
<style>
section#game {
width: 480px;
height: 800px;
max-width: 100%;
max-height: 100%;
overflow: hidden;
position: relative;
background-image: url('img/Splash.png');
position: relative;
color: #ffffff;
font-size: 30px;
font-family: "arial,sans-serif";
}
section#game .score{
display: block;
position: absolute;
top: 10px;
left: 10px;
}
section#game .time{
display: block;
position: absolute;
top: 10px;
right: 10px;
}
section#game .start{
display: block;
padding-top: 40%;
margin: 0 auto 0 auto;
text-align: center;
width: 70%;
cursor: pointer;
}
section#game .start .high-scores{
text-align: left;
}
section#game .gem{
display: block;
position: absolute;
width: 40px;
height: 44px;
cursor: pointer;
}
section#game .gem.green{
background: url('img/Gem Green.png') no-repeat top left;
}
section#game .gem.blue{
background: url('img/Gem Blue.png') no-repeat top left;
}
section#game .gem.red{
background: url('img/Gem Red.png') no-repeat top left;
}
</style>
<script>
function addEvent(element, event, delegate ) {
if (typeof (window.event) != 'undefined' && element.attachEvent)
element.attachEvent('on' + event, delegate);
else
element.addEventListener(event, delegate, false);
}
function Game(){
var game = document.querySelector("section#game");
var score = game.querySelector("section#game span.score");
var high_scores = game.querySelector("section#game ol.high-scores");
var time = game.querySelector("section#game span.time");
var start = game.querySelector("section#game span.start");
function Gem(Class, Value, MaxTTL) {
this.Class = Class;
this.Value = Value;
this.MaxTTL = MaxTTL;
};
var gems = new Array();
gems[0] = new Gem('green', 10, 1.2);
gems[1] = new Gem('blue', 20, 1);
gems[2] = new Gem('red', 50, 0.75);
function Click(event)
{
if(event.preventDefault) event.preventDefault();
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true;
var target = event.target || event.srcElement;
if(target.className.indexOf('gem') > -1){
var value = parseInt(target.getAttribute('data-value'));
var current = parseInt( score.innerHTML );
var audio = new Audio('music/blaster.mp3');
audio.play();
score.innerHTML = current + value;
target.parentNode.removeChild(target);
}
return false;
}
function Remove(id) {
var gem = game.querySelector("#" + id);
if(typeof(gem) != 'undefined')
gem.parentNode.removeChild(gem);
}
function Spawn() {
var index = Math.floor( ( Math.random() * 3 ) );
var gem = gems[index];
var id = Math.floor( ( Math.random() * 1000 ) + 1 );
var ttl = Math.floor( ( Math.random() * parseInt(gem.MaxTTL) * 1000 ) + 1000 ); //between 1s and MaxTTL
var x = Math.floor( ( Math.random() * ( game.offsetWidth - 40 ) ) );
var y = Math.floor( ( Math.random() * ( game.offsetHeight - 44 ) ) );
var fragment = document.createElement('span');
fragment.id = "gem-" + id;
fragment.setAttribute('class', "gem " + gem.Class);
fragment.setAttribute('data-value', gem.Value);
game.appendChild(fragment);
fragment.style.left = x + "px";
fragment.style.top = y + "px";
setTimeout( function(){
Remove(fragment.id);
}, ttl)
}
<!-- parse high score keeper -->
function HighScores() {
if(typeof(Storage)!=="undefined"){
var scores = false;
if(localStorage["high-scores"]) {
high_scores.style.display = "block";
high_scores.innerHTML = '';
scores = JSON.parse(localStorage["high-scores"]);
scores = scores.sort(function(a,b){return parseInt(b)-parseInt(a)});
for(var i = 0; i < 10; i++){
var s = scores[i];
var fragment = document.createElement('li');
fragment.innerHTML = (typeof(s) != "undefined" ? s : "" );
high_scores.appendChild(fragment);
}
}
} else {
high_scores.style.display = "none";
}
}
function UpdateScore() {
if(typeof(Storage)!=="undefined"){
var current = parseInt(score.innerHTML);
var scores = false;
if(localStorage["high-scores"]) {
scores = JSON.parse(localStorage["high-scores"]);
scores = scores.sort(function(a,b){return parseInt(b)-parseInt(a)});
for(var i = 0; i < 10; i++){
var s = parseInt(scores[i]);
var val = (!isNaN(s) ? s : 0 );
if(current > val)
{
val = current;
scores.splice(i, 0, parseInt(current));
break;
}
}
scores.length = 10;
localStorage["high-scores"] = JSON.stringify(scores);
} else {
var scores = new Array();
scores[0] = current;
localStorage["high-scores"] = JSON.stringify(scores);
}
HighScores();
}
}
function Stop(interval) {
clearInterval(interval);
}
this.Start = function() {
score.innerHTML = "0";
start.style.display = "none";
var interval = setInterval(Spawn, 750);
var count = 10;
var counter = null;
function timer()
{
count = count-1;
if (count <= 0)
{
var left = document.querySelectorAll("section#game .gem");
for (var i = 0; i < left.length; i++) {
if(left[i] && left[i].parentNode) {
left[i].parentNode.removeChild(left[i]);
}
}
Stop(interval);
Stop(counter);
time.innerHTML = "Game Over!";
start.style.display = "block";
UpdateScore();
return;
} else {
time.innerHTML = count + "s left";
}
}
counter = setInterval(timer, 1000);
setTimeout( function(){
Stop(interval);
}, count * 1000)
};
addEvent(game, 'click', Click);
addEvent(start, 'click', this.Start);
HighScores();
}
addEvent(document, 'readystatechange', function() {
if ( document.readyState !== "complete" )
return true;
var game = new Game();
});
</script>
</head>
<body>
<div id="page">
<section id="game">
<span class="score">0</span>
<span class="time">0</span>
<span class="start">START!
<ol class="high-scores"></ol>
</span>
</section>
</div>
</body>
</html>
Alessio -
You only need a few minor changes to your code to make it work. The example below should help you get started in the right direction. Good luck.
Changes:
Add an endGame() function and move the stop game logic from the timer() function into it.
Add a line to the click() function to check for red gem clicks.
if (target.className.indexOf('red') > 0) endGame("Red Gem - You win!");
Declare the count, counter, and interval variables at the top of your Game object.
The code below also has a few minor CSS changes used for debugging which you can remove.
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>HTML 5 Gem Game</title>
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1">
<style>
section#game {
width: 480px;
height: 800px;
max-width: 100%;
max-height: 100%;
overflow: hidden;
position: relative;
background-image: url('img/Splash.png');
border: 1px red dotted;
position: relative;
color: red;
font-size: 30px;
font-family: "arial,sans-serif";
}
section#game .score{
display: block;
position: absolute;
top: 10px;
left: 10px;
}
section#game .time{
display: block;
position: absolute;
top: 10px;
right: 10px;
}
section#game .start{
display: block;
padding-top: 40%;
margin: 0 auto 0 auto;
text-align: center;
width: 70%;
cursor: pointer;
}
section#game .start .high-scores{
text-align: left;
}
section#game .gem{
display: block;
position: absolute;
width: 40px;
height: 44px;
cursor: pointer;
}
section#game .gem.green{
background: url('img/Gem Green.png') no-repeat top left;
background-color: green;
}
section#game .gem.blue{
background: url('img/Gem Blue.png') no-repeat top left;
background-color: blue;
}
section#game .gem.red{
background: url('img/Gem Red.png') no-repeat top left;
background-color: red;
}
</style>
<script>
function addEvent(element, event, delegate ) {
if (typeof (window.event) != 'undefined' && element.attachEvent)
element.attachEvent('on' + event, delegate);
else
element.addEventListener(event, delegate, false);
}
function Game(){
var game = document.querySelector("section#game");
var score = game.querySelector("section#game span.score");
var high_scores = game.querySelector("section#game ol.high-scores");
var time = game.querySelector("section#game span.time");
var start = game.querySelector("section#game span.start");
var interval, counter, count;
function Gem(Class, Value, MaxTTL) {
this.Class = Class;
this.Value = Value;
this.MaxTTL = MaxTTL;
};
var gems = new Array();
gems[0] = new Gem('green', 10, 1.2);
gems[1] = new Gem('blue', 20, 1);
gems[2] = new Gem('red', 50, 0.75);
function Click(event)
{
if(event.preventDefault) event.preventDefault();
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true;
var target = event.target || event.srcElement;
if(target.className.indexOf('gem') > -1){
var value = parseInt(target.getAttribute('data-value'));
var current = parseInt( score.innerHTML );
var audio = new Audio('music/blaster.mp3');
audio.play();
score.innerHTML = current + value;
target.parentNode.removeChild(target);
if (target.className.indexOf('red') > 0) endGame("Red Gem - You win!");
}
return false;
}
function Remove(id) {
var gem = game.querySelector("#" + id);
if(typeof(gem) != 'undefined')
gem.parentNode.removeChild(gem);
}
function Spawn() {
var index = Math.floor( ( Math.random() * 3 ) );
var gem = gems[index];
var id = Math.floor( ( Math.random() * 1000 ) + 1 );
var ttl = Math.floor( ( Math.random() * parseInt(gem.MaxTTL) * 1000 ) + 1000 ); //between 1s and MaxTTL
var x = Math.floor( ( Math.random() * ( game.offsetWidth - 40 ) ) );
var y = Math.floor( ( Math.random() * ( game.offsetHeight - 44 ) ) );
var fragment = document.createElement('span');
fragment.id = "gem-" + id;
fragment.setAttribute('class', "gem " + gem.Class);
fragment.setAttribute('data-value', gem.Value);
game.appendChild(fragment);
fragment.style.left = x + "px";
fragment.style.top = y + "px";
setTimeout( function(){
Remove(fragment.id);
}, ttl)
}
<!-- parse high score keeper -->
function HighScores() {
if(typeof(Storage)!=="undefined"){
var scores = false;
if(localStorage["high-scores"]) {
high_scores.style.display = "block";
high_scores.innerHTML = '';
scores = JSON.parse(localStorage["high-scores"]);
scores = scores.sort(function(a,b){return parseInt(b)-parseInt(a)});
for(var i = 0; i < 10; i++){
var s = scores[i];
var fragment = document.createElement('li');
fragment.innerHTML = (typeof(s) != "undefined" ? s : "" );
high_scores.appendChild(fragment);
}
}
} else {
high_scores.style.display = "none";
}
}
function UpdateScore() {
if(typeof(Storage)!=="undefined"){
var current = parseInt(score.innerHTML);
var scores = false;
if(localStorage["high-scores"]) {
scores = JSON.parse(localStorage["high-scores"]);
scores = scores.sort(function(a,b){return parseInt(b)-parseInt(a)});
for(var i = 0; i < 10; i++){
var s = parseInt(scores[i]);
var val = (!isNaN(s) ? s : 0 );
if(current > val)
{
val = current;
scores.splice(i, 0, parseInt(current));
break;
}
}
scores.length = 10;
localStorage["high-scores"] = JSON.stringify(scores);
} else {
var scores = new Array();
scores[0] = current;
localStorage["high-scores"] = JSON.stringify(scores);
}
HighScores();
}
}
function Stop(interval) {
clearInterval(interval);
}
function endGame( msg ) {
count = 0;
Stop(interval);
Stop(counter);
var left = document.querySelectorAll("section#game .gem");
for (var i = 0; i < left.length; i++) {
if(left[i] && left[i].parentNode) {
left[i].parentNode.removeChild(left[i]);
}
}
time.innerHTML = msg || "Game Over!";
start.style.display = "block";
UpdateScore();
}
this.Start = function() {
score.innerHTML = "0";
start.style.display = "none";
interval = setInterval(Spawn, 750);
count = 10;
counter = null;
function timer()
{
count = count-1;
if (count <= 0)
{
endGame();
return;
} else {
time.innerHTML = count + "s left";
}
}
counter = setInterval(timer, 1000);
setTimeout( function(){
Stop(interval);
}, count * 1000)
};
addEvent(game, 'click', Click);
addEvent(start, 'click', this.Start);
HighScores();
}
addEvent(document, 'readystatechange', function() {
if ( document.readyState !== "complete" )
return true;
var game = new Game();
});
</script>
</head>
<body>
<div id="page">
<section id="game">
<span class="score">0</span>
<span class="time">0</span>
<span class="start">START!
<ol class="high-scores"></ol>
</span>
</section>
</div>
</body>
</html>
For starters, you shouldn't include a style sheet and your entire HTML file since neither is relevant and you should use a canvas element instead of this chaotic use of CSS and html elements, which would allow the size of your code to be halved. Furthermore, you should be able to fix this by just changing some global boolean variable to false when the red gem is clicked and when the boolean variable is false (this if statement belongs at the end of your game loop) you call Stop(arg)/clearInterval(arg). Given that your current code doesn't seem to have a global boolean variable indicating game state (using an enumeration would generally be a cleaner solution but a simple boolean seems to suit this case)

Undefined index after running function a few times

So I was trying to create my own Blackjack in javascript for learning purposes and even though the code is overall working, I came across a weird bug.
After some clicks on the Deal html button, which calls the function deal(), I will get either a playerHand[i] undefined or dealerHand[i] undefined error on line 114 or 118, respectively, of the code posted below.
I noticed this also happened if I clicked the button very fast for whatever reason.
I suspected it had something to do with memory optimization so I used the delete command to reset those arrays between game turns, but the error persists.
So, why do my arrays break after some use?
Thanks.
JS:
var deck = [];
var dealerHand = [];
var playerHand = [];
var dscore = 0;
var pscore = 0;
var turn = 0;
function Card(suit, src) {
this.src = src;
this.suit = getSuit(suit);
this.value = getValue(src);
};
function getSuit(suit) {
if (suit == 1) return "Clubs";
if (suit == 2) return "Diamonds";
if (suit == 3) return "Hearts";
if (suit == 4) return "Spades";
};
function getValue(src) {
if (src == 1) return 11;
if (src < 10) return src;
else return 10;
};
function createDeck() {
for (i=1; i<=4; i++) {
for(j=1; j<=13; j++) {
var card = new Card(i, j);
deck.push(card);
};
};
};
function getCard() {
var rand = Math.floor(Math.random()*deck.length);
deck.splice(rand,1);
return deck[rand];
};
function deal() {
if(turn == 0) {
dealerHand.push(getCard());
playerHand.push(getCard());
};
dealerHand.push(getCard());
playerHand.push(getCard());
};
function stand() {
dealerHand.push(getCard());
};
function clearBoard () {
$('#player').html("");
$('#dealer').html("");
};
function resetDeck () {
delete deck;
deck = [];
};
function resetHands () {
delete dealerHand;
delete playerHand;
dealerHand = [];
playerHand = [];
};
function resetScore () {
pscore = 0;
dscore = 0;
};
function isAce (arr) {
for(i=0; i<arr.length; i++) {
if (arr[i].src == 1) return true;
else return false;
};
}
function updateScore() {
resetScore();
if (playerHand.length > 0 && dealerHand.length > 0) {
for(i=0; i<playerHand.length; i++) {
pscore += playerHand[i].value;
};
for(i=0; i<dealerHand.length; i++) {
dscore += dealerHand[i].value;
};
//Regra do Às
if(pscore > 21 && isAce(playerHand)) {
pscore -= 10;
};
if(dscore > 21 && isAce(dealerHand)) {
dscore -= 10;
};
} else {
pscore = 0;
dscore = 0;
};
};
function showScore () {
$('#pscore').html("<p>Player Score: " + pscore + "</p>");
$('#dscore').html("<p>Dealer Score: " + dscore + "</p>");
};
function showCards () {
for(i=0; i<playerHand.length; i++) {
var div = $("<div>");
var img = $("<img>");
img.attr('src', 'img/cards/' + playerHand[i].suit + '/' + playerHand[i].src + '.png');
div.append(img);
$('#player').append(div);
};
for(i=0; i<dealerHand.length; i++) {
var div = $("<div>");
var img = $("<img>");
img.attr('src', 'img/cards/' + dealerHand[i].suit + '/' + dealerHand[i].src + '.png');
div.append(img);
$('#dealer').append(div);
};
};
function cleanUp () {
if (pscore == 21) {
alert("Blackjack!");
newGame();
};
if (pscore > 21) {
alert("Bust!");
newGame();
};
if (dscore == 21) {
alert("You lost!");
newGame();
};
if (dscore > 21) {
alert("You won!");
newGame();
};
};
function newGame () {
turn = 0;
clearBoard();
resetHands();
resetScore();
showScore();
resetDeck();
createDeck();
};
function gameTurn () {
clearBoard();
updateScore();
showCards();
showScore();
cleanUp();
turn++;
};
$(document).ready(function() {
newGame();
$('#deal').on('click', function(){
deal();
gameTurn();
});
$('#stand').on('click', function(){
stand();
gameTurn();
});
});
CSS:
body {
background: url(../img/greenbg.png);
}
.holder {
width:800px;
margin:auto;
}
.clearfix {
clear:both;
}
#pscore, #dscore {
color: white;
margin: 10px;
display: block;
font-size: 1.2rem;
text-shadow: 0 0 5px #000;
}
.container {
width: 600px;
height: 300px;
margin: 10px;
}
div img {
float: left;
margin: 10px;
}
div button {
margin: 10px;
}
HTML:
<html>
<head>
<div class="holder clearfix">
<div id="dscore"><p>Dealer Score: 0</p>
</div>
<div id="dealer" class="container">
</div>
<div id="pscore"><p>Player Score: 0</p>
</div>
<div id="player" class="container">
</div>
<div class="">
<button id="deal">Deal</button>
<button id="stand">Stand</button>
</div>
</div>
</body>
</html>
You have a problem in this function, which may be to blame:
function getCard() {
var rand = Math.floor(Math.random()*deck.length);
deck.splice(rand,1);
return deck[rand];
};
As written, it's removing a card, and then returning the card that now has that position in the deck. If rand was the last element in the array then there is no longer a card in that position, so it'll return undefined.
You should be returning the value of the removed card itself, part of the result of the splice call:
function getCard() {
var rand = Math.floor(Math.random() * deck.length);
var pick = deck.splice(rand, 1);
return pick[0];
};
p.s. it's worth learning modern ES5 utility functions for arrays. For example, your isAce function could be rewritten thus, avoiding the bug where you always return after testing the first element:
function isAce(arr) {
return arr.some(function(n) {
return n === 1;
});
};
or, more cleanly:
function isAce(card) {
return card === 1; // test a single card
};
function holdsAce(hand) {
return hand.some(isAce); // test an array (or hand) of cards
};

Categories