質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

3回答

16634閲覧

datalistタグの子要素optionタグに仕込んだ自作の属性をgetAttributeしたいができない

true

総合スコア440

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2015/08/17 07:31

編集2015/08/17 14:16

html5から使用できるようになったdatalistタグによるサジェストリストですが、optionタグに仕込んだ自作の属性fidをgetAttributeできません。

select タグを使った場合はvalue部分とテキスト部分に分けられたので見せたくない情報はvalue=に入れればよかったんですがdatalistの場合はそれができないので自分で属性を作ってgetAttributeで取得、と思ってやったのですが得られません。

ご存知のかた、よろしくお願い致します。

ブラウザはchrome バージョン 44.0.2403.125 (64-bit)

<html> <head> <meta charset="utf-8"> <script type="text/javascript"> function show() { // var fid = document.getElementById("fruits").getAttribute("fid"); // var fid = document.getElementById("keywords").childNodes[0].getAttribute("fid"); // var fid = document.querySelector("fid"); // fidの値を取得したいがうまくいかない・・ alert(fid); } </script> </head> <body> <input type="search" autocomplete="on" list="keywords" id="fruits"> <datalist id="keywords"> <option fid="1" value="みかん"> <option fid="2" value="ぶどう"> <option fid="3" value="ばなな"> </datalist> <input type="button" onclick="show();" value="表示"> </body> </html>

補足:用途はたくさんある候補からひとつ選ばせ、たとえばそれを削除したり、何かしらの登録をやるといった具合です。その際、DB上でユニークなのはidだけという設定です(no や nameは重複の余地を残している)。

test.php

1<?php 2$db = new PDO("sqlite:test.db"); 3/* 初期設定 */ 4$sql = "CREATE TABLE IF NOT EXISTS fruits (id INTEGER PRIMARY KEY AUTOINCREMENT, no INTEGER, name TEXT)"; 5$stmt = $db->prepare($sql); 6$stmt->execute(); 7$stmt = $db->query("SELECT COUNT(*) FROM fruits"); 8/* サンプルデータ投入 */ 9$count = $stmt->fetchColumn(); 10if ($count == 0) { 11 $fruits = ["みかん", "ぶどう", "ばなな"]; 12 $i = 1; 13 $db->beginTransaction(); 14 foreach ($fruits as $fruit) { 15 $db->exec("INSERT INTO fruits (no, name) VALUES ($i, '$fruit')"); 16 $i++; 17 } 18 $db->commit(); 19} 20/* 初期表示 */ 21if (isset($_GET["func"]) && $_GET["func"] == "init") { 22 $stmt = $db->query("SELECT * FROM fruits ORDER BY no"); 23 $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); 24 $json = json_encode($rows); 25 echo $json; 26 $db = null; 27 exit(); 28/* たとえば削除 */ 29} else if (isset($_POST["func"]) && $_POST["func"] == "postDB") { 30 $id = $_POST['id']; 31 $no = $_POST['no']; 32 $sql = "DELETE FROM fruits WHERE no = $no"; 33 $stmt = $db->prepare($sql); 34 $stmt->execute(); 35} 36$db = null; 37?> 38<html> 39<head> 40<meta charset="utf-8"> 41<script type="text/javascript"> 42 43Ajax = new XMLHttpRequest(); 44 45window.onload = init(); 46 47function init() { 48 var url = "test.php" + "?dummy=" + new Date().getTime() + "&func=" + "init"; 49 Ajax.open("GET", url, true); 50 Ajax.send(null); 51 Ajax.onreadystatechange = function() { 52 if (Ajax.readyState == 4 && Ajax.status == 200) { 53 var rows = JSON.parse(Ajax.responseText); 54 var out = "<input type='search' autocomplete='on' list='keywords' id='fruits'>"; 55 out += "<datalist id='keywords'>"; 56 /* 本来このなかにrows[i]['id']があって、それを拾えるようにしたいが表示させたくはない */ 57 for (var i in rows) { 58 out += "<option value='"+rows[i]['no']+"/"+rows[i]['name']+"'>"; 59 } 60 out += "</datalist>"; 61 out += "<input type='button' onclick='postDB();' value='送信'>"; 62 document.getElementById("result").innerHTML = out; 63 } 64 } 65} 66/* idをDBへ投げる */ 67function postDB() { 68 var name = document.getElementById('fruits').value; 69 var i = name.indexOf("/"); 70 var no = name.substr(0,i); 71 // var id = "" 本来これを取得して投げたいができないので代わりにほかのものを投げる 72 var id = 0; // エラー回避のためのダミー 73 var url = "test.php"; 74 Ajax.open("POST", url, true); 75 Ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 76 Ajax.send("func=" + "postDB" + "&id=" + id + "&no=" + no); 77 Ajax.onreadystatechange = function() { 78 if (Ajax.readyState == 4 && Ajax.status == 200) { 79 init(); 80 } 81 } 82} 83</script> 84</head> 85<body> 86<div id="result"></div> 87</body> 88</html> 89

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

まず、input要素datalist要素 の DOM プロパティを覚えると良いと思います。

JavaScript

1console.log(document.getElementById('fruits').list.options[0].getAttribute('fid')); // 1

true さんの目的はこれで達成できましたが、"fid" のようなカスタム属性を定義する為に HTML5 では data-* 独自属性が用意されています。
HTML5 では不明な属性(fid属性)は無視する仕様ですが、今後 fid 属性が定義されると問題になるので data-* 独自属性を使うことをお勧めします。

JavaScript

1// 参考URL: http://jsfiddle.net/5nfufwdh/2/ 2console.log(document.getElementById('fruits').list.options[0].dataset,fid); // 1

ところで、input[type=search] は list 属性で入力補完した場合もテキスト入力ボックスとして機能します。
例えば、datalist から "バナナ" を選択した後に "バナナカフェ" に変更したり、"チョコバナナ" に改変することも可能です。
このように自由入力可能な情報に対して <option fid="1" value="みかん"> で対応関係を作る事に意味を見出せるのか、という疑問は残りますが、実際の用途が見えないので何ともいえないところです。
厳密にリストから選択させるのであれば、ユーザの改変の余地が発生しない select 要素が望ましいとは思うのですが。

投稿2015/08/17 12:45

think49

総合スコア18156

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

true

2015/08/17 14:11

ありがとうございます。候補がたくさんあってかつ連続的な入力作業を想定しているのでセレクトは使わない方針です。カスタム属性の使用に関する情報は知らなかったので大変参考になりました。気をつけたいと思います。
think49

2015/08/17 14:33

差し支えなければ、教えていただきたいのですが、fid は具体的にどのような処理に使われるものなのでしょうか。 実際に送信されるのは input#fruits の値であり、datalist は補完的存在と認識していたので fid の用途については不思議に思っていました。
true

2015/08/17 14:55

fidはselectタグを使った場合のvalue=に相当するものだと思っています。 <select id="hoge"> <option value="xxx">xxx</option> </select> これならvalueの部分にfidを入れれば、fidを画面に表示せず、fidをサーバーに送れます。しかし、datalistの場合、 <option value="xxx">しかなく、fidを仕込みようがないなあと思っています。そして仕方なくカスタム属性を使って <option fid="xxx" value="xxx">といった形にしたうえでgetAttrしようと企んだのですがつまづいているということです。 追加サンプルでは本来fid(DB上ではid)を送りたいのですが送れないのでかわりのものを送っていますがわかりにくかったら申し訳ありません。 <option fid="xxx" value="xxx" onchange="funcA();"> とかで捕捉しようとしましたがそれも効かないのでとりあえずDB上の設計でnoやnameをユニークにしちゃおうかと思っています。そうすればもうidは捕まえる必要はなくなりますので。
think49

2015/08/17 16:33 編集

<datalist> は有体にいえば、単純な入力補完機能です。オートコンプリートとかサジェスト機能と呼ばれるものと同じです。 そこにユニークな fid の意味を持たせたいのなら <datalist> を使うべきではありません。 http://fiddle.jshell.net/5nfufwdh/5/show/light/ このフォームで送信が期待されるのは "fruits=みかん" であり、datalist の値は送信されません。 送信されるのはあくまで input[list=keywords] である事に注目してください。 datalist の内容は fid は元より、value 値すらも送信されません。 id を機械的に検出するなら input#fruits の value 値から ["みかん", "ぶどう", "バナナ"] と一致するかを検出すれば良いですが、そうするぐらいなら初めから select 要素を使えば良いという事になってしまいます。 仮に機械的に検出するにしてもその処理が必要なのは PHP の方であり、JavaScript は補助的なものです(JavaScript は容易に無効化できる事から、フォーム送信のバリデートを JavaScript に依存すべきではありません)。
true

2015/08/17 23:38

結局、id を仕込むことをやめ、no と name の組み合わせを一意のものとするような設計にしました(たとえばユーザーが新規アイテムを登録するときにすでに同一のno、nameの組み合わせがあったら弾くといったような)。今回はDOM操作でいろいろと学ぶところがあり、貴重なアドバイスをありがとうございました。
guest

0

全く別のやり方ですが、連想配列を使って似たようなことができます。

lang

1<html> 2<head> 3<meta charset="utf-8"> 4<script type="text/javascript"> 5var datalist = {'みかん':1,'ぶどう':2,'ばなな':3}; 6function load() { 7 for (var data in datalist) { 8 var option = document.createElement('option'); 9 option.id = datalist[data]; 10 option.value = data; 11 document.getElementById("keywords").appendChild(option); 12 } 13} 14 15function show() { 16 var text = document.getElementById('fruits').value; 17 if(text in datalist) { 18 alert(datalist[text]); 19 }else{ 20 alert('候補以外'); 21 } 22} 23</script> 24</head> 25<body onLoad="load()"> 26<input type="search" autocomplete="on" list="keywords" id="fruits"> 27<datalist id="keywords"> 28</datalist> 29<input type="button" onclick="show();" value="表示"> 30</body> 31</html>

投稿2015/08/17 08:47

sho_cs

総合スコア3541

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

true

2015/08/17 14:15

ありがとうございます。期待通りの動作を得ることが出来ました。もう少し自分でも考えてみたいと思います。連想配列の利用(オブジェクト?)は大変参考になりました。
guest

0

childNodes を使った場合、改行コードもノードの1つに数えられてしまうようです
ですので
<datalist id="keywords">
の末尾にある改行を先頭ノードとして数えると

javascript

1function show123() { 2 var elms = document.getElementById("keywords").childNodes; 3 console.log( elms[1].getAttribute("fid") ); // 0 4 console.log( elms[2].getAttribute("fid") ); // 1 5 console.log( elms[3].getAttribute("fid") ); // 2 6}

で取り出せると思います

別の方法として単純にタグ名でoption要素を抜き出すとか

javascript

1function show123() { 2 var elms = document.getElementById("keywords").getElementsByTagName("option"); 3 console.log( elms[0].getAttribute("fid") ); // 1 4}

以上ご参考までに

投稿2015/08/17 08:29

takito

総合スコア3111

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

true

2015/08/17 14:13

ありがとうございます。childNodesで最初のオプションしか拾えなかったのでなんでかなあと悩んでいたんですが(当たり前といえばそうですが)、その疑問点は解決しました。ただ、この動作を動的にやりたいと思っています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問