【问题标题】:Create a multifuctional Javascript reveal function that works without duplicating the code创建一个无需复制代码即可工作的多功能 Javascript 显示函数
【发布时间】:2021-12-25 19:34:37
【问题描述】:

这是我在 stackflow 上的第一篇文章。我对编程很陌生,但 我正在尝试弄清楚如何有效地生成一个多功能函数,该函数将允许我一次为多个 div/块分别显示信息。 例如, 这个函数只对这个特定的按钮和 div 有效。

<!-- Function 1 -->
  (function () {
    var n = 1;
    window.ShowStep1 = function () {
      document.getElementById("Step1" + "-" + n++).style.visibility = "visible";
      if (!document.getElementById("Step1" + "-" + n)) {
        document.getElementById("step1").disabled = true;
      }
      document.getElementById("reset1").disabled = false;
    }
    window.ResetSteps1 = function () {
      document.getElementById("step1").disabled = false;
      document.getElementById("reset1").disabled = true;
      var i = 1, step1; n = 1;
      while (step1 = document.getElementById("Step1" + "-" + i)) {
        step1.style.visibility = "hidden";
        i++
      }
    }
  })();

它仅适用于以下情况:

<p>
 <input type="button" onclick="ShowStep1()" value="Steps" id="step1"/> 
 <input type="button" onclick="ResetSteps1()" value="Reset" id="reset1" disabled="true"/>
</p>

但我想对许多具有唯一 ID 的按钮执行此操作,而不必手动创建新功能。截至目前,为了让我创建多个功能,我必须手动创建几个Function 1 代码集。如果说我想做其中的 10 个,我怎样才能更有效地做到这一点?代码工作正常,但我不想重复自己。此代码来自以下链接: MathJax-demos-web-link

但我以自己的方式对其进行了修改。任何帮助和提示将不胜感激!提前致谢。 由于某种原因,sn-p 中存在错误,但如果您在 jsfiddle 上运行它,它可以正常工作。这是整个脚本。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <meta name="viewport" content="width=device-width">
  <title>MathJax v3 dynamic equations using CSS and javascript</title>
  <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
  <script>
  MathJax = {
    tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]},
    chtml: {
      displayAlign: 'left'
    },
    startup: {
      pageReady: function () {
        //
        //  Do the usual startup (which does a typeset).
        //  When that is all done, un-hide the page.
        //
        return MathJax.startup.defaultPageReady().then(function () {
          document.getElementById("hidden").disabled = true;
        });
      }
    }
  };
  </script>
  <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>

  <script type="text/javascript">
<!-- Function 1 -->
  (function () {
    var n = 1;
    window.ShowStep1 = function () {
      document.getElementById("Step1" + "-" + n++).style.visibility = "visible";
      if (!document.getElementById("Step1" + "-" + n)) {
        document.getElementById("step1").disabled = true;
      }
      document.getElementById("reset1").disabled = false;
    }
    window.ResetSteps1 = function () {
      document.getElementById("step1").disabled = false;
      document.getElementById("reset1").disabled = true;
      var i = 1, step1; n = 1;
      while (step1 = document.getElementById("Step1" + "-" + i)) {
        step1.style.visibility = "hidden";
        i++
      }
    }
  })();
  
<!-- Function 2 -->
  (function () {
    var n = 1;
    window.ShowStep2 = function () {
      document.getElementById("Step2" + "-" + n++).style.visibility = "visible";
      if (!document.getElementById("Step2" + "-" + n)) {
        document.getElementById("step2").disabled = true;
      }
      document.getElementById("reset2").disabled = false;
    }
    window.ResetSteps2 = function () {
      document.getElementById("step2").disabled = false;
      document.getElementById("reset2").disabled = true;
      var i = 1, step2; n = 1;
      while (step2 = document.getElementById("Step2" + "-" + i)) {
        step2.style.visibility = "hidden";
        i++
      }
    }
  })();
  
  </script>

  <style>
    #Step1-1, #Step1-2, #Step1-3, #Step1-4, #Step1-5,
    #Step2-1, #Step2-2, #Step2-3, #Step2-4, #Step2-5 {
      visibility: hidden;
    }
  </style>

</head>
<body>
<h1>Dynamic Equations in MathJax</h1>

<div id="frame">
<p>
Expand the following:
\begin{align}
  (x+1)^2
    &= \cssId{Step1-1}{(x+1)(x+1)}            \\[3px]
    &\cssId{Step1-2}{{} = x(x+1) + 1(x+1)}    \\[3px]
    &\cssId{Step1-3}{{} = (x^2+x) + (x+1)}    \\[3px]
    &\cssId{Step1-4}{{} = x^2 + (x + x) + 1}  \\[3px]
    &\cssId{Step1-5}{{} = x^2 + 2x + 1}
\end{align}
</p>

<p>
<input type="button" onclick="ShowStep1()" value="Steps" id="step1"/> 
<input type="button" onclick="ResetSteps1()" value="Reset" id="reset1" disabled="true"/>
</p>

</div>

<div id="frame">
<p>
Expand the following:
\begin{align}
  (x+1)^2
    &= \cssId{Step2-1}{(x+1)(x+1)}            \\[3px]
    &\cssId{Step2-2}{{} = x(x+1) + 1(x+1)}    \\[3px]
    &\cssId{Step2-3}{{} = (x^2+x) + (x+1)}    \\[3px]
    &\cssId{Step2-4}{{} = x^2 + (x + x) + 1}  \\[3px]
    &\cssId{Step2-5}{{} = x^2 + 2x + 1}
\end{align}
</p>

<p>
<input type="button" onclick="ShowStep2()" value="Steps" id="step2"/> 
<input type="button" onclick="ResetSteps2()" value="Reset" id="reset2" disabled="true"/>
</p>

</div>

</body>
</html>

【问题讨论】:

    标签: javascript html css mathjax


    【解决方案1】:

    主要的变化将是为两个函数中的每一个创建一个版本,该版本采用参数,而不是现在发生的将步骤信息存储在变量中。

    不过,在此之前,还有一些其他的观察:

    • HTML 不“合法” - id 必须是唯一的,并且框架 id 在给定代码中不是唯一的。

    • 这个额外的 CSS 样式有点警钟,是否意味着你不能超过 5 个步骤?

       #Step1-1, #Step1-2, #Step1-3, #Step1-4, #Step1-5,
       #Step2-1, #Step2-2, #Step2-3, #Step2-4, #Step2-5 {
         visibility: hidden;
       }
      

    这个 sn-p 重命名框架 id 使其唯一,删除上面的多样式设置并替换更通用的“id 以 Step 开头的样式元素”。

    然后它只创建一个步进显示函数和一个复位函数,并用参数调用它们。它不会尝试存储 'n' 的值来显示在每种情况下显示的位置,而是每次通过查找那些已经可见的步骤来计算它。

    请注意(如问题中所述)无法在沙盒化的 SO sn-p 系统中运行此程序,因此这是完整的代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="utf-8">
      <meta http-equiv="x-ua-compatible" content="ie=edge">
      <meta name="viewport" content="width=device-width">
      <title>MathJax v3 dynamic equations using CSS and javascript</title>
      <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
      <script>
      MathJax = {
        tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]},
        chtml: {
          displayAlign: 'left'
        },
        startup: {
          pageReady: function () {
            //
            //  Do the usual startup (which does a typeset).
            //  When that is all done, un-hide the page.
            //
            return MathJax.startup.defaultPageReady().then(function () {
              document.getElementById("hidden").disabled = true;
            });
          }
        }
      };
      </script>
      <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
    
      <script>
    
      (function () {
        window.ShowStep = function (el, id) {
          //go through all the elements with id id-n and set the first non visible one to visible
          const steps = document.querySelectorAll('[id^="' + id + '"]');
          for (let i = 0; i < steps.length; i++) {
             if (steps[i].style.visibility != 'visible') {
               steps[i].style.visibility = 'visible';
               break;
             }
           }
          el.nextElementSibling.disabled = false;
        }
        window.ResetSteps = function (el, id, reset) {
          el.disabled = false;
          //go through all the elements with id id-n and set them all to hidden
          const steps = document.querySelectorAll('[id^="' + id + '"]');
          for (let i = 0; i < steps.length; i++) {
               steps[i].style.visibility = 'hidden';
             }      
        } 
      })();
        </script>
    <style>
    [id^="Step"] {
      visibility : hidden;
    }
    
    </style>
    
    </head>
    <body>
    <h1>Dynamic Equations in MathJax</h1>
    
    <div id="frame1">
    <p>
    Expand the following:
    \begin{align}
      (x+1)^2
        &= \cssId{Step1-1}{(x+1)(x+1)}            \\[3px]
        &\cssId{Step1-2}{{} = x(x+1) + 1(x+1)}    \\[3px]
        &\cssId{Step1-3}{{} = (x^2+x) + (x+1)}    \\[3px]
        &\cssId{Step1-4}{{} = x^2 + (x + x) + 1}  \\[3px]
        &\cssId{Step1-5}{{} = x^2 + 2x + 1}
    \end{align}
    </p>
    
    <p>
    <input type="button" onclick="ShowStep(this, 'Step1', 'reset1');" value="Steps"/> 
    <input type="button" onclick="ResetSteps(this, 'Step1', 'reset1')" value="Reset" disabled="true"/>
    </p>
    
    </div>
    
    <div id="frame2">
    <p>
    Expand the following:
    \begin{align}
      (x+1)^2
        &= \cssId{Step2-1}{(x+1)(x+1)}            \\[3px]
        &\cssId{Step2-2}{{} = x(x+1) + 1(x+1)}    \\[3px]
        &\cssId{Step2-3}{{} = (x^2+x) + (x+1)}    \\[3px]
        &\cssId{Step2-4}{{} = x^2 + (x + x) + 1}  \\[3px]
        &\cssId{Step2-5}{{} = x^2 + 2x + 1}
    \end{align}
    </p>
    
    <p>
    <input type="button" onclick="ShowStep(this, 'Step2', 'reset2');" value="Steps" id="step2"/> 
    <input type="button" onclick="ResetSteps(this, 'Step2', 'reset2')" value="Reset" id="reset2" disabled="true"/>
    </p>
    
    </div>
    
    </body>
    </html>
    

    【讨论】:

    • 感谢 A Haworth 的大力帮助!这种方法对我来说是新的。我确信我以前见过这种技术的各种变体,但从来没有真正理解过它。另外,我确实明白您所说的 HTML 不合法是什么意思,对于 CSS,我相信这是我手动计算创建解决方案的方式。你怎么做的看起来很简单。我看到了逻辑,但我仍然需要更多的练习并建立我的基础。这个级别的js有什么推荐的学习资源或者书籍吗?目前我正在阅读 Haverbeke 的 Eloquent Javascript 和 Wieruch 的 The Road to React。
    • 另外,上面的代码。我注意到来自 "\cssId{Step1-1}{...} & \cssId{Step1-1}{...}" 的 Step1 和 Step 2 的唯一 id -1, -2,... -n没关系。它可以有任何独特的价值,它仍然会以相同的顺序显示它们。脚本中的逻辑从何而来,为什么能够做到这一点。我不认为它会改变我使用它的方式,但我只是好奇,因为我想更好地理解代码。谢谢!
    • 这些 id 是由数学排版包创建的。这个答案中的代码不需要使用它们,因为在运行时更容易找到孩子,不必为每个孩子存储一个特殊的 n ,这基本上就是为什么问题中的代码有一个副本每个示例的函数。
    • 我明白了。好的,我会调查的,谢谢!
    • @Haworth 如何从一开始就隐藏所有 cssid 以便它开始隐藏?
    猜你喜欢
    • 2018-08-28
    • 2017-12-01
    • 1970-01-01
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    • 2012-09-22
    • 1970-01-01
    • 2021-03-13
    相关资源
    最近更新 更多