20708
以下のようにCMSのようなものを作っているのですが、id="ul"の内部にある「消す」や「追加する」のところだけ、javascriptが効きません。どのようにしたら、動きますでしょうか。  
詳しい方、ご教示頂けると幸いです。

```

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>記事投稿画面</title>
    </head>
    <body>
        <div id="container">
            <h1>記事の投稿画面</h1>
            <form id="form" method="post" name="insert" action="" enctype="multipart/form-data">    
                <ul>
                    <ul id="ul" >
                        <li class="button menu"><a id="title" class="btn_group" onclick="onClick('title')">大見出し</a></li>
                        <li class="button menu"><a id="h3" class="btn_group" onclick="onClick('h3')">中見出し</a></li>
                        <li class="button menu"><a id="img" class="btn_group"onclick="onClick('img')">画像</a></li>
                        <li class="button menu"><a id="text" class="btn_group" onclick="onClick('text')">テキスト</a></li>
                        <li><input type="hidden" name="type[]" value="text"><textarea name="content[]" style="width:400px;height:300px;"></textarea><a style="margin:10px;" class="del">消す</a><a style="margin:10px;" class="edit">追加する</a></li>
    <li><input type="hidden" name="type[]" value="text"><textarea name="content[]" style="width:400px;height:300px;"></textarea><a style="margin:10px;" class="del">消す</a><a style="margin:10px;" class="edit">追加する</a></li>
                    </ul>
                <li><input type="submit" value="Submit" id="senddiv"></li>
                </ul>
            </form>
        </div><!--.container-->
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
        <script>
            function getHtmlByType(type) {
                if(type == 'title'){
                    var html = '<input type="hidden" name="type[]" value="title"><input name="content[]' + '" type="text" placeholder="大見出し" style="width:400px;height:20px;margin-top:10px;"><a style="margin:10px;" class="del">消す</a><a style="margin:10px;" class="edit">追加する</a>';
                }
    
                if(type == 'h3'){
                    var html = '<input type="hidden" name="type[]" value="h3"><input name="content[]' + '" type="text" placeholder="中見出し" style="width:400px;height:20px;margin-top:10px;"><a style="margin:10px;" class="del">消す</a><a style="margin:10px;" class="edit">追加する</a>';
                }
    
                if(type == 'img'){
                    var html = '<input type="hidden" name="type[]" value="img"><input name="content[]' + '" type="text" placeholder="参照画像のURL" style="width:400px;height:20px;margin-top:10px;"><a style="margin:10px;" class="del">消す</a><a style="margin:10px;" class="edit">追加する</a>';
                }
    
                if(type == 'text'){
                    var html = '<input type="hidden" name="type[]" value="text"><textarea name="content[]' + '" style="width:400px;height:300px;"></textarea><a style="margin:10px;" class="del">消す</a><a style="margin:10px;" class="edit">追加する</a>';  
                }
    
                return html;
            }
    
            function bindEvents(elem) {
                $('a.del', elem).on('click', function() {
                    elem.remove();
                });
                $('a.edit', elem).on('click', function() {
                    var aa=$('<ul class="new_elem"><li class="button menu"><a class="title btn_group">大見出し</a></li><li class="button menu"><a class="h3 btn_group">中見出し</a></li><li class="button menu"><a class="img btn_group" >画像</a></li><li class="button menu"><a class="text btn_group">テキスト</a></li></ul>');
                    aa.insertAfter(elem);
    
                    $('a.title', aa).on('click', function() {
                        aa.remove();
                        aa = $('<li>'+getHtmlByType('title')+'</li>');
                        aa.insertAfter(elem);
                        bindEvents(aa);
                    });
                    $('a.h3', aa).on('click', function() {
                        aa.remove();
                        aa = $('<li>'+getHtmlByType('h3')+'</li>');
                        aa.insertAfter(elem);
                        bindEvents(aa);
                    });
                    $('a.img', aa).on('click', function() {
                        aa.remove();
                        aa = $('<li>'+getHtmlByType('img')+'</li>');
                        aa.insertAfter(elem);
                        bindEvents(aa);
                    });
                    $('a.text', aa).on('click', function() {
                        aa.remove();
                        aa = $('<li>'+getHtmlByType('text')+'</li>');
                        aa.insertAfter(elem);
                        bindEvents(aa);
                    });
                 });
            }
    
            function onClick(type){
                var html = getHtmlByType(type);
                var elem = $('<li>'+html+'</li>');
                $('#ul').append(elem);
    
                bindEvents(elem);    
            }
        </script>
    </body>
    </html>
    
```
CC BY-SA 3.0
2016-01-07T07:01:59.447
20705
2019-12-13T19:18:00.160
2016-01-07T09:57:35.057
8619
8619
question
javascript
javascriptに関する質問
「消す」「追加する」にイベントが設定されていないからではないでしょうか。

JavaScriptの関数をHTML要素にひもづけるには、HTMLタグに`onclick`属性で指定するか、JavaScriptの`onclick`や`addEventListener`を利用する必要があります。

「大見出し」「中見出し」には`onclick`属性で`onClick`関数がひもづけられていますが、「消す」「追加する」にはそれがありません。また、JavaScript部分でもイベントは設定されていないようです。

```

    <!-- onclick属性がある -->
    <a id="title" class="btn_group" onclick="onClick('title')">大見出し</a>
    <a id="h3" class="btn_group" onclick="onClick('h3')">中見出し</a>
    
    <!-- onclick属性がない -->
    <a style="margin:10px;" class="del">消す</a>
    <a style="margin:10px;" class="edit">追加する</a>
    
```

ただ、イベント設定用の関数は作られているようなので、JavaScript部分の最後に次の処理を足すと動くと思います。

```

    !function() {
      var elem = $("#ul > li:last-child");
    
      bindEvents(elem);
    }();
    
```

イベントをひもづけたい要素が複数存在する場合は、次のように書くと良いと思います。

```

    !function() {
      var elem = $("#ul > li:not(.menu)");
    
      bindEvents(elem);
    }();
    
```

実際に確認していないのでもし動かなければ以下も試してみてください。

```

    !function() {
      var elem = $("#ul > li:not(.menu)");
    
      $elem.each(function() {
        bindEvents($(this));
      });
    }();
    
```

上記のコードは変数`elem`を宣言しているにも関わらず`$elem`を利用しようとしているため動きません。  
以下検証用のスニペットと修正したコードを追記します（といっても`$`を消しただけですが。。。すみません。。。）。

```

    function getHtmlByType(type) {
      var html = '<input type="hidden" name="type[]" value="' + type + '">';
    
      if (type == 'title') {
        html += '<input name="content[]" type="text" placeholder="大見出し" style="width:400px;height:20px;margin-top:10px;">';
      }
      if (type == 'h3') {
        html += '<input name="content[]" type="text" placeholder="中見出し" style="width:400px;height:20px;margin-top:10px;">';
      }
      if (type == 'img') {
        html += '<input name="content[]" type="text" placeholder="参照画像のURL" style="width:400px;height:20px;margin-top:10px;">';
      }
      if (type == 'text') {
        html += '<textarea name="content[]" style="width:400px;height:300px;"></textarea>';
      }
    
      html += '<a style="margin:10px;" class="del">消す</a><a style="margin:10px;" class="edit">追加する</a>';
    
      return html;
    };
    
    function bindEvents(elem) {
      $('a.del', elem).on('click', function() {
        elem.remove();
      });
    
      $('a.edit', elem).on('click', function() {
        var aa = $('<ul class="new_elem"><li class="button menu"><a class="title btn_group">大見出し</a></li><li class="button menu"><a class="h3 btn_group">中見出し</a></li><li class="button menu"><a class="img btn_group" >画像</a></li><li class="button menu"><a class="text btn_group">テキスト</a></li></ul>');
    
        aa.insertAfter(elem);
    
        $('a.title', aa).on('click', function() {
          aa.remove();
    
          aa = $('<li>' + getHtmlByType('title') + '</li>');
          aa.insertAfter(elem);
    
          bindEvents(aa);
        });
    
        $('a.h3', aa).on('click', function() {
          aa.remove();
    
          aa = $('<li>' + getHtmlByType('h3') + '</li>');
          aa.insertAfter(elem);
    
          bindEvents(aa);
        });
    
        $('a.img', aa).on('click', function() {
          aa.remove();
    
          aa = $('<li>' + getHtmlByType('img') + '</li>');
          aa.insertAfter(elem);
    
          bindEvents(aa);
        });
    
        $('a.text', aa).on('click', function() {
          aa.remove();
    
          aa = $('<li>' + getHtmlByType('text') + '</li>');
          aa.insertAfter(elem);
    
          bindEvents(aa);
        });
      });
    };
    
    function onClick(type) {
      var html = getHtmlByType(type);
      var elem = $('<li>' + html + '</li>');
    
      $('#ul').append(elem);
    
      bindEvents(elem);
    };
    
    ! function() {
      var elem = $("#ul > li:not(.menu)");
    
      elem.each(function() {
        bindEvents($(this));
      });
    }();
```

```

    <div id="container">
      <h1>記事の投稿画面</h1>
      <form id="form" method="post" name="insert" action="" enctype="multipart/form-data">
        <ul>
          <ul id="ul">
            <li class="button menu">
              <a id="title" class="btn_group" onclick="onClick('title')">大見出し</a>
            </li>
            <li class="button menu">
              <a id="h3" class="btn_group" onclick="onClick('h3')">中見出し</a>
            </li>
            <li class="button menu">
              <a id="img" class="btn_group" onclick="onClick('img')">画像</a>
            </li>
            <li class="button menu">
              <a id="text" class="btn_group" onclick="onClick('text')">テキスト</a>
            </li>
            <li>
              <input type="hidden" name="type[]" value="text">
              <textarea name="content[]" style="width:400px;height:300px;"></textarea>
              <a style="margin:10px;" class="del">消す</a>
              <a style="margin:10px;" class="edit">追加する</a>
            </li>
            <li>
              <input type="hidden" name="type[]" value="text">
              <textarea name="content[]" style="width:400px;height:300px;">
                </textarea><a style="margin:10px;" class="del">消す</a>
              <a style="margin:10px;" class="edit">追加する</a>
            </li>
          </ul>
          <li>
            <input type="submit" value="Submit" id="senddiv">
          </li>
        </ul>
      </form>
    </div>
    <!--.container-->
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
```

```

    !function() {
      var elem = $("#ul > li:not(.menu)");
    
      elem.each(function() {
        bindEvents($(this));
      });
    }();
    
```

念の為補足しておきます。

```

    var elem = $("#ul > li:not(.menu)");
    
```

この部分ですが、

> `id`に`ul`が指定されている要素の子要素で、かつ`class`が`menu`ではない`li`要素

を取得しています（ややこしいですが）。  
つまり、現状のHTMLの構造に対する依存性が高く、HTMLの構造が変わると簡単に動作しなくなってしまいます。

もし将来的にHTMLを書き換えてコードが動かなくなったら、HTMLの構造とjQueryのセレクタがマッチしていない可能性を疑ってみてください。
CC BY-SA 4.0
2016-01-07T08:04:58.833
20708
2019-12-13T19:18:00.160
2019-12-13T19:18:00.160
32986
13493
20705
answer