Comparing the elements in memory game - javascript

It's my first steps with programming in js.
I've problem with compare elements in memory game.
After clicking, the code compares only one element from the first click and it causes the function and does not compare further elements despite the collected value -
For example: if I click img with src="f1.png", it's comparing only that element with that same src, not comparing other elements. Here it's f2.png
(This can be confusing but I don't know how to best to describe it)
Please, help me fix that problem.
html
<div class="c ef">
<div class="f"></div>
<div class="b"><img src="f1.png" /></div>
</div>
<div class="c ef">
<div class="f"></div>
<div class="b"><img src="f2.png" /></div>
</div>
<div class="c ef">
<div class="f"></div>
<div class="b"><img src="f1.png" /></div>
</div>
<div class="c ef">
<div class="f"></div>
<div class="b"><img src="f2.png" /></div>
</div>
script
(function() {
var open = "";
var cards = $(".c.ef");
for ( var i = 0, len = cards.length; i < len; i++ ) {
var card = cards[i];
clickListener(card);
}
function clickListener(card) {
card.addEventListener( "click", function() {
var c = this.classList;
c.add("flip");
var open1="";
if(open == ""){
open = $( ".flip" ).contents().find("img").attr("src");
}else{
open1 = $( ".flip" ).contents().find("img").attr("src");
}
if(open !== open1){
setTimeout(function(){
c.remove("flip");
}, 1200);
}else{
setTimeout(function(){
$(".flip").css("visibility", "hidden");
c.remove("flip");
}, 800);
}
});
}
})();

I will try to describ how i will proceded
1rst : you can use data attribute for manipulate easier dom img
2nd : save data value in variable when you click on image
3rd : compare if you second click match with your first variable
so e.g :
<div class="c ef">
<div class="f"></div>
<div class="b" data-img-value="1"><img src="f1.png" /></div>
</div>
<div class="c ef">
<div class="f"></div>
<div class="b" data-img-value="2"><img src="f2.png" /></div>
</div>
<div class="c ef">
<div class="f"></div>
<div class="b" data-img-value="1"><img src="f1.png" /></div>
</div>
<div class="c ef">
<div class="f"></div>
<div class="b" data-img-value="2"><img src="f2.png" /></div>
</div>
------------------- script----------
(function() {
var $card= $('.b');
var $firstVal = null;
$card.on('click',function(){
if($firstVal === null){
$firstVal = $(this).first().attr('data-img-value');
}
else{
if($firstVal === $(this).first().attr('data-img-value')){
//your code if pair match
console.log('pair founded')
$firstval = null;
}
else{
//your code if not match
console.log('not pair')
}
}
});
})();
you can run this exemple here
https://jsfiddle.net/a1na9hLe/5/

After the comparison was made, you have to reset open in order to make a new comparison.
After the first click, open is set to, for example, "f1.png". (btw, imo, you should return here).
After the second click, open1 is set to, for example, "f2.png".
Then the comparison open !== open1 gives you a result, but you never reset open back to "".
So, for the third click, open is already set to the previous value ("f1.png"), and it'll compare the same thing again and again.
TL;DR
This should do the trick:
if(open !== open1){
setTimeout(function(){
c.remove("flip");
open = '';
}, 1200);
}else{
setTimeout(function(){
$(".flip").css("visibility", "hidden");
c.remove("flip");
open = '';
}, 800);
}

Related

How to add function in every single element in javascript nodelist

so here's an example of the working code
const test = document.getElementById('test')
const time = 1000
var timer;
test.addEventListener('touchstart', hlt)
test.addEventListener('touchend', endt)
function onlongtouch(){
console.log('it has been 600 milisecond')
}
function hlt(){
console.log('test');
timer = setTimeout(onlongtouch, time)
console.log(timer)
}
function endt(){
if(timer){
clearTimeout(timer)
}
}
And the HTML
<div class="data" id="test">
<div class="num"><p>1</p></div>
<div class="title"><p>Crush It</p></div>
<div class="author"><p>Gary Vaynerchunk</p></div>
<div class="ISBN"><p>132132312</p></div>
</div>
<div class="data">
<div class="num"><p>2</p></div>
<div class="title"><p>Crush It</p></div>
<div class="author"><p>Gary Vaynerchunk</p></div>
<div class="ISBN"><p>132132312</p></div>
</div>
<div class="data">
<div class="num"><p>3</p></div>
<div class="title"><p>Crush It</p></div>
<div class="author"><p>Gary Vaynerchunk</p></div>
<div class="ISBN"><p>132132312</p></div>
</div>
so i was taking a single element with an id of "test" and add the touch functionality to it, but what if i replace const test = document.getElementById('test') with document.querySelectorAll('data') im grabbing the same element but instead of a single element it's a whole nodelist full of element. How do i add functionality to all of them?
Thank you in advance!
let elements = [...document.querySelectorAll('.data')];
for(let el of elements) {
el.addEventListener('touchstart', hlt)
el.addEventListener('touchend', endt)
}

How to get previous element from click target?

Hello I have this html code:
<div class="row newrow">
<div class="col-10"><b>this</b></div>
<div class="col-2">
<img src="close.png" id="exit"/>
</div>
</div>
When I click on img with id exit using this code
$('body').on('click','#exit',function(e){
})
I need to get the text of the <b>behind it which would be "this"
I have tried this but it does not work:
$('body').on('click','#exit',function(e){
$q = $(e.target).prev('b')
var word = $q.text()
)}
It only gives me the that I clicked from the beginning
try this:
$('body').on('click','#exit',function(e){
var this_b = $(this).parent().prev().children(0).html();// get the text
alert(this_b);
});
You can use $(this).closest('.row').find('b'):
$('#exit').click(function(e){
$q = $(this).closest('.row').find('b');
var word = $q.text();
console.log(word);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row newrow">
<div class="col-10"><b>this</b></div>
<div class="col-2">
<img src="close.png" id="exit"/>
</div>
</div>
You need to select the parent of the clicked img to get the the .col-2, and then get the col-2's prev() to get to the .col-10, and then you can access its children() to get the children (the single <b>). Also, there's no need for e.target if you use this:
$('body').on('click', '#exit', function() {
$q = $(this).parent().prev().children();
var word = $q.text()
console.log(word);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row newrow">
<div class="col-10"><b>this</b></div>
<div class="col-2">
<img src="close.png" id="exit" />
</div>
</div>
Try this
$('body').on('click','#exit',function(e){
var word = $(this).closest('.newrow').find('b').text();
});

Get sibling of clicked element and removeClass pure javascript or angular js without directive

So the problem is i know how to do it in jQuery, and i know jQuery is open platform so I could find what siblings() actually do.
But i want to do it in pure js or angular but without directive.
Preferable solution in pure JS.
So when div is clicked addClass, but siblings remove that same class.
Thanks in advance.
Here is html
<div class="container">
<div class="row">
<div id="1">
<h1>asfsaff</h1>
</div>
<div id="2">
<h1>asfsaff</h1>
</div>
<div id="3">
<h1>asfsaff</h1>
</div>
<div id="4">
<h1>asfsaff</h1>
</div>
<div id="5">
<h1>asfsaff</h1>
</div>
<div id="6">
<h1>asfsaff</h1>
</div>
</div>
</div>
Here is my js
$scope.addParent = function(e) {
var men = event.target.getAttribute('data');
console.log(men);
var divSlide = document.querySelectorAll('div');
divSlide.forEach(function(getId){
var divId = getId.getAttribute('id');
if(men === divId) {
getId.className = "fsafsa";
}
});
}
Here's how it might be applied. Find the node you want, then call getSiblings and retrieve a collection of sibling nodes, then iterate over them and do whatever you'd like to them:
var mySel = document.getElementById("2");
var myOthers = getSiblings(mySel);
// First, let's set the style of our selection
mySel.className = "selected"
// Next, let's de-toggle any others
for (var i=0; i<myOthers.length; i++){
myOthers[i].className = "not-selected";
}
// utility functions
function getChildren(n, skipMe){
var r = [];
for ( ; n; n = n.nextSibling )
if ( n.nodeType == 1 && n != skipMe)
r.push( n );
return r;
};
function getSiblings(n) {
return getChildren(n.parentNode.firstChild, n);
}
.row div {
padding: 5px;
}
.selected {
border: 1px dotted blue;
}
.not-selected {
border: 1px solid red;
}
<div class="container">
<div class="row">
<div id="1">
<h1>asfsaff</h1>
</div>
<div id="2">
<h1>asfsaff</h1>
</div>
<div id="3">
<h1>asfsaff</h1>
</div>
<div id="4">
<h1>asfsaff</h1>
</div>
<div id="5">
<h1>asfsaff</h1>
</div>
<div id="6">
<h1>asfsaff</h1>
</div>
</div>
</div>
Looked at the example I mention in the comments, here's the relevant piece of code. A very elegant pure-javascript solution:
function getChildren(n, skipMe){
var r = [];
for ( ; n; n = n.nextSibling )
if ( n.nodeType == 1 && n != skipMe)
r.push( n );
return r;
};
function getSiblings(n) {
return getChildren(n.parentNode.firstChild, n);
}
So getSiblings calls getChildren for the current nodes parent, then simply removes the current node from the returned list. I like it!

Accordion with javascript

I've been trying to get an accordion movement going with javascript.
The problem that I'm having is having one close if it's already open and stay closed.
Right now the according closing one and opening another when I click a different div.
I see that the argument is always resolving to true because I'm removing the classes.. but I can't seem to find a away to get around that so I could have a nice accordion.
<div class="speaker-container">
<div class="span3 offset1 speaker" id="sp-info-0">
<div class="speaker-img">
<div class="hover"></div>
<img src="" alt="">
</div>
<h4>Title</h4>
</div>
<div class="speaker-info" id="sp-info-0">
<button class="close-speaker">Close</button>
<h2>Title</h2>
</div>
<div class="span3 offset1 speaker" id="sp-info-1">
<div class="speaker-img">
<div class="hover"></div>
<img src="" alt="">
</div>
<h4>Sub Title</h4>
</div>
<div class="speaker-info" id="sp-info-1">
<button class="close-speaker">Close</button>
<h2>Title</h2>
</div>
<div class="span3 offset1 speaker" id="sp-info-2">
<div class="speaker-img">
<div class="hover"></div>
<img src="" alt="">
</div>
<h4>Title</h4>
</div>
<div class="speaker-info" id="sp-info-2">
<button class="close-speaker">Close</button>
<h2>Title</h2>
</div>
</div>
var timer;
$('.speaker-container .speaker').on('click', function(){
var speakerContainer = document.getElementsByClassName('speaker-container');
var self = this;
var children = $('.speaker-container').children();
var selfHeight = this.clientHeight;
var parentOffset = this.parentElement.offsetHeight;
var selfOffset = this.nextElementSibling.offsetHeight;
console.dir(children);
console.log(parentOffset);
$('.speaker-container').removeClass('open').css({'height' : selfHeight + 'px'});
for (var i = 0; i < children.length; i++) {
if (children[i].className == 'speaker-info fade') {
console.dir(children[i]);
$(children[i]).removeClass('fade');
}
}
if (self.parentElement.className !== 'speaker-container open' && self.nextElementSibling.className !== 'speaker-info fade') {
timer = setTimeout(function(){
self.parentElement.setAttribute('class' , 'speaker-container open');
self.parentElement.style.height = selfOffset + selfHeight + 'px';
self.nextElementSibling.style.top = selfHeight + 'px';
self.nextElementSibling.setAttribute('class' , 'speaker-info fade');
// return false;
}, 500);
} else {
$('.speaker-container').removeClass('open').css({'height' : selfHeight + 'px'});
self.nextElementSibling.setAttribute('class' , 'speaker-info');
window.clearTimeout(timer);
}
});
Make a class that has the item open. (let's say the class is "open")
Make a class that has the item closed. (let's say the class is closed")
let's say all the accordion items are in the accordion class.
function that opens an item:
cycle through and remove any existing open item classes, add closed class.
add open class to the selected item.
by default, give closed class to all items (except the one you want open by default, if any)
with javascript it would look something like:
function openOnClick()
{
var openaccordion=document.getElementsByClassName('open');
openaccordion.className.replace( /(?:^|\s)open(?!\S)/g , 'close' );
this.className.replace( /(?:^|\s)close(?!\S)/g , 'open' );
}
with jQuery it would look like this:
$('div.accordion').click(function(){
$('.open').removeClass('open').addClass('close');
$(this).removeClass('close').addClass('open');
}
you can use jqueryui to get some sliding effects in there pretty simply too:
$(this).switchClass('close','open',1000);

How to alter the value of a div on each click

I have got a task to create a puzzle.I have 12 div.Each div contains different value up to 12.I have button like start now.I want to change my div value on each click of the start now button.
DEMO
<div id="container">
<div class="finder">
<div class="block1"> <div id="one"><h1>1</h1></div>
</div>
<div class="block1"> <div id="two"><h1>2</h1></div>
</div>
<div class="block1"> <div id="three"><h1>3</h1></div>
</div>
<div class="block1"> <div id="four"><h1>4</h1></div>
</div>
<div class="block1"> <div id="five"><h1>5</h1></div>
</div>
<div class="block1"> <div id="six"><h1>6</h1></div>
</div>
<div class="block1"> <div id="seven"><h1>7</h1></div>
</div>
<div class="block1"> <div id="eight"><h1>8</h1></div>
</div>
<div class="block1"> <div id="nine"><h1>9</h1></div>
</div>
<div class="block1"> <div id="ten"><h1>10</h1></div>
</div>
<div class="block1"> <div id="eleven"><h1>11</h1></div>
</div>
<div class="block1"> <div id="twelve"><h1>12</h1></div>
</div>
</div>
<div class="button">
<div id="startButton">
<button>Start</button>
</div>
</div>
</div>
js is
$(".finder").css('display','none');
$("#startButton").click(function () {
$(".finder").css('display','block');
});
var myDiv;
$(".block1 div").on('click', function(){myDiv = $(this)});
$(".block1 div").click(function () {
if(myDiv.text() < 12)
{
myDiv.text(parseInt(myDiv.text())+1);
}
if(myDiv.text() > 12)
{
myDiv.text(1);
myDiv.text(parseInt(myDiv.text())+1);
}
});
How can i change the values?
I have provided a solution below. One of the key takeaways you should get from it, is that when an event handler is used this will be assigned the element the event was trigger on within the bound function.
To Fill the boxes with random numbers use this code
$(function() {
//Array of values
var values = [1,2,3,4,5,6,7,8,9,10,11,12];
$( "input[type=submit], button" )
.button()
.click(function( event ) {
event.preventDefault();
});
$(".finder").css('display','none');
$("#startButton").click(function () {
var tmpValues = values.slice(); //copy array
$(".block1 div h1").each(function(){
var r = Math.floor(Math.random()*tmpValues.length);
//assign html to random array value that gets removed from array
$(this).html(tmpValues.splice(r,1));
});
$(".finder").css('display','block');
});
$(".block1 div").click(function () {
//Instead of setting myDiv use $(this) which will refer to the div
//We can grab the value of the H1 within the div using a scoped selector
var value = parseInt($("h1",this).html());
//Set the html of the clicked div
//When setting the html we must include new value in h1 to maintain style
//Ternary expression tidies up the logic, not sure why it sets to to 2 though?
$(this).html("<h1>" + ((value > 12) ? 2: value+1) + "</h1>");
});
});
Working Example http://jsfiddle.net/W55xc/3/
I didnt quite get the question, but I guess you want to generate random numbers for the div's, right? Use Math.random()
$(".block1 div").each(function() {
$(this).children('h1').text(Math.floor((Math.random() * 12) + 1)); // Generate a random number <-> [1, 12]
}

Categories

Resources