Natural Intelligence による記事要点まとめ
・JavaScript を使えば URL のパラメータを取得できる。
・日本語のパラメータはエンコードされてしまう。
・自身でエンコードすれば設定によらずデコードできる。
JavaScript を用いて URL に付けられたパラメータを取得するテストです。
下記に示すリンクをクリックするか、このページの URL にパラメータを指定すると、 JavaScript で解析された様子が、この下に表示されます。
※ 表示が正しくないと思う場合は、JavaScript を有効にしてください。
パラメータなしの場合
js-getparam.html
js-getparam.html?
パラメータとして、name と favorite を欲しいとします。
キーおよび値が英数字の場合、期待通り name と favorite が解析されます。
js-getparam.html?name=Tom&favorite=vegetables
不要なパラメータが指定されている場合、あるいは欲しいパラメータが不足している場合でも、期待通り name と favorite が解析されます。
js-getparam.html?name=Tom&favorite=organic foods&age=43
js-getparam.html?name=Tom&age=43&team=TB
値に日本語が混ざると、うまくいきません(パラメータがエンコードされています)。
このページの Content-Type が charset=shift_jis だからかも知れません。
js-getparam.html?name=トム&favorite=パスタ
js-getparam.html?name=Mike&favorite=チーズ
日本語を自分でエンコードして URL を生成すると、デコードできます。
name :
favorite :
生成されたリンクが、ここに表示されます。
取得したパラメータ(name と favorite)が、ここに表示されます。
取得したパラメータ(キー名自由)が、ここに表示されます。
解析中のデータが、ここに表示されます。
URL に加えられているパラメータを取得し、解析できるまで準備します。
ブラウザのアドレスバーに表示される URL には、?マークのあとにパラメータを指定できます。
例;js-getparam.html?name=John&age=25
それを JavaScript で解析し、何らかの処理を行えれば便利です。
解析途中の情報も出力していますので、どのような指定がどういう具合で解析されるか、確認できます。
現時点でのテスト済みブラウザは、
です。
スマホやタブレットで開く場合は、
https://www.straightapps.com/web/js-getparam.html
)
投稿 October 30, 2020
ここから先は、上記、URL パラメータ取得プログラム開発を行った際に調べたりした JavaScript コードについての情報です。
まずは、HTML 部です。 ※ ただリンクを置いてある部分は省略しています。
パラメータに日本語を入力した場合のリンク部分です。
日本語が混じると、うまくいきません(パラメータがエンコードされています)。<br> このページの Content-Type が charset=shift_jis だからかも知れません。<br> <a href="js-getparam.html?name=トム&favorite=パスタ" class="indent30">js-getparam.html?name=トム&favorite=パスタ</a><br> <a href="js-getparam.html?name=マイク&favorite=チーズ" class="indent30">js-getparam.html?name=Mike&favorite=チーズ</a><br>
これも単なるリンクではありますが、Chrome のステータスバーに表示されるリンク先は、 日本語(全角カタカナ)になっていませんので、特別に書いています。
自動的にエンコードされていますが、
unescape、decodeURI、decodeURIComponent のいずれでも戻せませんでした。
上に書いている通り、このページが
次は自由に値を指定してリンクを作成する部分です。
日本語を自分でエンコードして URL を生成すると、デコードできます。<br> <span class="indent30"/>name : <input type="text" id="iname"><br> <span class="indent30"/>favorite : <input type="text" id="ifavorite"><br> <button onclick="link()" title="リンクを作成する" class="indent30"> リンクを作成する </button><br> <span id="link" class="indent30">生成されたリンクが、ここに表示されます。</span>
name キーと favorite キーの自由入力欄を用意し、 「リンクを作成する」ボタンが押されたとき、 JavaScript の link 関数を呼び出して、その下に、生成したリンクを表示します。 生成されたリンクをクリックすることにより、いろいろなパターンを試すことができます。
なお、indent30 は自分で用意した字下げの css です。 表示のためだけですので、動作には影響ありません。
この先は、解析されたパラメータや途中経過を表示するための領域を用意している部分です。
<span class="darkred">取得したパラメータ(name と favorite)が、ここに表示されます。</span><br> <span id="param" class="mkB"></span> <span class="darkred">取得したパラメータ(キー名自由)が、ここに表示されます。</span><br> <span id="param2" class="mkB"></span> <span class="darkred">解析中のデータが、ここに表示されます。</span><br> <span id="data" class="mkPink"></span> <script type="text/javascript" src="js/getparam.js"></script>
解析された情報の出力欄を用意しています。 グレーになっている class の部分、darkred は暗い赤文字、mkB は薄い青網掛け、mkPink はピンクの網掛けをする貯めに用意した css です。 指定しなくて構いません。
span id="param" の部分には、 パラメータにあるキー名が name と favorite とわかっている場合の、 連想配列に値を設定したときの結果を表示します。
span id="param2" の部分には、 パラメータに書かれるキー名が決まっていないかわからない場合の結果を表示します。
span id="data" の部分には、 解析途中の経過を表示します。
ここまでで表示を更新する部分がすべて定義されたので、JavaScript を読み込んで、 URL にあるパラメータを解析、結果を表示しています。
以降のセクションで、それぞれ詳細を確認していきます。
なお、ご参考までに、JavaScript ソースコードそのものを、拡張子 js を拡張子 txt に変えて、次のリンクより開けるようにしてあります。
getparam.txt
※ 作成時はタブを4文字としていますので、環境によってはタブが8文字のため、
コメント等がずれて見えるかも知れません。
※ 念のため書き添えますが、このソースコードをこのまま転載・公開することはご遠慮ください。
なお、本サイトのご利用に際しては、必ずプライバシーポリシー(免責事項等)をご参照ください。
投稿 October 30, 2020
body が読み進まれていき、script の行まで到達すると、src で指定されたファイルが読み込まれます。
<script type="text/javascript" src="js/getparam.js"></script>
すべての処理は、この getparam.js にて実行されています。 一般的には </body> の直前でいいようですが、 このページでは、読みにくくならないように、 必要なすべての HTML 要素の定義が終わった直後に置いています。
getparam.js の先頭部分は、次のような流れになっています。
//---------------------------------------- // ページの読み込みが完了したら処理します window.onload = function () { jsPutTopics('js-getparam'); // 内容については、このあと参照します。 }
関数の定義になっていない、 つまり読み込み時に実行されるのはこの部分だけです。 これよりあとの関数定義は、この部分から呼び出されるものとなっています。
この部分では、ブラウザのロード処理が完了したら、 ここに定義されている onload 時の無名関数が実行されます。 無名関数とは、関数名が省略されたもので、 関数を別に書いて呼び出す代わりに、必要な場所に直接書く、という形です。 そしてこの関数が終了すると、JavaScript の処理が終了となります。
あとから気付いたことですが、
この関数の中身は、次のように2つの部分で構成されています。
let str = "パラメータはありません。"; let param = GetQueryString(); if (param != null){ str = "name = " + param["name"]; str += "<br/>favorite = " + param["favorite"]; } let elem = document.getElementById("param"); elem.innerHTML = str;
1つ目は、欲しいパラメータが name と favorite であることが 事前に決められている場合の解析です。
変数 str は、span id="param" に表示する文字列です。 パラメータがない場合に備えて、「パラメータはありません。」と設定しています。 パラメータがあれば、このあと書き換えます。
解析関数 GetQueryString を呼び出し、結果を param で受け取ります。 パラメータがなかった場合は param が null になりますので、 if 文を通らず、このまま str、「パラメータはありません。」と表示して完了とします。
パラメータがあった場合には、param には連想配列というものが返されます。 連想配列とは、配列ではあるのですが、 インデックスに数字ではなく文字列を指定できるもののようです。
上記コードを見るとわかるように、普通の配列なら param[ 0 ] のように参照しますが、 連想配列の場合は、1次元の配列 param に対して、インデックス指定を文字列で、 param["name"] のように参照できるということです。 正確ではありませんが、C/C++ で言えば、"name" が enum で数字に置き換えられている、というイメージと思います。
このことより、str には、name キーの値と favorite キーの値が設定され、 span id="param" に表示されることになります。
同時に、name あるいは favorite キーがなかった場合の様子なども、確認することができます。
str = "パラメータはありません。"; param = GetQueryString2(); if (param != null){ str = ""; for (let i = 0; i < param.length; i ++){ if ( i > 0 ){ str += "<br/>"; } str += param[i].paramName + " = " + param[i].paramValue; } } elem = document.getElementById("param2"); elem.innerHTML = str;
2 つ目は、欲しいパラメータが未定義か、わからない場合の解析です。
変数 str を再初期化したあと、GetQueryString2 関数を呼び出します。 結果を param で受け取りますが、上記同様、パラメータがなかった場合は null が返されますので、 if 文を通らず、このまま str、「パラメータはありません。」と表示して完了とします。
パラメータがあった場合には、param には1次元の Object 配列が返されます。 Object 型の変数が1次元配列の各要素に設定されたものです。 要素数は for ループで参照しているように、param.length プロパティに入っています。 つまり、パラメータにはこの数だけ、キーが含まれていた、ということになります。
可変サイズの 1 次元配列の取り扱いについては、 「素因数分解トレーニング」の 「【基礎】可変サイズの配列と操作」をご覧ください。 また、オブジェクトについては、同「【基礎】Object 型の変数の使い方」をご覧ください。
if 文の中では、戻された配列の要素数 param.length だけループし、 str にキー名 paramName とその値 paramValue をペアで追記しています。
最後に span id="param2" に出力して、完了です。 1 行に 1 つの組み合わせで、& でつながれたパラメータがあればあるだけ、表示されます。
投稿 October 31, 2020
URL パラメータを解析し、連想配列を返す関数 GetQueryString を見ていきます。 どんなパラメータが指定されるのか、あらかじめ決まっている、わかっている場合に便利そうです。
function GetQueryString() { let elem = document.getElementById("data"); elem.innerHTML = "document.location.search = [" + document.location.search + "]"; // パラメータがないか、"js-getparam.html?" の場合 if (document.location.search.length < 2) { return null; }
まず elem に、途中経過を表示する領域 span id="data" を取得します。 そしてすぐ、document.location.search を出力しています。 これは、? 記号以降のパラメータ全体を含む文字列になります。 パラメータがあれば ? 記号を含めそこから先が全部、 パラメータがなければ(? 記号で終わっている場合を含む)空データになっています。
js-getparam.html?name=Tom&favorite=pasta なら、 document.location.search は ?name=Tom&favorite=pasta です。 js-getparam.html でも js-getparam.html? でも document.location.search は空になりました。
length プロパティを参照すれば、その文字数がわかります。 調べた範囲では値が 1 になることはありませんでしたが、 パラメータがない時 0 になり、1文字以上あれば ? 記号を含めて2文字以上になりましたので、 2文字に満たない場合はパラメータがない、と判断しています。
パラメータがないと判断した場合には、null を返します。
// URL パラメータの最初の1文字(?記号)以降の文字列を取得します。 var query = document.location.search.substring(1);
変数 query に、パラメータ部の ? 記号を除いた部分を設定しています。 substring 関数は、引数で指定した文字インデックス以降の文字列を返すものです。 文字インデックスは先頭が 0 ですので、1 指定の場合、先頭の 1 文字を取り去る、です。
// クエリの区切り記号 (&) で文字列を配列に分割します。 // "name=Tom", "favorite=pasta" のようになります。 var params = query.split('&');
変数 query に入っている文字列を、 & 記号を区切りとして分割しています。 変数 params は、文字列の1次元配列となります。
query が name=Tom&favorite=pasta なら、 params[ 0 ] = "name=Tom" となり、 params[ 1 ] = "favorite=pasta" となります。
var result = new Object(); for (var i = 0; i < params.length; i++) { elem.innerHTML += ("<br/>" + params[i]); // パラメータ名とパラメータ値に分割します。 var element = params[i].split('='); elem.innerHTML += (" -> " + element[0] + ", " + element[1]); var paramName = decodeURIComponent( element[0] ); var paramValue = decodeURIComponent( element[1] ); // パラメータ名をキーとして連想配列に追加します。 result[ paramName ] = paramValue; } return result; }
連想配列となる result をオブジェクトとして作成しています。 利用はできているものの、まだ構造を十分に理解していないため、これ以上の説明は、今はできませんが。
params は文字列の1次元配列ですので、length プロパティには要素数が入っています。 1つずつ、for ループ内で処理します。
まずは途中経過出力領域 elem に、1つのキーと値の組み合わせ、例えば name=Tom を出力します。 += で書き込んでいますので、今あるものへの追記になります。 また、あえて右辺をカッコでくくっていますが、「これを先にやって欲しい」という明示的な指定です。 必ずしも必要ではないようですが、「左から順に解釈・実行される」とおかしなことになるので書いています。
split 関数に = 記号を渡し、そこで切り離して element に文字列の1次元配列として設定します。 element[ 0 ] = "name"、element[ 1 ] = "Tom" となります。 分割できた様子を、途中経過出力領域 elem に追記しています。
これでキー名とその値が分離できましたので、 キー名を paramName に、値を paramValue に、いったん設定しています。 decodeURIComponent 関数の戻り値にしているのは、 これがエンコードされていた場合には戻す、という作業を行うためです。 Unicode 以外は戻せないと思いますが、英数だけとは限りませんので、この形が良さそうです。 デコード関数は数種類あるようですが、今は追及しません。
最後に、連想配列への設定です。
Object の result に対し、インデックスとして文字列、キー名を渡しています。 そしてその値は、対応する文字列です。 これで、キー名が name である値へのアクセスは、result["name"] で行う、ということになります。
result が Object であることから、想像ですが、 result["name"] は、result.name と同等、とイメージすると良さそうに思えます。 result.name を result["name"] でアクセス可能かはわかりませんが。
オブジェクトについては、「【基礎】Object 型の変数の使い方」に書いています。
投稿 November 1, 2020
今度は、URL パラメータを解析し、Object 配列を返す関数 GetQueryString2 を見ていきます。 どんなパラメータが指定されるのかわからないとき、役に立ちそうです。
function GetQueryString2() { // パラメータがないか、"js-getparam.html?" の場合 if (document.location.search.length < 2) { return null; }
先ほどの GetQueryString 関数と同じように、 パラメータがない場合は処理できませんので、null を返します。
// URL パラメータの最初の1文字(?記号)以降の文字列を取得します。 var query = document.location.search.substring(1); // クエリの区切り記号 (&) で文字列を配列に分割します。 // "name=Tom", "favorite=pasta" のようになります。 var params = query.split('&');
ここも同じように、document.location.search に入っているパラメータの 先頭の ? 記号を substring 関数を使って取り去り、 変数 query に設定しています。
さらに、split 関数に & 記号を渡し、 & 記号で区切られている文字列を1次元配列にして、変数 params に設定します。
var result = []; for (var i = 0; i < params.length; i++) { // パラメータ名とパラメータ値に分割します。 var element = params[i].split('='); var paramName = decodeURIComponent( element[0] ); var paramValue = decodeURIComponent( element[1] ); // パラメータ名と値をオブジェクト配列に追加します。 result.length = i + 1; result[i] = new Object(); result[i].paramName = paramName; result[i].paramValue = paramValue; } return result; }
まず、変数 result に、要素数未定の1次元配列を設定します。 要素数未定の1次元配列については、 「【基礎】可変サイズの配列と操作」に書いています。
& 記号で区切られた文字列の数 params.length だけ for 文でループします。
params の 1 要素には、"name=Tom" のような文字列が入っていますので、 split 関数に = 記号を渡して、キー名と値に分解して、 変数 element に、2要素の1次元配列として設定しています。
それぞれ、エンコードされている場合に備え、 decodeURIComponent 関数を使用して、それぞれの文字列を paramName と paramValue に設定します。
1 次元配列 result の length プロパティを再設定し、配列を 1 つ拡張しています。 すでに配列に入っているデータは壊されません。 拡張された result[ i ] に、キー名 paramName とその値 paramValue を設定し、終わりです。
呼び出し元では、result の length を調べればキーの数がわかり、 配列としてアクセスし、.paramName と .paramValue を参照すれば、キー名とその値がわかります。
投稿 November 1, 2020
次のようなリンクを作成する関数が、link() です。 「リンクを生成する」ボタンが押されたときに呼び出されます。
js-getparam.html?
name=%E3%82%B1%E3%83%AA%E3%83%BC&
favorite=%E3%82%AA%E3%83%AC%E3%83%B3%E3%82%B8
name キーの値となる input id="iname" と、 favorite キーの値となる input id="ifavorite" の値を取得し、 エンコードして、URL 文字列を作成します。
このエンコードにより、リンクした先で元の日本語に正常にデコードすることができます。
function link() { let url, str; url = 'js-getparam.html';
最終的なリンク文字列を保持する変数 url に、 まずは html ファイル名を設定しています。
str = encodeURIComponent( document.getElementById("iname").value ); url += '?name=' + str;
input id="iname" に入力された文字列を参照し、 encodeURIComponent 関数に渡して、エンコードした文字列 str を取得しています。 文字列をエンコードするには encodeURI 関数もありますが、 テストした様子では、それでも問題なくデコードできていました。
エンコードされた値 str を url に追加し、name キーの設定は完了です。 ここでは右辺を(明示的に)カッコで囲んでいませんが、問題ないようです。
str = encodeURIComponent( document.getElementById("ifavorite").value ); url += '&favorite=' + str; str = '<a href="' + url + '">' + url + '</a>'; // 出力します。 let elem = document.getElementById("link"); elem.innerHTML = str; }
iname と同じように、input id="ifavorite" に入力された値を取得し、 encodeURIComponent 関数でエンコードして、str に設定します。 それを url に追加しています。
できた URL 文字列 url を、 span id="link" の innerHTML を書き換えることにより、表示を行っています。 innerHTML による書き換えについては、 「【基礎】HTML 要素のテキストの書き換え」に書いています。
ウェブ開発に関するトピックは、「ウェブ開発トップ」にまとめられています。