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イベントが発生してしまうという……。どうすりゃいいんだ……。

フレームページをHTML5化する方法


普段、残業なんて滅多にしない職場で働いている自分ですが、この2週間ほどは激務でした(どれぐらい激務だったかはいいません。あくまで個人的にそう思っただけで、中にはそんなの激務じゃないと言われそうなレベルの量なので)

それはともかく、その間にやっていた仕事がframesetやframeタグを使っているフレームを利用したHTMLファイルをHTML5化するというもの。しかし、知ってる人も多いと思いますが、framesetやframeタグはHTML5で廃止されてしまっています。とりあえず代替方法としてiframeタグを使うことになったのだけれども(この実装方法に突っ込まないでください。時間がなかったのでこうするしかなかった)、最初、うまい実装方法が思いつきませんでした。しかも、対応ブラウザはIE6以上と言われています(HTML5なのに、IE6以上って………)。

例えば、以下のようなコード。

サンプルページ
ヘッダとして上部に50px、フッタとして下部に70px、そしてメインのページをその間に入れたフレームページです。ヘッダとフッタは問題ありません。問題はメインページです。動的に高さを変更しなければいけないわけですが、うまい方法が思いつきませんでした。

最初はそれぞれのiframeをtable,tr,tdタグで囲って、tableの高さを100%にし、一番上のtrの高さを50px、一番下のtrの高さを70pxにしてみました。一見、うまくいったように思えたのですが、IE10以下でダメでした・・・。

次に考えたほうほうが、#mainをdivタグで囲み、そのdiv(#main_containerとする)をbodyと同じ幅と高さと位置にして、box-sizingをborder-boxにしたうえで、padding-topを50px、padding-bottomを70pxにしたうえで、#mainの高さと横幅を100%にしたらいけるんじゃ・・・なんて思ったけど、よくよく考えるとIE7ではbox-sizing非対応だったのでできません(IE6はもともとbox-sizing:border:box;と指定した時と同じ振る舞いだったはずです)。

困ったなぁ。どうしたらいいんだ・・・。と思いながらふと思いついた。先ほどの#main_containerのtopを50pxにして、bottomを70pxにしたらどうなるんだろう・・・。と。

結果、期待通り、上部に50px、下部に70px空いた要素となりました(てっきり、どっちも指定している場合、どっちかが優先されるもんだと・・・。CSSはある程度わかってきたと思ったんだけどなぁ。CSS界隈では常識だったりするんだろうか?)

というわけで、以下が実装結果。

CSS

HTML

サンプルページ

IE6やIE7ではうまくいかないところもあったので、何度か試行錯誤してどのブラウザでも実装することができました。同じように左・中央・右にわけたフレームページでは下記のようになります。

HTML4

HTML4:サンプルページ

HTML5

HTML5:サンプルページ

応用として、framesetの中にframesetがあるページも下記の通り。
HTML4:サンプルページ
HTML5:サンプルページ

ただし、最後のはIE6でうまく動きませんでした。こういうページの場合は、最初に作ったframe1-html5.htmlの中の#mainのsrc属性を、二つ目に作ったframe2-html5.htmlにするほうがいいかもしれません。

ios8にfloatバグがあるようだからFlexboxで対応してみた


先日、1年ほど前に仕事でiPad用に作ったサイトを触っていると、floatを利用した箇所が大きく崩れることがあることが分かった(いつもではないし、崩れ方も異なる)。

確か下記のようなCSSでした。

家に帰って実装してみて試してみると再現されなかったので違うかもしれませんが、とにかく上記のレイアウト指定ならリストは3列の並びになるはずなのに、3つ並んでる行もあれば2つしかない行もあるし1つしかない行もあったわけです。

調べてみたらiOS8のバグのようでした。
参考:iOS8でリストのレイアウトが崩れたら : のり記
参考:W3GさんはTwitterを使っています: “iOS8 SafariのCSSレンダリングが不安定化になるのは特定のJS実行下で発生する模様。pushStateでnth-childが効かなくなると。http://t.co/bO2Kasuyk3 他にもcliclイベント発火でfloatが無効されたりJSとの因果関係で不安定化する”

最初は、『display:inline-block』で対処するか。と思ったのだけど、試してみると全て2行表示になってしまった。inline-blockを指定した要素は改行すると隙間ができてしまうんですよね。対処方法はあるのは知ってるのですが(参考:inline-blockを並べた場合に発生する「隙間」を消去するCSS » INSPIRE TECH)、勉強がてらFlexboxを使ってみることにしました。

例えば先ほどのスタイル指定だと、下記のようにすれば同じレイアウトになります。

ただ、これだとちょっと古いブラウザだとレイアウトが崩れます。そこで、Flexboxの『flex-wrap』が指定してるかどうか調べたうえで、指定できるならFlexboxを、指定できないならfloatを指定することにしました。

CSS

JavaScript(jQuery使用)

実行結果:ios8でのfloatバグ対応

Flexboxは結構前から知ってはいたのですが、実装されてるブラウザも少なく、ころころ仕様も変わるもんだから利用を避けてたのですが、最近になって十分に使えるようになってきたようです(参考:これからのCSSレイアウトはFlexboxで決まり! | Webクリエイターボックス)。いろいろなプロパティがあってややこしいのですが、機会があればまた使ってみようと思います。

CSS3で追加されたcurrentColorキーワードを試してみた


先日、ブックオフのタッチでおトクなメンバーズが8月で利用できなくなると知り(参考:【BOOKOFF タッチでおトクなメンバーズ】サービス名称・内容変更について)、ブックオフに行きました。そこで2011年に発売された定価2800円のCSS3本の値札が700円、しかもその日は半額デイだったため350円で売られていたので思わず購入。まだほとんど読んでないのですが、パラパラめくっていると色の指定方法について書かれた項目に『currentColor』という値が書いてありました。

一瞬、「現在の色? それって何も指定しないのと同じじゃ……」と思ったのですが、よくよく読んでみると現在の要素の文字色を表す値ということが分かりました(参考:color value – CSS | MDN(currentColor キーワード))。

たまに文字色とボーダーの色を同じにするようなレイアウトのスタイルを記述することがありますが、そういう時に便利なキーワードですね。

というわけで試してみました。

HTML

CSS

実行結果:currentColorテスト

確かに、指定の色が、その要素の文字色と同じ色になっていることが分かります。覚えておきたいです。

ここから余談です。

先日、プロとして恥ずかしくない 新・WEBデザインの大原則を読みました。タイトルにWEBデザインとありますが、デザインだけでない、WEB制作について広範囲に書かれており、わかりやすかったので良書といえると思います。
ですが、一つだけ気になった点があります。その点を以下に引用します。CSSの基本について書かれた項目の一部です。
名前からも想像できる通り、colorは文字色(前景色)を、background-colorは背景色を指定するためのプロパティだ。
自分は、background-colorが背景色を表すのは一目見たら分かると思うのですが、colorプロパティは見ただけでは文字色を表すと分からないと思います。時々、疑問に思うんです。なんで、CSSを作った人は、文字色の指定するプロパティを、font-colorとかtext-colorという書き方にしなかったのだろうかと。
まあ、こんな疑問もつの自分だけかもしれないんですけどね。

jQueryのisメソッドのセレクタ指定でhover擬似クラスを使う


jQueryにはhover擬似クラスは対応してないはずなので、isメソッドでも使えないだろうと思って使ってみたら、使えました。

あれ? でも前にやった時には使えなかったような・・・、と思ってjQueryのバージョンをいろいろ変えてみて試してみると、1.4.3からis(‘:hover’)という指定ができるようになったようです。1.4.2以前だと、『Syntax error, unrecognized expression: hover』というエラーが表示されました。結構前からできたんですね。ただ、調べても1.4.3からできるようになったと書かれてるサイトがないのですが。

例えば、下記のように、setIntervalを用いて3秒ごとにあるブロック要素が左右に動くという指定をし、さらに当該要素にマウスが乗っている場合は動かないようにする場合は、『if(!($moveDiv.is(‘:hover’)))』で動かなくなります。

さて、ところで最初に『jQueryにはhover擬似クラスは対応してないはず』と書き、その後にisメソッド内だと対応していると書きましたが、よくよく考えたら試してないので下記のようなコードで試してみました。

mouseenterはその要素にマウスが入ったら、つまりhover状態になったら実行するイベントです。なので、mouseenterのイベントが発動した時には確実にカーソルが要素上に乗っている状態なので、hover擬似クラスが対応していたら背景が赤くなるはずです。

普通に赤くなりました。実行サンプル:jQueryのhover擬似クラス

うーん。なんで自分はできないと思いこんでたんだ・・・(まあ、こんな使い方することはめったにないとは思いますが)。