How can I add a button to display a timer when clicked - javascript

I have a simple memory game that is won by matching two letter. How can I add a button to start a timer that displays some where by the game, and when you win the timer stops but shows best times, furthermore, you can keep count to beat your best time. Also, how do I change my letter to substitute for images?
<title>Memory</title>
</head>
<body>
<div id="container">
<div id="header">
Memory!
</div>
<div id="content">
<table id="gameBoard">
<tbody>
</tbody>
</table>
<button id="playAgain">Play Again</button>
</div>
</div>
body {
font-family:copperplate;
font-size: 0.9em;
background-color:#ccc;
}
html, body {
margin:0;
padding:0;
height:100%;
}
#container {
width:950px;
min-width:950px;
background-color:#fff;
margin:0 auto;
min-height:100%;
}
#header {
font-size:4em;
line-height:95px;
text-align:center;
border-bottom:1px solid #000;
}
#content {
clear:both;
border-top:1px solid #000;
padding-top:5px;
padding:10px;
text-align:center;
}
h1 {
text-transform: capitalize;
}
#gameBoard {
margin-left:auto;
margin-right:auto;
margin-bottom:25px;
}
.card {
width:100px;
height:100px;
border:1px solid #000;
cursor: pointer;
}
.down {
background-color: #E8DD5B;
}
.up {
background-color: #ccc;
line-height: 100px;
text-align:center;
font-size:5em;
}
button {
font-size:2em;
padding:5px;
background-color:#E97A54;
}
$(function() {
var cards = [
{ id: 1, matchesId: 2, content: "A" },
{ id: 2, matchesId: 1, content: "A" },
{ id: 3, matchesId: 4, content: "B" },
{ id: 4, matchesId: 3, content: "B" },
{ id: 5, matchesId: 6, content: "C" },
{ id: 6, matchesId: 5, content: "C" },
{ id: 7, matchesId: 8, content: "D" },
{ id: 8, matchesId: 7, content: "D" },
{ id: 9, matchesId: 10, content: "E" },
{ id: 10, matchesId: 9, content: "E" },
{ id: 11, matchesId: 12, content: "F" },
{ id: 12, matchesId: 11, content: "F" }
];
var shuffledCards = [];
var cardToMatchElement;
setupGame();
$("#playAgain").click(function() {
setupGame();
});
function setupGame() {
cardToMatchElement = null;
shuffleCards();
dealCards();
}
function shuffleCards() {
shuffledCards = [];
for(var i = 0; i < cards.length; i++) {
var randomCardIndex = getRandomCardIndex();
while($.inArray(randomCardIndex,shuffledCards) != -1) {
randomCardIndex = getRandomCardIndex();
}
shuffledCards.push(randomCardIndex);
}
}
function getRandomCardIndex() {
return Math.floor((Math.random() * cards.length));
}
function dealCards() {
setupGameBoard();
attachCardEvents();
}
function attachCardEvents() {
$(".card").click(function() {
var selectedCardElement = $(this);
var selectedCard = getCardFromElement(selectedCardElement);
flipCard(selectedCardElement, selectedCard);
if(cardToMatchElement) {
var cardToMatch = getCardFromElement(cardToMatchElement);
if(cardToMatch.matchesId == selectedCard.id) {
selectedCardElement.off();
cardToMatchElement.off();
cardToMatchElement = null;
}
else {
$.blockUI({ message: "", overlayCSS : { backgroundColor: '#fff', cursor:'normal', opacity:0.5 } });
setTimeout(function() {
flipCard(selectedCardElement, selectedCard);
flipCard(cardToMatchElement, cardToMatch);
cardToMatchElement = null;
$.unblockUI();
},1000);
}
}
else {
cardToMatchElement = selectedCardElement;
}
});
}
function getCardFromElement(cardElement) {
return cards[cardElement.attr("data-cardindex")];
}
function flipCard(cardElement, card) {
if(cardElement.hasClass("down")) {
cardElement.removeClass("down").addClass("up");
cardElement.html(card.content);
}
else {
cardElement.removeClass("up").addClass("down");
cardElement.html("");
}
}
function setupGameBoard() {
var numberColumns = 4;
var tableBody = "";
var tableRow = "<tr>";
$.each(shuffledCards, function(index, card) {
tableRow += "<td><div class='card down' data-cardindex='" + shuffledCards[index] + "'>&nbsp</div></td>";
if(index > 0 && (index + 1) % numberColumns == 0) {
tableRow += "</tr>";
if(index < cards.length - 1) {
tableRow += "<tr>";
}
}
if(index == cards.length - 1 && (index + 1) % numberColumns != 0) {
tableRow += "</tr>";
}
tableBody += tableRow;
tableRow = "";
});
$("#gameBoard tbody").html(tableBody);
}
});
http://jsfiddle.net/Brannan2/VkKRa/1/

To create a timer call below function on your button click (id is some global js variable)
function createTimer() {
id = setInterval(function(){
var secondEl = document.getElementById('second');
if (secondEl.value == null || secondEl.value == "") {
secondEl.value = 0;
}
var seconds = parseInt(secondEl.value) + 1;
if (seconds == 60) {
seconds = 0;
var minuteEl = document.getElementById('minute');
if (minuteEl.value == null || minuteEl.value == "") {
minuteEl.value = 0;
}
var minutes = parseInt(minuteEl.value) + 1;
if (minutes == 60) {
minutes = 0;
var hourEl = document.getElementById('hour');
if (hourEl.value == null || hourEl.value == "") {
hourEl.value = 0;
}
hourEl.value = parseInt(hourEl.value) + 1;
}
minuteEl.value = minutes;
}
secondEl.value = seconds;
},1000);
}
For my sample I have created three input types in html with ids 'hour','minute' and 'second'. You can create any other based on UI need and update function accordingly.
To stop timer just remove the setInterval function as shown below
window.clearInterval(id);
Once you have stop the watch you can calculate total times easily by using below formula
var totalTime = (hours * 3600) + (minutes * 60) + seconds;
This will return the total time in seconds. Now to get best times, I think you have to use localStorage so that you can store best times in client browser and refer to it later whenever user returns again to play your game.
To substitute letter with images, there can be many ways. For e.g. you can add a css class to the element which will set the background image for you or you can directly use a img tag in your div with image location. Its totally up to you. I am not sure though why you want to show image with your current requirement.

Related

Is there an alternative for using setInterval() for animating fading text in javascript when iterating through objects in an array?

I'm currently trying to fade in and fade out text from an array with the help of using the setInterval() function. My init() function loops through the array and calls FadeInThenFadeOut() function to apply fade animations for each object in the array; however, while debugging I noticed that when setInterval() is called, my program iterates to the next object in the array and skips the code to apply the fade animation.
My understanding is that setInterval() delays the callback for applying the fade animation by 50 ms (milliseconds), so I believe this is causing the code to skip. Can anyone please help me find a way to allow my FadeInThenFadeOut() function to complete before iterating to the next object in the array
let quotes = [
{
"id": 1,
"text": "text1",
"author": "author1"
},
{
"id": 2,
"text": "text2",
"author": "author2"
},
{
"id": 3,
"text": "text3",
"author": "author3"
}
];
const quotePlacement = document.createElement('div');
quotePlacement.classList.add('text-example');
function init() {
for(let quoteIndex = 0; quoteIndex < quotes.length; quoteIndex++){
AssignAndAppendElement(quotes[quoteIndex].text, quotes[quoteIndex].author);
FadeInThenFadeOut();
// now wait for FadeInThenFadeOut() to finish
// then iterate to the next quoteindex
}
}
let elementOpacity = 0;
const callBackTimeInterval = 50;
function FadeInThenFadeOut() {
const timerId = setInterval(function() {
IncreaseOpacity();
if(elementOpacity >= 1){
clearInterval(timerId);
SetElementVisibility(true);
FadeOut();
ResetQuotePlacement();
}
quotePlacement.style.opacity = elementOpacity;
}, callBackTimeInterval);
}
function FadeOut() {
const timerId = setInterval(function() {
DecreaseOpacity();
if(elementOpacity <= 0){
clearInterval(timerId);
SetElementVisibility(false);
}
quotePlacement.style.opacity = elementOpacity;
}, callBackTimeInterval);
}
function DecreaseOpacity() {
elementOpacity -= 0.025;
}
function IncreaseOpacity(){
elementOpacity += 0.025;
}
function SetElementVisibility(visibility) {
if(visibility){
quotePlacement.style.opacity = 1;
elementOpacity = 1;
return;
}
elementOpacity = 0;
}
function AssignAndAppendElement(quoteText, author) {
quotePlacement.innerHTML = "<h1> <q>" + quoteText + "</q> - " + author + "</h1>";
quotePlacement.style.opacity = 0;
document.body.appendChild(quotePlacement);
}
function ResetQuotePlacement() {
quotePlacement.innerHTML = "";
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
<script defer src="main.js"></script>
<!-- <link rel="stylesheet" href="../bootstrap.css"> -->
<title>Inspirational Quotes</title>
</head>
<body onload="init()">
</body>
</html>
I found the issue. You were calling the reset function at the wrong time
function FadeInThenFadeOut() {
const timerId = setInterval(function() {
IncreaseOpacity();
if(elementOpacity >= 1){
clearInterval(timerId);
SetElementVisibility(true);
FadeOut();
ResetQuotePlacement(); // <---------------- this line
}
quotePlacement.style.opacity = elementOpacity;
}, callBackTimeInterval);
}
If I move it to the FadeOut function it works properly
Also, to wait for every fade animation to end you can simply declare a function showNextQuote and call that at the end of the FadeOut function.
Here is the working code:
let quotes = [{
"id": 1,
"text": "text1",
"author": "author1"
},
{
"id": 2,
"text": "text2",
"author": "author2"
},
{
"id": 3,
"text": "text3",
"author": "author3"
}
];
const quotePlacement = document.createElement('div');
quotePlacement.classList.add('text-example');
function init() {
showNextQuote();
}
let quoteIndex = 0;
function showNextQuote() {
if (quoteIndex >= quotes.length) return; //alternatively, set it back to 0 to keep looping
ResetQuotePlacement();
AssignAndAppendElement(quotes[quoteIndex].text, quotes[quoteIndex].author);
quoteIndex++;
FadeInThenFadeOut();
}
let elementOpacity = 0;
const callBackTimeInterval = 50;
function FadeInThenFadeOut() {
const timerId = setInterval(function() {
IncreaseOpacity();
if (elementOpacity >= 1) {
clearInterval(timerId);
SetElementVisibility(true);
FadeOut();
}
quotePlacement.style.opacity = elementOpacity;
}, callBackTimeInterval);
}
function FadeOut() {
const timerId = setInterval(function() {
DecreaseOpacity();
if (elementOpacity <= 0) {
clearInterval(timerId);
SetElementVisibility(false);
showNextQuote();
}
quotePlacement.style.opacity = elementOpacity;
}, callBackTimeInterval);
}
function DecreaseOpacity() {
elementOpacity -= 0.025;
}
function IncreaseOpacity() {
elementOpacity += 0.025;
}
function SetElementVisibility(visibility) {
if (visibility) {
quotePlacement.style.opacity = 1;
elementOpacity = 1;
return;
}
elementOpacity = 0;
}
function AssignAndAppendElement(quoteText, author) {
quotePlacement.innerHTML = "<h1> <q>" + quoteText + "</q> - " + author + "</h1>";
quotePlacement.style.opacity = 0;
document.body.appendChild(quotePlacement);
}
function ResetQuotePlacement() {
quotePlacement.innerHTML = "";
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
<script defer src="main.js"></script>
<!-- <link rel="stylesheet" href="../bootstrap.css"> -->
<title>Inspirational Quotes</title>
</head>
<body onload="init()">
</body>
</html>
Alternatively, you could use the css transition property. This makes things quite a bit simpler. Here is a quick example:
const quotes = ["Quote 1", "Quote 2", "Quote 3"];
const el = document.getElementById("holder");
el.style.opacity = 0;
let currentIndex = 0;
let currentShown = false;
const intervalID = setInterval(() => {
if (currentIndex >= quotes.length) {
clearInterval(intervalID);
return;
}
if (!currentShown) {
el.style.opacity = 1;
el.innerText = quotes[currentIndex];
currentShown = true;
} else {
el.style.opacity = 0;
currentShown = false;
currentIndex++;
}
}, 2000);
#holder {
transition: opacity 1.9s;
}
<h1 id="holder"></h1>
css method, with animationend event and no use of setInterval()
I used the standard html method for quotes with auth.
the loop is restarted on the next element as soon as the animationend event occurs
const DomParser = new DOMParser()
const quotes =
[ { id: 1, text: 'text1', author: 'author1' }
, { id: 2, text: 'text2', author: 'author2' }
, { id: 3, text: 'text3', author: 'author3' }
]
const quotePlacement = document.createElement('div')
quotePlacement.index = -1
function newQuote(txt,auth)
{
let elm = `<blockquote>
<p>${txt}</p>
<footer>${auth}</footer>
</blockquote>`
return DomParser.parseFromString( elm, 'text/html').body.firstChild
}
function nextQuoteLoop()
{
quotePlacement.index = ++quotePlacement.index % quotes.length
let { text, author } = quotes[quotePlacement.index]
if (quotePlacement.firstChild)
{ quotePlacement.firstChild.remove() }
quotePlacement.appendChild( newQuote(text,author ))
quotePlacement.firstChild.classList.add('fade-in-out')
}
// main
document.body.appendChild(quotePlacement)
quotePlacement.onanimationend = nextQuoteLoop
nextQuoteLoop() // start the first one...
.fade-in-out { animation: fadeInOut ease 7s; }
#keyframes fadeInOut {
0% { opacity:0; }
50% { opacity:1; }
100% { opacity:0; }
}
/* classic blockquote */
blockquote {
padding: 6px 16px;
border: none;
quotes: "\201C\2009" "\2009\201D";
display: block;
float: right;
opacity:0;
}
blockquote p {
font-size: 36px;
padding: 0 16px 0 0;
text-indent: -12px;
color: #251487;
font-style: italic;
margin-bottom: 0.3em;
}
blockquote p:before {
content: open-quote;
font-weight: bold;
font-size: 40px;
line-height: 32px;
}
blockquote p:after {
content: close-quote;
font-weight: bold;
font-size: 40px;
line-height: 32px;
}
blockquote footer {
text-align: right;
padding-right: .7em;
font-style: oblique;
color: #2d0068;
}

code does not work outside jsfiddle

There is a jsfiddle code that I'd like to use on my page.
I copied css and put it into <style> tag on my page. Then I separate part that starts with
$(function(){
$('.anyClass').liEqualizer({
and put it into custom.js. And the first part that starts with (function ($) { I put into audio_frequency.js. I added its imports to head tag. The page looks like this
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<style>
.sampleWrap {
margin-left: 6%;
margin-top: 5%;
}
.eqCol {
width: 80px;
margin: 0 0 0 2px;
float: left;
}
.eqItem {
height: 20px;
width: 100%;
background: transparent;
margin: 1px 0 0 0;
opacity: 0;
box-shadow: 15px 20px 0px rgba(0,0,0,0.1);
}
.eqCol .eqItem:last-child {
opacity:1 !important
}
</style>
<script src="jquery-3.2.1.slim.min.js"></script>
<script src="audio_frequency.js"></script>
<script src="custom.js"></script>
</head>
<body>
<div class="sampleWrap d-flex">
<div class="anyClass"></div>
<div style="clear:both; padding:15px 0">
<button class="start">start</button>
<button class="stop">stop</button>
</div>
</div>
</div>
</body>
</html>
custom.js looks like this
$(document).ready(function() {
$('.anyClass').liEqualizer({
row:7,
col:20,
speed:20,
freq:400,
on:true
});
$('.start').click(function(){
$('.anyClass').liEqualizer('start');
return false;
})
$('.stop').click(function(){
$('.anyClass').liEqualizer('stop');
return false;
})
});
and audio_frequency looks like this
(function ($) {
var methods = {
init: function (options) {
var p = {
row: 7,
col: 6,
speed: 20,
freq: 400,
on: true
};
if (options) {
$.extend(p, options);
}
var eqWrap = $(this).addClass('eqWrap');
for (c = 0; c < p.col; c++) {
var eqColEl = $('<div>').addClass('eqCol').appendTo(eqWrap);
for(r = 0; r < p.row; r++){
$('<div>').addClass('eqItem').appendTo(eqColEl);
}
}
var
eqCol = $('.eqCol', eqWrap),
eqItem = $('.eqItem', eqWrap),
randomNumber = function (m, n){
m = parseInt(m);
n = parseInt(n);
return Math.floor(Math.random() * (n - m + 1)) + m;
},
eqUp = function(colEl, val) {
var
speed = p.speed,
v = p.row - val,
i = p.row,
j = 0,
flag2 = true,
eachItemUp = function(){
$('.eqItem', colEl).eq(i - 1).nextAll().stop().css({ opacity:'1' });
if ($('.eqItem', colEl).eq(i - 1).css('opacity') == 1) { flag2 = false }
else { flag2 = true }
$('.eqItem', colEl).eq(i - 1).stop(true).animate({ opacity:'1' }, p.speed, function() {
if ($('.eqItem', colEl).index(this) == v) {
if(flag2) {
eqDown(colEl,val);
}
} else {
i--;
j++;
if(i>v){
eachItemUp()
}
}
})
}
eachItemUp()
},
eqDown = function(colEl,val){
var
v = p.row - val,
i = (p.row-val),
j = 0,
speed = p.speed * 2,
eachItemDown = function(){
if (i == (p.row - val)) {
$('.eqItem', colEl).eq(i).animate({ opacity:'0' }, speed * 10)
setTimeout(function() {
i++;
j++;
if(i < p.row){
eachItemDown();
}
}, speed)
} else {
$('.eqItem', colEl).eq(i).animate({ opacity:'0' }, speed, function(){
i++;
j++;
if(i < p.row){
eachItemDown();
}
})
}
}
eachItemDown();
},
eqInterval = function(){
eqCol.each(function(){
eqUp($(this), randomNumber(0, p.row))
})
}
eqInterval()
if (p.on) {
var eqIntervalId = setInterval(eqInterval, p.freq)
$(this).data({
'eqIntId': eqIntervalId,
'eqInt': eqInterval,
'freq': p.freq,
'on': p.on
})
} else {
$(this).data({
'eqIntId':eqIntervalId,
'eqInt':eqInterval,
'freq':p.freq,
'on':p.on
})
}
}, start: function () {
if (!$(this).data('on')) {
$(this).data('eqInt')();
var eqIntervalId = setInterval($(this).data('eqInt'), $(this).data('freq'));
$(this).data ({
'eqIntId':eqIntervalId,
'on':true
})
}
},
stop: function () {
if($(this).data('on')) {
clearInterval($(this).data('eqIntId'));
$('.eqItem', $(this)).animate({opacity:0})
$(this).data({
'on':false
})
}
}
};
$.fn.liEqualizer = function (method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' in jQuery.liEqualizer does not exist');
}
};
})(jQuery);
But when I load page I get
TypeError: $(...).eq(...).nextAll(...).stop is not a function[Learn More]
What is the problem? Is it trying to evaluate something before all the components are ready on the page?
This $(...).eq(...).nextAll(...).stop error is because of jquery-3.2.1.slim.min.js this ist not complete.
Note:
In the jquery.slim.js, the following functions of code are removed:
jQuery.fn.extend
jquery.fn.load
jquery.each // Attach a bunch of functions for handling common AJAX events
jQuery.expr.filters.animated
ajax settings like jQuery.ajaxSettings.xhr, jQuery.ajaxPrefilter, jQuery.ajaxSetup, jQuery.ajaxPrefilter, jQuery.ajaxTransport,
jQuery.ajaxSetup
xml parsing like jQuery.parseXML,
animation effects like jQuery.easing, jQuery.Animation, jQuery.speedIn the jquery.slim.js, the following function of code are removed:
Here is the complete code, you need jquery lib <script type="text/javascript" src="//code.jquery.com/jquery-1.10.1.js"></script>
<style>
/*Layout css*/
body {
margin: 0;
padding: 20px 10px;
text-align: center
}
.sampleWrap {
height: 290px
}
/*plugin css*/
.eqWrap {
margin: -1px 0 0 -2px;
overflow: hidden;
display: inline-block; //display:inline; //zoom:1;}
.eqCol {
width: 37px;
margin: 0 0 0 2px;
float: left;
}
.eqItem {
height: 10px;
width: 100%;
background: #e7aa3b;
margin: 1px 0 0 0;
opacity: 0
}
.eqCol .eqItem:last-child {
opacity: 1 !important
}
</style>
<script type="text/javascript" src="//code.jquery.com/jquery-1.10.1.js"></script>
<div class="sampleWrap">
<div class="anyClass"></div>
<div style="clear:both; padding:15px 0">
<button class="start">start</button>
<button class="stop">stop</button>
</div>
<div class="anyClass2"></div>
<div style="clear:both; padding:15px 0">
<button class="start2">start</button>
<button class="stop2">stop</button>
</div>
</div>
<script>
/*код плагина*/
(function($) {
var methods = {
init: function(options) {
var p = {
row: 7, //кол-во столбцов
col: 6, //кол-во колонок
speed: 20, //скорость подсветки кубиков
freq: 400, //частота сигнала
on: true //включено по умолчанию (true,false)
};
if (options) {
$.extend(p, options);
}
var eqWrap = $(this).addClass('eqWrap');
for (c = 0; c < p.col; c++) {
var eqColEl = $('<div>').addClass('eqCol').appendTo(eqWrap);
for (r = 0; r < p.row; r++) {
$('<div>').addClass('eqItem').appendTo(eqColEl);
}
}
var
eqCol = $('.eqCol', eqWrap),
eqItem = $('.eqItem', eqWrap),
randomNumber = function(m, n) {
m = parseInt(m);
n = parseInt(n);
return Math.floor(Math.random() * (n - m + 1)) + m;
},
eqUp = function(colEl, val) {
var
speed = p.speed,
v = p.row - val,
i = p.row,
j = 0,
flag2 = true,
eachItemUp = function() {
$('.eqItem', colEl).eq(i - 1).nextAll().stop().css({
opacity: '1'
});
if ($('.eqItem', colEl).eq(i - 1).css('opacity') == 1) {
flag2 = false
} else {
flag2 = true
}
$('.eqItem', colEl).eq(i - 1).stop(true).animate({
opacity: '1'
}, p.speed, function() {
if ($('.eqItem', colEl).index(this) == v) {
if (flag2) {
eqDown(colEl, val);
}
} else {
i--;
j++;
if (i > v) {
eachItemUp()
}
}
})
}
eachItemUp()
},
eqDown = function(colEl, val) {
var
v = p.row - val,
i = (p.row - val),
j = 0,
speed = p.speed * 2,
eachItemDown = function() {
if (i == (p.row - val)) {
$('.eqItem', colEl).eq(i).animate({
opacity: '0'
}, speed * 10)
setTimeout(function() {
i++;
j++;
if (i < p.row) {
eachItemDown();
}
}, speed)
} else {
$('.eqItem', colEl).eq(i).animate({
opacity: '0'
}, speed, function() {
i++;
j++;
if (i < p.row) {
eachItemDown();
}
})
}
}
eachItemDown();
},
eqInterval = function() {
eqCol.each(function() {
eqUp($(this), randomNumber(0, p.row))
})
}
eqInterval()
if (p.on) {
var eqIntervalId = setInterval(eqInterval, p.freq)
$(this).data({
'eqIntId': eqIntervalId,
'eqInt': eqInterval,
'freq': p.freq,
'on': p.on
})
} else {
$(this).data({
'eqIntId': eqIntervalId,
'eqInt': eqInterval,
'freq': p.freq,
'on': p.on
})
}
},
start: function() {
if (!$(this).data('on')) {
$(this).data('eqInt')();
var eqIntervalId = setInterval($(this).data('eqInt'), $(this).data('freq'));
$(this).data({
'eqIntId': eqIntervalId,
'on': true
})
}
},
stop: function() {
if ($(this).data('on')) {
clearInterval($(this).data('eqIntId'));
$('.eqItem', $(this)).animate({
opacity: 0
})
$(this).data({
'on': false
})
}
}
};
$.fn.liEqualizer = function(method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Метод ' + method + ' в jQuery.liEqualizer не существует');
}
};
})(jQuery);
/*инициализация плагина*/
$(function() {
$('.anyClass').liEqualizer({
row: 7, //кол-во столбцов
col: 6, //кол-во колонок
speed: 20, //скорость подсветки кубиков
freq: 400, //частота сигнала
on: true //включено по умолчанию (true,false)
});
$('.start').click(function() {
$('.anyClass').liEqualizer('start');
return false;
})
$('.stop').click(function() {
$('.anyClass').liEqualizer('stop');
return false;
})
$('.anyClass2').liEqualizer({
row: 7, //кол-во столбцов
col: 6, //кол-во колонок
speed: 20, //скорость подсветки кубиков
freq: 400, //частота сигнала
on: false //включено по умолчанию (true,false)
});
$('.start2').click(function() {
$('.anyClass2').liEqualizer('start');
return false;
})
$('.stop2').click(function() {
$('.anyClass2').liEqualizer('stop');
return false;
})
});
</script>

Javascript not adding questions or buttons to webpage

I am trying to make a quiz website and I used some simple interactive quiz code and the next button is there (only button I have that doesn't have display set to none). The Javascript was supposed to show the first question upon opening the page, and then showing the next one each time you hit next. After the first question the previous button should show up and at the end it would give you your score and the start over button.
Html:
<!DOCTYPE html>
<html>
<head>
<title>History</title>
<link rel="stylesheet" type="text/css" href="../css.css">
<script src="javascript.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src='javascript.js'></script>
</head>
<div id="background">
<div id="headnav">
<h1 class="navitem">World Wide Water</h1> <!-- Going to be the header with navigatioon bar-->
<ul id="nav">
<li class="navitem">Home</li>
<li class="navitem">About</li>
<li class="navitem">Subjects</li>
<li class="navitem">Share</li>
<li class="navitem">Donate More!</li>
</ul>
<div id="header">
<div id="headerbar">
<div id="logo"></div>
<div id="site-sloagan"></div>
</div>
</div>
</div>
<div id="mainhis">
<p>If i do this will it work</p>
<div id="quiz"></div>
<div class='button' id='next'><a href='#'>Next</a></div>
<div class='button' id='prev'><a href='#'>Previous</a></div>
<div class='button' id='start'><a href='#'>Start Over</a></div>
</div>
</div></html>
CSS:
body {
background-image: url("bg.jpeg");
background-repeat: no-repeat;
}
#headnav {
background-color: rgb(0, 0, 153);
color: white;
}
#main {
background-color: white;
text-align: left;
min-width: 900px;
max-width: 900px;
}
#nav {
list-style-type: none;
margin: 0;
padding: 0;
float: center;
}
.navitem {
display: inline;
color: white;
}
.linkonsub {
color: black;
}
#id {
text-align: left;
}
#sub {
background-color: rgb(211, 112, 40);
text-align: left;
}
#mainhis {
width:50%;
margin:auto;
padding: 0 25px 40px 10px;
background-color: #1E90FF;
border:4px solid #B0E0E6;
border-radius:5px;
color: #FFFFFF;
font-weight: bold;
box-shadow: 5px 5px 5px
#888;
}
#quiz {
text-indent: 10px;
display:none;
}
.button {
border:4px solid;
border-radius:5px;
width: 40px;
padding-left:5px;
padding-right: 5px;
position: relative;
float:right;
background-color: #DCDCDC;
color: black;
margin: 0 2px 0 2px;
}
.button.active {
background-color: #F8F8FF
color: #525252;
}
button {
position: relative;
float: right;
}
.button a {
text-decoration: none;
color: black;
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
}
#prev {
display: none;
}
#start {
display: none;
width: 90px;
}
Javascript:
(function() {
var questions = [{
question: "What is 2*5?",
choices: [2, 5, 10, 15, 20],
correctAnswer: 2
}, {
question: "What is 3*6?",
choices: [3, 6, 9, 12, 18],
correctAnswer: 4
}, {
question: "What is 8*9?",
choices: [72, 99, 108, 134, 156],
correctAnswer: 0
}, {
question: "What is 1*7?",
choices: [4, 5, 6, 7, 8],
correctAnswer: 3
}, {
question: "What is 8*8?",
choices: [20, 30, 40, 50, 64],
correctAnswer: 4
}];
var questionCounter = 0; //Tracks question number
var selections = []; //Array containing user choices
var quiz = $('#quiz'); //Quiz div object
// Display initial question
displayNext();
// Click handler for the 'next' button
$('#next').on('click', function (e) {
e.preventDefault();
// Suspend click listener during fade animation
if(quiz.is(':animated')) {
return false;
}
choose();
// If no user selection, progress is stopped
if (isNaN(selections[questionCounter])) {
alert('Please make a selection!');
} else {
questionCounter++;
displayNext();
}
});
// Click handler for the 'prev' button
$('#prev').on('click', function (e) {
e.preventDefault();
if(quiz.is(':animated')) {
return false;
}
choose();
questionCounter--;
displayNext();
});
// Click handler for the 'Start Over' button
$('#start').on('click', function (e) {
e.preventDefault();
if(quiz.is(':animated')) {
return false;
}
questionCounter = 0;
selections = [];
displayNext();
$('#start').hide();
});
// Animates buttons on hover
$('.button').on('mouseenter', function () {
$(this).addClass('active');
});
$('.button').on('mouseleave', function () {
$(this).removeClass('active');
});
// Creates and returns the div that contains the questions and
// the answer selections
function createQuestionElement(index) {
var qElement = $('<div>', {
id: 'question'
});
var header = $('<h2>Question ' + (index + 1) + ':</h2>');
qElement.append(header);
var question = $('<p>').append(questions[index].question);
qElement.append(question);
var radioButtons = createRadios(index);
qElement.append(radioButtons);
return qElement;
}
// Creates a list of the answer choices as radio inputs
function createRadios(index) {
var radioList = $('<ul>');
var item;
var input = '';
for (var i = 0; i < questions[index].choices.length; i++) {
item = $('<li>');
input = '<input type="radio" name="answer" value=' + i + ' />';
input += questions[index].choices[i];
item.append(input);
radioList.append(item);
}
return radioList;
}
// Reads the user selection and pushes the value to an array
function choose() {
selections[questionCounter] = +$('input[name="answer"]:checked').val();
}
// Displays next requested element
function displayNext() {
quiz.fadeOut(function() {
$('#question').remove();
if(questionCounter < questions.length){
var nextQuestion = createQuestionElement(questionCounter);
quiz.append(nextQuestion).fadeIn();
if (!(isNaN(selections[questionCounter]))) {
$('input[value='+selections[questionCounter]+']').prop('checked', true);
}
// Controls display of 'prev' button
if(questionCounter === 1){
$('#prev').show();
} else if(questionCounter === 0){
$('#prev').hide();
$('#next').show();
}
}else {
var scoreElem = displayScore();
quiz.append(scoreElem).fadeIn();
$('#next').hide();
$('#prev').hide();
$('#start').show();
}
});
}
// Computes score and returns a paragraph element to be displayed
function displayScore() {
var score = $('<p>',{id: 'question'});
var numCorrect = 0;
for (var i = 0; i < selections.length; i++) {
if (selections[i] === questions[i].correctAnswer) {
numCorrect++;
}
}
score.append('You got ' + numCorrect + ' questions out of ' +
questions.length + ' right!!!');
return score;
}
})();
The issue is very simple. You're missing the $ at the very start of the Javascript code. Add that in and you're golden. To explain, you can use the dollar sign as a function name. jQuery (which you're using) does this to make it very quick and easy to type. When you use $ all by itself, it takes a function as an argument (i.e. you pass in a callback function) and that callback function is called as soon as the page is loaded. That's nothing special or magical, it's just what the $() function does, and it's part of jQuery. People use it because the callback function is called when the page is ready to be manipulated; that is, it's called when all the HTML has been generated, which means it's safe for the Javascript to start messing around with it.
So your code was just running before the page was ready.
Fix like so:
$(function() {
var questions = [{
question: "What is 2*5?",
choices: [2, 5, 10, 15, 20],
correctAnswer: 2
}, {
question: "What is 3*6?",
choices: [3, 6, 9, 12, 18],
correctAnswer: 4
}, {
question: "What is 8*9?",
choices: [72, 99, 108, 134, 156],
correctAnswer: 0
}, {
question: "What is 1*7?",
choices: [4, 5, 6, 7, 8],
correctAnswer: 3
}, {
question: "What is 8*8?",
choices: [20, 30, 40, 50, 64],
correctAnswer: 4
}];
var questionCounter = 0; //Tracks question number
var selections = []; //Array containing user choices
var quiz = $('#quiz'); //Quiz div object
// Display initial question
displayNext();
// Click handler for the 'next' button
$('#next').on('click', function (e) {
e.preventDefault();
// Suspend click listener during fade animation
if(quiz.is(':animated')) {
return false;
}
choose();
// If no user selection, progress is stopped
if (isNaN(selections[questionCounter])) {
alert('Please make a selection!');
} else {
questionCounter++;
displayNext();
}
});
// Click handler for the 'prev' button
$('#prev').on('click', function (e) {
e.preventDefault();
if(quiz.is(':animated')) {
return false;
}
choose();
questionCounter--;
displayNext();
});
// Click handler for the 'Start Over' button
$('#start').on('click', function (e) {
e.preventDefault();
if(quiz.is(':animated')) {
return false;
}
questionCounter = 0;
selections = [];
displayNext();
$('#start').hide();
});
// Animates buttons on hover
$('.button').on('mouseenter', function () {
$(this).addClass('active');
});
$('.button').on('mouseleave', function () {
$(this).removeClass('active');
});
// Creates and returns the div that contains the questions and
// the answer selections
function createQuestionElement(index) {
var qElement = $('<div>', {
id: 'question'
});
var header = $('<h2>Question ' + (index + 1) + ':</h2>');
qElement.append(header);
var question = $('<p>').append(questions[index].question);
qElement.append(question);
var radioButtons = createRadios(index);
qElement.append(radioButtons);
return qElement;
}
// Creates a list of the answer choices as radio inputs
function createRadios(index) {
var radioList = $('<ul>');
var item;
var input = '';
for (var i = 0; i < questions[index].choices.length; i++) {
item = $('<li>');
input = '<input type="radio" name="answer" value=' + i + ' />';
input += questions[index].choices[i];
item.append(input);
radioList.append(item);
}
return radioList;
}
// Reads the user selection and pushes the value to an array
function choose() {
selections[questionCounter] = +$('input[name="answer"]:checked').val();
}
// Displays next requested element
function displayNext() {
quiz.fadeOut(function() {
$('#question').remove();
if(questionCounter < questions.length){
var nextQuestion = createQuestionElement(questionCounter);
quiz.append(nextQuestion).fadeIn();
if (!(isNaN(selections[questionCounter]))) {
$('input[value='+selections[questionCounter]+']').prop('checked', true);
}
// Controls display of 'prev' button
if(questionCounter === 1){
$('#prev').show();
} else if(questionCounter === 0){
$('#prev').hide();
$('#next').show();
}
}else {
var scoreElem = displayScore();
quiz.append(scoreElem).fadeIn();
$('#next').hide();
$('#prev').hide();
$('#start').show();
}
});
}
// Computes score and returns a paragraph element to be displayed
function displayScore() {
var score = $('<p>',{id: 'question'});
var numCorrect = 0;
for (var i = 0; i < selections.length; i++) {
if (selections[i] === questions[i].correctAnswer) {
numCorrect++;
}
}
score.append('You got ' + numCorrect + ' questions out of ' +
questions.length + ' right!!!');
return score;
}
})();
Of course your head should also look more like this:
<head>
<title>History</title>
<link rel="stylesheet" type="text/css" href="../css.css">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src='javascript.js'></script>
</head>
You need to replace your function "(function() {" with
"$(window).on("load", function() {"
Your Quiz div is getting loaded later on after the functions get executed and hence your first question is not getting loaded. Hope this resolves the issue.
I believe that you have two problems here and both are related to html and js loading.
you are linking your script twice (maybe copy error?) and the first time before you add reference to jQuery, so your script is failing because it is loaded before you add jQuery and since your script is self executing function it will try to run immediately after it is loaded but will fail because jQuery which it relies on is not loaded yet.
again your script will run as soon as it is loaded and not add the correct handlers, etc.. because it is actually loaded before the rest of the html code, so it can't add those handlers to elements. So your solution here is either use some body onload hook and do the init there, or put the <script type="text/javascript" src='javascript.js'></script>at the bottom of the page so when it is loaded you can be sure that rest of the HTML code is loaded as well.

Count-up Timer required

I've been wanting to create a timer for my website that countsup, and displays alerts at certain intervals. So like, it starts from 0 and counts upwards when the user pushes a button. From there, it will display a a custom alert at certain intervals... (4 minutes for example)... 45 seconds before that interval, I need the number to change to yellow and 10 seconds before that interval, I need it to change to red... then back to the normal color when it passes that interval.
I've got a basic timer code but I am not sure how to do the rest. I am quite new to this. Any help? Thanks so much in advance.
var pad = function(n) { return (''+n).length<4?pad('0'+n):n; };
jQuery.fn.timer = function() {
var t = this, i = 0;
setInterval(function() {
t.text(pad(i++));
}, 1000);
};
$('#timer').timer();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='timer'></div>
You could do something like this
var pad = function (n) {
return ('' + n).length < 4 ? pad('0' + n) : n;
};
jQuery.fn.timer = function () {
var t = this,
i = 0;
setInterval(function () {
t.text(pad(i++));
checkTime(i, t);
}, 1000);
};
$('#timer').timer();
checkTime = function (time, t) {
switch (time -1) {
case 10:
t.css('color','red');
break;
case 20:
t.css('color','yellow');
break;
case 30:
t.css('color','green');
break;
case 40:
t.css('color','black');
break;
default:
}
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='timer'></div>
Something like this should work:
Here is a jsFiddle DEMO
jQuery
$.fn.timer = function (complete, warning, danger) {
var $this = $(this);
var total = 0;
$this.text(total);
var intervalComplete = parseInt(complete, 10);
var intervalWarning = parseInt(intervalComplete - warning, 10);
var intervalDanger = parseInt(intervalComplete - danger, 10);
var clock = setInterval(function () {
total += 1;
$this.text(total);
if (intervalWarning === total) {
// set to YELLOW:
$this.addClass('yellow');
}
if (intervalDanger === total) {
// set to RED:
$this.removeClass('yellow').addClass('red');
}
if (intervalComplete === total) {
// reset:
clearInterval(clock);
$this.removeClass();
alert('COMPLETE!');
}
}, 1000);
};
$(function () {
$('#timer').timer(240, 45, 10);
});
CSS
.red {
background-color: red;
}
.yellow {
background-color: yellow;
}
An additional point:
You should place some error validation within the function to ensure your counter completion time is greater than both the warning and danger time intervals.
You can try something like this:
JSFiddle
This is a pure JS timer code. Also for popup you can use something like Bootbox.js.
Code
function timer() {
var time = {
sec: 00,
min: 00,
hr: 00
};
var finalLimit = null,
warnLimit = null,
errorLimit = null;
var max = 59;
var interval = null;
function init(_hr, _min, _sec) {
time["hr"] = _hr ? _hr : 0;
time["min"] = _min ? _min : 0;
time["sec"] = _sec ? _sec : 0;
printAll();
}
function setLimit(fLimit, wLimit, eLimit) {
finalLimit = fLimit;
warnLimit = wLimit;
errorLimit = eLimit;
}
function printAll() {
print("sec");
print("min");
print("hr");
}
function update(str) {
time[str] ++;
time[str] = time[str] % 60;
if (time[str] == 0) {
str == "sec" ? update("min") : update("hr");
}
print(str);
}
function print(str) {
var _time = time[str].toString().length == 1 ? "0" + time[str] : time[str];
document.getElementById("lbl" + str).innerHTML = _time;
}
function validateTimer() {
var c = "";
var secs = time.sec + (time.min * 60) + (time.hr * 60 * 60);
console.log(secs, finalLimit)
if (secs >= finalLimit) {
stopTimer();
} else if (secs >= errorLimit) {
c = "error";
} else if (secs >= warnLimit) {
c = "warn";
} else {
c = "";
}
var element = document.getElementsByTagName("span");
console.log(element, c)
document.getElementById("lblsec").className = c;
}
function startTimer() {
init();
if (interval) stopTimer();
interval = setInterval(function() {
update("sec");
validateTimer();
}, 1000);
}
function stopTimer() {
window.clearInterval(interval);
}
function resetInterval() {
stopTimer();
time["sec"] = time["min"] = time["hr"] = 0;
printAll();
startTimer();
}
return {
'start': startTimer,
'stop': stopTimer,
'reset': resetInterval,
'init': init,
'setLimit': setLimit
}
};
var time = new timer();
function initTimer() {
time.init(0, 0, 0);
}
function startTimer() {
time.start();
time.setLimit(10, 5, 8);
}
function endTimer() {
time.stop();
}
function resetTimer() {
time.reset();
}
span {
border: 1px solid gray;
padding: 5px;
border-radius: 4px;
background: #fff;
}
.timer {
padding: 2px;
margin: 10px;
}
.main {
background: #eee;
padding: 5px;
width: 200px;
text-align: center;
}
.btn {
-webkit-border-radius: 6;
-moz-border-radius: 6;
border-radius: 6px;
color: #ffffff;
font-size: 14px;
background: #2980b9;
text-decoration: none;
transition: 0.4s;
}
.btn:hover {
background: #3cb0fd;
text-decoration: none;
transition: 0.4s;
}
.warn {
background: yellow;
}
.error {
background: red;
}
<div class="main">
<div class="timer"> <span id="lblhr">00</span>
: <span id="lblmin">00</span>
: <span id="lblsec">00</span>
</div>
<button class="btn" onclick="startTimer()">Start</button>
<button class="btn" onclick="endTimer()">Stop</button>
<button class="btn" onclick="resetTimer()">Reset</button>
</div>
Hope it helps!

javascript game ( 3 in line ) line check logic

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;
}
};

Categories