フォームのinputタグに type=“hidden” の設定された物を可視化するブックマークレットを作ってみました。
hiddenのinput項目は、Chromeとかのデベロッパーツールでエレメントをほじくればわかるのだけど、項目の多いフォームとかでは把握に苦労することも多いですよね。
そんなときに手軽に使えて便利ですよー。
できること
- <input type=“hidden”>の設定されたinputタグエレメントのそばに、その内容を表示するテーブルを生成してくれます。
- ブックマークレットをもう一度実行すると、表示していたテーブルをまとめて削除して元通りになります。
- テーブルのヘッダー行をクリックすると、テーブルを個別に削除できます。
- テーブルにあるデータはにコピペしやすくしています。
- “display: none"が設定されたタグの中に配置されたエレメントにも、ある程度表示対応してます。
- potision: absoluteやfixedでレイヤー重ねされた構造のページでの動作は苦手です。
簡略化すると、こんな感じに見えるようにしてくれます。 こんな感じのHTMLが……
<form>
<input type="hidden" value="大石制作" data-domain="s0014">
</form>
↓↓↓
……こんな感じになります。
<form>
<input type="hidden" value="大石制作" data-domain="s0014.com">
<table>
<thead>
<tr>
<th colspan="2">hidden data</th>
</tr>
</thead>
<tbody>
<tr>
<th>value</th>
<td>大石制作</td>
</tr>
<tr>
<th>data-domain</th>
<td>s0014.com</td>
</tr>
</tbody>
</table>
</form>
実際に生成されるコードはこれにcssやjsが組み込まれているので、もっと複雑です。 害は無いので、詳しくは実際にうごかしてみてください。
以前作ったJavaScriptでフォームに仮入力できるブックマークレットと組み合わせて利用すると、フォームの調査に便利です。
ブックマークレットはこちら
下記リンクをブラウザのブックマークバー等にぐぐっとドラッグして登録してみてください。
動作デモ
仮フォームを用意しました。
上記ブックマークレットをブックマークから実行するか、直接クリックすると、下記フォームのinput="hidden"の埋め込まれた箇所にそのデータの内容が表示されます。
ブックマークレット化前のコード
圧縮前の下のコードはこんな感じです。 ブックマークレットではこれをClosure Compiler Serviceでコンパイルしています。
(() => {
// 挿入するテーブルのクラス
const tableClass = "s0014com-show-hidden-data";
// テーブルのスタイル
const style = {
table: "border-top: 1px solid #666;" +
"border-right: 1px solid #666;" +
"border-bottom: 0;" +
"border-left: 0;" +
"border-spacing: 0;" +
"margin-bottom: .5rem;",
thead: {
th: "background: #666;" +
"border-top: 0;" +
"border-right: 0;" +
"border-bottom: 1px solid #666;" +
"border-left: 1px solid #666;" +
"color: white;" +
"font-size: .7rem;" +
"padding: .1rem;" +
"text-align: center;",
childOfNoDisplay: "background: #eee;" +
"color: black;",
},
tbody: {
th: "background: #999;" +
"border-top: 0;" +
"border-right: 0;" +
"border-bottom: 1px solid #666;" +
"border-left: 1px solid #666;" +
"color: white;" +
"padding: .2rem .5rem;" +
"text-align: left;",
td: "background: white;" +
"border-top: 0;" +
"border-right: 0;" +
"border-bottom: 1px solid #666;" +
"border-left: 1px solid #666;" +
"color: #333;" +
"padding: .2rem .5rem;" +
"text-align: left;",
input: "background: transparent;" +
"border: 0;" +
"color: inherit;" +
"width: 100%",
},
};
// テーブルを表示させている場合は削除
function deleteTables(tables) {
for (let i in tables) {
if(tables.hasOwnProperty(i)){
if(typeof tables[i] === "object") {
tables[i].remove();
}
}
}
}
// parentnoedを検索してdisplay: noneの設定されたエレメントを返す
function findHideParentElms(elm) {
const hideElms = [];
function find(e) {
const parent = e.parentElement;
const parentStyle = window.getComputedStyle(parent);
if (parentStyle.display === "none") {
hideElms.push(parent);
}
if(parent.tagName === "BODY") {
return hideElms;
} else {
return find(e.parentElement);
}
}
find(elm);
return hideElms;
}
function makeTableBody(attributes) {
let tableBody = "";
for (let i in attributes) {
if (attributes.hasOwnProperty(i)) {
const val = attributes[i].value;
const name = attributes[i].name;
if (val === undefined || name === "type") {
continue;
}
const allSelect = "onclick=\"this.select(0,this.value.length)\"";
const thInput = `<input value="${name}" style="${style.tbody.input}" ${allSelect}>`;
const th = `<th style="${style.tbody.th}">${thInput}</th>`;
const tdInput = `<input value="${val}" style="${style.tbody.input}" ${allSelect}>`;
const td = `<td style="${style.tbody.td}">${tdInput}</td>`;
tableBody += `<tr>${th}${td}</tr>`;
}
}
return tableBody;
}
// テーブルを作成
function makeTables() {
const inputs = document.getElementsByTagName("input");
let numOfHiddenInputs = 0;
const insertTables = [];
for (let i in inputs) {
if (Number(i) >= 0 && inputs[i].getAttribute("type") === "hidden") {
const table = document.createElement("table");
table.setAttribute("style", style.table);
table.setAttribute("class", tableClass);
let targetElm;
let tableHeadText = "Hidden data";
let tableHeadStyle = style.thead.th;
const parentHideElms = findHideParentElms(inputs[i]);
if (parentHideElms.length) {
targetElm = parentHideElms.slice(-1)[0];
tableHeadText += "<br>(\"display: none\"の設定されたエレメント内)";
tableHeadStyle += style.thead.childOfNoDisplay;
} else {
targetElm = inputs[i];
}
const theadJsProp = "onclick=\"this.parentElement.remove()\" " +
"onmouseover=\"this.parentElement.style.opacity = 0.5\" " +
"onmouseout=\"this.parentElement.style.opacity = 1\"";
const th = `<th colspan=\"2\" style=\"${tableHeadStyle}\">${tableHeadText}</th>`;
const tableHead = `<thead ${theadJsProp}><tr>${th}</tr></thead>`;
const tableBody = makeTableBody(inputs[i].attributes);
table.innerHTML = tableHead + tableBody;
insertTables.push([targetElm, table]);
numOfHiddenInputs += 1;
}
}
if (numOfHiddenInputs === 0) {
alert(`"type=\"hidden\""の設定されたinputタグが見つかりませんでした`);
} else {
for(let i in insertTables){
const target = insertTables[i][0];
const table = insertTables[i][1];
target.parentElement.insertBefore(table, target.nextSibling);
}
}
}
function main() {
const tables = document.querySelectorAll(`.${tableClass}`);
if (tables.length > 0) {
deleteTables(tables)
} else {
makeTables();
}
}
main();
})();