フォームの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"の内容を表示

動作デモ

仮フォームを用意しました。

上記ブックマークレットをブックマークから実行するか、直接クリックすると、下記フォームのinput="hidden"の埋め込まれた箇所にそのデータの内容が表示されます。

なにも送信しないフォーム

項目1


項目2


項目3


ブックマークレット化前のコード

圧縮前の下のコードはこんな感じです。 ブックマークレットではこれを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();

})();