0

I have a web page that shows four buttons, one for each suit in a deck of cards. When a user clicks on a button, it should show the card image of that suit, starting with Ace, 2, 3, etc. through King. The first card should show for three seconds, then be replaced by the next card for three seconds, etc. Here is my HTML:

<!DOCTYPE html> 
<html> 
<head> 
    <title>jQuery Assignment 4 - Cards</title> 
    <link href="styles/my_style.css" rel="stylesheet">
</head> 
<body>
    <div id="main">
        <h1>Click a suit to reveal a card</h1>
        <div id="my_hand">
            <img src="images/hit_small.jpg" id="cardBack">
        </div>
        <div id="controls">
            <div id="btnHearts">
                <button>Hearts</button>
            </div>
            <div id="btnDiamonds">
                <button>Diamonds</button>
            </div>
            <div id="btnClubs">
                <button>Clubs</button>
            </div>
            <div id="btnSpades">
                <button>Spades</button>
            </div>
        </div>
    </div>

    <script src="scripts/jquery-1.6.2.min.js"></script>
    <script src="scripts/my_scripts.js"></script>
</body>
</html>

Here is the CSS:

#cardBack {
    float: left;
}

#cardFront {
    float: right;
}

h1 {
    text-align: center;
}

#my_hand{
    clear: both;
    border: 1px solid gray;
    height: 245px;
    width: 350px;
    margin: auto;
}

#controls {
    width: 100%;
    float: left;
    text-align: center;
    margin-top: 50px;
}

#btnHearts, #btnDiamonds, #btnClubs, #btnSpades{
    text-align: center;
    display: inline-block;
    padding: 20px;
}

Here is my javascript:

$(document).ready(function(){

function card(name,suit,value) {
    this.name = name;
    this.suit = suit;
    this.value = value;
};

var old_cards = new Array();

var hearts = [
    new card('Ace', 'Hearts',1),
    new card('Two', 'Hearts',2),
    new card('Three', 'Hearts',3),
    new card('Four', 'Hearts',4),
    new card('Five', 'Hearts',5),
    new card('Six', 'Hearts',6),
    new card('Seven', 'Hearts',7),
    new card('Eight', 'Hearts',8),
    new card('Nine', 'Hearts',9),
    new card('Ten', 'Hearts',10),
    new card('Jack', 'Hearts',10),
    new card('Queen', 'Hearts',10),
    new card('King', 'Hearts',10)

];

var diamonds = [
    new card('Ace', 'Diamonds',1),
    new card('Two', 'Diamonds',2),
    new card('Three', 'Diamonds',3),
    new card('Four', 'Diamonds',4),
    new card('Five', 'Diamonds',5),
    new card('Six', 'Diamonds',6),
    new card('Seven', 'Diamonds',7),
    new card('Eight', 'Diamonds',8),
    new card('Nine', 'Diamonds',9),
    new card('Ten', 'Diamonds',10),
    new card('Jack', 'Diamonds',10),
    new card('Queen', 'Diamonds',10),
    new card('King', 'Diamonds',10)
];

var clubs = [
    new card('Ace', 'Clubs',1),
    new card('Two', 'Clubs',2),
    new card('Three', 'Clubs',3),
    new card('Four', 'Clubs',4),
    new card('Five', 'Clubs',5),
    new card('Six', 'Clubs',6),
    new card('Seven', 'Clubs',7),
    new card('Eight', 'Clubs',8),
    new card('Nine', 'Clubs',9),
    new card('Ten', 'Clubs',10),
    new card('Jack', 'Clubs',10),
    new card('Queen', 'Clubs',10),
    new card('King', 'Clubs',10)
];

var spades = [
    new card('Ace', 'Spades',1),
    new card('Two', 'Spades',2),
    new card('Three', 'Spades',3),
    new card('Four', 'Spades',4),
    new card('Five', 'Spades',5),
    new card('Six', 'Spades',6),
    new card('Seven', 'Spades',7),
    new card('Eight', 'Spades',8),
    new card('Nine', 'Spades',9),
    new card('Ten', 'Spades',10),
    new card('Jack', 'Spades',10),
    new card('Queen', 'Spades',10),
    new card('King', 'Spades',10)
];

var hand = {
    cards : new Array(),
};

$("#btnHearts").click(function(){
    var index = $.inArray(index, hearts);

    do {
        //Show a new card every 3 seconds, starting with the Ace, then 2, 3, etc...
    }while {

    }

    var c = hearts[ index ];
            old_cards[old_cards.length] = index;
            hand.cards[hand.cards.length] = c;

    var $i = $("<img>");
            $i.addClass("current_hand")
              .appendTo("#my_hand");

            $("<img>").attr('id', 'cardFront')
                      .attr('alt', c.name + ' of ' + c.suit )
                      .attr('title', c.name + ' of ' + c.suit )
                      .attr('src', 'images/cards/' + c.suit + '/' + c.name + '.jpg' )
                      .appendTo($i);   
    });
});

I'm pretty lost on this one. I know I want to start the index at 0 for the Ace, the loop through each one while setting a timer of three seconds. Any help is very much appreciated!

nponinski
  • 53
  • 1
  • 10
  • Dont reinvent the slideshow, use one of the 4 billion plugins already out there instead – Wesley Smith Oct 28 '17 at 01:11
  • I'm not sure what plugins you're talking about. All I know is that I have to make it work with the requirements I mentioned. What plugins are you referring to? – nponinski Oct 28 '17 at 01:14

2 Answers2

1

https://jsfiddle.net/Lupvk4sy/

Ok, so here is a really quick example of one way you could do it. Not saying this is the best or even necessarily the most clean way of doing it but it's just some callback function finagling with some self-called functions to maintain proper scopes where needed.

HTML

<div>
  <img src="https://lh4.ggpht.com/FUWsXiCVl9xt1bxfdtZk7QgMQpbui_uxv7qONujjFMrf-B-aU0N4gPJ9qY5hoBsoTuo=w300" id="cover" height="100" width="100">
  <img src="http://1389blog.com/pix/happy-cat-wallpaper-thumbnail.jpg" id="1" style="display:none;" height="100" width="100">
  <img src="https://prime.peta.org/wp-content/uploads/2009/03/cateyes.thumbnail.jpg" id="2" style="display:none;" height="100" width="100">
  <img src="https://lh5.ggpht.com/z-HSdeRxdeE5ExB6VliQiKpi7o5VWQ3xpbXfs_8Q8rFO8O7sF52hGEhLNYTG7un_nw=h310" id="3" style="display:none;" height="100" width="100">
</div>
<div>
  <button id="cycle">
    Click Me to cycle stuff!
  </button>
</div>

JS (just jQuery)

$(function() {
    var arrayOfCats = [
    $("#1"),
    $("#2"),
    $("#3")
  ];
    $("#cycle").click(progressImage);

  function progressImage() {
    $("#cycle").prop("disabled", "disabled");
    $("#cover").toggle();
        for (var x = 0; x < arrayOfCats.length; x++) {
        delay = x * 3000;
      (function(x, delay){ 
          setTimeout(function() {
            if (x > 0)
              arrayOfCats[x - 1].toggle();
            arrayOfCats[x].toggle();
            if (x === arrayOfCats.length - 1) {
                (function(x, delay){
                    setTimeout(function() {
                      arrayOfCats[x].toggle();
                      $("#cycle").prop("disabled", ""); 
                      $("#cover").toggle();
                  }, delay)
              })(x, 3000);
            }
          }, delay);
        })(x, delay);    
    }
  }
})

Explanation:

First thing I do is disable the button to make the for loop run so I don't get interleaved toggles which would disrupt how everything appears on screen.

Then I remove the "cover" photo which is just there as a stand-in for what could be the back of the deck in your homework assignment.

Then I iterate through all of the elements in my array of jQuery selectors and assign to them an increasing delay (I multiply because all of the setTimeouts will be called 1 after the other because they are asynchronous. The for loop will not wait for them to finish before moving on to the next one. So essentially I tell all of the images "Show yourself in x * 3 seconds time, and when you show yourself, hide the previous image". 1st image shows itself immediately (0 * 3), the second shows itself in 3 seconds (1 * 3) and hides the first image, the third one shows itself in 6 seconds (2 * 3) and hides the second image.

Finally I get to the last image. Here I need to tell it to hide itself after 3 seconds (and since the 3 second setTimeout will only execute after it is done with the animation for its own image, which itself will have taken the due amount of time, I do not need to make this (x * 3). 3 seconds will do because it will have already waited (x * 3) before even calling that code, and at that point, it would just need to wait 3 seconds.) and reshow the album cover, as well as re-enabling the button to let you go through them again.

The reason why you see this notation

({
    // code here
})(x, delay)

is because I need to make a self calling function. This is because of a concept discussed here: setTimeout in for-loop does not print consecutive values

Which I won't reiterate on because they do a great job of explaining it anyway.

Pedro
  • 129
  • 6
  • Ok I will check it out, thank you! I would just like to know how the coding works and understand it, that way I can learn from this and hopefully get better – nponinski Oct 28 '17 at 01:36
  • I can’t use a plugin like that, I have to write the code to make it happen – nponinski Oct 28 '17 at 02:43
  • Gotcha, alright well I'll try and type up an example of how you *could* do this, without actually doing the assignment itself so you have a chance to try for yourself. – Pedro Oct 28 '17 at 03:46
  • Done! Sorry it took so long, I got distracted. – Pedro Oct 28 '17 at 04:39
  • 1
    Thank you so much! This is amazing, awesome awesome job of explaining this and helping people like me actually understand the concepts! I appreciate it! – nponinski Oct 28 '17 at 04:48
  • Sure thing! Glad to help. Good luck on your assignment. – Pedro Oct 28 '17 at 04:50
1

I've done it in another way.

Mainly, you will need:

  1. An event listener for each button
  2. A timer setInterval that runs every 3 seconds
  3. A timer setTimeout that expires after all cards (3*13)

First things first, the definitions:

var index = 0;

var cards = [
  'Ace',
  'Two',
  'Three',
  'Four',
  'Five',
  'Six',
  'Seven',
  'Eight',
  'Nine',
  'Ten',
  'Jack',
  'Queen',
  'King'
];

var types = [
  {
    name: 'hearts',
    imgSrc: 'img/hearts/'
  },
  {
    name: 'diamonds',
    imgSrc: 'img/diamonds/'
  },
  {
    name: 'clubs',
    imgSrc: 'img/clubs/'
  },
  {
    name: 'spades',
    imgSrc: 'img/spades/'
  }
];

Next, we add the event listeners:

$('#btnHearts').click(function(type) {
  render(0);
});

$('#btnDiamonds').click(function(type) {
  render(1);
});

$('#btnClubs').click(function(type) {
  render(2);
});

$('#btnSpades').click(function(type) {
  render(3);
});

Then, we put our function, the render function, which fires the 2 timers, and startShow which runs every 3 seconds...

The render function:

var render = function(type) {

  // Disable all buttons
  $(':button').prop('disabled', true);

  // Start the cards show
  var clock = setInterval(function() {
    startShow(type, index);
    index++;
  }, 3000);

  // Set a timer to stop the show
  setTimeout(function() {
    // Stop the cards show
    clearInterval(clock);
    // Enable all buttons
    $(':button').prop('disabled', false);
    // Reset index
    index = 0;
  }, 41990);

}

The startShow function:

var startShow = function(type, index) {
  $('#cardBack').attr('src', types[type].imgSrc + cards[index] + '.jpg');
  $('#cardBack').attr('title', types[type].name);
}

Note: Your images need to be like: img/hearts/Ace.jpg

Hope that helps!

Sami Almalki
  • 588
  • 2
  • 17