URLパラメーターから取得した内容をそのままテキストボックス上に反映する

URLパラメーターから取得した内容をそのままテキストボックス上に反映する

読んで字の如し。フォーム関連の話多いねこのブログ。

あっそういえばGoogle AdSenseの審査が通ったので設置してみました。
広告ウザいという方や筆者にビタ一文与えたくねえという方はAdblockなどで自衛してくだされ。

とか書いたら配信停止されるんかな…?
まあ広告をブロックすることだってユーザーの自由でしょというのが個人的見解です。

用件とデモ

タイトルだけだとナンノコッチャって感じですが。
例題を用意しましたので、これをどうやって解決するか考えてみてください。

用件

  • 製品一覧ページ・製品詳細ページ・製品お問い合わせページがある。
    製品一覧ページとお問い合わせページは単一だが、製品詳細ページは複数存在
    (CMSの商品詳細とかWordPressの記事みたいに無数に追加されうるイメージ)。
  • 製品詳細ページからお問い合わせページにリンクするボタンを設置する。
    このボタンでお問い合わせページに遷移してきた場合、
    テキストボックス内に前ページの製品名を自動入力させる。
  • CMSサービスなどを利用していてPHPなどは使えない想定。
    フロント側でなんとかする必要がある。

サイトマップはこんなイメージになります。

ホーム
 ├ 製品一覧
 │ ├ 製品詳細1
 │ ├ 製品詳細2
 │ └ …(無数に存在)
 └ 製品お問い合わせ

「製品詳細ページからお問い合わせページに製品名の情報を渡すにはどうすれば…?」→
URLパラメーター使ってどうにかするか~」というのが今回のお話になります。

世間的な感覚に合わせて『パラメーター』と表記してきましたが、あんまりパラメーターパラメーターって
伸ばし棒つけて連呼するの好きじゃないんで、ここから下では『パラメータ』表記で統一します。

デモ

動くものを見ればよりイメージが湧きやすいと思うので例によってデモを用意しています。

デモ

デモの動作を画像で補足説明しておきます。

一覧画面 まず、こんな風に一覧画面がありましてー

詳細画面 それぞれの詳細画面がたくさんありましてー

お問い合わせ画面(製品情報引き継ぎ状態) ボタンを押したらお問い合わせページに飛んで、
テキストボックス内には製品名の情報が引き継がれているイメージです。

お問い合わせ画面(通常) なお、普通にお問い合わせページに飛んだ場合のテキストボックスは自由入力とします。

いざ実戦へ

それではやっておきましょう。と、その前に。
先にHTMLの構造の説明だけしておきますね。
今回は複数ページに跨っている都合上、要点だけの抜粋としますが。

前説

詳細ページからお問い合わせページへのリンクボタンは、下記のような設定をしています。

<a href=”(お問い合わせページへのリンク)?key=製品名01“>製品に関する~</a>

このようにすることで、遷移後のURLに『?key=製品名01』というような
パラメータが付与されるという寸法です。

また、お問い合わせページのテキストボックスの記述は下記のようになっています。

<input id=”prodName” type=”text” placeholder=”製品名をご記入ください。”>

特に説明することもないですが、操作対象となる部分なので一応記載しておきます。

とりあえず動くものを書く

詳細ページではお問い合わせページに向けてURL経由でパラメータを送るだけなので、
特にJSでどうこうする必要はないです。肝になってくるのはお問い合わせページの処理で、
URLからパラメータを取得し、対象のテキストボックス上に反映する記述が必要になります。

シンプルに書くとこんな感じでしょうか
(上記の書き方はいくつか欠点があるので後で直します)。

用語の補足:キーと値

先に用語について触れておきましょうか。

https://ideacase.jp/wp-content/uploads/demofiles/demo07/contact/index.html?key=%E8%A3%BD%E5%93%81%E5%90%8D01

「?」以降の赤枠部分がパラメータなのは説明不要として。
黄色く塗り潰した箇所(key)をキー、緑色で塗り潰した箇所(製品名01)といいます。

なお、パラメータって言葉の意味については割愛します(意味広すぎるため説明するだけ不毛)。
「要するにURLパラメータってのはキーと値が1セットになってるものなんだなあ
っていうことだけ理解していただければOKです。JSONファイルとかと似てますね。

解説

それではソースコードに戻って解説いたします。

var url = location.href;

URLを取得してますね。

var urlArray = url.split(‘?’);

取得したURLを?で区切って配列urlArrayに格納していますね。

var paramData = urlArray[1].split(‘=’);

URLのパラメータ部分、すなわちurlArray[1]を更に=で区切ってキーと値に分けていますね。

paramArray.push(paramData[0]);
paramArray[paramData[0]] = paramData[1];

parramArray[(キー名)] = (値)の形になるようにしてあげます。連想配列ってやつですね。追記参照

連想配列とは
要素の指定を数字でなく文字列で行うことができる配列。
例:
(普通の配列)arr[0]
(連想配列)arr[‘key’]

var text = decodeURI(paramArray[‘key’]);
(略)
$(‘#prodName’).val(text);

あとはパラメータの値(=表示させたいテキスト内容)を
テキストボックス側に送ってあげればおしまいです。

ちなみに、送りたいパラメータ値が半角英数字のみの場合は
text = paramArray[‘key’]でもOKです。
ただし、今回のケース(値の内容にマルチバイト文字などが含まれる場合)では
下図のようになってしまうため、decodeURI(hoge~~)としてこの問題この解消しているわけです。

テキストボックスに「%E8%A3%BD%E5%93%81%E5%90%8D01」とパーセントエンコーディングされた値が入力されてしまう。

こんな具合に文字化けして残念な感じになってしまいます。
文字化けというか、厳密にはパーセントエンコーディングされたんですけども。

なぜなにURLエンコード

なんでこんな風にされてしまうかというと、
URLに日本語(などのマルチバイト文字列)は本来使用できないからです。

嘘つきキツツキもんじゃ焼きと思った方もおられるかもしれません。
たしかにWikipediaの記事とか読んでるとブラウザのURL欄に日本語が表示されていますよね。

おとなはウソつきではないのです…じゃなくて。
それじゃあ今挙げたWikipediaのページをIEで見てみましょうか。

ご覧の有様でござい。といってもこれはIEがダメなんじゃなく、
他のブラウザでも内部的には同じことになっているんです
(気をきかせて見かけ上は日本語で表示してくれますが)。
とまれこうまれURL上で日本語などを扱うにはエンコードする必要があるのです。厳密にはURLというかURIなんですが、URIとURLとURNの話とかはややこしいしめんどいんで今回は省きます。

エンコードというのは、データを別の形式に変換することです
デコードはその逆でエンコードされたものを元に戻すこと)。
URLにおいて使用できない文字を使う場合に行われるエンコードが
パーセントエンコーディング(一般にURLエンコードとも呼ばれる)で、なんとこれはブラウザ側でよしなにやってくれてます。

が、今回はそこから更にURLにくっついているパラメータの値を拾ってきたいので、

var text = decodeURI(paramArray[‘key’]);

ってな記述をして、
パーセントエンコードされた文字列から元の文字列に戻した状態(デコード)で
テキストボックス上に情報を送る、というフローになっております。

余談:ところで日本語ドメインってどうなん?

日本語.jpとかってあるじゃないですか。
あれってIEで見ててもドメイン名がパーセントエンコーディング表示されてないですよね。
なんでかというと、実はドメインの場合は別の手法でマルチバイト文字が変換されているのです。

これをPunycodeエンコーディングといいまして、たとえば日本語.jpの場合、
内部的には「http://xn--wgv71a119e.jp/ 」というURLに変換されているのです。
なおPunycodeはピュニコードまたはプニコードと読むらしいです。プニ…? ウッ 頭が http://games.kids.yahoo.co.jp/sports/013.html
そういやHTML5かなんかへの移植も検討中らしいけどあんま進んでる話は聞かないすね。版権とかで難しいんかな

まあ今回の話とはあんまり関係ないんで詳しい話は割愛して、
名前だけのご紹介にとどめておきます(面倒なだけともいう)。
もし国際化ドメイン関連で何かしたい場合はこの辺の記事が参考になるかも?参考:
Punycodeのjavascript実装と変換テスト
PHPで手軽にURLをピュニコード変換する関数を作ってみました(日本語ドメイン⇔Punycode表記)

手直し ~複数パラメータ問題とハッシュ

ところで、URLパラメータは複数指定することができるんですよね。
?key=製品名01&size=s&color=red みたいな具合でね。
ではURLを直接編集してどうなるか試してみましょうか。

( ^ω^)・・・

あと、ハッシュってあるじゃないですか。ほら、ページ内リンクさせたい時に使うやつ。
さてここで問題です。ハッシュとパラメータはどっちが先に書くでしょうか?

正解はパラメータ→ハッシュの順番です。
パラメータ→ハッシュの順で書くとページ内ジャンプが機能しないのです…。
で、やっぱりこうなると。

( ^ω^)・・・

これらをどうにかしてみましょう。

解決例

これで解決。正規表現の話は前したんで省きます。
input部分の消したり出したりも特に補足するほどじゃないですかね。

レアケース パラメータがなんか文字化けしてる

「よし。んじゃ上のソースを本番環境で早速動・・・って、あれ?
IEだけなんか入力値が化けてるし、なんならURLパラメータ自体が文字化けしてるぞ」

?key=製品名01
※文字化けのため正しい表現不能

URLパラメータが正しく取得できてない! なぜ!?
HTTPヘッダを確認したらちゃんとcharset=UTF-8にはなっているのに…。

あー、これね。さっきパラメータ値に日本語とか使ってても
ブラウザ側でパーセントエンコーディングしてくれるって書いたんですけど。
サーバー側の設定が絡んでてうまくいかないことがあるみたいです。
いや知らんけど。筆者にバックエンドの知識はほぼないんで……。

とりあえず自分が遭遇したケースだと、
IEだけなぜかURLパラメータがISO-8859-1に変換されてるようでした。
そこで…

仕方ないので対症療法的にこんな方法で解決しました。
バックエンドの担当者に相談したら良かったじゃんって? 大人の世界には色々あるんや…。

あとがき

jQueryで書いてますけどこのぐらいならバニラなJavaScriptに書き換えるのも
わけないと思うんで省きました(面倒なだけとも…)

ウェブフォームってのはめんどくさいんだよって話もこないだやったから
あんま書くことないっすね。まあアレだ。
PHP弄ったりAjax通信であれこれやったりしなくてもこのぐらいは出来るということです。

ちなみに、「アドレスバーにパラメータがゴチャゴチャついてるのをどうにかしたい!」
って思う方は、テキストボックスに値を送った後にこういうことすればいいと思いまーす。 参考:
アドレスバーのURLを書き換える

以上でーす。終わりまーす。ばいばーい。

追記

すみません、連想配列とオブジェクトを混同していました。連想配列とオブジェクトがどう違うかというと、連想配列の場合は値にデータしか入れられませんが、JavaScriptにおけるオブジェクトの場合、値として関数も入れることができるのです。どういうことかというと…。

var obj = {
  id: 0,
  name: ‘test’,
  func: function() { console.log(‘test’); }
};

こういうことも出来るのです。ただし…

オブジェクトは一般的な言語の「連想配列」ではない。そのまま使うのはプロトタイプ汚染が行われ危険である 引用:JavaScriptのプロトタイプ汚染攻撃対策は難しい

と、なんかしらの処理まで入れることが出来てしまうのはメリットがある一方で上記のような危険性もあるわけで。連想配列を用いたい場合は、map()メソッドを使うようにしましょう。

解説ブログでニワカ知識を晒してしまう失態。しかしまた一つ自分にとっても勉強になりました。