IE10モード以上のHTAでHTA:APPLICATIONオプションを使う方法


このところの仕事は、入社してから今までなかったほどの忙しさです。仕事が終わったと思ったら、次の仕事がどこからともなく舞い込んできます。しかも、人が少ないせいで、やってる仕事のプロジェクトはほぼ一人でやっている感じがします(たまに、上司にお願いや相談や報告をするぐらい)。

そんな中、既存のウェブサイトに似たローカルアプリを作る必要がありました。しかも、ローカルにファイルを保存したりデータベースを読み書きしたりする必要があるとわかり、いろいろ悩んだすえ、HTAを使うことにしました。
参考:HTAを利用したウインドウ付きアプリケーション – マンガで分かる JavaScriptプログラミング講座

標準だと、HTAはIE7モードで起動してしまいますが、canvasを使うこともあり、metaタグでIE10モードとしました。Ajaxを使いたかったのですが、IE11からローカルだとAjaxを利用できないと分かり、IE10モードにしました。よくよく考えると、ActiveXObjectが利用できるので、最終的にはそんなことする必要なかったんですが……。
参考:VBScript + HTA(HTML Application)で Canvas を使う方法 – CX’s VBScript Diary – VBScript グループ
参考:IE11のActiveXObjectはfunctionとして存在しているが!!window.ActiveXObjectがfalse – イム日記

だけど、ここで問題が発覚。なんと、aタグでリンクをつけて同じ階層のファイルに移動しようとすると、IEが開いてしまうではないですか!! いろいろ調べてみると、HTA:APPLICATIONタグでNAVIGABLE属性を”yes”にすると同じウィンドウで開くということが分かりました(なぜデフォルトが”no”なのか不思議でなりません)。なので、設定してみたのですが、なんとIE10からこのHTA:APPLICATIONタグによる設定はなくなったとのこと。
参考:IE10 の HTA 問題 – ※ただの日記ブログです※

なので、IE9モードにしたのですが、CSSでグラデーションの指定が効きませんでした。IE9には対応していないようです。まあ、正直そこはそんなに問題ないのですが、それでもやっぱりIE10モードで使いたいなと思って試行錯誤していると簡単に解決しました。

やり方としては、リダイレクト用のhtaを用意して、下記のように記述するだけ。

ここでは、”ie10-hta.hta”が実際に利用するアプリです。拡張子はhtaではなく、htmlでも問題ありません。自分は拡張子htmlで作成して、開発時にはIEで開いて確認しました。IEだと、F12 開発者ツールを使ってデバッグできるためです。

ところで、今回作成したアプリは、タッチでの動作でも対応するようにしていたのですが、ここで問題が発覚しました。なんと、HTAのほうではポインター イベントがありませんでした。例えば、scriptタグ内に『alert(window.navigator.msPointerEnabled);』と記述すると、IEで開いた場合には、『true』となるのにたいし、HTAで開くと『false』となりました。仕方なく、mousedownやmousemoveで対応したのですが、なぜかタッチした時ではなく、離した時にmousedownイベントが発生してしまうという……。どうすりゃいいんだ……。

タブやウィンドウをただ閉じるだけのHTML


ちょっとわけあってタブ(もしくはウィンドウ)をただ閉じるだけのHTMLを作る必要があったのでそのメモ。

最初、タブを閉じるのはwindow.close()を呼んだらいいだけなので、下記のようにすればできるだろうと思っていました。

実行サンプル(短いのでBase64のData URIを利用しています)

しかし、Chromeでこのページを開いてみるとタブを閉じてくれません(他のブラウザを試したわけではないです。iOSのSafariで試してみましたがそれもダメでした)。試しにChromeの開発者ツールのコンソール画面で確認すると、下記のように書かれていました。

Scripts may close only the windows that were opened by it.

自分のない英語力で読解してみると、ただウィンドウを閉じるだけとかいうことが書かれているのだと思います(ちなみに、エキサイト翻訳で翻訳してみたけっか、「スクリプトは、それによって開かれたウィンドウだけを閉じるかもしれません。」となった)。

ということは、いろいろな処理をいれると閉じてくれるのだろうか。と思ったけれども、まずは上記の英文でGoogle検索してみることに。
Scripts may close only the windows that were opened by it. – Google 検索

英文で検索しているので、英語のページばかりヒットします。タイトル見てもいったいどれが自分の求めている情報に近いかわからないので、とりあえずGoogleを信じて一番上のページを開くことに。
javascript – window.close and self.close do not close the window in Chrome – Stack Overflow
たどりついた先は、プログラミングをやっていて困った時に検索するとやたらヒットするStack Overflowのサイト。英語は苦手なので、英語は読まずにソースコードを探してみると、ありました。”open(location, ‘_self’).close();”とすればいいようです。

実行サンプル

これで無事、タブをただ閉じるだけのHTMLを作成することができました。

今回に限らず、英語が苦手でも、とりあえず表示された英文のエラー文や警告文で検索してヒットしたページからソースコードを探してみるだけでなんとか解決することって、意外とあります。
というわけで、何か英語でエラーがでたとしてもあわてず、ググってみることにしましょう。案外すぐ解決するかもしれません。

IE11で@cc_onステートメントを試してみる


昨日IE11がリリースされたので、インストールしてみました。
IE11

知ってはいましたが、F12開発者ツールがかなり変わってます。いろいろ進化しているようですが、縦幅が狭いと少し使いづらい気も・・・。
後、DOMツリー画面で要素を右クリックすると『要素をスタイル付きでコピー』なんて項目が。使い所があるか分かりませんが、面白そうではあります。
でも、カラーピッカーやルーラー機能はなくなった? あれ便利だったのに。

とまあ、もうちょっとF12開発者ツールはおいといて、今回はIE11で@cc_onステートメントは使えるかどうかという話。
@cc_onについて詳しくは下記のリンク先に書いてあります。
参考:@cc_on ってなに? – Clouder::Blogger
参考:@cc_onを使ってブラウザ判別 | Smart
参考:@cc_on ステートメント (JavaScript)
すなわち、簡単にいってしまえばIEのみで動作するスクリプトのようなものです。

知ってる人もいると思いますが、IE11ではユーザーエージェントに”MSIE”という文字がなくなりました。
試しに、F12開発者ツールのコンソールで”navigator.userAgent”とやってみると、以下の様な文字列が。

見ての通り、ユーザーエージェントの文字列に”MSIE”という文字がありません。なので、MSIEがあるかないかだけでIEを判別することができないわけです。

でも、IEを判別する方法はもうひとつあって、それが上でかいた@cc_onステートメントと呼ばれるもの。これがIE11でも動いてくれるのかどうか試してみました。
まずは、下記のコードで書いたHTMLを作成。

もし@cc_onステートメントが動くならばブラウザ上に”IEだね!”と表示され、動かないのであれば”IEじゃないよ!”と表示されます。
さて、この結果はというと・・・。

IE判別

動きませんでした。書き方間違えたか? と思ってF12開発者ツールの一番下のエミュレーション機能からドキュメントモードを10(IE10とほぼ同じ)にすると、ちゃんと”IEだね!”と表示されました。

もう、ここまでするならIEではなくて、全く新しいブラウザということにしたほうがいいんじゃないのかと思います(ユーザーエージェントにブラウザ名が入ってないって・・・)。

ただ、ユーザーエージェントにTridentというIEのレンダリングエンジンの名前は入っているので、IE11も含めたブラウザ判定をするのは、Tridentという文字があるかどうかを見るのが一番よさそうですね。
参考:javaScriptで対応ブラウザ判定 – Qiita [キータ]

HTMLのvalue値は、Web開発者ツールで簡単に変更できるという話


うちの会社の話です。ある会員用ウェブサイトにおいて、ログイン後のページではその会員のIDをinputタグをhiddenにして保持するという方法をとり、全ページPOSTで送信するようにして、それぞれのページで会員の情報を得るという手法をとっていたのですが、これだとログイン後、inputタグのhidden内のIDだけを書き換えると、簡単に他の会員の情報が見えてしまうということが発覚しました。

他にも、3種類の選択肢が用意されているセレクトボックスがあったのですが、それぞれのoptionタグのvalue値は、『2』『3』『4』というようなものでした(実際は少し違うのですが、こんな感じです)。気になる人は気になると思いますが、なぜ『1』がなく、2からなのかと。そこで、optionタグのvalue値、例えば現在『2』となっているvalue値を『1』と書き換え、その箇所を選択すると・・・。なんと、その会員には見せてはいけない情報がズラリ。

上記は上司や先輩社員に報告することにより解決に至ったのですが、その時の上司や先輩社員の反応は、「えっ? そんなことできるの?」という感じをうけました。「GET渡しからPOST渡しに変更したうえに、リファラチェックしてるんだよ?」という感じで(注:あくまで自分の勝手なイメージです)。
結論からいうと、簡単にできます。ブラウザに付属のWeb開発者ツールをつかえば。Web開発者ツールとは、IE(8以上)では『F12 開発者ツール』、Chromeでは『Developer Tools』、Firefoxでは『開発ツール』と呼ばれてるものです(Firefoxはむしろ、『Firebug』のほうが有名ですが、Firebugはアドオンをインストール必要があり、『開発ツール』は標準で付属しているという違いがあります。機能面でいえば『Firebug』のほうが多いので、ウェブ制作に関わってる人なら『Firebug』をインストールしたほうがいいと思われます)。

では、その方法を簡単に説明します。
今回は、サンプルとして前回のHTMLのテキストボックスを、できるかぎり半角数値のキー入力のみにするで作成した半角数値しか入力できないようにしたテキストボックスから数値以外のテキストを入力し、送信する方法を三種類ご紹介。
 
下記ページが今回利用するページです。
テキスト入力項目の制限
HTMLとJavaScriptとPHPは下記のようになっています。

HTML

JavaScript

PHP

HTMLとJavaScript側では、数値以外の値が入力できないようなテキストボックスを用意しています。formタグ内のテキストボックス内でエンターキーを押すと、フォームを送信するという仕様を利用して、エンターキーを押すと同じページに送信するようにしています。
PHP側では、POSTで渡されたOnlyNumの値をみて、数値かどうか判定しています(7行目)。特別今回の記事に必要なわけではありませんが、5行目でリファラと自身のページの情報をチェックし、同じかどうかを判定しています。

まずは開発者ツールの表示方法を説明。ChromeかIEかFirebugならF12キーを、Firefoxの開発者ツールならCtrl+Shift+Iキーを押してみてください。すると、ブラウザの下にHTMLのDOMツリーが書かれたツールが表示されると思います。これが開発者ツールです。以下、画像はChromeのDeveloper Toolsです。
Chrome Developer Tools
このDOMツリーはソースコード(Ctrl+U で表示したソース)と全く同じというわけではなく、JavaScriptで変更したものが反映された結果となっています(その他にも、DOMツリーの仕様にしたがって変更されていることがあります)。
以下、このWeb開発者ツールを使って数値のみの入力制限をしているテキストボックスに数値以外を入れる方法を、三種類説明します。

その1

1つ目の方法は、入力制限を取り除く方法です。
まず、Chromeだと左下の虫眼鏡のようなアイコン、IEやFirefoxだと左上の矢印のアイコンをクリックし、その後にテキストボックスをクリックしてみてください。そうすると、開発者ツールの中のDOMツリーが、テキストボックスの箇所を選択した状態となります。
Chrome Developer Tools

つづいて、テキストボックス中の、onkeydown属性の中、『return OnlyNumber(event)』をダブルクリックするとその箇所が編集できるようになるので、onkeydown属性の中身を削除してください。
Chrome Developer Tools
これで、テキストボックスの中に数値以外の値が入力できるようになりました。試しに、『aiueo』と入力してエンターキーを押した結果は以下のようになります(style属性の中を削除するとIEとFirefoxで全角を入力できるようになり、oncontextmenu属性の中を削除すると右クリックしてメニューを表示させることができるようになります)。
数値以外を入力した場合の結果

その2

2つ目の方法は、ツール内で直接、値を入力する方法です。
テキストボックスの要素を選択してそのコード上で右クリックします。すると、メニューが表示されるので、Chromeでは『Add Attribute』、IEでは『属性の追加』、Firebugでは『新規属性』をクリックしてください。
Chrome Developer Tools

すると、入力ボックスがでてくると思うので、そこに『value=”aiueo”』などとして、value属性を追加し、その中に文字を入力してみてください。(Firefoxの開発者ツールでは属性を追加するという項目はないよう。仕方がないので、適当にどこか(例えば、『autocomplete=”off”』上)でダブルクリックし、そのテキスト入力項目内の最後に『value=”aiueo”』と追加してみてください)。
Chrome Developer Tools

上記の作業をすることにより、ブラウザ上のテキストボックスにもvalue属性にいれた文字が入るはずです。その状態でテキストボックスにフォーカスをあてたあと、エンターキーを押すことによって数値でない値が送信されます。
数値以外を入力した場合の結果

その3

3つ目の方法は、コンソールを使う方法。ちょっとだけ難しくなりますが、JavaScriptが分かるのであれば難しくありません。
まず、開発者ツールの上部にある『Console』もしくは『コンソール』タブをクリックしてみてください。すると、開発者ツール内がコンソールモードに切り替わります。
そしてそのコンソール内に、『document.querySelector(‘input’).value=”aiueo”』と入力して、エンターキーを押してみてください(querySelectorについては、右記を参考:document.querySelector – Web API リファレンス | MDN)。
Chrome Developer Tools

すると、テキストボックス内に『aiueo』と入力された状態になるので、先ほどと同じく、テキストボックスにフォーカスをあてて、エンターキーを押します。すると、数値でない『aiueo』という値が送信されます。
数値以外を入力した場合の結果
ところで、ChromeとFirefoxのWeb開発者ツールにはコマンドラインAPIというものが用意されており、その1やその2でしたように、テキストボックスの要素を選択状態にした後、コンソール画面にいって『$0.value=”aiueo”』としても同じ動作をします。この$0というのがコマンドラインAPIで、$0は直前で選択した要素を返すAPIとなっています。コマンドラインAPIについてはそのうち書くかもしれません。

以上、inputタグ内のvalue値を変更する方法を3つ紹介しました。これ以外にもあるかもしれませんが、思いつくかぎり3つです。
もちろん、上記で紹介した方法はinputタグ内のvalue値を変更する方法以外にも利用できます。例えば、style属性を追加してレイアウトを変更することもできますし、onclick属性を追加して新たにクリックした時に発生するイベントを追加することも簡単にできます。
いろいろ気になった箇所を変更してみると、新たに脆弱性が発見できるかもしれませんね。mixiでは脆弱性報告制度なんてものができたので、これでお小遣いを増やすこともできるかも? (参考:脆弱性報告制度 << mixi Developer Center (ミクシィ デベロッパーセンター))
まあ、さすがにmixiぐらいの規模のサイトが、こんな簡単に変更できるような脆弱性を持ち合わせているとは思いませんが(あえて、『思いたくありませんが』とは書いてません・・・)。

以下、応用問題。
今回のサンプルで、送信前にJavaScriptで半角数値かどうかのチェックをいれたら、半角数値以外の値を送ることはできないんじゃないか? なんて思われた方もいるかと思いますが、そんなことはありません。
それ用のサンプルページも作ってみました:テキスト入力項目のチェック
今回はjQeuryを外部JavaScriptとして呼び出すようにし、JavaScriptのコードは以下のように変更しています。

簡単に説明すると、フォーム送信時にテキストボックス内が半角数値かどうかチェックして、半角数値でなければアラートを出して注意を促し、送信しないという動作になっています(実は言うとこのコードでは何も入力しないと送信してしまうのですが、あくまで半角数値以外の値を入力することを考えてみてください)。

上記のページでどうやって数値以外の値を送信するかは次回説明しようと思います。

HTMLのテキストボックスを、できるかぎり半角数値のキー入力のみにする


HTMLのフォームのテキストボックスに、数値のみのキー入力してほしくないということもあると思いますが、そういう時のための実装を考えてみたので紹介。

HTML

JavaScript

続きを読む