You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

点击训练卡片跳转Workout页面后出现userSelection.js元素错误

健身应用页面跳转问题

最终目标

用户选择训练卡片后,跳转至包含计时器和MP4格式训练视频的训练页面;计时器结束后,当前练习会切换为下一个练习。计时器和视频均从Firebase加载。

期望实现

跳转至新页面后,传递选中卡片的标题,将其添加到Firebase引用中,以便页面加载时获取对应的训练视频和计时器数据。(忽略setTimeout,后续会改为Promise)

当前问题

点击卡片跳转至Workout页面后,出现来自userSelection.js模块中某些元素的错误,但并未跨模块导入这些元素。

错误截图

ERROR

代码文件

workout.js

import { initializeApp } from "https://www.gstatic.com/firebasejs/9.8.4/firebase-app.js";
import letitGo from "./UserSelection.js";
import {
  getDatabase,
  ref,
  onValue,
} from "https://www.gstatic.com/firebasejs/9.8.4/firebase-database.js";

const firebaseConfig = {
  apiKey: apiKey,
  authDomain: "danifitness.firebaseapp.com",
  projectId: "danifitness",
  storageBucket: "danifitness.appspot.com",
  messagingSenderId: "194472376905",
  appId: "1:194472376905:web:82111669300a777e7b5d98",
  measurementId: "G-KCRJXR6YH8",
};

window.onload = letsGo;

function letsGo() {
  console.log("hey man");
  letitGo();
}

// Initialize Firebase
const app = initializeApp(firebaseConfig);
const database = getDatabase(app);
// Get reference
let newref = ref(database, "workout/"); // Needs to have the selected exercise heading in the url path. E.G. + I AM LEGEND

onValue(
  newref,
  (snapshot) => {
    let dataVal = snapshot.val();
    console.log(dataVal);
  },
  (errorObject) => {
    console.log("The read failed: " + errorObject.name);
  }
);

const playBtn = document.getElementById("playBtn");
const pauseBtn = document.getElementById("pauseBtn");

playBtn.addEventListener("click", (event) => {
  console.log(event);
  startTimer();
});

pauseBtn.addEventListener("click", () => {
  console.log("paused!");
  clearInterval(timerInterval);
});

// Countdown Timer Animation
const FULL_DASH_ARRAY = 283;
const WARNING_THRESHOLD = 10;
const ALERT_THRESHOLD = 5;

const COLOR_CODES = {
  info: {
    color: "green",
  },
  warning: {
    color: "orange",
    threshold: WARNING_THRESHOLD,
  },
  alert: {
    color: "red",
    threshold: ALERT_THRESHOLD,
  },
};

const TIME_LIMIT = 20; // This will be replaced by working time
let timePassed = 0;
let timeLeft = TIME_LIMIT;
let timerInterval = null;
let remainingPathColor = COLOR_CODES.info.color;

document.getElementById("timer").innerHTML = `
<div class="base-timer">
  <svg class="base-timer__svg" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
    <g class="base-timer__circle">
      <circle class="base-timer__path-elapsed" cx="50" cy="50" r="45"></circle>
      <path
        id="base-timer-path-remaining"
        stroke-dasharray="283"
        class="base-timer__path-remaining ${remainingPathColor}"
        d="
          M 50, 50
          m -45, 0
          a 45,45 0 1,0 90,0
          a 45,45 0 1,0 -90,0
        "
      ></path>
    </g>
  </svg>
  <span id="base-timer-label" class="base-timer__label">${formatTime(
    timeLeft
  )}</span>
</div>
`;

function onTimesUp() {
  clearInterval(timerInterval);
}

function startTimer() {
  timerInterval = setInterval(() => {
    timePassed = timePassed += 1;
    timeLeft = TIME_LIMIT - timePassed;
    document.getElementById("base-timer-label").innerHTML =
      formatTime(timeLeft);
    setCircleDasharray();
    setRemainingPathColor(timeLeft);

    if (timeLeft === 0) {
      onTimesUp();
      //   rnds -1
    }
  }, 1000);
}

function formatTime(time) {
  const minutes = Math.floor(time / 60);
  let seconds = time % 60;

  if (seconds < 10) {
    seconds = `0${seconds}`;
  }

  return `${minutes}:${seconds}`;
}

function setRemainingPathColor(timeLeft) {
  const { alert, warning, info } = COLOR_CODES;
  if (timeLeft <= alert.threshold) {
    document
      .getElementById("base-timer-path-remaining")
      .classList.remove(warning.color);
    document
      .getElementById("base-timer-path-remaining")
      .classList.add(alert.color);
  } else if (timeLeft <= warning.threshold) {
    document
      .getElementById("base-timer-path-remaining")
      .classList.remove(info.color);
    document
      .getElementById("base-timer-path-remaining")
      .classList.add(warning.color);
  }
}

function calculateTimeFraction() {
  const rawTimeFraction = timeLeft / TIME_LIMIT;
  return rawTimeFraction - (1 / TIME_LIMIT) * (1 - rawTimeFraction);
}

function setCircleDasharray() {
  const circleDasharray = `${(
    calculateTimeFraction() * FULL_DASH_ARRAY
  ).toFixed(0)} 283`;
  document
    .getElementById("base-timer-path-remaining")
    .setAttribute("stroke-dasharray", circleDasharray);
}

userSelection.js

import { initializeApp } from "https://www.gstatic.com/firebasejs/9.8.4/firebase-app.js";
import {
  getDatabase,
  ref,
  onValue,
} from "https://www.gstatic.com/firebasejs/9.8.4/firebase-database.js";

const firebaseConfig = {
  apiKey: APIKEY,
  authDomain: "danifitness.firebaseapp.com",
  projectId: "danifitness",
  storageBucket: "danifitness.appspot.com",
  messagingSenderId: "194472376905",
  appId: "1:194472376905:web:82111669300a777e7b5d98",
  measurementId: "G-KCRJXR6YH8",
};

const userSelections = document.querySelector(".user-exercises");

// Initialize Firebase
const app = initializeApp(firebaseConfig);
const database = getDatabase(app);
// Get reference
let newref = ref(database, "workout/");

onValue(
  newref,
  (snapshot) => {
    let dataVal = snapshot.val();
    console.log(dataVal);

    const newKey = Object.keys(dataVal);
    getCards(newKey);

    const userSelHeading = document.querySelectorAll(".workoutSelHeading");
    userSelHeading.forEach((userEl) => {
      words.push(userEl.innerHTML);
      console.log(userEl);
    });
  },
  (errorObject) => {
    console.log("The read failed: " + errorObject.name);
  }
);

function timeit() {
  //   LOAD AFTER EXERCISE CARD HAS BEEN LOADED
  setTimeout(() => {
    const selectIt = document.querySelectorAll(".exercise-card");
    selectIt.forEach((element) => {
      console.log(element);
      element.addEventListener("click", () => {
        console.log(element);
        letitGo();
      });
    });
  }, 3000);
}

timeit();

// USE SEARCH BAR TO SEARCH FOR WORKOUTS-------------------------------------
const searchbtn = document.querySelector(".searchBtn");
const userSearch = document.querySelector(".userSearch");

let words = [];

userSearch.addEventListener("keyup", (e) => {
  let newLetter = e.target.value.toLowerCase();
  const filteredWords = words.filter((word) => {
    return word.toLowerCase().includes(newLetter);
  });
  getCards(filteredWords);
});

const getCards = (cards) => {
  const htmlString = cards.map((card) => {
    console.log(card[0]);
    return `
    <div class="exercise-card">
        <div class="exercise-img">
            <img src="" alt="Image will go here">
        </div>
        <div class="exercise-info">
            <div class="topsection">
                <!-- Pull the heading and description data -->
                <h3 class="workoutSelHeading">${card}</h3>
                <!-- What is the exercise -->
                <h5>Legs</h5>
            </div>
            <div class="des-container">
                <p>Legless is a high intensity, full lower body, resistance based leg workout bound to have you crawling out of the gym. It is a great workout if you're looking to build strength and muscle growth.</p>
            </div>
        </div>
</div>`;
  });
  userSelections.innerHTML = htmlString.join("");
};

export default function letitGo() {
  console.log("please work");
  window.location.href = "workout"; // WORKOUT SCREEN - Redirects to the new screen to start workout
}

内容的提问来源于stack exchange,提问作者LM17

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:42:27