使用DOM和appendChild的函数中的JavaScript数组

问题描述 投票:3回答:1

我的简单脚本添加问题和答案时遇到问题。更具体地说,通过增加对以下问题的进一步答案,第二个问题继续从第一个停止的地方命名答案 - 例如

问题1回答a,b,c

问题2回答a,b,d

我想我必须使用数组,每个问题 - >自己的数组。

  n = 1;

  function add_question() {

    var textarea = document.createElement("textarea");
    textarea.name = "question[" + n + "]";
    textarea.className = "form-control";
    textarea.id = "pytanie_id_" + n;
    textarea.name = "data[" + n + "][pytanie]";
    textarea.autocomplete = "off";
    var addone = document.createElement("input");
    addone.type = "button";
    addone.value = "+";
    addone.id = "id_" + n;
    addone.className = "btn  btn-success-my";
    addone.innerHTML = "<span class=\"glyphicon glyphicon-plus\">";
    var label_pyt = document.createElement("label");
    label_pyt.className = "col-md-4 control-label";
    label_pyt.for = "pytanie_id_" + n;
    label_pyt.innerHTML = "Question " + n + ".";
    var label_odp_a = document.createElement("label");
    label_odp_a.className = "col-md-4 control-label";
    label_odp_a.for = "odp_a_id_" + n;
    label_odp_a.innerHTML = " A";
    var input_odp_a = document.createElement("input");
    input_odp_a.id = "odp_a_id_" + n;
    input_odp_a.name = "data[" + n + "][odp_a]";
    input_odp_a.type = "text";
    input_odp_a.className = "form-control input-md";
    input_odp_a.autocomplete = "off";
    var label_odp_b = document.createElement("label");
    label_odp_b.className = "col-md-4 control-label";
    label_odp_b.for = "odp_b_id_" + n;
    label_odp_b.innerHTML = " B";
    var input_odp_b = document.createElement("input");
    input_odp_b.id = "odp_b_id_" + n;
    input_odp_b.name = "data[" + n + "][odp_b]";
    input_odp_b.type = "text";
    input_odp_b.className = "form-control input-md";
    input_odp_b.autocomplete = "off";
    //addone.addEventListener("onclick", function(n){add_answer(n);});
    var divquest = document.createElement("div");
    divquest.id = "us_pytanie_" + n;
    divquest.innerHTML = "<div class=\"form-group\"> <hr>" + label_pyt.outerHTML 
    										+ "<div class=\"col-md-4\"> " + textarea.outerHTML 
                        + "</div></div>" + "<div class=\"form-group\">" 
                        + label_odp_a.outerHTML + "<div class=\"col-md-4\">" 
                        + input_odp_a.outerHTML 
                        + "</div></div>" 
                        + "<div class=\"form-group\">" 
                        + label_odp_b.outerHTML 
                        + "<div class=\"col-md-4\">" 
                        + input_odp_b.outerHTML 
                        + "</div></div>" 
                        + "<div id=\"radiodown" + n + "\" ></div>" 
                        + "<div class=\"form-group\">" 
                        + "<label class=\"col-md-4 control-label\"> </label>" 
                        + "<div class=\"col-md-4\">" 
                        + "<div class=\"btn-group btn-group-justified\">" 
                        + "<div class=\"btn-group\">" 
                        + addone.outerHTML 
                        + "</div>"
                        + "<div class=\"btn-group\">" 
                        + "</div>" 
                        + "</div>" 
                        + "</div>" 
                        + "</div>" 
                        + "</div></div>";
    document.getElementById("question").appendChild(divquest);
    var btn = document.getElementById("id_" + n);
    if (btn.addEventListener) {
      btn.addEventListener('click', function() {
        add_answer(this);
      });
    } else if (btn.attachEvent) { // IE < 9 :(
      btn.attachEvent('onclick', function() {
        add_answer(this);
      });
    }
    n++;
  }

  abc_index = 0;

  function add_answer(index) {
    //alert("called"+(this).id);
    index = index.id.split("_")[1];
    var abc_table_answer = [];
    for (var x = 0; x < 20; x++) {
      abc_table_answer[x] = ['C', 'D', 'E', 'F'];
    }
    var abc_table_db_answer = [];
    for (var x = 0; x < 20; x++) {
      abc_table_db_answer[x] = ['c', 'd', 'e', 'f'];
    }
    //alert(abc_index + index);
    var option = document.createElement("input");
    option.id = "odp_" + abc_table_db_answer[index][abc_index] + "_id_" + index + "";
    option.name = "data[" + index + "][odp_" + abc_table_db_answer[index][abc_index] + "]";
    option.type = "text";
    option.className = "form-control input-md";
    option.autocomplete = "off";
    var label_option = document.createElement("label");
    label_option.className = "col-md-4 control-label";
    label_option.for = "odp_" + abc_table_db_answer[index][abc_index] + "_id_" + index + "";
    label_option.innerHTML =  abc_table_answer[index][abc_index] + "";
    var optiondiv = document.createElement("div");
    optiondiv.id = "us_answer_" + index + "_" + abc_index + "";
    optiondiv.className = "form-group";
    optiondiv.innerHTML = label_option.outerHTML + "<div class=\"col-md-4\">" + option.outerHTML + "</div></div>";
    document.getElementById("radiodown" + index).appendChild(optiondiv);
    abc_index++;
  }
<input type="submit" value="ADD" onclick="add_question();" />
<br/><br/>
<div id="question"></div><br/>

但是,以下问题不使用单独的表,这就是问题所在。

请告诉我是否有解决此问题的方法。

预先感谢您的帮助。

编辑

还添加jsfiddle

jsfiddle DEMO

javascript arrays dom button
1个回答
0
投票

演示大纲

Problem

OP为列表添加额外答案的预期行为。

  1. 题 一个。回答 湾回答 C。回答 d。回答< - 附加到列表

这是实际行为:

  1. 题 一个。回答 湾回答 C。回答 即回答< - 附加到列表,因为问题1有d. answer

因为表单是由来自用户交互的事件(即点击按钮)驱动的,所以循环和数组并非完全必要。如果此项目稍后要使用来自动态源的数据,则应考虑数组和循环。

Demo Outline

  1. base()函数创建了几个基本元素(这是不重复的布局部分),并设置了必需的属性。
  2. 所有元素都附加到documentFragment,然后附加到DOM。
  3. #1和#2中描述的过程是首选,因为在DOM中运行任何东西都需要为浏览器做更多的工作。
  4. 加载后,布局有一个<fieldset>,左边是表单字段,右边是iframe。其目的是显示提交给测试服务器的数据。注意:由于SO沙箱,此功能不起作用。查看此PLUNKER以获得功能齐全的演示。
  5. 单击绿色的“添加”按钮将附加QA(问题和答案)。
  6. 单击蓝色“提交”按钮不会在SO堆栈片段中执行任何操作。 (见#4)
  7. 标记为True / False的复选框将隐藏4个答案中的2个以容纳布尔性质的问题。
  8. 加号+按钮将为其所属的质量检查添加答案。
  9. 所有带有数据的表单控件字段(<textarea><input>)都有唯一的#id和[name]。

更多详细信息在演示中进行了评论,参考文献位于本文末尾

演示(有关正常运行的演示,请参阅PLUNKER

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1, user-scalable=no">
  <title></title>
  <link href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' rel='stylesheet'>
  <style>
    #quiz {
      display: flex;
    }
    
    section {
      order: 2
    }
    
    textarea {
      vertical-align: top;
    }
    
    .alpha {
      list-style: lower-alpha
    }
    
    li {
      margin: 0 0 10px 20px
    }
    
    .list-group-item-heading {
      margin-left: 0
    }
    /* When True/False checkbox is checked, 
    || the following rulesets are invoked 
    */
    
    .tf:checked+ol>li:last-of-type,
    .tf:checked+ol>li:nth-of-type(3) {
      display: none;
    }
    
    button,
    input[type=submit] {
      margin: 0 0 10px 0
    }
  </style>
</head>

<body>


  <script>
    var n = 0;
    /* Fastest way to use .createElement() and 
    || .appendChild() is to create a documentFragment,
    || append all elements to the fragment,
    || set attributes to the elements,
    || then append the documentFragment to the DOM
    */
    var base = function(n) {
      var frag = document.createDocumentFragment();
      var quiz = document.createElement('form');
      var sec = document.createElement('section');
      var btn = document.createElement('button');
      var sbt = document.createElement('input');
      var fSet = document.createElement('fieldset');
      var lgd = document.createElement('legend');
      var ol = document.createElement('ol');
      quiz.id = 'quiz';
      quiz.classList.add('container', 'form-group-lg');
      quiz.action = 'http://httpbin.org/post';
      quiz.method = 'post';
      quiz.target = 'view';
      sec.className = 'col-md-6';
      btn.id = 'add0';
      btn.type = 'button';
      btn.classList.add('btn', 'btn-primary', 'pull-right');
      sbt.type = 'submit';
      sbt.classList.add('btn', 'btn-success', 'pull-right');
      btn.textContent = 'Add';
      fSet.id = 'set0';
      fSet.classList.add("form-group", "col-md-6");
      lgd.textContent = "Quiz Template";
      ol.id = 'qa0';
      ol.className = 'list-group';
      frag.appendChild(quiz);
      quiz.appendChild(sec);
      fSet.appendChild(sbt);
      fSet.appendChild(btn);
      quiz.appendChild(fSet);
      fSet.appendChild(lgd);
      fSet.appendChild(ol);
      document.body.appendChild(frag);
      genQA(n, '#qa0');
      /* .insertAdjacentHTML() is .innerHTML on
      || steroids. 
      || Use this for complex layouts and elements that
      || are heavy with attributes
      */
      sec.insertAdjacentHTML('beforeend', "<iframe name='view' src='about:blank' width='100%' height='60%' frameborder='1'></iframe>");
    }

    var genQA = function(n, sel) {
      var dock = document.querySelector(sel);
      /* This is an ES6 Template Literal
      || It's a Literal String with a new powerful
      || syntax:
Wrap - LS: in quotes ' or " | TL: wrap in backticks `
Variables - LS: ' + var + ' | TL: ${var}
2+Lines - LS: + or \[enter] | TL: [enter]
      */
      var cFields = `
	<li class='list-group-item-heading'>
	<textarea id='q${n}' name="q${n}" rows='3' cols='25'></textarea>
	</li>
	<label>True/False</label>&nbsp;&nbsp;<input class='tf checkbox-inline' type='checkbox'>
	
	<ol class='list-group alpha'>
	<li>
	<input id="a${n}_1" name="a${n}_1" type="text" class="input-md" autocomplete="off">
	</li>
	<li>
	<input id="a${n}_2" name="a${n}_2" type="text" class="input-md" autocomplete="off">
	</li>
	<li>
	<input id="a${n}_3" name="a${n}_3" type="text" class="input-md" autocomplete="off">
	</li>
	<li>
	<input id="a${n}_4" name="a${n}_4" type="text" class="input-md" autocomplete="off">
	</li>
	</ol>
	<label id='a${n}' class='btn btn-info ans'>&#65291;</label>
<hr>
`;

      dock.insertAdjacentHTML('beforeend', cFields);

    }
    // Invoked once per session
    base(n);

    /* Referencing form and its form control fields
    || using HTMLFormControlsCollection 
    */
    var form = document.forms[0];
    var field = form.elements;

    /* Register the click event on button#add0
    || invoke addQA() callback function
    */
    field.add0.addEventListener('click', addQA);

    /* Simple callback to generate a QA and 
    || increment counter
    */
    function addQA(e) {
      n++;
      genQA(n, '#qa0');
    }

    /* Register the click event on fieldset#set0
    || invoke the callback function addA()
    */
    field.set0.addEventListener('click', addA);

    function addA(e) {
      // if the node clicked has the .class '.ans'...
      if (e.target.classList.contains('ans')) {
        // Reference e.target by #id
        var tgt = document.getElementById(e.target.id);
        // Get the main index (the number in its #id)
        var idx = parseInt(e.target.id.substring(1), 10);
        // Find the <ol> sibling preceding it (older bro)
        var list = tgt.previousElementSibling;
        /* Get the #id of the <ol>'s child's child
        || element (grandkid)
        */
        var last = list.lastElementChild.lastElementChild.id;
        // Get the last digit of its #id and increment it
        var jdx = parseInt(last.split('_').pop(), 10) + 1;
        /* This is a Template Literal of a list item and
        || input with interpolated #id and [name]
        */
        var li = `<li><input id="a${idx}_${jdx}" name="a${idx}_${jdx}" type="text" class="input-md" autocomplete="off"></li>`;
        // Append new list item to list
        list.insertAdjacentHTML('beforeend', li);
      }
      return false;
    }
  </script>
</body>

</html>

参考

© www.soinside.com 2019 - 2024. All rights reserved.