<html lang="en">
<head>
<meta charset="UTF-8">
<title>Yoga Pose Game</title>
<link rel="stylesheet" href="styles.css">
<!-- Include jsPDF Library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
</head>
<body>
<!-- Settings Screen -->
<div id="settings-screen" class="screen-container">
<!-- Title -->
<h1>Yoga Pose Game</h1>
<!-- Settings Content -->
<div class="main-sections">
<!-- Sequence Type -->
<div class="settings center-align">
<label class="setting-header">Sequence Type</label><br>
<select id="sequence-type">
<option value="Hatha Yoga">Hatha Yoga</option>
<option value="Deep Stretch Yoga">Deep Stretch Yoga</option>
<option value="Random Poses">Random Poses</option>
</select>
</div>
<!-- Difficulty -->
<div class="settings center-align">
<label class="setting-header">Difficulty</label><br>
<select id="difficulty">
<option value="Beginner">Beginner</option>
<option value="Normal" selected>Normal</option>
</select>
</div>
<!-- Spacer -->
<p></p>
<!-- Divider Line -->
<hr>
<!-- Settings Grid -->
<div class="settings-grid">
<!-- Column 1 Row 1 - Game Duration -->
<div class="settings">
<label class="setting-header">Game Duration</label>
<div class="radio-group vertical center-align">
<label><input type="radio" name="duration" value="15" checked> 15 Minutes</label>
<label><input type="radio" name="duration" value="30"> 30 Minutes</label>
<label><input type="radio" name="duration" value="60"> 60 Minutes</label>
</div>
</div>
<!-- Column 2 Row 1 - Time to Transition -->
<div class="settings">
<label class="setting-header">Time to Transition</label>
<div class="radio-group vertical center-align">
<label><input type="radio" name="transition-time" value="5"> 5 Seconds</label>
<label><input type="radio" name="transition-time" value="10" checked> 10 Seconds</label>
<label><input type="radio" name="transition-time" value="15"> 15 Seconds</label>
</div>
</div>
<!-- Column 1 Row 2 - Start Poses On -->
<div class="settings">
<label class="setting-header">Start Poses On</label>
<div class="radio-group center-align">
<label><input type="radio" name="starting-side" value="Right Side" checked> Right Side</label>
<label><input type="radio" name="starting-side" value="Left Side"> Left Side</label>
</div>
</div>
<!-- Column 2 Row 2 - Sound -->
<div class="settings">
<label class="setting-header">Sound</label>
<div class="radio-group center-align">
<label><input type="radio" name="sound-setting" value="On" checked> On</label>
<label><input type="radio" name="sound-setting" value="Off"> Off</label>
</div>
</div>
</div>
<button id="start-button">Start Game</button>
</div>
</div>
<!-- Game Container -->
<div id="game-container" class="screen-container" style="display: none;">
<!-- Title -->
<h1>Yoga Pose Game</h1>
<!-- Controls -->
<div class="controls">
<button id="pause-button">Pause</button>
<button id="skip-button">Skip Pose</button>
<button id="sound-button">Sound On</button>
</div>
<!-- Main Sections -->
<div class="main-sections">
<!-- Pose Section -->
<div id="pose-section">
<!-- Timer Above Current Pose -->
<div id="current-timer">
<div id="timer-text">0:00</div>
</div>
<!-- Current Pose Header -->
<h2 id="current-pose-header">Current Pose</h2>
<!-- Current Pose -->
<div id="current-pose">
<p id="current-pose-name"></p>
<img id="current-pose-image" src="https://cdn.shopify.com/s/files/1/0566/4800/7733/files/Image_Coming_Soon.jpg?v=1730325411" alt="Current Pose">
<p id="current-pose-category"></p>
</div>
</div>
<!-- Info Section -->
<div id="info-section">
<div id="time-details">
<!-- Time Remaining -->
<div id="time-remaining-container">
<p id="time-remaining">0:00</p>
<p>Time Remaining</p>
</div>
<!-- Settings Info -->
<div id="settings-info">
<p id="display-sequence-type"></p>
<p id="display-difficulty"></p>
<p id="display-duration"></p>
</div>
</div>
</div>
</div>
<!-- End Game Button at the Bottom -->
<div class="end-game-container">
<button id="end-game-button">End Game</button>
</div>
</div>
<!-- End Game Screen -->
<div id="end-screen" class="screen-container" style="display: none;">
<!-- Title -->
<h1>Yoga Pose Game</h1>
<!-- Thanks For Playing Heading -->
<h2>Thanks For Playing!</h2>
<!-- End Screen Content -->
<div class="main-sections">
<!-- Sequence Section with Border -->
<div id="sequence-container">
<h2 class="center-align">Sequence</h2>
<ul id="pose-sequence">
<!-- List of poses with durations will be displayed here -->
</ul>
<!-- Buttons for Download and Share -->
<div class="sequence-buttons">
<button id="print-button">Download Sequence</button>
<button id="share-button">Share</button>
</div>
</div>
<!-- Buttons Row -->
<div class="buttons-row">
<button id="play-again-button">Play Again</button>
<button id="new-game-button">New Game</button>
</div>
<!-- Feedback -->
<p class="feedback-text">
Brought to You By Asivana Yoga Company<br>
<i><a href="mailto:Feedback@Asivana.com">Feedback</a></i>
</p>
</div>
</div>
<!-- Modal for Skip Confirmation -->
<div id="skip-modal" class="modal" style="display: none;">
<div class="modal-content">
<p>Would you like to end the game early?</p>
<button id="confirm-end-button">End Game</button>
<button id="resume-button">Resume</button>
</div>
</div>
<!-- Modal for Share Content -->
<div id="share-modal" class="modal" style="display: none;">
<div class="modal-content">
<h2>Share Your Sequence</h2>
<textarea id="share-textarea" readonly></textarea>
<!-- Share Buttons -->
<div class="share-buttons">
<button id="share-facebook-button">Share on Facebook</button>
<button id="share-twitter-button">Share on X</button>
<button id="copy-share-button">Copy to Clipboard</button>
</div>
<button id="close-share-modal">Close</button>
</div>
</div>
<!-- Include your JavaScript file -->
<script src="script.js"></script>
</body>
</html>
/* General Styles */
body {
background-color: #ffffff;
color: #333f48;
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
h1 {
color: #333f48;
text-align: center;
}
h2 {
color: #333f48;
margin: 10px 0;
text-align: center;
}
p {
margin: 5px 0;
text-align: center;
color: #7b5a6d; /* Secondary color for body text */
}
button {
background-color: #333f48;
color: #ffffff;
border: none;
padding: 10px 20px;
margin: 5px;
cursor: pointer;
font-size: 16px;
border-radius: 8px;
}
button:hover {
background-color: #7b5a6d;
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
select {
padding: 5px;
font-size: 16px;
}
input[type="radio"] {
margin-right: 5px;
}
label {
color: #333f48;
}
hr {
border: none;
border-top: 1px solid #333f48;
margin: 15px 0;
}
textarea {
width: 100%;
height: 150px;
padding: 10px;
font-size: 14px;
margin-bottom: 10px;
box-sizing: border-box;
resize: none;
}
.spacer {
height: 10px; /* Adjust the height as needed */
}
/* Center Alignment Class */
.center-align {
text-align: center;
}
/* Screen Container */
.screen-container {
max-width: 420px;
margin: 0 auto;
border: 2px solid #333f48;
border-radius: 10px;
padding: 10px;
box-sizing: border-box;
}
/* Settings Screen Styles */
#settings-screen .main-sections {
display: flex;
flex-direction: column;
align-items: center;
}
.settings {
margin: 15px 0;
width: 100%;
text-align: center;
}
.setting-header {
font-size: 18px;
font-weight: bold;
}
.settings select {
width: 60%;
margin-top: 5px;
font-size: 16px;
}
/* Settings Grid */
.settings-grid {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 100%;
}
.settings-grid .settings {
width: 48%;
margin-bottom: 15px;
}
.radio-group {
display: flex;
flex-direction: column;
align-items: center;
}
.radio-group label {
margin: 5px 0;
font-size: 14px;
font-weight: normal;
}
.radio-group.center-align {
align-items: center;
}
.radio-group.vertical label {
text-align: center;
}
/* Controls */
.controls {
display: flex;
justify-content: center;
flex-wrap: wrap;
margin-bottom: 10px;
}
/* Pose Section */
#pose-section {
width: 100%;
border: 2px solid #333f48;
border-radius: 10px;
padding: 10px;
margin-bottom: 10px;
box-sizing: border-box;
}
#current-timer {
display: flex;
justify-content: center;
margin-bottom: 5px;
}
#timer-text {
font-size: 48px;
color: #333f48;
}
#current-pose-header {
margin-bottom: 5px;
}
#current-pose {
text-align: center;
margin-bottom: 10px;
}
#current-pose-name {
font-size: 24px;
margin-bottom: 5px;
color: #333f48;
}
#current-pose-category {
font-size: 18px;
color: #7b5a6d; /* Secondary color for category */
}
#current-pose img {
width: 300px;
height: 300px;
max-width: 100%;
background-color: #e0e0e0;
border-radius: 8px;
}
/* Info Section */
#info-section {
width: 100%;
}
#time-details {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
margin-bottom: 10px;
}
#time-remaining-container, #settings-info {
width: 48%;
text-align: center;
}
#settings-info p {
margin: 2px 0;
}
#time-remaining {
font-size: 36px;
color: #333f48;
}
.end-game-container {
text-align: center;
margin-top: 10px;
}
/* End Screen Styles */
#end-screen .main-sections {
display: flex;
flex-direction: column;
align-items: center;
}
#sequence-container {
width: 100%;
border: 2px solid #333f48;
border-radius: 10px;
padding: 10px;
margin-bottom: 10px;
box-sizing: border-box;
}
#sequence-container h2 {
text-align: center; /* Center the "Sequence" header */
}
#pose-sequence {
list-style-type: none;
padding: 0;
margin: 10px 0;
}
#pose-sequence li {
margin: 5px 0;
font-size: 18px;
display: flex;
align-items: center;
}
#pose-sequence .time-display {
color: #333f48;
font-weight: bold;
width: 60px;
text-align: right;
margin-right: 10px;
}
#pose-sequence .pose-name {
color: #7b5a6d;
}
/* Sequence Buttons */
.sequence-buttons {
display: flex;
justify-content: center;
margin-top: 10px;
}
.sequence-buttons button {
margin: 5px 10px;
}
/* Share Buttons */
.share-buttons {
display: flex;
flex-direction: column;
align-items: center;
}
.share-buttons button {
margin: 5px 0;
width: 80%;
}
.buttons-row {
display: flex;
justify-content: center;
width: 100%;
}
.buttons-row button {
margin: 5px 10px;
}
.feedback-text {
font-size: 12px;
margin-top: 10px;
text-align: center;
}
.feedback-text a {
color: #7b5a6d;
text-decoration: none;
}
.feedback-text a:hover {
text-decoration: underline;
}
/* Modal Styles */
.modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(51, 63, 72, 0.8);
}
.modal-content {
background-color: #ffffff;
margin: 15% auto;
padding: 20px;
border: 2px solid #333f48;
width: 80%;
max-width: 400px;
text-align: center;
border-radius: 10px;
}
.modal-content p {
color: #333f48;
font-size: 18px;
}
.modal-content h2 {
color: #333f48;
font-size: 24px;
margin-bottom: 10px;
}
.modal-content input[type="email"] {
width: 80%;
padding: 10px;
margin: 10px 0;
font-size: 16px;
}
.modal-content button {
margin: 10px;
}
@media (max-width: 420px) {
#current-pose img {
width: 100%;
height: auto;
}
.settings select {
width: 80%;
}
#time-details {
flex-direction: column; /* Stack elements on smaller screens */
}
#time-remaining-container, #settings-info {
width: 100%;
}
.buttons-row {
flex-direction: column;
align-items: center;
}
.buttons-row button {
width: 100%;
margin-bottom: 10px;
}
.settings .radio-group {
flex-direction: column;
align-items: center;
}
.settings .radio-group label {
margin: 5px 0;
}
}
// script.js
// JSON data (insert your JSON data here)
const poses = [
{
"Pose Name": "Tabletop Pose",
"Sanskrit": "Bharmāṇāsana",
"Difficulty": "Beginner",
"Categories": ["Start"],
"Hold Times": 0,
"Image URL": ""
},
{
"Pose Name": "Crow Pose",
"Sanskrit": "Kakasana",
"Difficulty": "Normal",
"Categories": ["Peak", "Floor"],
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "Tree Pose",
"Sanskrit": "Vṛkṣāsana",
"Difficulty": "Normal",
"Categories": ["Standing"],
"Both Sides": true,
"Hold Times": 120,
"Image URL": ""
},
{
"Pose Name": "Cat Pose",
"Sanskrit": "Mārjāriāsana",
"Difficulty": "Beginner",
"Categories": ["Warm Up"],
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Child's Pose",
"Sanskrit": "Bālāsana",
"Difficulty": "Beginner",
"Categories": ["Warm Up", "Floor", "Cooldown"],
"Hold Times": 120,
"Image URL": ""
},
{
"Pose Name": "Cobra Pose",
"Sanskrit": "Bhujaṅgāsana",
"Difficulty": "Beginner",
"Categories": ["Warm Up", "Floor"],
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "Cow Pose",
"Sanskrit": "Bitilāsana",
"Difficulty": "Beginner",
"Categories": ["Warm Up"],
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Downward Facing Dog",
"Sanskrit": "Adho Mukha Śvānāsana",
"Difficulty": "Beginner",
"Categories": ["Warm Up", "Floor"],
"Hold Times": 120,
"Image URL": ""
},
{
"Pose Name": "Eight-Point Pose",
"Sanskrit": "Aṣṭāṅgāsana",
"Difficulty": "Normal",
"Categories": ["Warm Up", "Floor"],
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "Forearm Plank",
"Sanskrit": "Mākāra Adho Mukha Svānāsana",
"Difficulty": "Normal",
"Categories": ["Warm Up", "Floor"],
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "Four-Limbed Staff Pose",
"Sanskrit": "Caturaṅga Daṇḍāsana",
"Difficulty": "Normal",
"Categories": ["Warm Up", "Floor"],
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "Lizard Pose",
"Sanskrit": "Utthāna Pristhāsana",
"Difficulty": "Normal",
"Categories": ["Warm Up", "Floor"],
"Both Sides": true,
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Locust Pose",
"Sanskrit": "Śalabhāsana",
"Difficulty": "Beginner",
"Categories": ["Floor"],
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Plank Pose",
"Sanskrit": "Kumbhakāsana",
"Difficulty": "Beginner",
"Categories": ["Warm Up", "Floor"],
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Side Plank Pose",
"Sanskrit": "Vaśiṣṭhāsana",
"Difficulty": "Normal",
"Categories": ["Floor"],
"Both Sides": true,
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "Sphinx Pose",
"Sanskrit": "Śalamba Bhujaṅgāsana",
"Difficulty": "Beginner",
"Categories": ["Warm Up", "Floor"],
"Hold Times": 120,
"Image URL": ""
},
{
"Pose Name": "Thread the Needle",
"Sanskrit": "Sucīrandhrāsana",
"Difficulty": "Beginner",
"Categories": ["Warm Up", "Floor"],
"Both Sides": true,
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Upward Facing Dog",
"Sanskrit": "Ūrdhva Mukha Śvānāsana",
"Difficulty": "Normal",
"Categories": ["Warm Up", "Floor"],
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "Bound Angle Pose",
"Sanskrit": "Baddha Koṇāsana",
"Difficulty": "Normal",
"Categories": ["Floor"],
"Hold Times": 120,
"Image URL": ""
},
{
"Pose Name": "Head to Knee Forward Fold",
"Sanskrit": "Jānu Śirṣāsana",
"Difficulty": "Beginner",
"Categories": ["Floor"],
"Both Sides": true,
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Hero Pose",
"Sanskrit": "Vīrāsana",
"Difficulty": "Beginner",
"Categories": ["Warm Up"],
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Marichi's Pose",
"Sanskrit": "Marīchyāsana",
"Difficulty": "Beginner",
"Categories": ["Floor"],
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Seated Forward Fold",
"Sanskrit": "Paśchimottānāsana",
"Difficulty": "Beginner",
"Categories": ["Warm Up"],
"Hold Times": 120,
"Image URL": ""
},
{
"Pose Name": "Staff Pose",
"Sanskrit": "Daṇḍāsana",
"Difficulty": "Beginner",
"Categories": ["Floor"],
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Thunderbolt Pose",
"Sanskrit": "Vajrasana",
"Difficulty": "Normal",
"Categories": ["Warm Up", "Floor"],
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Crescent Lunge",
"Sanskrit": "Añjaneyāsana",
"Difficulty": "Beginner",
"Categories": ["Standing"],
"Both Sides": true,
"Hold Times": 90,
"Image URL": ""
},
{
"Pose Name": "Downward Dog Split",
"Sanskrit": "Eka Pāda Adho Mukha Śvānāsana",
"Difficulty": "Normal",
"Categories": ["Standing"],
"Both Sides": true,
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "Extended Side Angle Pose",
"Sanskrit": "Utthita Pārśvakoṇāsana",
"Difficulty": "Beginner",
"Categories": ["Standing", "Peak"],
"Both Sides": true,
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Fierce Pose",
"Sanskrit": "Utkaṭāsana",
"Difficulty": "Normal",
"Categories": ["Standing", "Peak"],
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Forward Fold",
"Sanskrit": "Uttānāsana",
"Difficulty": "Beginner",
"Categories": ["Standing"],
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "Garland Pose",
"Sanskrit": "Mālāsana",
"Difficulty": "Normal",
"Categories": ["Standing"],
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Gorilla Pose",
"Sanskrit": "Pādahastāsana",
"Difficulty": "Normal",
"Categories": ["Standing"],
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Half Forward Fold/Half Lift",
"Sanskrit": "Ardha Uttānāsana",
"Difficulty": "Beginner",
"Categories": ["Standing"],
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "Intense West Side Stretch Pose",
"Sanskrit": "Pārśvottānāsana",
"Difficulty": "Beginner",
"Categories": ["Standing"],
"Both Sides": true,
"Hold Times": 120,
"Image URL": ""
},
{
"Pose Name": "Reverse Warrior",
"Sanskrit": "Viparīta Vīrabhadrāsana",
"Difficulty": "Normal",
"Categories": ["Standing"],
"Both Sides": true,
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Standing Backbend",
"Sanskrit": "Anuvṛttāsana",
"Difficulty": "Beginner",
"Categories": ["Standing"],
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "Triangle Pose",
"Sanskrit": "Utthita Trikoṇāsana",
"Difficulty": "Normal",
"Categories": ["Standing"],
"Both Sides": true,
"Hold Times": 120,
"Image URL": ""
},
{
"Pose Name": "Upward Salute",
"Sanskrit": "Ūrdhva Hastāsana",
"Difficulty": "Beginner",
"Categories": ["Standing"],
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "Warrior 1",
"Sanskrit": "Vīrabhadrāsana I",
"Difficulty": "Beginner",
"Categories": ["Standing"],
"Both Sides": true,
"Hold Times": 120,
"Image URL": ""
},
{
"Pose Name": "Warrior 2",
"Sanskrit": "Vīrabhadrāsana II",
"Difficulty": "Normal",
"Categories": ["Standing"],
"Both Sides": true,
"Hold Times": 120,
"Image URL": ""
},
{
"Pose Name": "Wide Legged Forward Fold",
"Sanskrit": "Prasārita Pādottānāsana A",
"Difficulty": "Beginner",
"Categories": ["Standing"],
"Hold Times": 120,
"Image URL": ""
},
{
"Pose Name": "Bridge Pose",
"Sanskrit": "Setu Bandha Sarvāṅgāsana",
"Difficulty": "Beginner",
"Categories": ["Cooldown"],
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Final Relaxation",
"Sanskrit": "Śavāsana",
"Difficulty": "Beginner",
"Categories": ["End"],
"Hold Times": 600,
"Image URL": ""
},
{
"Pose Name": "Happy Baby Pose",
"Sanskrit": "Ānanda Bālāsana",
"Difficulty": "Beginner",
"Categories": ["Cooldown"],
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Knees to Chest",
"Sanskrit": "Āpanāsana",
"Difficulty": "Beginner",
"Categories": ["Cooldown"],
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Legs-Up-the-Wall Pose",
"Sanskrit": "Viparīta Karanī",
"Difficulty": "Normal",
"Categories": ["Cooldown"],
"Hold Times": 120,
"Image URL": ""
},
{
"Pose Name": "Reclining Hand-To-Big-Toe Pose",
"Sanskrit": "Supta Pādāṅguṣṭhāsana",
"Difficulty": "Normal",
"Categories": ["Cooldown"],
"Both Sides": true,
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Supine Spinal Twist",
"Sanskrit": "Supta Matsyendrāsana",
"Difficulty": "Beginner",
"Categories": ["Cooldown"],
"Both Sides": true,
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Warrior 3",
"Sanskrit": "Vīrabhadrāsana III",
"Difficulty": "Normal",
"Categories": ["Standing", "Peak"],
"Both Sides": true,
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Bow Pose",
"Sanskrit": "Dhanurāsana",
"Difficulty": "Normal",
"Categories": ["Floor"],
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "Dolphin Pose",
"Sanskrit": "Ārdha Adho Mukha Śvānāsana",
"Difficulty": "Normal",
"Categories": ["Floor"],
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "One Leg King Pigeon Pose",
"Sanskrit": "Eka Pāda Rājakapotāsana",
"Difficulty": "Normal",
"Categories": ["Floor"],
"Both Sides": true,
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Melting Heart Pose",
"Sanskrit": "Ānāhatāsana",
"Difficulty": "Normal",
"Categories": ["Warm Up"],
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "Camel Pose",
"Sanskrit": "Uṣṭrāsana",
"Difficulty": "Normal",
"Categories": ["Floor"],
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "Half Lord of the Fishes Pose",
"Sanskrit": "Ardha Matsyeṅdrāsana",
"Difficulty": "Normal",
"Categories": ["Floor"],
"Both Sides": true,
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Wide Angle Seated Forward Fold",
"Sanskrit": "Upaviṣṭha Koṇāsana",
"Difficulty": "Normal",
"Categories": ["Floor"],
"Hold Times": 120,
"Image URL": ""
},
{
"Pose Name": "Gate Pose",
"Sanskrit": "Parighasana",
"Difficulty": "Normal",
"Categories": ["Warm Up", "Floor"],
"Both Sides": true,
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "Half Splits",
"Sanskrit": "Ardha Hanumanasana",
"Difficulty": "Normal",
"Categories": ["Warm Up", "Floor"],
"Both Sides": true,
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Side Lunge",
"Sanskrit": "Skandāsana",
"Difficulty": "Normal",
"Categories": ["Standing"],
"Both Sides": true,
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Standing Splits",
"Sanskrit": "Ūrdhva Prasārita Eka Pādāsana",
"Difficulty": "Normal",
"Categories": ["Standing", "Peak"],
"Both Sides": true,
"Hold Times": 30,
"Image URL": ""
},
{
"Pose Name": "Boat Pose",
"Sanskrit": "Nāvāsana",
"Difficulty": "Normal",
"Categories": ["Floor"],
"Hold Times": 60,
"Image URL": ""
},
{
"Pose Name": "Reclining Bound Angle",
"Sanskrit": "Supta Baddhakoṇāsana",
"Difficulty": "Normal",
"Categories": ["Cooldown"],
"Hold Times": 120,
"Image URL": ""
},
{
"Pose Name": "Upward Facing Bow",
"Sanskrit": "Ūrdhva Dhanurāsana",
"Difficulty": "Normal",
"Categories": ["Cooldown"],
"Hold Times": 30,
"Image URL": ""
}
];
// Game variables
let difficulty = 'Normal'; // Default to Normal
let duration = 15; // in minutes
let totalTimeRemaining = 0;
let poseTimeRemaining = 0;
let transitionTimeRemaining = 10; // Default to 10 seconds
let transitionTimeSetting = 10;
let gameInterval;
let currentPoseIndex = -1;
let poseSequence = [];
let isPaused = false;
let soundOn = true;
let sequenceType = 'Hatha Yoga';
let categoryTimings = [];
let currentCategoryIndex = 0;
let elapsedTime = 0;
let poseSkipped = false;
let nextPoseData = null;
let repeatSide = false;
let currentSide = 'Right Side';
let startingSide = 'Right Side';
const placeholderImageUrl = 'https://cdn.shopify.com/s/files/1/0566/4800/7733/files/Yoga_Poses_Games_Image_Coming_Soon.jpg?v=1730403825';
// Sound files
const transitionSoundUrl = 'https://cdn.shopify.com/s/files/1/0566/4800/7733/files/683671__cogfirestudios__yoga-meditation-bells.wav?v=1730309404';
const currentPoseSoundUrl = 'https://cdn.shopify.com/s/files/1/0566/4800/7733/files/337048__shinephoenixstormcrow__131348__kaonaya__bell-at-daitokuji-temple-kyoto_modified.mp3?v=1730309380';
const timeRemainingSoundUrl = 'https://cdn.shopify.com/s/files/1/0566/4800/7733/files/50405__daddoit__chimes_part_6.wav?v=1730309780';
// DOM Elements
const settingsScreen = document.getElementById('settings-screen');
const gameContainer = document.getElementById('game-container');
const endScreen = document.getElementById('end-screen');
const startButton = document.getElementById('start-button');
const pauseButton = document.getElementById('pause-button');
const skipButton = document.getElementById('skip-button');
const soundButton = document.getElementById('sound-button');
const endGameButton = document.getElementById('end-game-button');
const difficultySelect = document.getElementById('difficulty');
const sequenceTypeSelect = document.getElementById('sequence-type');
// Radio button selections
const durationRadios = document.getElementsByName('duration');
const startingSideRadios = document.getElementsByName('starting-side');
const transitionTimeRadios = document.getElementsByName('transition-time');
const soundSettingRadios = document.getElementsByName('sound-setting');
const currentPoseHeader = document.getElementById('current-pose-header');
const currentPoseName = document.getElementById('current-pose-name');
const currentPoseImage = document.getElementById('current-pose-image');
const currentPoseCategory = document.getElementById('current-pose-category');
const timerText = document.getElementById('timer-text');
const timeRemainingText = document.getElementById('time-remaining');
const displaySequenceType = document.getElementById('display-sequence-type');
const displayDifficulty = document.getElementById('display-difficulty');
const displayDuration = document.getElementById('display-duration');
const poseSequenceList = document.getElementById('pose-sequence');
const playAgainButton = document.getElementById('play-again-button');
const newGameButton = document.getElementById('new-game-button');
const printButton = document.getElementById('print-button');
const shareButton = document.getElementById('share-button');
// Skip Modal Elements
const skipModal = document.getElementById('skip-modal');
const confirmEndButton = document.getElementById('confirm-end-button');
const resumeButton = document.getElementById('resume-button');
// Share Modal Elements
const shareModal = document.getElementById('share-modal');
const shareTextarea = document.getElementById('share-textarea');
const copyShareButton = document.getElementById('copy-share-button');
const closeShareModal = document.getElementById('close-share-modal');
const shareFacebookButton = document.getElementById('share-facebook-button');
const shareTwitterButton = document.getElementById('share-twitter-button');
// Event Listeners
startButton.addEventListener('click', startGame);
pauseButton.addEventListener('click', togglePause);
skipButton.addEventListener('click', skipPose);
soundButton.addEventListener('click', toggleSound);
endGameButton.addEventListener('click', endGame);
playAgainButton.addEventListener('click', playAgain);
newGameButton.addEventListener('click', newGame);
confirmEndButton.addEventListener('click', confirmEndGame);
resumeButton.addEventListener('click', resumeGame);
// Print and Share Button Event Listeners
printButton.addEventListener('click', printSequence);
shareButton.addEventListener('click', shareSequence);
// Share Modal Event Listeners
copyShareButton.addEventListener('click', copyShareText);
closeShareModal.addEventListener('click', () => {
shareModal.style.display = 'none';
});
shareFacebookButton.addEventListener('click', shareOnFacebook);
shareTwitterButton.addEventListener('click', shareOnTwitter);
function startGame() {
// Get settings
difficulty = difficultySelect.value;
sequenceType = sequenceTypeSelect.value;
// Get duration from radio buttons
for (const radio of durationRadios) {
if (radio.checked) {
duration = parseInt(radio.value);
break;
}
}
// Get starting side from radio buttons
for (const radio of startingSideRadios) {
if (radio.checked) {
startingSide = radio.value;
currentSide = startingSide;
break;
}
}
// Get transition time from radio buttons
for (const radio of transitionTimeRadios) {
if (radio.checked) {
transitionTimeSetting = parseInt(radio.value);
break;
}
}
// Get sound setting from radio buttons
for (const radio of soundSettingRadios) {
if (radio.checked) {
soundOn = radio.value === 'On';
break;
}
}
// Update sound button text
soundButton.textContent = soundOn ? 'Sound Off' : 'Sound On';
transitionTimeRemaining = transitionTimeSetting;
totalTimeRemaining = duration * 60; // Convert to seconds
// Update settings display
displaySequenceType.textContent = sequenceType;
displayDifficulty.textContent = difficulty + ' Difficulty';
displayDuration.textContent = duration + ' Minutes';
// Initialize category timings for sequences that use category timings
if (sequenceType === 'Hatha Yoga' || sequenceType === 'Deep Stretch Yoga') {
categoryTimings = getCategoryTimings(duration);
currentCategoryIndex = 0;
}
// Initialize game variables
currentPoseIndex = -1;
poseSequence = [];
isPaused = false;
isTransition = true; // Start with transition to Tabletop Pose
poseTimeRemaining = 0;
elapsedTime = 0;
poseSkipped = false;
nextPoseData = getPoseByName('Tabletop Pose'); // Start with Tabletop Pose
repeatSide = false;
// Hide settings screen and show game container
settingsScreen.style.display = 'none';
gameContainer.style.display = 'block';
// Display "Start In" instead of "Transition To"
currentPoseHeader.textContent = 'Start In';
currentPoseName.textContent = nextPoseData['Pose Name'];
currentPoseImage.src = nextPoseData['Image URL'] ? nextPoseData['Image URL'] : placeholderImageUrl;
currentPoseCategory.textContent = 'Start Poses';
// Disable Skip Pose button during Start In phase
skipButton.disabled = true;
// Do not play sound for "Start In" Tabletop Pose
// Start the game loop
gameInterval = setInterval(updateGame, 1000);
}
// Variables to track previous pose
let previousPoseName = '';
let firstTransitionPlayed = false;
function updateGame() {
if (!isPaused) {
// Disable "Skip Pose" during "Start In" phase
if (isTransition && nextPoseData && nextPoseData['Pose Name'] === 'Tabletop Pose') {
skipButton.disabled = true;
} else {
skipButton.disabled = false;
}
if (isTransition) {
if (transitionTimeRemaining > 0) {
transitionTimeRemaining--;
totalTimeRemaining--;
elapsedTime++;
updateTimers();
// Play time remaining sound when there are 17 seconds left
if (totalTimeRemaining === 17 && soundOn) {
playSound('time-remaining');
}
} else {
isTransition = false;
currentPoseHeader.textContent = 'Current Pose';
// Move to the current pose
showCurrentPose();
}
} else {
// Check if current pose is "Final Relaxation" to disable "Skip Pose" button
if (currentPoseName.textContent.includes('Final Relaxation')) {
skipButton.disabled = true;
} else {
skipButton.disabled = false;
}
if (poseTimeRemaining > 0) {
poseTimeRemaining--;
totalTimeRemaining--;
elapsedTime++;
updateTimers();
// Play time remaining sound when there are 17 seconds left
if (totalTimeRemaining === 17 && soundOn) {
playSound('time-remaining');
}
} else {
// Calculate actual duration
let currentPose = poseSequence[poseSequence.length - 1];
if (currentPose && !currentPose.duration) {
if (poseSkipped) {
currentPose.duration = 'Skip';
} else {
currentPose.duration = elapsedTime - currentPose.startTime;
}
}
// Prepare next pose
prepareNextPose();
if (!nextPoseData) {
endGame();
return;
}
// Start transition to next pose
isTransition = true;
transitionTimeRemaining = transitionTimeSetting;
currentPoseHeader.textContent = 'Transition To';
currentPoseName.textContent = getPoseDisplayName(nextPoseData);
currentPoseImage.src = nextPoseData['Image URL'] || placeholderImageUrl;
currentPoseCategory.textContent = getCurrentCategory() + ' Poses';
// Play transition sound
if (soundOn) {
playSound('transition');
}
poseSkipped = false; // Reset skip flag
}
}
// Check if total time is up
if (totalTimeRemaining <= 0) {
endGame();
}
} else {
// Game is paused
updateTimers();
}
}
function showCurrentPose() {
let currentPose = nextPoseData;
if (!currentPose) {
endGame();
return;
}
// Handle poses that need both sides
if (currentPose['Both Sides']) {
repeatSide = true;
} else {
repeatSide = false;
}
// Set pose time remaining
poseTimeRemaining = currentPose['Hold Times']; // In seconds
// Store the initial hold time and start time
currentPose.startTime = elapsedTime;
poseSequence.push({
currentPose,
side: currentSide
});
// Update current pose display
currentPoseHeader.textContent = 'Current Pose';
currentPoseName.textContent = getPoseDisplayName(currentPose);
currentPoseImage.src = currentPose['Image URL'] || placeholderImageUrl;
currentPoseCategory.textContent = getCurrentCategory() + ' Poses';
// Play sound for current pose, but not on the first transition from "Start In"
if (soundOn && firstTransitionPlayed) {
playSound('current-pose');
} else {
firstTransitionPlayed = true;
}
// Update previousPoseName
previousPoseName = currentPose['Pose Name'];
// Reset nextPoseData if not repeating side
if (!repeatSide) {
nextPoseData = null;
}
// Update timers
updateTimers();
}
function prepareNextPose() {
if (repeatSide && currentSide === startingSide) {
// Switch to other side
currentSide = (startingSide === 'Right Side') ? 'Left Side' : 'Right Side';
} else {
// Get next pose
currentSide = startingSide;
nextPoseData = getNextPoseData();
repeatSide = nextPoseData && nextPoseData['Both Sides'];
}
}
function getPoseDisplayName(pose) {
let poseNameDisplay = pose['Pose Name'];
if (pose['Both Sides']) {
poseNameDisplay += ` (${currentSide})`;
}
return poseNameDisplay;
}
function getNextPoseData() {
if (sequenceType === 'Random Poses') {
return getRandomPose();
} else if (sequenceType === 'Hatha Yoga' || sequenceType === 'Deep Stretch Yoga') {
return getHathaYogaPose();
}
return null;
}
function getRandomPose() {
let availablePoses = poses.filter(
pose => (difficulty === 'Beginner' ? pose.Difficulty === 'Beginner' : true) &&
!pose.Categories.includes('End')
);
// Exclude the previous pose
if (previousPoseName) {
availablePoses = availablePoses.filter(pose => pose['Pose Name'] !== previousPoseName);
}
if (availablePoses.length === 0) {
return null;
}
const randomIndex = Math.floor(Math.random() * availablePoses.length);
return availablePoses[randomIndex];
}
function getHathaYogaPose() {
if (currentCategoryIndex >= categoryTimings.length) {
return null;
}
const currentCategory = getCurrentCategory();
// Move to next category if elapsed time exceeds category duration
const categoryDuration = categoryTimings[currentCategoryIndex].duration;
if (elapsedTime >= categoryDuration) {
currentCategoryIndex++;
return getHathaYogaPose();
}
let availablePoses = poses.filter(
pose => ((difficulty === 'Beginner') ? pose.Difficulty === 'Beginner' : true) &&
pose.Categories.includes(currentCategory)
);
// Special handling for "End" category
if (currentCategory === 'End') {
let finalRelaxationPose = getPoseByName('Final Relaxation');
if (finalRelaxationPose) {
finalRelaxationPose['Hold Times'] = totalTimeRemaining; // Set to remaining total time
return finalRelaxationPose;
} else {
return null;
}
}
// Exclude the previous pose
if (previousPoseName) {
availablePoses = availablePoses.filter(pose => pose['Pose Name'] !== previousPoseName);
}
if (availablePoses.length === 0) {
currentCategoryIndex++;
return getHathaYogaPose();
}
const randomIndex = Math.floor(Math.random() * availablePoses.length);
return availablePoses[randomIndex];
}
function getPoseByName(name) {
return poses.find(pose => pose['Pose Name'] === name);
}
function getCurrentCategory() {
if (sequenceType === 'Random Poses') {
return 'Random';
}
if (currentCategoryIndex < categoryTimings.length) {
return categoryTimings[currentCategoryIndex].category;
}
return '';
}
function getCategoryTimings(duration) {
let timings = [];
if (sequenceType === 'Hatha Yoga') {
if (duration === 15) {
timings = [
{ category: 'Warm Up', duration: 120 },
{ category: 'Standing', duration: 300 },
{ category: 'Peak', duration: 480 },
{ category: 'Floor', duration: 660 },
{ category: 'Cooldown', duration: 720 },
{ category: 'End', duration: 900 }
];
} else if (duration === 30) {
timings = [
{ category: 'Warm Up', duration: 240 },
{ category: 'Standing', duration: 720 },
{ category: 'Peak', duration: 1080 },
{ category: 'Floor', duration: 1380 },
{ category: 'Cooldown', duration: 1560 },
{ category: 'End', duration: 1800 }
];
} else if (duration === 60) {
timings = [
{ category: 'Warm Up', duration: 600 },
{ category: 'Standing', duration: 1500 },
{ category: 'Peak', duration: 2220 },
{ category: 'Floor', duration: 2820 },
{ category: 'Cooldown', duration: 3300 },
{ category: 'End', duration: 3600 }
];
}
} else if (sequenceType === 'Deep Stretch Yoga') {
if (duration === 15) {
timings = [
{ category: 'Warm Up', duration: 150 },
{ category: 'Floor', duration: 630 },
{ category: 'Cooldown', duration: 750 },
{ category: 'End', duration: 900 }
];
} else if (duration === 30) {
timings = [
{ category: 'Warm Up', duration: 300 },
{ category: 'Floor', duration: 1260 },
{ category: 'Cooldown', duration: 1500 },
{ category: 'End', duration: 1800 }
];
} else if (duration === 60) {
timings = [
{ category: 'Warm Up', duration: 540 },
{ category: 'Floor', duration: 2700 },
{ category: 'Cooldown', duration: 3240 },
{ category: 'End', duration: 3600 }
];
}
}
return timings;
}
function updateTimers() {
// Update timer text
if (isPaused) {
timerText.textContent = 'Paused';
} else if (isTransition) {
timerText.textContent = transitionTimeRemaining > 0 ? transitionTimeRemaining : '0';
} else {
timerText.textContent = poseTimeRemaining > 0 ? poseTimeRemaining : '0';
}
// Update total time remaining
let minutes = Math.floor(totalTimeRemaining / 60);
let seconds = totalTimeRemaining % 60;
timeRemainingText.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
}
function skipPose() {
// Skip both transition and pose, and move to the next pose
if (!isTransition) {
// Calculate actual duration for the skipped pose
let currentPose = poseSequence[poseSequence.length - 1];
if (currentPose && !currentPose.duration) {
currentPose.duration = 'Skip';
}
}
// Prepare next pose
prepareNextPose();
if (!nextPoseData) {
endGame();
return;
}
// Start transition to next pose
isTransition = true;
transitionTimeRemaining = transitionTimeSetting;
currentPoseHeader.textContent = 'Transition To';
currentPoseName.textContent = getPoseDisplayName(nextPoseData);
currentPoseImage.src = nextPoseData['Image URL'] || placeholderImageUrl;
currentPoseCategory.textContent = getCurrentCategory() + ' Poses';
// Play transition sound
if (soundOn) {
playSound('transition');
}
poseSkipped = true; // Reset skip flag
poseTimeRemaining = 0; // Reset pose time remaining
// Update timers
updateTimers();
}
function confirmEndGame() {
skipModal.style.display = 'none';
endGame();
}
function resumeGame() {
skipModal.style.display = 'none';
// Continue with Final Relaxation
}
function togglePause() {
isPaused = !isPaused;
pauseButton.textContent = isPaused ? 'Resume' : 'Pause';
updateTimers();
}
function toggleSound() {
soundOn = !soundOn;
soundButton.textContent = soundOn ? 'Sound Off' : 'Sound On';
}
function endGame() {
clearInterval(gameInterval);
// Calculate duration for the current pose if not already calculated
if (poseSequence.length > 0) {
let currentPose = poseSequence[poseSequence.length - 1];
if (currentPose && !currentPose.duration) {
if (poseSkipped) {
currentPose.duration = 'Skip';
} else {
currentPose.duration = elapsedTime - currentPose.startTime;
}
}
}
// Hide game container and show end screen
gameContainer.style.display = 'none';
endScreen.style.display = 'block';
// Display pose sequence with durations
poseSequenceList.innerHTML = '';
poseSequence.forEach((pose) => {
const li = document.createElement('li');
let timeDisplay;
if (pose['Pose Name'] === 'Tabletop Pose') {
timeDisplay = 'Start';
} else if (pose['Pose Name'] === 'Final Relaxation') {
timeDisplay = 'End';
} else if (pose.duration === 'Skip') {
timeDisplay = 'Skip';
} else {
let duration = pose.duration || 0;
let minutes = Math.floor(duration / 60);
let seconds = duration % 60;
timeDisplay = `${minutes}:${seconds.toString().padStart(2, '0')}`;
}
const timeSpan = document.createElement('span');
timeSpan.textContent = timeDisplay + ' ';
timeSpan.classList.add('time-display');
let poseNameDisplay = pose['Pose Name'];
if (pose['Both Sides']) {
poseNameDisplay += ` (${pose.side})`;
}
const poseNameSpan = document.createElement('span');
poseNameSpan.textContent = poseNameDisplay;
poseNameSpan.classList.add('pose-name');
li.appendChild(timeSpan);
li.appendChild(poseNameSpan);
poseSequenceList.appendChild(li);
});
}
function playAgain() {
// Restart the game with the same settings
endScreen.style.display = 'none';
startGame();
}
function newGame() {
// Return to settings screen
endScreen.style.display = 'none';
settingsScreen.style.display = 'block';
gameContainer.style.display = 'none';
}
function playSound(type) {
let audio;
if (type === 'transition') {
audio = new Audio(transitionSoundUrl);
} else if (type === 'current-pose') {
audio = new Audio(currentPoseSoundUrl);
} else if (type === 'time-remaining') {
audio = new Audio(timeRemainingSoundUrl);
}
if (audio) {
audio.play();
}
}
// Share Sequence Function
function shareSequence() {
const shareText = `I just finished this yoga sequence using the Yoga Pose Game by Asivana Yoga. Check it out and practice a random sequence. See if you can hold each pose for the full duration!\nwww.asivanayoga.com/pages/yoga-pose-game
Sequence:
`;
const sequenceText = poseSequence.map(pose => {
let timeDisplay;
if (pose['Pose Name'] === 'Tabletop Pose') {
timeDisplay = 'Start';
} else if (pose['Pose Name'] === 'Final Relaxation') {
timeDisplay = 'End';
} else if (pose.duration === 'Skip') {
timeDisplay = 'Skip';
} else {
let duration = pose.duration || 0;
let minutes = Math.floor(duration / 60);
let seconds = duration % 60;
timeDisplay = `${minutes}:${seconds.toString().padStart(2, '0')}`;
}
let poseNameDisplay = pose['Pose Name'];
if (pose['Both Sides']) {
poseNameDisplay += ` (${pose.side})`;
}
return `${timeDisplay} - ${poseNameDisplay}`;
}).join('\n');
const shareContent = `${shareText}\n${sequenceText}`;
// Show custom share modal
showShareModal(shareContent);
}
function showShareModal(content) {
shareTextarea.value = content;
shareModal.style.display = 'block';
}
function copyShareText() {
shareTextarea.select();
document.execCommand('copy');
alert('Sequence copied to clipboard!');
}
function shareOnFacebook() {
const shareContent = encodeURIComponent(shareTextarea.value);
const facebookUrl = `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent('https://www.asivanayoga.com/pages/yoga-pose-game')}"e=${shareContent}`;
window.open(facebookUrl, '_blank');
}
function shareOnTwitter() {
const shareContent = encodeURIComponent(shareTextarea.value);
const twitterUrl = `https://twitter.com/intent/tweet?text=${shareContent}`;
window.open(twitterUrl, '_blank');
}
// Print Sequence Function
function printSequence() {
// Create a new jsPDF instance
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
// Asivana logo
const logoUrl = 'https://cdn.shopify.com/s/files/1/0566/4800/7733/files/Asivana_Yoga_Company_CV_Circle_Logo.png?v=1685652034';
// Load the logo image
let img = new Image();
img.src = logoUrl;
img.onload = function () {
// Add logo to the PDF (scaled to 50%) at top-left corner
const imgWidth = 30; // Adjusted for 50% scaling
const imgHeight = 30; // Adjusted for 50% scaling
doc.addImage(img, 'PNG', 10, 10, imgWidth, imgHeight);
// Main Header centered at the top
doc.setFontSize(20);
doc.setTextColor(51, 63, 72); // Theme color
doc.text('Yoga Pose Game', 105, 25, null, null, 'center');
// "Brought to you by Asivana Yoga Company" centered below the header
doc.setFontSize(12);
doc.text('Brought to you by Asivana Yoga Company', 105, 34, null, null, 'center');
// Title "Yoga Sequence" at top-right corner
doc.setFontSize(16);
doc.text('Yoga Sequence', 200 - 10, 20, null, null, 'right');
// Add a line break before the line separator
doc.text('', 10, 44);
// Line separator
doc.setLineWidth(0.5);
doc.setDrawColor(51, 63, 72);
doc.line(10, 46, 200 - 10, 46);
// Prepare the sequence text in a single column
doc.setFontSize(12);
doc.setTextColor(123, 90, 109); // Secondary theme color
let yPosition = 56;
const lineHeight = 7;
poseSequence.forEach((pose) => {
let timeDisplay;
if (pose['Pose Name'] === 'Tabletop Pose') {
timeDisplay = 'Start';
} else if (pose['Pose Name'] === 'Final Relaxation') {
timeDisplay = 'End';
} else if (pose.duration === 'Skip') {
timeDisplay = 'Skip';
} else {
let duration = pose.duration || 0;
let minutes = Math.floor(duration / 60);
let seconds = duration % 60;
timeDisplay = `${minutes}:${seconds.toString().padStart(2, '0')}`;
}
let poseNameDisplay = pose['Pose Name'];
if (pose['Both Sides']) {
poseNameDisplay += ` (${pose.side})`;
}
let lineText = `${timeDisplay} - ${poseNameDisplay}`;
doc.text(lineText, 10, yPosition);
yPosition += lineHeight;
// Add new page if necessary
if (yPosition > 270) {
doc.addPage();
yPosition = 20;
}
});
// Footer with duration before sequence type
doc.setFontSize(10);
doc.setTextColor(0, 0, 0); // Black color
let durationText = `${duration} Minute`;
let sequenceTypeText = `${sequenceType}`;
let footerText = `${durationText} ${sequenceTypeText} Sequence`;
doc.text(105, 285, footerText, null, null, 'center');
// Download the PDF
doc.save('Yoga_Pose_Sequence.pdf');
};
img.onerror = function () {
alert('Error loading logo image.');
};
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.