1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

jQueryでニコニコみたいなタグ追加機構を作る

1
Last updated at Posted at 2017-02-03

結構悩んだ上に笑える落とし穴があったのでメモがてら。

結論から言うと、domを後付けで増やしまくる構造なので、イベント拾うためにちゃんと書かなきゃいけない。
・増やしたボタンは.clickでなく、.on("click",~)で拾う
・増やしたタグの再読み込みもちゃんと考慮すること

使用バージョンは1.11.4。たぶんonが使える1.9以降なら大丈夫。たぶん。
IE11とちょろめで動作確認済み。

html的にこんな感じ。
初期表示分のタグについてはイテレータやらなにやらでちゃんと連番を付けていると想定。

sandbox.html
<script src="./js/sandbox.js"></script>
(略)
<h1>sandbox - タグを編集してみるテスト</h1>
<div id="wrap-tag">
 <div id="tags">
  <span id="1">タグ1</span>
  <span id="2">タグ2</span>
  <span id="3">タグ3</span>
  <span id="4">タグ4</span>
  <span id="5">タグ5</span>
  <span id="6">タグ6</span>
  <span id="7">タグ7</span>
 </div>
</div>

<div class="form-group">
 <button type="button" class="btn btn-default neon" id="edit_btn" value="edit" >編集</button>
</div>

<div id="tagform"></div>

見え方
sandbox - タグを編集してみるテスト
タグ1 タグ2 タグ3 タグ4 タグ5 タグ6 タグ7

編集(ボタン)

で、jQuery側。エラー処理とかは結構適当なので適宜どうぞ。

sandbox.js

$(document).ready(function(){
	console.log("sandbox page is loaded.");

	// IEは悪い文明!粉砕する!(
	Number.isNaN = Number.isNaN || function(any) {
	  return typeof any === 'number' && isNaN(any);
	};

	// 編集ボタン押下時
	$(".form-group").on("click", "#edit_btn", function(){
		var val = $(this).val();
		console.log('clicked', val);
		if(val == "edit"){
			$('#tags span').each(function(){
				$(this).append("<button type=\"button\" class=\"btn btn-default neon\" id=\"delete_btn\" value=\"" + this.id + "\" >削除</button>");
			});
			$('#edit_btn').text("編集完了");
			$('#edit_btn').val("end_edit");
			var form = $("<form>").attr({"class":"tageditform","action":"#"}),
			input = $("<input>").attr({"class":"tageditinput","type":"text"});
			$(form).append(input).append("<button type=\"button\" class=\"btn btn-default neon\" id=\"insert_btn\" value=\"add\" >追加</button>").appendTo($("#tagform"));

			// 追加ボタン押下時 編集ボタン押下後の単発部分に書かないと多重処理になることに注意
			$(document).on("click", "#insert_btn", function(){
				var id = parseInt($('#tags span:last').attr("id"));
				var addid = Number.isNaN(id) ? 1 : (id + 1) ;
				var addtag = $(".tageditinput").val();
				console.log('clicked add', addid, addtag);
				if(addtag != ""){
					$('#tags').append("<span id=\"" + addid + "\">" + addtag + "<button type=\"button\" class=\"btn btn-default neon\" id=\"delete_btn\" value=\"" + addid + "\" >削除</button></span>");
				}
			});

			// 削除ボタン押下時
			$(document).on("click", "#delete_btn", function(){
				var delval = $(this).val();
				console.log('clicked delete', delval);
			    $(this).parents("#tags span").remove();
			});
		}
		else if(val == "end_edit"){
			// 編集完了処理
			console.log('DB更新処理とかしたり');
		}
	});
});

ajaxでDBと連携するなら追加時適宜でも通信する方がよいかも知れない。とりあえず見た目実装。

引っ掛かったポイント

$(#delete_btn).click(function(){ ~(略
よくあるボタンの書き方だけど、これでやると最初に作ってないせいでボタンが有効にならないケースが出たりする。

その他凡ミス:数え切れないほど エスケープ漏れとか(書き方変えろ説

もっと楽な書き方とかプラグインがあればいいんだけど、とりあえず強引すぎる力技でなんとかした系。たぶん。
(こっちは環境的にプラグイン入れられなけど)。

追記:NaNパターン消し忘れてたのでちょっとだけ修正

追記2:余りにコードが汚過ぎたのできれいにしてみた版。

sandbox.js
$(document).ready(function(){

	console.log("sandbox page is loaded.");

	// IE死すべし慈悲はない(どう見ても慈悲
	Number.isNaN = Number.isNaN || function(any) {
	  return typeof any === 'number' && isNaN(any);
	};

	var append_html = function(target, add_html){
		target.append(add_html);
	}

	var add_form = function(target){
		var form = $("<form>").attr({"class":"tageditform","action":"#"}),
		input = $("<input>").attr({"class":"tageditinput","type":"text"}),
		button_html = '<button type="button" class="btn btn-default neon" id="insert_btn" value="add" >追加</button>';
		$(form).append(input).append(button_html).appendTo(target);
	}

	var press_add = function(){
		var id = parseInt($('#tags span:last').attr("id")),
		addid = Number.isNaN(id) ? 1 : (id + 1) ,
		addtag = $(".tageditinput").val();
		console.log('clicked add', addid, addtag);
		if(addtag != ""){
			var add_html = '<span id="' + addid + '">' + addtag + '<button type="button" class="btn btn-default neon" id="delete_btn" value="' + addid + '" >削除</button></span>',
			target = $('#tags');
			append_html(target, add_html);
		}
	}
	var press_del = function(own){
		var delval = own.val();
		console.log('clicked delete', delval);
		own.parents("#tags span").remove();
	}

	var press_edit = function(own){
		var val = own.val();
		console.log('clicked', val);
		if(val == "edit"){
			$('#tags span').each(function(){
				var add_html = '<button type="button" class="btn btn-default neon" id="delete_btn" value="' + this.id + '" >削除</button>',
				target = $(this);
				append_html(target, add_html);
			});
			own.text("編集完了");
			own.val("end_edit");

			// フォーム要素を追加する
			var target = $("#tagform");
			add_form(target);

			// 追加ボタン押下時 編集ボタン押下後の単発部分に書かないと多重処理になることに注意
			$(document).on("click", "#insert_btn", function(){
				press_add();
			});

			// 削除ボタン押下時
			$(document).on("click", "#delete_btn", function(){
				var own = $(this);
				press_del(own);
			});
		}
		else if(val == "end_edit"){
			// 編集完了処理
			console.log('ajaxで実際に更新処理投げたりとか');
		}
	};

	// 編集ボタン押下
	$(function(){
		$(".form-group").on("click", "#edit_btn", function(){
			var own = $(this);
			press_edit(own);
		})
	});
});
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?