title
Memory Card Game - JavaScript Tutorial
description
Learn the fundamentals of pure javascript by building a memory card game. No frameworks or libraries, just vanilla JavaScript.
This video will cover how to:
‣ select elements in the DOM with querySelector
‣ iterate through lists with forEach
‣ add/remove an element class
‣ add/remove event listeners
‣ timeout
‣ html5: data-attribute
‣ css3: positioning, flexbox, perspective, backface-visibility, transitions
🔗Demo: https://marina-ferreira.github.io/memory-game/
💻Repo: https://github.com/code-sketch/memory-game/
💻Finished files: https://marina-ferreira.github.io/projects/js/memory-game/
⭐️ Course Contents ⭐️
⌨️ (00:00) Intro
⌨️ (00:47) Basic Structure / Create the Project
⌨️ (03:53) Board HTML
⌨️ (07:13) Board Styles
⌨️ (12:41) Flip Card
⌨️ (15:53) 3d Effect / CSS3 Perspective
⌨️ (18:25) Store Cards
⌨️ (22:37) Match Cards
⌨️ (25:12) Refactoring
⌨️ (27:27) Lock Board
⌨️ (28:53) Card Double Click
⌨️ (31:04) Shuffling
🎥Tutorial by Code Sketch. Check out the Code Sketch channel for more great tutorials: https://www.youtube.com/channel/UCHFmShpjG-8N52O0JD2ut3A/
--
Learn to code for free and get a developer job: https://www.freecodecamp.org
Read hundreds of articles on programming: https://medium.freecodecamp.org
detail
{'title': 'Memory Card Game - JavaScript Tutorial', 'heatmap': [{'end': 1874.076, 'start': 1870.194, 'weight': 1}], 'summary': 'This javascript tutorial series covers building a memory card game, creating a flexbox layout, understanding position absolute in css, styling the game layout, adding 3d effects, implementing matching logic, bug fixes, and shuffling cards using flexbox, catering to beginners with basic html, css, and js knowledge.', 'chapters': [{'end': 103.071, 'segs': [{'end': 103.071, 'src': 'embed', 'start': 0.069, 'weight': 0, 'content': [{'end': 6.033, 'text': 'Hello everybody, welcome to this tutorial, which is a memory card game built in pure JavaScript.', 'start': 0.069, 'duration': 5.964}, {'end': 17.44, 'text': "So, to follow this tutorial, you don't have to know a lot just the basics of HTML, CSS and JS, like basic tags,", 'start': 6.753, 'duration': 10.687}, {'end': 20.602, 'text': "basic CSS selectors and what's a function.", 'start': 17.44, 'duration': 3.162}, {'end': 28.621, 'text': 'You can find the files for each video at github.com.', 'start': 24.258, 'duration': 4.363}, {'end': 38.107, 'text': 'slash codesketch and a written tutorial and the game demo at marina slash ferreira dot, github dot io.', 'start': 28.621, 'duration': 9.486}, {'end': 44.911, 'text': "So, if you get lost along the way, please refer to those, okay? Let's get started.", 'start': 39.007, 'duration': 5.904}, {'end': 59.399, 'text': 'We are going to start with the basic file structure.', 'start': 56.718, 'duration': 2.681}, {'end': 63.72, 'text': "So in our terminal, let's make a directory called MemoryGame.", 'start': 60.019, 'duration': 3.701}, {'end': 67.742, 'text': "Let's change directory into that new directory.", 'start': 64.821, 'duration': 2.921}, {'end': 76.064, 'text': 'To create the files, we are going to touch index.html, styles.css, and scripts.js.', 'start': 68.302, 'duration': 7.762}, {'end': 81.666, 'text': 'We are also going to make a directory called mig for our images.', 'start': 77.505, 'duration': 4.161}, {'end': 98.068, 'text': "So in the editor, Let's open our index.html and declare our file as an HTML5 document with doc type.", 'start': 83.147, 'duration': 14.921}, {'end': 103.071, 'text': "In the root tag, let's specify the language as English.", 'start': 100.009, 'duration': 3.062}], 'summary': 'Tutorial on building a memory card game using pure javascript, requiring basic knowledge of html, css, and js. files are available on github.com/codesketch.ferreira.io', 'duration': 103.002, 'max_score': 0.069, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek69.jpg'}], 'start': 0.069, 'title': 'Building a memory card game in javascript', 'summary': 'Covers building a memory card game in pure javascript, requiring only basic knowledge of html, css, and js, along with providing access to files and demo.', 'chapters': [{'end': 103.071, 'start': 0.069, 'title': 'Memory card game in javascript', 'summary': 'Covers building a memory card game in pure javascript, requiring only basic knowledge of html, css, and js, along with providing access to files and demo.', 'duration': 103.002, 'highlights': ['The tutorial covers building a memory card game in pure JavaScript. The tutorial focuses on building a memory card game using pure JavaScript.', 'Basic knowledge of HTML, CSS, and JS is required to follow the tutorial. The tutorial only requires basic knowledge of HTML, CSS, and JS, such as basic tags, CSS selectors, and functions.', 'Access to files for each video is available at github.com/slashcodesketch. The tutorial provides access to files for each video at github.com/slashcodesketch.', 'A written tutorial and game demo are available at marina/ferreira.github.io. Written tutorial and game demo can be found at marina/ferreira.github.io.', 'Creation of index.html, styles.css, and scripts.js files is part of the process. The process includes creating index.html, styles.css, and scripts.js files.']}], 'duration': 103.002, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek69.jpg', 'highlights': ['The tutorial covers building a memory card game in pure JavaScript.', 'Basic knowledge of HTML, CSS, and JS is required to follow the tutorial.', 'Access to files for each video is available at github.com/slashcodesketch.', 'A written tutorial and game demo are available at marina/ferreira.github.io.', 'Creation of index.html, styles.css, and scripts.js files is part of the process.']}, {'end': 464.204, 'segs': [{'end': 156.306, 'src': 'embed', 'start': 109.836, 'weight': 0, 'content': [{'end': 120.44, 'text': "And inside the head tag, Let's set our character encoding to UTF-8, set the title to MemoryGame, and link the stylesheet.", 'start': 109.836, 'duration': 10.604}, {'end': 130.985, 'text': 'And inside our body tag, we are going to add the script.', 'start': 127.944, 'duration': 3.041}, {'end': 147.382, 'text': 'In styles.css, we are going to add a reset to all items by setting padding to zero, margin to zero, and box sizing to border box.', 'start': 136.798, 'duration': 10.584}, {'end': 156.306, 'text': 'The box sizing property handles how padding and border will be added to an element.', 'start': 151.584, 'duration': 4.722}], 'summary': 'Set utf-8 encoding, title to memorygame, and link stylesheet. add script and reset styling in styles.css.', 'duration': 46.47, 'max_score': 109.836, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek109836.jpg'}, {'end': 266.7, 'src': 'embed', 'start': 212.368, 'weight': 1, 'content': [{'end': 218.692, 'text': 'By setting it to 100, our body will take 100% of the available height space.', 'start': 212.368, 'duration': 6.324}, {'end': 224.095, 'text': "And finally, let's set the background color.", 'start': 221.774, 'duration': 2.321}, {'end': 244.486, 'text': 'Our board will be composed of a container div called MemoryGame and by 12 cards.', 'start': 239.463, 'duration': 5.023}, {'end': 257.733, 'text': "Each card consists of a memory card div that holds two images, one representing the card's back face and the other representing its front face.", 'start': 246.668, 'duration': 11.065}, {'end': 266.7, 'text': "So back in the editor, let's make that into HTML.", 'start': 263.578, 'duration': 3.122}], 'summary': 'Set body height to 100% and create memorygame container with 12 cards.', 'duration': 54.332, 'max_score': 212.368, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek212368.jpg'}, {'end': 395.945, 'src': 'embed', 'start': 346.457, 'weight': 2, 'content': [{'end': 350.619, 'text': "So let's add a border to each one of them so we can better visualize them.", 'start': 346.457, 'duration': 4.162}, {'end': 364.206, 'text': "Let's remove that temporary image width and let's add a 640 pixel width and height to our container.", 'start': 356.822, 'duration': 7.384}, {'end': 383.096, 'text': "Let's also set display to flex.", 'start': 380.754, 'duration': 2.342}, {'end': 395.945, 'text': "So what's going on here is that when we apply display flex to a container, we kind of get some other properties set for us by default.", 'start': 385.998, 'duration': 9.947}], 'summary': 'Adding 640px width and height to container, setting display to flex.', 'duration': 49.488, 'max_score': 346.457, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek346457.jpg'}], 'start': 109.836, 'title': 'Creating memory game with flexbox layout', 'summary': 'Explains setting up a memorygame web page, creating a memory game with html and css, and implementing a flexbox layout resulting in a 3x4 grid of memory cards.', 'chapters': [{'end': 210.787, 'start': 109.836, 'title': 'Setting up memorygame web page', 'summary': 'Explains how to set character encoding to utf-8, title to memorygame, link the stylesheet, and add a script in the body tag. it also covers setting a reset in styles.css and explains the box sizing property and its impact on element dimensions.', 'duration': 100.951, 'highlights': ['The chapter explains the process of setting character encoding to UTF-8, title to MemoryGame, linking the stylesheet, and adding a script in the body tag.', 'It discusses the box sizing property, highlighting its impact on element dimensions and the difference between content box and border box. It also mentions the application of the box sizing property to padding and border, affecting the total width and height of an element.', 'It also covers setting a reset in styles.css by setting padding to zero, margin to zero, and box sizing to border box, to ensure uniformity across items.']}, {'end': 345.496, 'start': 212.368, 'title': 'Creating memory game with html and css', 'summary': 'Discusses creating a memory game with html and css, including setting height space to 100%, adding a container div called memorygame, and styling memory game container and card elements.', 'duration': 133.128, 'highlights': ['Setting height space to 100% By setting the height space to 100, the body will take 100% of the available height space.', 'Adding a container div called MemoryGame The board will be composed of a container div called MemoryGame and by 12 cards, each consisting of a memory card div holding two images.', 'Styling memory game container and card elements In styles.css, the chapter discusses styling the memory game container and the memory card front face and back face elements.']}, {'end': 464.204, 'start': 346.457, 'title': 'Implementing flexbox layout', 'summary': 'Discusses applying flexbox layout properties to a container, setting specific dimensions for items, and addressing default properties to achieve the desired layout, resulting in a 3x4 grid of memory cards.', 'duration': 117.747, 'highlights': ['Applying flexbox layout to the container The chapter explains setting the display property to flex for the container to achieve default properties for item layout and equal distribution of space.', 'Setting specific dimensions for memory cards It discusses setting a 25% width and 33.33% height for the memory cards to achieve the desired layout.', 'Addressing default properties for flex container The chapter addresses the default flex-wrap property, setting it to wrap to allow items to be laid out across multiple rows.']}], 'duration': 354.368, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek109836.jpg', 'highlights': ['The chapter explains the process of setting character encoding to UTF-8, title to MemoryGame, linking the stylesheet, and adding a script in the body tag.', 'Adding a container div called MemoryGame The board will be composed of a container div called MemoryGame and by 12 cards, each consisting of a memory card div holding two images.', 'Applying flexbox layout to the container The chapter explains setting the display property to flex for the container to achieve default properties for item layout and equal distribution of space.']}, {'end': 588.093, 'segs': [{'end': 588.093, 'src': 'embed', 'start': 559.956, 'weight': 0, 'content': [{'end': 564.059, 'text': "The element says, cool, then I'm going to position myself relative to you.", 'start': 559.956, 'duration': 4.103}, {'end': 570.97, 'text': 'And the same goes if we apply position relative to box 2 and 3.', 'start': 564.879, 'duration': 6.091}, {'end': 579.331, 'text': 'which means that an element with position absolute positions itself relative to the nearest positioned ancestor.', 'start': 570.97, 'duration': 8.361}, {'end': 582.432, 'text': 'Back in our template.', 'start': 581.272, 'duration': 1.16}, {'end': 588.093, 'text': "what's going on here is that, since none of our elements are positioned to the screen,", 'start': 582.432, 'duration': 5.661}], 'summary': 'Positioning elements using relative and absolute positioning relative to nearest ancestor.', 'duration': 28.137, 'max_score': 559.956, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek559956.jpg'}], 'start': 466.666, 'title': 'Position absolute in css', 'summary': 'Explains the concept of position absolute in css, emphasizing its behavior relative to the nearest positioned ancestor and the impact of applying position relative to parent elements.', 'chapters': [{'end': 588.093, 'start': 466.666, 'title': 'Position absolute in css', 'summary': 'Explains the concept of position absolute in css, highlighting that an element with position absolute positions itself relative to the nearest positioned ancestor and the implications of applying position relative to the parent elements.', 'duration': 121.427, 'highlights': ['An element with position absolute positions itself relative to the nearest positioned ancestor, which determines its positioning in the layout.', 'The element queries its parent elements to find a positioned ancestor, and if none are found, it positions itself relative to the body, affecting its current layout.']}], 'duration': 121.427, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek466666.jpg', 'highlights': ['An element with position absolute positions itself relative to the nearest positioned ancestor, determining its layout.', 'The element queries parent elements to find a positioned ancestor; if none are found, it positions relative to the body, affecting the layout.']}, {'end': 862, 'segs': [{'end': 710.313, 'src': 'embed', 'start': 636.576, 'weight': 0, 'content': [{'end': 642.062, 'text': 'The layout has broken because the margin makes our cards overflow the available space.', 'start': 636.576, 'duration': 5.486}, {'end': 649.531, 'text': 'So on calculating our width and height, we have to take that margin under consideration.', 'start': 643.484, 'duration': 6.047}, {'end': 656.219, 'text': 'The CSS calc function allows us to subtract the margin value from the width and height.', 'start': 650.652, 'duration': 5.567}, {'end': 657.3, 'text': "So let's apply that.", 'start': 656.439, 'duration': 0.861}, {'end': 665.004, 'text': 'For centering the memory game container.', 'start': 662.901, 'duration': 2.103}, {'end': 675.4, 'text': "we're gonna apply a display flex to the body and margin auto to the memory game and that's gonna center it vertically and horizontally.", 'start': 665.004, 'duration': 10.396}, {'end': 696.317, 'text': "Let's add a click effect to the memory card.", 'start': 694.255, 'duration': 2.062}, {'end': 703.726, 'text': 'So the active pseudo class is going to be triggered whenever an element gets clicked.', 'start': 697.939, 'duration': 5.787}, {'end': 710.313, 'text': "So we're going to apply a transform scale of 97% of its original size.", 'start': 705.147, 'duration': 5.166}], 'summary': 'Using css calc to subtract margin for layout, applying flex for centering, and adding click effect to memory cards.', 'duration': 73.737, 'max_score': 636.576, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek636576.jpg'}, {'end': 813.466, 'src': 'embed', 'start': 778.956, 'weight': 2, 'content': [{'end': 784.997, 'text': 'To do that we are going to use document.carrySelectorAll passing the memory card class.', 'start': 778.956, 'duration': 6.041}, {'end': 796.499, 'text': 'So then we are going to loop through that list and to each one of the cards we are going to attach an event listener.', 'start': 788.358, 'duration': 8.141}, {'end': 807.041, 'text': 'We are going to listen for a click event and whenever that event is fired we are going to execute a function named flipCard.', 'start': 797.639, 'duration': 9.402}, {'end': 813.466, 'text': "Let's declare the Flipkart function.", 'start': 811.505, 'duration': 1.961}], 'summary': 'Using document.carryselectorall to attach event listeners to memory cards.', 'duration': 34.51, 'max_score': 778.956, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek778956.jpg'}], 'start': 588.093, 'title': 'Styling memory game layout and adding interactivity', 'summary': "Covers styling the memory game layout with width, height, padding, and border radius adjustments, applying centering techniques using display flex and margin auto, adding click effects with active pseudo class and transform scale, and making the cards flip with event listeners and the 'this' keyword.", 'chapters': [{'end': 862, 'start': 588.093, 'title': 'Styling memory game layout and adding interactivity', 'summary': "Covers styling the memory game layout with width, height, padding, and border radius adjustments, applying centering techniques using display flex and margin auto, adding click effects with active pseudo class and transform scale, and making the cards flip with event listeners and the 'this' keyword.", 'duration': 273.907, 'highlights': ['The CSS calc function is used to subtract the margin value from the width and height, fixing the layout overflow caused by the margin.', 'Applying display flex to the body and margin auto to the memory game centers it vertically and horizontally, providing a responsive layout.', 'Adding a click effect to the memory card by applying a transform scale of 97% of its original size and making it smoother with the transition property.', 'Making the cards flip when clicked by creating a list of all memory card elements and attaching an event listener to each one to execute the flipCard function.']}], 'duration': 273.907, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek588093.jpg', 'highlights': ['Applying display flex to the body and margin auto centers the memory game vertically and horizontally.', 'Adding a click effect to the memory card by applying a transform scale of 97% and using the transition property.', 'Making the cards flip when clicked by attaching an event listener to each one to execute the flipCard function.', 'Using the CSS calc function to fix layout overflow caused by margin when styling the memory game layout.']}, {'end': 1033.717, 'segs': [{'end': 1033.717, 'src': 'embed', 'start': 908.891, 'weight': 0, 'content': [{'end': 912.493, 'text': "So back in styles.css, let's set that flip class.", 'start': 908.891, 'duration': 3.602}, {'end': 919.877, 'text': 'So we want to select the memory card element that also has a flip class.', 'start': 914.034, 'duration': 5.843}, {'end': 925.639, 'text': "Remember that there's no space between the names because the two classes belong to the same element.", 'start': 919.977, 'duration': 5.662}, {'end': 933.523, 'text': 'So when the flip class is present, we are going to rotate the y-axis 180 degrees.', 'start': 927.981, 'duration': 5.542}, {'end': 961.225, 'text': "Let's add a 3D effect to the card flipping.", 'start': 958.707, 'duration': 2.518}, {'end': 966.901, 'text': "So the perspective property is what's going to give some depth to our elements, okay?", 'start': 962.239, 'duration': 4.662}, {'end': 979.246, 'text': "So we're going to add a 1000 pixel perspective to the memory game container and also a property that's called transform style preserve 3D to the memory card,", 'start': 967.521, 'duration': 11.725}, {'end': 987.65, 'text': "because that's what's going to insert our memory card element inside the 3D space we just created in the memory game container,", 'start': 979.246, 'duration': 8.404}, {'end': 993.673, 'text': 'because otherwise the memory card is going to keep being flat sitting on the 2D plane.', 'start': 987.65, 'duration': 6.023}, {'end': 1000.377, 'text': "So back in the editor let's add those properties.", 'start': 996.154, 'duration': 4.223}, {'end': 1007.622, 'text': '1000px perspective to memory game and transform style preserve 3D to the memory card.', 'start': 1000.417, 'duration': 7.205}, {'end': 1021.002, 'text': "We still don't see the 3D effect because we have to add a transition to the transform property.", 'start': 1015.936, 'duration': 5.066}, {'end': 1033.717, 'text': 'And there we have it, the 3D effect.', 'start': 1031.935, 'duration': 1.782}], 'summary': 'Adding 3d effect to memory card with 1000px perspective and transform style preserve 3d.', 'duration': 124.826, 'max_score': 908.891, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek908891.jpg'}], 'start': 862.8, 'title': 'Adding 3d effect', 'summary': 'Explains the process of adding a 3d effect to the memory card through toggling the flip class, setting the perspective property to 1000 pixels, and adding the transform style preserve 3d, achieving a visually immersive effect.', 'chapters': [{'end': 1033.717, 'start': 862.8, 'title': 'Adding 3d effect to memory card', 'summary': 'Explains adding a 3d effect to the memory card by toggling the flip class, setting the perspective property to 1000 pixels, and adding the transform style preserve 3d to the memory card, resulting in a 3d effect.', 'duration': 170.917, 'highlights': ['Toggling the flip class: Explains that toggling the flip class involves removing it if present and adding it if not, used to rotate the y-axis 180 degrees for the memory card.', 'Setting the perspective property: Describes adding a 1000 pixel perspective to the memory game container, providing depth to the elements.', 'Adding transform style preserve 3D: Explains the usage of this property to insert the memory card element inside the 3D space created in the memory game container, enabling the 3D effect.', 'Adding transition to the transform property: Mentions that adding a transition to the transform property results in the 3D effect for the memory card.']}], 'duration': 170.917, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek862800.jpg', 'highlights': ['Toggling the flip class: Rotate y-axis 180 degrees for memory card.', 'Adding transform style preserve 3D: Insert memory card inside 3D space.', 'Adding transition to the transform property: Results in 3D effect for memory card.', 'Setting the perspective property: Adding 1000 pixel perspective to memory game container.']}, {'end': 1630.648, 'segs': [{'end': 1059.352, 'src': 'embed', 'start': 1034.52, 'weight': 10, 'content': [{'end': 1043.023, 'text': 'Well, when we flip the card, we should be seeing the front face, right? And right now, what we are seeing is the inverted JS badge.', 'start': 1034.52, 'duration': 8.503}, {'end': 1051.148, 'text': 'That happens because every HTML element has a back face, which is a mirrored image of itself.', 'start': 1044.165, 'duration': 6.983}, {'end': 1059.352, 'text': "okay?. There's also a property called back face visibility that defaults to visible, and this is why we are seeing the inverted badge.", 'start': 1051.148, 'duration': 8.204}], 'summary': 'Html elements have a back face with a mirrored image, causing the badge to appear inverted.', 'duration': 24.832, 'max_score': 1034.52, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek1034520.jpg'}, {'end': 1154.572, 'src': 'embed', 'start': 1122.845, 'weight': 3, 'content': [{'end': 1133.469, 'text': "Okay? So let's declare a variable called hasFlippedCard and set it to false and also declare a first card and second card variables.", 'start': 1122.845, 'duration': 10.624}, {'end': 1141.057, 'text': "Let's update here, toggle to add and we are going to add a condition, okay?", 'start': 1136.011, 'duration': 5.046}, {'end': 1150.247, 'text': 'So if has flipped, card is false, this means this is the first time the player has clicked a card.', 'start': 1141.457, 'duration': 8.79}, {'end': 1154.572, 'text': 'So then we are going to set has flipped card to true.', 'start': 1151.388, 'duration': 3.184}], 'summary': 'Declare hasflippedcard as false, then set it to true on first click.', 'duration': 31.727, 'max_score': 1122.845, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek1122845.jpg'}, {'end': 1271.8, 'src': 'embed', 'start': 1203.551, 'weight': 4, 'content': [{'end': 1210.415, 'text': 'So if hasFlippedCard is set to false it means the player is clicking at the first card.', 'start': 1203.551, 'duration': 6.864}, {'end': 1219.773, 'text': "If it is set to true, it means the player is clicking in the second card and it's going to fall inside the else clause.", 'start': 1211.463, 'duration': 8.31}, {'end': 1228.563, 'text': 'So we are going to set has flipped card back to false and we are going to set the second card variable to this.', 'start': 1220.213, 'duration': 8.35}, {'end': 1230.505, 'text': "And let's console log those.", 'start': 1229.363, 'duration': 1.142}, {'end': 1247.622, 'text': 'Okay, so it fires only at the second click and we can see we have the both cards we just clicked.', 'start': 1239.611, 'duration': 8.011}, {'end': 1261.037, 'text': 'So now that we have both cards we just clicked, we have to check if those cards match.', 'start': 1255.256, 'duration': 5.781}, {'end': 1271.8, 'text': 'And how are we going to do that? So, we are going to make use of a very handy attribute in HTML, which is the data attribute.', 'start': 1261.797, 'duration': 10.003}], 'summary': 'Player clicks on first and second cards, using data attribute to check for match.', 'duration': 68.249, 'max_score': 1203.551, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek1203551.jpg'}, {'end': 1372.646, 'src': 'embed', 'start': 1322.97, 'weight': 6, 'content': [{'end': 1336.45, 'text': 'In order to access the data attribute that you defined in your HTML, we do this through the dataset object, okay? So it goes your element.dataset.', 'start': 1322.97, 'duration': 13.48}, {'end': 1337.792, 'text': 'the name you have chosen.', 'start': 1336.81, 'duration': 0.982}, {'end': 1372.646, 'text': 'Now that we can identify our cards, we have to check if the dataset.framework from the first card and the second card are the same.', 'start': 1362.719, 'duration': 9.927}], 'summary': 'Access data attribute using dataset object to identify cards and check for similarity.', 'duration': 49.676, 'max_score': 1322.97, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek1322970.jpg'}, {'end': 1560.082, 'src': 'embed', 'start': 1411.306, 'weight': 0, 'content': [{'end': 1416.649, 'text': "To make sure they have been removed, let's add a log message here.", 'start': 1411.306, 'duration': 5.343}, {'end': 1425.294, 'text': 'Alright, they were correctly executed.', 'start': 1421.593, 'duration': 3.701}, {'end': 1431.936, 'text': "And then when we click again, it won't fire because it's not going to the function anymore.", 'start': 1425.874, 'duration': 6.062}, {'end': 1443.619, 'text': "And then if it's not a match, we'll unflip the cards.", 'start': 1440.378, 'duration': 3.241}, {'end': 1450.161, 'text': "To do that, we're going to remove the flip class from the card.", 'start': 1447, 'duration': 3.161}, {'end': 1470.306, 'text': "Okay, so the second card hasn't turned.", 'start': 1467.685, 'duration': 2.621}, {'end': 1476.268, 'text': 'so when we clicked the card, it has immediately removed the flip glass.', 'start': 1470.306, 'duration': 5.962}, {'end': 1479.769, 'text': "so we don't even we cannot even see it being flipped.", 'start': 1476.268, 'duration': 3.501}, {'end': 1492.053, 'text': "What we have to do is to add a set timeout with a 1500 second delay, so there's enough time available for us to see the flipping.", 'start': 1480.869, 'duration': 11.184}, {'end': 1521.373, 'text': 'Right now, we have a bunch of nested conditions inside our code.', 'start': 1517.611, 'duration': 3.762}, {'end': 1524.435, 'text': 'And that makes our method very hard to read.', 'start': 1522.114, 'duration': 2.321}, {'end': 1528.478, 'text': "So let's make some refactoring here.", 'start': 1525.016, 'duration': 3.462}, {'end': 1534.281, 'text': 'And first of all, we are going to extract the matching logic to its own method.', 'start': 1529.298, 'duration': 4.983}, {'end': 1536.543, 'text': 'And we are going to call it CheckForMatch.', 'start': 1534.822, 'duration': 1.721}, {'end': 1553.096, 'text': 'The code inside the ifelse blocks are also going to be extracted to their own methods.', 'start': 1547.731, 'duration': 5.365}, {'end': 1560.082, 'text': "In case it is a match, we're going to call disable cards, and in case it's not, we're going to call unflipped cards.", 'start': 1553.836, 'duration': 6.246}], 'summary': 'Refactoring code to improve readability and organization, extracting matching logic and nested conditions into separate methods.', 'duration': 148.776, 'max_score': 1411.306, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek1411306.jpg'}, {'end': 1630.648, 'src': 'embed', 'start': 1596.54, 'weight': 1, 'content': [{'end': 1602.023, 'text': 'Alright? So a ternary operator allows you to write an if-else block in just one line.', 'start': 1596.54, 'duration': 5.483}, {'end': 1616.386, 'text': 'And up here, we can switch the else clause for a return statement in the end of our if.', 'start': 1609.444, 'duration': 6.942}, {'end': 1623.607, 'text': 'Because if the condition evaluates to true, the return statement is going to stop the function execution there.', 'start': 1617.306, 'duration': 6.301}, {'end': 1630.648, 'text': "And in case it's not true, the code executed, it's the one that would be inside the else clause.", 'start': 1625.006, 'duration': 5.642}], 'summary': 'Ternary operator condenses if-else block into one line, enabling efficient coding.', 'duration': 34.108, 'max_score': 1596.54, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek1596540.jpg'}], 'start': 1034.52, 'title': 'Implementing memory card matching game', 'summary': 'Explains how to handle the flipping and matching logic of memory cards, implementing a game using html data attributes and javascript, and refactoring the code to improve code readability and execution efficiency.', 'chapters': [{'end': 1230.505, 'start': 1034.52, 'title': 'Memory card matching logic', 'summary': 'Explains how to handle the flipping and matching logic of memory cards, including hiding the back face, setting variables for the first and second cards, and toggling the hasflippedcard variable based on user actions.', 'duration': 195.985, 'highlights': ['The back face visibility property defaults to visible, causing the inverted badge to appear.', 'The process involves declaring variables for hasFlippedCard, first card, and second card, and toggling the hasFlippedCard variable based on user actions.', 'The logic includes setting hasFlippedCard to true when the first card is clicked and setting it back to false when the second card is clicked.']}, {'end': 1372.646, 'start': 1239.611, 'title': 'Memory cards matching game', 'summary': 'Explains how to implement a memory cards matching game using html data attributes and javascript, emphasizing the use of dataset object for accessing the data attribute and checking if the dataset.framework from the first and second card are the same.', 'duration': 133.035, 'highlights': ['The chapter explains how to implement a memory cards matching game using HTML data attributes and JavaScript. Introduction to implementing a memory cards matching game using HTML data attributes and JavaScript.', 'Emphasizes the use of dataset object for accessing the data attribute. Importance of using dataset object for accessing the data attribute.', 'Stresses the process of checking if the dataset.framework from the first and second card are the same. Importance of checking if the dataset.framework from the first and second card are the same.']}, {'end': 1630.648, 'start': 1373.646, 'title': 'Refactoring matching logic and using ternary operator', 'summary': 'Focuses on refactoring the code to extract matching logic into its own method, calling separate methods for matching and non-matching cases, and utilizing a ternary operator for concise if-else blocks, aiming to improve code readability and execution efficiency.', 'duration': 257.002, 'highlights': ['The chapter emphasizes refactoring the code to extract matching logic into its own method and separate methods for matching and non-matching cases for improved code readability and maintenance.', 'Utilizing a ternary operator is introduced as a method to write concise if-else blocks, enhancing code efficiency and readability.', 'The addition of a log message is recommended to ensure that the event listener has been effectively removed, providing a means to verify the execution of the code.', 'The use of setTimeout with a 1500-second delay is suggested to allow sufficient time for card flipping to be visually perceivable, enhancing user experience and interaction.', "The adverse impact of nested conditions on code readability is acknowledged, prompting the need for refactoring to improve the method's clarity and maintainability."]}], 'duration': 596.128, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek1034520.jpg', 'highlights': ['The chapter emphasizes refactoring the code to extract matching logic into its own method and separate methods for matching and non-matching cases for improved code readability and maintenance.', 'Utilizing a ternary operator is introduced as a method to write concise if-else blocks, enhancing code efficiency and readability.', 'The use of setTimeout with a 1500-second delay is suggested to allow sufficient time for card flipping to be visually perceivable, enhancing user experience and interaction.', 'The process involves declaring variables for hasFlippedCard, first card, and second card, and toggling the hasFlippedCard variable based on user actions.', 'The logic includes setting hasFlippedCard to true when the first card is clicked and setting it back to false when the second card is clicked.', 'The chapter explains how to implement a memory cards matching game using HTML data attributes and JavaScript. Introduction to implementing a memory cards matching game using HTML data attributes and JavaScript.', 'Emphasizes the use of dataset object for accessing the data attribute. Importance of using dataset object for accessing the data attribute.', 'Stresses the process of checking if the dataset.framework from the first and second card are the same. Importance of checking if the dataset.framework from the first and second card are the same.', 'The addition of a log message is recommended to ensure that the event listener has been effectively removed, providing a means to verify the execution of the code.', "The adverse impact of nested conditions on code readability is acknowledged, prompting the need for refactoring to improve the method's clarity and maintainability.", 'The back face visibility property defaults to visible, causing the inverted badge to appear.']}, {'end': 2034.988, 'segs': [{'end': 1766.134, 'src': 'embed', 'start': 1738.561, 'weight': 4, 'content': [{'end': 1744.984, 'text': 'The second corner case we have to pay attention to is if we click twice over the same card,', 'start': 1738.561, 'duration': 6.423}, {'end': 1751.287, 'text': "because in that case isMatch is going to evaluate to true and it's going to disable the cards by removing its event listener.", 'start': 1744.984, 'duration': 6.303}, {'end': 1753.748, 'text': 'So the card is going to remain flipped.', 'start': 1751.967, 'duration': 1.781}, {'end': 1758.83, 'text': 'We have to add a condition to the beginning of our flipCard function to avoid that.', 'start': 1754.849, 'duration': 3.981}, {'end': 1766.134, 'text': 'So if it is the first card, click then that this variable holds the first card.', 'start': 1761.112, 'duration': 5.022}], 'summary': 'Prevent double-clicking on the same card to avoid disabling it and leaving it flipped.', 'duration': 27.573, 'max_score': 1738.561, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek1738561.jpg'}, {'end': 1895.065, 'src': 'heatmap', 'start': 1870.194, 'weight': 0, 'content': [{'end': 1874.076, 'text': 'The last thing left for us to do in our game is to shuffle our cards.', 'start': 1870.194, 'duration': 3.882}, {'end': 1879.179, 'text': 'We are going to do this with a flexbox property called order.', 'start': 1875.297, 'duration': 3.882}, {'end': 1884.062, 'text': "That's a flexitems property and it defaults to zero,", 'start': 1880.4, 'duration': 3.662}, {'end': 1891.186, 'text': 'which means that every flexitem belongs to the same group and then they will be grouped by source order.', 'start': 1884.062, 'duration': 7.124}, {'end': 1895.065, 'text': 'If you assign a different integer to the order,', 'start': 1892.142, 'duration': 2.923}], 'summary': "Using flexbox property 'order' to shuffle cards in a game.", 'duration': 104.448, 'max_score': 1870.194, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek1870194.jpg'}, {'end': 2009.507, 'src': 'embed', 'start': 1931.385, 'weight': 2, 'content': [{'end': 1944.972, 'text': 'And to generate our random number we are going to use the math.random function, which returns us a random number between 0 and 1 excluding 1.', 'start': 1931.385, 'duration': 13.587}, {'end': 1953.14, 'text': 'Since we want a number that goes from 0 to 11, we are going to multiply that number by 12.', 'start': 1944.972, 'duration': 8.168}, {'end': 1961.585, 'text': 'And since the order property needs an integer, we have to apply math.floor in order to get that.', 'start': 1953.14, 'duration': 8.445}, {'end': 1968.89, 'text': 'So now that we have our random number, we can apply it to the order property.', 'start': 1965.067, 'duration': 3.823}, {'end': 1992.657, 'text': 'We need our deck of cards to be shuffled before the player starts the game.', 'start': 1986.994, 'duration': 5.663}, {'end': 1997.64, 'text': 'So, instead of calling the shuffle function as we normally would,', 'start': 1993.418, 'duration': 4.222}, {'end': 2003.744, 'text': "let's wrap it inside a parentheses and add an extra pair of parentheses to the end of it.", 'start': 1997.64, 'duration': 6.104}, {'end': 2009.507, 'text': 'And that makes that function into an immediately invoked function,', 'start': 2004.584, 'duration': 4.923}], 'summary': 'Using math.random function to generate a random number for shuffling a deck of cards.', 'duration': 78.122, 'max_score': 1931.385, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek1931385.jpg'}], 'start': 1631.428, 'title': 'Memory game bug fixes and shuffling cards with flexbox', 'summary': 'Outlines bug fixes for a memory game, including handling corner cases to prevent crashes and double-clicking issues. it also details shuffling a deck of cards using flexbox, generating random numbers, and ensuring the deck is shuffled before the game begins.', 'chapters': [{'end': 1823.253, 'start': 1631.428, 'title': 'Memory game bug fixes', 'summary': 'Outlines the bug fixes required for a memory game, including the need to handle corner cases such as preventing crashes when flipping cards and avoiding issues with double-clicking the same card.', 'duration': 191.825, 'highlights': ['We need to handle corner cases such as preventing crashes when flipping cards and avoiding issues with double-clicking the same card.', 'The game is currently buggy due to corner cases that need to be addressed, such as crashing logic when flipping a second set of cards before the first set finishes unflipping.', "A 'lock board' variable is declared to prevent crashing logic when flipping a second set of cards before the first set finishes unflipping.", "The 'lock board' variable is set to false initially to prevent crashing logic when flipping a second set of cards before the first set finishes unflipping.", 'A method called resetBoard is introduced to set firstCard and secondCard to null after each round, using the ES6 destructuring assignment to keep the code short.']}, {'end': 2034.988, 'start': 1870.194, 'title': 'Shuffling cards with flexbox', 'summary': 'Details how to shuffle a deck of cards using the flexbox property order, generating and applying random numbers, and utilizing immediately invoked function expressions, to ensure the deck is shuffled before the game begins.', 'duration': 164.794, 'highlights': ["The flexbox property 'order' is used to shuffle the cards by assigning a different integer to the order property, ordering items first by ascending order according to the value in the order property and then by source order. Flexbox property 'order' used to shuffle cards by assigning different integers, ordering by ascending order and then by source order.", 'A random number between 0 and 11 is generated for each card using the math.random function multiplied by 12, and then applied to the order property to shuffle the deck of cards. Random numbers generated for each card between 0 and 11, applied to the order property to shuffle the deck of cards.', 'The shuffle function is wrapped inside immediately invoked function expressions to ensure the cards are shuffled before the game begins. Shuffle function wrapped inside immediately invoked function expressions to ensure shuffling before the game begins.']}], 'duration': 403.56, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/ZniVgo8U7ek/pics/ZniVgo8U7ek1631428.jpg', 'highlights': ['A method called resetBoard is introduced to set firstCard and secondCard to null after each round, using the ES6 destructuring assignment to keep the code short.', "The flexbox property 'order' is used to shuffle the cards by assigning a different integer to the order property, ordering items first by ascending order according to the value in the order property and then by source order.", 'A random number between 0 and 11 is generated for each card using the math.random function multiplied by 12, and then applied to the order property to shuffle the deck of cards.', 'The shuffle function is wrapped inside immediately invoked function expressions to ensure the cards are shuffled before the game begins.', 'We need to handle corner cases such as preventing crashes when flipping cards and avoiding issues with double-clicking the same card.']}], 'highlights': ['The tutorial covers building a memory card game in pure JavaScript.', 'Basic knowledge of HTML, CSS, and JS is required to follow the tutorial.', 'Access to files for each video is available at github.com/slashcodesketch.', 'A written tutorial and game demo are available at marina/ferreira.github.io.', 'Creation of index.html, styles.css, and scripts.js files is part of the process.', 'The chapter explains the process of setting character encoding to UTF-8, title to MemoryGame, linking the stylesheet, and adding a script in the body tag.', 'Adding a container div called MemoryGame The board will be composed of a container div called MemoryGame and by 12 cards, each consisting of a memory card div holding two images.', 'An element with position absolute positions itself relative to the nearest positioned ancestor, determining its layout.', 'The element queries parent elements to find a positioned ancestor; if none are found, it positions relative to the body, affecting the layout.', 'Applying display flex to the body and margin auto centers the memory game vertically and horizontally.', 'Adding a click effect to the memory card by applying a transform scale of 97% and using the transition property.', 'Making the cards flip when clicked by attaching an event listener to each one to execute the flipCard function.', 'Using the CSS calc function to fix layout overflow caused by margin when styling the memory game layout.', 'Toggling the flip class: Rotate y-axis 180 degrees for memory card.', 'Adding transform style preserve 3D: Insert memory card inside 3D space.', 'Adding transition to the transform property: Results in 3D effect for memory card.', 'Setting the perspective property: Adding 1000 pixel perspective to memory game container.', 'The chapter emphasizes refactoring the code to extract matching logic into its own method and separate methods for matching and non-matching cases for improved code readability and maintenance.', 'Utilizing a ternary operator is introduced as a method to write concise if-else blocks, enhancing code efficiency and readability.', 'The use of setTimeout with a 1500-second delay is suggested to allow sufficient time for card flipping to be visually perceivable, enhancing user experience and interaction.', 'The process involves declaring variables for hasFlippedCard, first card, and second card, and toggling the hasFlippedCard variable based on user actions.', 'The logic includes setting hasFlippedCard to true when the first card is clicked and setting it back to false when the second card is clicked.', 'The chapter explains how to implement a memory cards matching game using HTML data attributes and JavaScript. Introduction to implementing a memory cards matching game using HTML data attributes and JavaScript.', 'Emphasizes the use of dataset object for accessing the data attribute. Importance of using dataset object for accessing the data attribute.', 'Stresses the process of checking if the dataset.framework from the first and second card are the same. Importance of checking if the dataset.framework from the first and second card are the same.', 'The addition of a log message is recommended to ensure that the event listener has been effectively removed, providing a means to verify the execution of the code.', "The adverse impact of nested conditions on code readability is acknowledged, prompting the need for refactoring to improve the method's clarity and maintainability.", 'The back face visibility property defaults to visible, causing the inverted badge to appear.', 'A method called resetBoard is introduced to set firstCard and secondCard to null after each round, using the ES6 destructuring assignment to keep the code short.', "The flexbox property 'order' is used to shuffle the cards by assigning a different integer to the order property, ordering items first by ascending order according to the value in the order property and then by source order.", 'A random number between 0 and 11 is generated for each card using the math.random function multiplied by 12, and then applied to the order property to shuffle the deck of cards.', 'The shuffle function is wrapped inside immediately invoked function expressions to ensure the cards are shuffled before the game begins.', 'We need to handle corner cases such as preventing crashes when flipping cards and avoiding issues with double-clicking the same card.']}