tag:blogger.com,1999:blog-50037614853773665372024-03-14T05:23:04.893+09:00クラウド番外地エメラルドマウンテンの麓。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.comBlogger5011500tag:blogger.com,1999:blog-5003761485377366537.post-28815113514245754922024-01-26T01:19:00.074+09:002024-03-02T16:22:41.855+09:00アイコンの為に Web フォント、合字を深堀してフォールバックを検討する<div class="note"><p>表の修正。「AOSP」→「Android WebView ~4.4.4」など。(2024/03/02)
<p>Web フォントをサポートするゲーム機用ブラウザの情報を追記しました。但し PS5, New 3DS については端末を所持していないため未調査です。(2024/02/06, 02/07 表の誤りの微修正)
<p>「FontFaceDetector → Font Face Observer」誤記の修正とリンクの追加。(2024/02/04)
<p>Android x86 4.4.2の調査結果を元に AOSP の WOFF のサポートバージョンを微修正。(2024/02/01)
<p>「<a href="#webkit-fallback-bug">WebKit フォールバックバグ</a>」について追記しました。「<a href="#svg-font-limitation">SVG フォントの制限</a>」についてカラムを追加しました。(2024/01/27)
</div>
<h2>3行まとめ</h2>
<ol>
<li><a href="https://caniuse.com/" target="_blank" rel="nofollow">Can I use</a>, <a href="https://github.com/mdn/browser-compat-data" target="_blank" rel="nofollow">browser-compat-data</a> は必ずしも正しくはない。
<li>サポートするフォント形式の開始時期と終了時期の他にも、微妙な差異として合字周り、Data URI、SVG に関するものに加えて、絵文字の可否、WebKit フォールバックバグの有無が見つかりました。
<li>合字を使う場合 Chrome 1~14, Safari 3.1~5.1, AOSP 3~4.3では SVG フォント一択です。
</ol>
<h2>はじめに</h2>
<p>このブログのアイコンを「<a href="/2018/02/PureCssIcon.html">Pure CSS アイコン</a>」から Web フォントと動的 SVG の2段構えによる「ベクターアイコン」へ変更中です。
<p>これにあわせて、Web フォントのロード監視コードを見直しました。
<h3>ブラウザがサポートするフォント形式を動的調査からカタログ方式へ</h3>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8dnTECIPkYYTRkumG1iq-djCeocYNCO1TI0vlwyQlBGtxnhbJt_WjGsPhVELBZPMmcWbF-W7VPYRZDLeS06Xqf8A6Yyp_OvzoiFmCRX8FoyHDlKFfEReAVQOqptuJp9x1AGKU4-9rGoi0hXqoZovbyGe7CGwAXp-s1JGk_mIHv4ZDXWawBsnb2i98-gU/s800/test-webfont.drawio.png"><img alt="" data-original-height="800" data-original-width="800" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8dnTECIPkYYTRkumG1iq-djCeocYNCO1TI0vlwyQlBGtxnhbJt_WjGsPhVELBZPMmcWbF-W7VPYRZDLeS06Xqf8A6Yyp_OvzoiFmCRX8FoyHDlKFfEReAVQOqptuJp9x1AGKU4-9rGoi0hXqoZovbyGe7CGwAXp-s1JGk_mIHv4ZDXWawBsnb2i98-gU/s160/test-webfont.drawio.png"></a>
<figcaption><a href="https://viewer.diagrams.net/?tags=%7B%7D&highlight=0000ff&edit=_blank&layers=1&nav=1&title=test-webfont#R7V1dd9o4E%2F4te8HZ7kV8bMky9mUCpM1p2m1L2m7fmz3GFuBdY1PbJNBf%2F0r%2BwpYEGAcbWMhFgoSQhZ5nZjSjkdKBvdnybWDOpx98G7sdINvLDux3AFAUBZA%2FtGaV1Giwm1RMAsdOG60rhs4vnFbKae3CsXFYahj5vhs583Kl5XsetqJSnRkE%2Fku52dh3y0%2BdmxPMVQwt0%2BVrvzt2NE1qdVle17%2FDzmQaMW%2BMTOvfSeAvvPRxHQCBDjVFT96emVlXaftwatr%2BS6EKDjqwF%2Fh%2BlLyaLXvYpVObzVryufsN7%2BbDDrAXVfnA%2F0zw9g7N4MeHL%2FcI%2F3z3pL%2Ft3qS9PJvuAmdfIx5stMrmJ%2F6KmHYid%2BDdy9SJ8HBuWvTdF8IIUjeNZi4pKeTl2HHdnu%2F6ASl7vkca3dlmOI0%2FTt9PH4eDCC83fg8lnx1COuzPcBSsSJP0A2o6nyndkJGWX9bgaRlG0wJwStbQTAkzybtezxp5kU6ceBJnw58eUp%2FfLwe%2F%2Bt%2B9sf75yyq60Q48iWEU%2BP%2FibBoJr%2B7vB8gw6PT6XpRKkKKm5WK7wf3tQBbDsGGaBWBUnfmc2YWZV5Fo5kFTMw%2B4mVckUh4u5nM%2FiMIOfbD2c0FF7M72rcWMfHmJTlq4rqeN4D2HGJmTqDIs%2FHSbrjPxSNHFY9oNnWSH6JzbtHrm2DZ9kpAKZbJsxLjABUiHRzpxvMlj%2FMA%2B%2FVINYK6gitKmNgU55CAHFPKeGX%2B0DLLk%2Bqb9hr78Q9ob4BTIU8XWNUfY%2FeSHTuT49KkW%2BdY4KAznkWmQD6sdTQBgm6xQOVZ8wGa4CMik0fXEFOeDA7I%2FpiOIyUDf358ZFyL6isygrPMow26bKCMOZUhl%2FwueYzPCtksHP4txx7tQj1eKAS2SsdHGzgy%2FQSG2pD%2BufKjGhxz7Xfa%2FMT50dy%2B8sGffUieBakjXDEPHKiNZnmAO137%2FVkGD8hSDrVAU8Cf1dz2tBxCpx0sn%2Bos%2BReoq3bT8Ix0Dfd1fpkOIC6tC4RMOCDdj3d7fiiS2S44Oj2MBJxFMWV2AXTNynsvukQi79AmffIeMJKcJUmQJyIUfVF5BsMvw0F8EFk47KfovfL9i%2BmUdRWYwwRHXUcysfBbqk03nyPbRP9lFRaYNwBaqHkAlICCLwS2aCAHVYFMaweBAih2Crx9vv90%2BPN7ePQ5Iqf%2BV%2Fn76k%2Fy6e%2Fyz9%2F7xYfh0VfqVVnqCJUC7y%2F9MCbSs8%2BMZ3lfnn7qm1hnhZd30qpqZ7Qe1q5gVPoh11czGBmyPpZizKPFVbg8vt3VXVEw%2FgJX%2FpuWWD%2BX8wOFVcE9rRaXwoZWr4NYUXEVjJI61lFUll%2BtIb1l0%2BUiMFE2x92b%2F4Ml%2FTHw3QlxgmChm1pz88rtTKnWJ%2BmZEo2EdoLlR4j14pBiLb9wq2x55eBwvvtml7RLX9CalNv%2BYxfe1Sfp3e8fTyfuBa%2FEf%2FPrlgTLImmIamEs6Id886afcN1ctT0266TPCmD4zwmFEOEAm1aO%2FnTCZBjpd1%2F2eav6eqqocffNATDsOHx%2Fk025ip%2F4Fj%2B7JnDwRlP92wnTPD9tx3WqObyP6qjcc1lBKFwI2KoOtAR5sVW8VbD7Idl1s1FxsaDpjiEC9tUaX1QjtLjUyp6RAiQD%2Fg61Ys1%2F2WqO7e6kh4ldjS41MWAtQIaqo539TS0wXHMS2v6mxFX8h6pjdYEOKQB%2B3usEGeOfv6qJzGlHnYWrVRQe8N3a1mjWtJlKQGNz9tyvLHeXC3Jbd5P2%2Ba1QcgQ3oHk10%2BQWvZXqLEF86Ugqb5osEjmirSPFby9oNSJY3NM1wsIxw4Jnu1eHcw%2BE0BKC26nBC3ru4ms6appNZFmlaTcvJ9mO0azghv508D%2FyROYrTC8MszHTpClrfgHaBa7kOb0VBQ3478WRFeZ0NaOiws84GlCVZ1jsHywhMJK6CUTsRDQIZ0UdqTRWiMXlpWstBK3hGm6aENMEqJaMGs4ofGd9oYU3FuLQqllgyZtRWCJVBidrq4YjN8BXICZ5JlfCgWzb%2FuyQi2W44mvfJ2j6Wt5W9T2YbElVMliWMNFeFZnPaINw84E2CVlUws3Ftaq%2Fq%2Brb25EUy4sNKb4UDfScjvZm4lUQNbRe1tcQrQH21xNc3P4gXXnE7dFJmSmN8U6gbEqppqLRuuSuDGU3Thuo4RyiOQXWkG0Wq35C11tr%2BtcN39Tz5jmCZ78Coz3fGwEG55YUZH8U5Wb5XXf0cixZsqhOsmz%2FOddTyyZ5MnV9D5cUALCup2SwdK1Su8rtclun9Tnl0jZcDjQmtIpmPx7Sad6jyi%2Bjr1jEHU77lfzSpEi0Ak%2BxK23nOMisXXiHumedeFhpcOq4IljcWNdngcBVtbDSGK%2BJtGt2loqsHsrYJLh4vxoXTNB4vQ4BXYzfZINFNTImkzUtIZenSruPhm2xot6SJEgfY%2BHzq73jUoZcdxCuuOP3ZiehMWL43doJZnCA9KtycEF%2BfUpDy%2BdnIuNowZzjfBUmyztFGEZ2HZc9nHI43oIr%2BpqJ%2FVd2VNrK6kF84aa1qbn7voCTCC898Nh3XHLn4t72xI3M30hFNIuT8zrFuYcsqoMjdKPRKHPX43chM7yO6MQT5CJomyxAeBlgValK3bJahLotEVlOBlOVLlTDWJR01BbMoaa90ZIbX%2BTuUe5EXGw7I7E8XzdLxaMzTxTaxPm6dLvGtV3f5zYusSiqTiV4%2BcigyIRrjVUpkAkZXqP8NJCGDJ5MqS9qWGMvryMSnkdFjMaRGTJBT1%2FmwYZ0PWS%2BMQ1EVWfHmdD4flgQygKQvmfhn9%2FRVItCjgD0DV7Dk8SrOifxfqwUReTIS2V9ElusvbGnk%2BpNw7keS5c%2FOdBmwLYR6EAHfyYl89X9oTjhLuPz25a1ztxr1P3969%2Fn5w1%2B64G5LDqJTiVQXdlmIwegUNxQlWc53GA%2ByybJ163%2FLCdhTiZKrCkOYulHyBg9iCfnIp1fRO%2FOIhjl5zdF0pFxhEW4vVXlbrksxU5k9LxvEVyY%2B%2BU%2Frg1nY7g2H35M2%2F4lz%2FK%2B6ZVphzIHommnYlD0QosoHanF8rD2%2B2DLB89JB01QmCiuQRFEUtrGoHjyjk1mvS68oG%2F3ursSK6uZ9dw4rOKZ5Z3OBEIR1cyO6gq6Mwo%2FelLkXqpszymDdwJwKeqMljuzKRq7LkNbTms%2FoeoZNqkkGepP%2ByKnoIVZb1KWY0ZUMpaCEtHYJd5ZOcJlwtU3h7jTBk2IgszuW76Ps7ecytyCo7Ir6QKnr7HjTA0ybhgVe1RwaLeStg7M8ASWrWbnefeiF4NM61JRl%2BB44%2BLT7%2BIjGy%2B62f7x0IrLLHrxSax%2B8Kqeza6xn1fSlB%2BeUzl44hYEUjrjKQYm7%2F4Gp46YWMxs0%2Ben%2FvY0J2xF7nUfDXhS%2Fr%2FNAwzUTn0IwJVSb0P9Nklwk0OOoemHhG4W5%2B1YUSBVm1zQWczun2%2BbF8RtQ%2BXyMoWusElK0%2BkpotzteNqfb9hxOW1lxZy3rGs8um8Ot1gkA7X2Ek1GRKnjVUpUU1%2F%2FTMmm%2B%2Fr%2BhcPB%2F" target="_blank" rel="me nofollow">draw.io で編集する</a></figcaption>
</figure>
</span>
<p><a href="/2018/02/IsWebfontEffective.html">以前のコード</a>はブラウザがサポートするフォント形式を動的に調べていました。 この為にとても小さい Data URI 化したフォントを CSS に組み込んでいました。しかし、僕の用意した小さいフォントでは動作せず、アイコンフォントを Data URI 化したものは動作するケースがありました。
<p>この原因の特定が僕の手には余ったこともあり、CSS を太らせる小さいフォントの利用は止めて、ブラウザ毎にサポートするフォント形式のリストを持つことにしました。
</div>
<p>この他にもテストページを使った検証作業で、寡聞にして言及されているのを知らない差異を発見しました。Web フォントを使用しているデベロッパー諸賢は、併せてよくご覧ください。
<div class="note">
<h3>Data URI 化した Web フォントを使用する先行事例</h3>
<p>同様に Data URI 化した Web フォントを使用している <a href="https://github.com/RoelN/font-face-render-check/" target="_blank" rel="nofollow">RoelN / font-face-render-check</a> プロジェクトがありました。こちらの最小フォントで試したところ、僕の用意したものとは結果が異なりました。
<p>また font-face-render-check は「<a href="https://www.paulirish.com/2009/font-face-feature-detection/" target="_blank" rel="nofollow">@font-face Feature Detection</a>」を参考にしているとのことです。
</div>
<h2>テスト結果</h2>
<p>? マークは暫定のバージョンです。Can I use のバージョン番号をそのままコピーして来た場合、括弧内に記載しています。
<h3>フォント形式をサポートするバージョン</h3>
<div class="hscroll">
<table>
<thead>
<tr>
<th rowspan=2>ブラウザ<th rowspan=2>WOFF2<th rowspan=2>WOFF<th rowspan=2>TTF, OTF<th colspan=2>SVG<th rowspan=2>EOT
<tr>
<th><th id="svg-font-limitation"><a name="svg-font-limitation"></a>制限(*1)
<tbody>
<tr>
<th>IE, EdgeHTML<td>14(Can I use)<td>9<td>9<td>-<td>-<td>4
<tr>
<th>Presto Opera<td>-<td>11.50<td>10.10<td>11.50(*1)<td>~12.x<td>-
<tr>
<th>Gecko<td>39(Can I use)<td>1.9.2<td>1.9.1<td>-<td>-<td>-
<tr>
<th>Safari<td>10(Can I use, *7)<td>5.0<td>3.1<td>3.1(*1)<td>~3.x<td>-
<tr>
<th>iOS Safari(*6)<td>10(Can I use)<td>5.0(Can I use, 6.1で〇)<td>4<td>3.1(*1)<td>~4<td>-
<tr>
<th>Chrome<td>36<td>6<td>2<td>1~36(*1, *2)<td>~5<td>-
<tr>
<th>Android WebView ~4.4.4<td>-<td>4.4.0(*4)<td>2.2(*3)<td>3.0(*3)<td>-<td>-
<tr>
<th><a href="https://developer.android.com/about/versions/lollipop?utm_source=ausdroid.net&hl=ja#WebView" target="_blank" rel="nofollow">Chrome for WebView</a>(*5)<td>37<td>37<td>37<td>-<td>-<td>-
<tr>
<th>PS4 WebKit 605.1.15, 11.0<td>-<td>〇<td>〇<td>〇<td>-<td>-
<tr>
<th>PS Vita WebKit 537.73, 3.74<td>-<td>〇<td>〇<td>〇<td>-<td>-
<tr>
<th>PS3 WebKit 531.22.8, 4.90<td>-<td>-<td>〇<td>〇<td>〇<td>-
<tr>
<th>Switch WebKit 609.4<td>-<td>〇<td>〇<td>〇<td>-<td>-
<tr>
<th>WiiU WebKit 536.30<td>-<td>〇<td>〇<td>〇<td>-<td>-
</table>
</div>
<ol>
<li>SVG フォントの制限について詳しくは「<a href="/2023/07/optimize-svg-font-with-svgo.html#svg-font-limitation">svgo を使って SVG フォントを最適化する、その際の注意点は? / <font> タグの id 属性は残す / SVG フォントの制限</a>」参照。
<li><q cite="https://caniuse.com/?search=SVG%20font">Chrome 38 and newer support SVG fonts only on Windows Vista and XP.</q> <del>Can I use では Chrome ~37 となっている。多分誤り。ただし動作確認はポータブル版の Iron で確認している。</del>Windows XP + Iron では39までサポートする。
<li>Android 2.3, 3.1実機で確認。
<li>Android x86 4.4.2, 4.4.4で確認。
<li>Android x86 5.1.1 Chromium M39 で確認。
<li>iPod touch 実機 3.1.3, 4.2.1 6.1.6 で確認
<li><q cite="https://caniuse.com/?search=WOFF2">Supported only on Safari for Mac OS Sierra, not El Capitan & older.</q> ちなみに Sierra のバージョン番号は10.12
</ol>
<h3>合字、絵文字への割り当て、Data URI、WebKit フォールバックバグ</h3>
<p>合字をサポートするブラウザの中には、アルファベットの文字列のみをサポートするもの(合字 1)から、記号の組み合わせをサポートするものまで何段階かあるようです。
<div class="hscroll">
<table>
<thead>
<tr>
<th>ブラウザ<th><a href="#ligature">合字 1</a><th>合字 2<th>合字 3<th><a href="#emoji">絵文字</a><th><a href="#data-uri-scheme">Data URI</a><th><a href="#webkit-fallback-bug">WebKit フォールバックバグ</a>
<tbody>
<tr>
<th>IE, EdgeHTML<td>18?<td>18?<td>18?<td>8<td>9<td>-
<tr>
<th>Presto Opera<td>10.10<td>-<td>-<td>10.50<td>10.10(*1)<td>-
<tr>
<th>Gecko<td>1.9.1<td>1.9.1<td>2.0<td>1.9.1<td>1.9.1b3(*12)<td>-
<tr>
<th>Safari(*8)<td>3.1(*5)<td><td><td>3.1(*4)<td>3.1<td>~6.x(<a href="https://github.com/bramstein/fontfaceobserver/blob/39f19c41830eac7726e08b09f60d2aa2b74dc38b/src/observer.js#L88" target="_blank" rel="nofollow">Font Face Observer より</a>)
<tr>
<th>iOS Safari<td>3.1(*11)<td>(6.1でも-, 12.5で〇)<td>(6.1でも-, 12.5で〇)<td>3.1<td>4.2<td>~6.1
<tr>
<th>Chrome(*8)<td>1(*6)<td>15(*7)<td>34(*7)<td>1<td>2(*2)<td>9~17
<tr>
<th>Android WebView ~4.4.4<td>3.0(*3, *9)<td>-<td>-<td>2.2(*3)<td>2.2(*3)<td>~2.3
<tr>
<th>Chrome for WebView(*10)<td>37<td>37<td>37<td><td>37<td>-
<tr>
<th>PS4 WebKit 605.1.15, 11.0<td colspan=3>SVG:一部, 他:〇<td>〇<td>〇<td>-
<tr>
<th>PS Vita WebKit 537.73, 3.74<td>SVG:〇, 他:-<td>-<td>-<td>SVG:〇, 他:一部<td>〇<td>-
<tr>
<th>PS3 WebKit 531.22.8, 4.90<td>SVG:〇, 他:-<td>-<td>-<td>〇<td>〇<td>〇
<tr>
<th>Switch WebKit 609.4<td>SVG:-, 他:〇<td>-<td>-<td>〇<td>〇<td>-
<tr>
<th>WiiU WebKit 536.30<td>SVG:〇, 他:-<td>-<td>-<td>SVG:〇, 他:一部<td>〇<td>-
</table>
</div>
<ol>
<li>但し、テスト用の最小フォントでは何故か不可
<li>4~5 テスト用の最小フォントでは何故か不可、6~31 テスト用の最小フォントは SVG のみ
<li>Android 2.3, 3.1実機で確認
<li>Safari 3.x では SVG フォントのみ、4.0 以降では全てのフォント形式で有効
<li>SVG フォントのみ(3.x, 4.0.5, 5.1.1 で確認)
<li><ul><li>Chrome 1~14では合字は SVG フォントのみ。
<li>TTF, OTF, WOFF には <code>-webkit-font-feature-settings:"liga";</code> が必要。一方の SVG フォントはこのプロパティが不要。
</ul>
<li>SVG 形式を除く
<li>Safari 3.xと Chrome 1は SVG フォントのみ、合字1, 合字2, 合字3 が有効だった。
<li>SVG フォントのみ(3.1実機, 4.2.2実機, Android x86 4.3で確認)。4.4.0では他のフォントも(Android x86 4.4.2, 4.4.4で確認)。
<li>Android x86 5.1.1 Chromium M39 で確認。
<li>SVG フォントのみ(iOS 3.1.3, 4.2.1 6.1.6 で確認)
<li>1.9.1b1 不可, 1.9.1b2 未確認
</ol>
<a name="ligature"></a>
<h3 id="ligature">1. 合字</h3>
<p>てっきり <code>font-feature-settings:"liga"</code> をサポートするブラウザで使用可能かと考えていましたが、思ったよりも古いブラウザから合字をサポートしています。JavaScript でフォールバックするブラウザの範囲はかなり絞られるようです。
<h4>部分的合字サポート</h4>
<p>しかし、文字列によっては合字しない「部分的合字サポート」のブラウザが存在します。これに該当するブラウザは、ページ上に存在する全ての合字の描画状況を JavaScript で調査してフォールバックします。
<a name="emoji"></a>
<h3 id="emoji">2. 絵文字にフォントを当てる事が出来るか</h3>
<p>Web フォントが読み込まれない場合にも、元が絵文字であれば影響が最小と考えました。しかし案の定、絵文字には Web フォントが当たらないブラウザが見つかりました。IE7 以下、Opera 10.5 未満、Safari 3.x の TTF, OTF が該当します。
<h4>副作用の少ない空白文字のセットを探す</h4>
<p>この結果を承けて僕のブログでは、空白文字にアイコンフォントを割り当てる方向で考えていきます。因みに空白文字が豆腐になったり、点になるブラウザも存在します。44個の空白文字の内、IE5 で綺麗に空白になる22個を見つけたので、これに割り当てていきます。
<a name="data-uri-scheme"></a>
<h3 id="data-uri-scheme">3. Data URI スキーム</h3>
<ul>
<li>IE8 は制限が大きく、画像しか Data URI 化できない。
<li>Gecko 1.9.1b1 では不可。
<li><a href="/2023/07/optimize-svg-font-with-svgo.html#svg-font-limitation">SVG の制限</a>と組み合わさって、SVG フォントしかサポートしない Chrome 1, iOS Safari 3.x ではフォントを Data URI 化して利用することが出来ない。しかし <a href="/2018/02/IsWebfontEffective.html#2-3">Data URI 化したフォントは、通信最適化アプリ等によるブロックをすり抜けるために用意している</a>。画像ファイル形式である SVG までブロックするとは考えずらいのであまり気にしていない。
</ul>
<a name="webkit-fallback-bug"></a>
<h3 id="webkit-fallback-bug">4. WebKit フォールバックバグ</h3>
<p>初期の WebKit は、Web フォントの適用前の状態が他のブラウザと異なります。この為に「<a href="https://web.archive.org/web/20180425063949/http://www.lalit.org/lab/javascript-css-font-detect/" target="_blank" rel="nofollow">伝統的な Web フォントの適用の検出法</a>」が使えません。
<p>一部の WebKit では Web フォントの適用前に「最後の手段フォント(Last Resort Font)」が使用される為に、伝統的な検出法を欺いてしまいます。これを回避する為に一部の WebKit では異なる検出コードを用います。
<p>この詳しい挙動と解決法については <a href="https://github.com/bramstein/fontfaceobserver/blob/39f19c41830eac7726e08b09f60d2aa2b74dc38b/src/observer.js#L93" target="_blank" rel="nofollow">Font Face Observer の <code>Observer.hasWebKitFallbackBug</code> を参照しました</a>。<ins title="2024/02/07 追記">Font Face Observer では Webkit 536.11 以下(Safari 6に相当)に対して異なる検出コードを用いています。しかし UserAgent 文字列のバージョンを調べる簡易な方法では Webkit の派生ブラウザをカバーしきれません。</ins><ins title="2024/02/04 追記">ご覧の通り、本記事では同時代の様々な WebKit ブラウザについてフォールバックの必要なバージョンを特定しています。</ins>
<h4>iOS 4.2で検出に失敗する問題</h4>
<p>このコードを用いても iOS 4.2では5秒のタイムアウト迄に Web フォントが適用されない問題に遭遇しました。原因は <code>setTimeout</code> のインターバルを 16ms にしていた為で、<a href="https://github.com/itozyun/web-doc-base/commit/809332ef9cf333ec094f64a42cb002a1058294e8#r137897167" target="_blank" rel="me nofollow">64ms に変更した</a>ところ、iOS 3や iOS 6と挙動が一致し検出ができるようになりました。iOS 5では端末を所持していなくて確認出来ていません。
<p><em>iOS 4では、文書読み込み時などの忙しい時に、短いインターバルを設定してしまうと、Web フォントの処理が極端に後回しにされてしまうようです。</em>32ms でも問題に遭遇することを確認しています。
<p>因みに Font Face Observer ではタイマーではなく、より巧みな <code>scroll</code> イベントで Web フォントの適用タイミングを検出しているため、この問題を踏んでいません。
<h2>最後に</h2>
<p>本記事で示した対応表は Can I use 提供のソレと微妙に一致しません。Can I use が参照している browser-compat-data も怪しいデータはあるので、やはりブラウザをインストールして愚直な調査が重要ということです。
<p>iOS 5のインストールされた iPod touch 第三世代が入手困難なのと、Genymotion が古い Android のサポートを切っていくのに難儀します。頑張って行きましょう。
<h2>参考記事</h2>
<ol>
<li><a href="https://hail2u.net/documents/bulletproof-at-font-face-syntax.html" target="_blank" rel="nofollow">安全な <code>@font-face</code> の書き方</a>
<li><a href="https://docs.google.com/presentation/d/1n4NyG4uPRjAA8zn_pSQ_Ket0RhcWC6QlZ6LMjKeECo0/edit" target="_blank" rel="nofollow">@font-face web font research</a>
</ol>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-1141503622986213072023-09-19T13:47:00.070+09:002023-09-30T15:56:44.988+09:00アイデアスケッチ、JavaScript だけで宣言的 UI を読みやすく記述する<div class="note"><p><a href="https://cycle.js.org/">Cycle.js</a> が同じ発想の記法を採用していました。この記事に新規性はゼロですね…(2023/09/30)
</div>
<p>宣言的 UI を JavaScript だけで、人間に読みやすく表現するアイデアです。Vue の作者による 6KB の <a href="https://github.com/vuejs/petite-vue" target="_blank" rel="nofollow">petite-vue</a> を眺めていたら頭に浮かびました。実装はありません、悪しからず!
<h2>はじめに</h2>
<p>これまでも JavaScript の関数呼び出しで UI 構造を表現していくことは、度々取り組んできて、これが上手くいくことは分かっています。直近では、<a href="https://github.com/itozyun/TinyTemplete" target="_blank" rel="me nofollow">JavaScirpt の関数呼び出しで HTML 構造を定義するテンプレートライブラリ</a>を書いて WebViewPanel を使う VSCode 拡張の開発に使っています。(<a href="#note-1">*1</a>)
<p>しかし、プライベートで宣言的 UI に向く Web アプリを作る動機が弱い(<a href="#note-2">*2</a>)ので、宣言的 UI ライブラリ自体に疎かったりします。例えば、この記事を書くための調べごとの最中に <a href="https://svelte.dev/" target="_blank" rel="nofollow">Svelte</a> を知りました。(<a href="#note-3">*3</a>)
<div class="note"><p><a id="note" name="note-1">*1</a> WebView パネルを使う VSCode 拡張は、SPA でも実装できますが、初回表示の HTML はバックエンド(nodejs)側で生成し、以降は WebView 側で CSR する、ハイブリッドレンダリングにしました。この Webview と nodejs で UI 関連のコードを共通化する為に、テンプレートライブラリを自作しました。UX への貢献は微量だと思いますが、こういう機会でもないと、ハイブリッドレンダリングに挑戦しないので。
<p><a id="note" name="note-2">*2</a> 一方で業務向け開発では、宣言的 UI に適した案件が多いと思います。
<p>ブラウザの提供する文書閲覧機能とフォーム部品をほぼそのまま使ってデータを表示して操作するアプリケーション開発は、宣言的 UI ライブラリとの相性が抜群だと思います。
<p>React や Vue 等に関心が低いのは、React と同時期に Virtual DOM を備えた <a href="/2015/03/vdom.html">DOM フレームワーク</a>の開発に取り組んでいて、<i>ふーん</i>と横目に見たまま来てしまった、というのがあります。しかし VSCode 拡張で Webview アプリに取り組むと、正に宣言的 UI ライブラリに頼るべきものでした。
<p><a id="note-3" name="note">*3</a> 僕には Svelte の「ビルド時に負荷を移すコンパイラ」というアプローチが決定的に思えて、記事を残す意欲が少し萎えたのですが。コンパイル結果をほぼ Vanilla JS 状態に出来るなら、宣言的 UI ライブラリの軽量版が登場する動機の大半を解消していると思います。
<p>いずれ Svelte を触ってみて、この方向を進めるか、Svelte で満足するか、判断しますね。
</div>
<h2>商品リストをクリックするとカートの数字が増えていくだけのモックアプリ</h2>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1MLdEb9-6JawML8jrWAyBIDxeW-GdZie1iPLTZ0qqmRp6qf1XsF0BXrbgjsm8WWBvg3i0xhYfoJjsZx8cuf40_DOlxOFP8DfUkzz58JUeKmoer92VWOiOFKhulLn2Nd02lP0w8mO9SYSwjP2mT2cR-a2wIHBUJRoavz8JbHAkBMroRU0ivrwSrUvly5A/s800/cart.drawio.png"><img alt="" data-original-height="800" data-original-width="800" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1MLdEb9-6JawML8jrWAyBIDxeW-GdZie1iPLTZ0qqmRp6qf1XsF0BXrbgjsm8WWBvg3i0xhYfoJjsZx8cuf40_DOlxOFP8DfUkzz58JUeKmoer92VWOiOFKhulLn2Nd02lP0w8mO9SYSwjP2mT2cR-a2wIHBUJRoavz8JbHAkBMroRU0ivrwSrUvly5A/s160/cart.drawio.png"></a>
<figcaption><a href="https://viewer.diagrams.net/?tags=%7B%7D&highlight=0000ff&edit=_blank&layers=1&nav=1&title=cart.drawio#R7Vpbk5s2FP41PMYDiOsj%2BJI%2BtDOe7kObvGS0IGMlGFGQY5xfXwnEVdheb7HjdNezs5Y%2BiSN0vnMTWAHzXfExg%2Bn2DxKiWNHVsFDAQtF1xzTYfw4cK8C27AqIMhxWkNYCT%2FgHEqAq0D0OUd6bSAmJKU77YECSBAW0h8EsI4f%2BtA2J%2B6umMEIS8BTAWEb%2FwiHdim2paov%2FhnC0pYOBHaznCiDfwpAcOhBYKmCeEUKr1q6Yo5irrlZLdd3qxGhzXxlK6Esu%2BEr%2B%2FPzx62f1x9yBXw7m0kbqpw%2BCnO8w3ov9ipulx1oBhy2m6CmFAe8fGMcK8Ld0F7OexpowTyu1b3CB2FL%2BBsfxnMQkY1iINnAfs1E%2Fpxn51miQbd4XK6OMouLklrRGUcy%2BENkhmh3ZFHGBIVR77HcPLU92rf1th6MGhMI2okZyqz%2FWECq8Qp3aZXV2VMf3jpml%2FQ6fUbwmOaaYJGzsmVBKdly3MY44EDB9IKZPP%2BYzfRh8izKyT8JazYoONuWnI9QT11KSSuo3GqQjQVUddaXykdpQeSeE%2BZbTuhAjKd%2FGroi4r88wye0ZZp6Xz%2FItSVOcRF8CmNFp2DXdPr22TK%2BmjdDr3opd%2Fc2yG%2Byf0TSkDjhlNyaR6t6TU3CZU5SEHk8krJeQBPXDX8lUq8ITUQ6FUpK5qLCORswRjdRYhmJI8fe%2B%2BDE1iRXWBLOFT4VQzRkoOif7LEDiom52GcixrQuCKMwiRCVBJWnNrl%2FPoznCo1Vmng0p77Ml1PpnT%2BqBD3lZcHhsgqGmRUlYPc5aEf9eo6SWxW6tEleNSKbC%2FIL27aPviMJ%2BuilSQHUwiNGGjvj5DochX8Qfy8Z9G%2BQ3KMooQ53GaYdWoluy11ojNgpu5bWWzPZypfgrxTOblDApLU2MfixiTOcyMRq4JzPOpPEUFZj%2Bzdsz1bRE%2F1PZN5y6vyg6kxfHTmeNMsx2xXmrsITtsBLnGkYN9ORxoBVY9o7d3lDko4d325253Y%2FRMxdgMcV2P9Yrg7%2FmzoDZruJctcqNM0MdD86aZByz8%2BQpNz532rnJucay%2B279wnBr3exYI59rtLcTZIds2ObPTX7a%2Bzlk8nOIof7kc4gmH0S8NGV0vtES0xg5GN7Xy0YejTU1piV73P82%2FA1rzDFm7ltjamOHvfci80GLTHNoB9NUlZLYW5eRI2fO96z737KuOfJI975Z15ZIXeMEwbecea2RUui%2BmXfkGUKdeQ1gvd3MO8bMnTOv%2B555f53Ma6s3ybyS2BtnXl1%2B%2BiAZXZ29NjEqhPX5HUMMYpjnODhni%2F0sanOfF22zkiWc25k52i9gGWDwPgYYr7QFAPqCpGR8a%2FZf8LTjOqY7ccIC1iBOtIHjmjjRBjJDs3uBDLCQeW0gk58pNpWaJjprSNn8pER09RqDZIormT%2BjchFFKmLPZYNHMnD9tW8ujYGBA%2FtlBs4sDh4701I%2BIT9zw8NXrVrv9zqsUUmc1ntG3m8vgeLoircqG0DxPNFgf70hTXFdgTi%2BQDynnuOLq%2Fx5fblTz1kqS0txTcVXlaWpeAvFtcWQMy8RvYM47RIPXnBr1jRl3dBytbEHKs40ZR3rtr8wq4yq%2FZUeWP4L" target="_blank" rel="me nofollow">draw.io で編集する</a></figcaption>
</figure>
</span>
<p>商品リスト(<code>products.json</code>)を <code>fetch</code> して表示し、クリックするとカートの数字が増えていく、というアプリケーションのモックを考えてみます。
<p>商品リストは、SPA で実行する場合は <code>XMLHTTPRequest</code>(<code>fetch</code>) で取得します。SSR する場合は <code>fs</code> で読み込んでリストを完成させ、併せてクリックイベントハンドラを <code><script></code> で埋め込みます。
</div>
<p><code>products.json</code> は次のようなものとします。
<pre class="prettyprint lang-json"><code>[
{ "name" : "pen", "price" : 110 },
{ "name" : "apple", "price" : 162 },
{ "name" : "pineapple", "price" : 436 }
]
</code></pre>
<h2>以上のモックを JavaScript だけで宣言的に書いてみる</h2>
<p>JavaScript の関数呼び出しを使って、HTML 的な構造を表現しています。<code>.vue</code> 的なアプローチでなくとも、生の JavaScirpt の表現力で UI 構造とスクリプトをひと纏めにしてみました。
<pre class="prettyprint lang-js"><code>scope(
section( // <section>
Icon('cart'), // <svg>
span('{{count}}') // scope.data.count
),
section( // <section>
ul() // <ul>
.each(
'products', // scope.data.products
li( // <li>
b('{{name}}'), // products[i].name
span('{{price}}') // products[i].price
).on(
'click',
() => {
this.setData('count', this.getData('count') + 1);
}
)
)
)
).initData(
'count', 0, 'w' // read / write
).onDOMReady(
() =>
fetch('products.json').then(
(response) =>
this.initData('products', response.json, 'r')
)
);
</code></pre>
<ol>
<li><code>getter</code>, <code>setter</code> はあえて使いませんでした。
<li>Vue の <code>"computed"</code> 的なものは要りますね。
<li><code>li</code> インスタンスの <code>getData, setData</code> は、自身と対になる <code>product</code> オブジェクトのデータを探し、続いてスコープのデータを探す。
</ol>
<h3>SPA またはアプリ開発中の簡易実行</h3>
<p>上記 JavaScript を次の HTML の中に記入すれば、SPA として実行できる、とします。
<pre class="prettyprint lang-html"><code><script src="spa.js"></script>
<div v-scope>
<script>
// document.currentScript から [v-scope] 要素を求める
// scope( ... );
</script>
</div>
</code></pre>
<p>グローバルが <code>section</code>, <code>ul</code> といった関数(というか Virtual DOM のコンストラクタ)で汚染されているのが前提になるので、やっぱり簡易実行用途ですね…
<h3>SSR された HTML はこんな感じ</h3>
<p>Web サーバ内にある <code>products.json</code> を使って SSR した HTML が次です。
<p><code>onDOMReady</code> ハンドラが解決されるまでに構築出来た HTML を配信して、<code>.on('click')</code> などのハンドラは回収して、<code><script></code> タグに埋め込んでいます。
<p>このくらい単純でしたら、僕でも SSR のコードを書けそうな気もしますが…。ある程度複雑なアプリに耐えうる SSR が書ける自信やモチベーションは今のところ無しです。
<pre class="prettyprint lang-html"><code><script src="ssr.js"></script>
<div v-scope>
<section>
<svg>...</svg>
<span v-bind="count">0</span>
</section>
<section>
<ul v-each="products">
<li v-click="func-xxxxx"><b v-bind="name">pen</b><span v-bind="price">110</span></li>
<li v-click="func-xxxxx"><b v-bind="name">apple</b><span v-bind="price">162</span></li>
<li v-click="func-xxxxx"><b v-bind="name">pineapple</b><span v-bind="price">436</span></li>
</ul>
</section>
<script>
init(
{
data: {
count: 0,
products: [
{name: 'pen', price: 110},
{name: 'apple', price: 162},
{name: 'pineapple', price: 436}
]
},
xxxxx: () => {
this.setData('count', this.getData('count') + 1);
}
}
);
</script>
</div>
</code></pre>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-43276908678536906632023-07-16T11:12:00.024+09:002024-01-26T02:31:47.169+09:00svgo を使って SVG フォントを最適化する、その際の注意点は?<div class="note">
<p>「<a href="/2023/10/webfont.html">アイコンの為に Web フォント、合字を深堀してフォールバックを検討する</a>」での調査を元に「<code><font></code> タグの id 属性は残す」の id が必要なブラウザに iOS Safari 3~4 を追記。(2024/01/26)
<p>「エンティティ」表記を「数値文字参照」に修正しました。追記と修正をしています。(2023/08/16)</div>
<div class="box">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5yRCKdNxxQ8OR2mNd3qUgMbn8hsDN-24p6tZ5CVJa3FysM0PuduziFFW76O9dlYLXiReTyhLo_XOdfRzhK2wwZ4p9mK3xjxdLJ4yISp3KbrVHhEGlSU579XGpC9u94-W2qptZ3X1_FPZ3xjWH_XonE_4MAHIB-swRyufwN_kmEhkeYuYVemSIEynYLGU/s1120/glyphs-to-svg.png"><img alt="" data-original-height="1120" data-original-width="1120" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5yRCKdNxxQ8OR2mNd3qUgMbn8hsDN-24p6tZ5CVJa3FysM0PuduziFFW76O9dlYLXiReTyhLo_XOdfRzhK2wwZ4p9mK3xjxdLJ4yISp3KbrVHhEGlSU579XGpC9u94-W2qptZ3X1_FPZ3xjWH_XonE_4MAHIB-swRyufwN_kmEhkeYuYVemSIEynYLGU/s160/glyphs-to-svg.png"></a>
<p>icomoon で作成した SVG フォントを <a href="https://github.com/svg/svgo" target="_blank" rel="nofollow">svgo 3.0.2</a> で最適化したところ<strong>ファイルサイズは、53KB から 23KB へ43%になりました</strong>。
その注意点と svgo の設定をご紹介します。
<p>因みに、svgo は SVG フォントを最適化することにも使われていますが(<a href="https://github.com/svg/svgo/issues/140" target="_blank" rel="nofollow">issue 140:Hex Entities Incorrectly Converted to Unicode</a>)、公式にサポートされてはいません。自分でトライエラーを繰り返して設定を特定しました。
</div>
<h2>unicode 属性を数値文字参照へ</h2>
<p>icomoon が出力する SVG フォントを参考に unicode 属性を数値文字参照にしていますが、この処理は不要かもしれません。いずれ各ブラウザでチェックして追記します。(2023/08/16 追記)
<pre class="prettyprint lang-xml"><code><glyph unicode="🏠" d="..." />
↓
<glyph unicode="&#x1f3e0;" d="..."/>
</code></pre>
<p>先の issue 140にある通り、svgo が利用している XML パーサーの <a href="https://github.com/svg/sax" target="_blank" rel="nofollow">sax</a> は unicode 属性の数値文字参照を解除してします。これを再び数値文字参照にします。
<p>svgo のコードを見ていくと、XML DOM をテキスト化する工程をカスタマイズする手段が無いようなので、文字列操作で数値文字参照にしました。詳しくは <a href="https://github.com/itozyun/web-doc-base/blob/c725f4b92e9bce8380c35956d25d207368d98e9e/js-buildtools/web-font.js#L127" target="_blank" rel="me nofollow">web-doc-base / js-buildtools / web-font.js</a> 127行を確認ください。
<h2><code><font></code> タグの id 属性は残す</h2>
<p>id 属性は削除しません。そして一部のブラウザは CSS 側でフォントの URL のハッシュフラグメントに id を指定しないとフォントが適用されません。id が必要なブラウザは、Chrome 1~5, Safari 3.1~3.2, <ins title="2024/01/26 追記">iOS Safari 3~4,</ins> Presto Opera でした。
<pre class="prettyprint lang-xml"><code><font id="<u>web-doc-base</u>" horiz-adv-x="1024">
</code></pre>
<pre class="prettyprint lang-css"><code>@font-face {
font-family: myIconFont;
font-weight: 400;
font-style: normal;
src: url(icon.eot?rw1juc);
src: …, url(icon.svg?rw1juc#<u>web-doc-base</u>) format("svg")
}
</code></pre>
<a name="svg-font-limitation"></a>
<h3 id="svg-font-limitation">SVG フォントの制限</h3>
<p>余談になりますが、つまりこれらのブラウザでは Data URI 化して CSS に埋めることができません。Data URI ではハッシュフラグメントを表現できないためです。そもそも CSS 化したフォントは、ネットワークの最適化ツールのブロックのすり抜けを狙っています。しかし、他のフォント形式と異なり、画像形式である SVG はネットワークの最適化ツールのブロック対象からはお目こぼししてもらえそうですので、問題にならないようにも思います。
<h2>最適化</h2>
<p>この為のオプションは <a href="https://github.com/itozyun/web-doc-base/blob/c725f4b92e9bce8380c35956d25d207368d98e9e/js-buildtools/web-font.js#L55" target="_blank" rel="me nofollow">web-doc-base / js-buildtools / web-font.js</a> 55行にあります。
<h3>最適化しない属性</h3>
<p>半角スペースのグリフを最適化から保護します。この為の指定が <code>cleanupAttrs:false</code>, <code>removeEmptyAttrs:false</code> です。
<pre class="prettyprint lang-xml"><code><glyph />
↓
<glyph unicode="&#x20;" d="" />
</code></pre>
<h3>パスデータを整数に丸めて glyph-name 属性を削除</h3>
<p>整数に丸める事で SVG フォントのファイルサイズを大きく削減出来ます。例えば icomoon の出力する SVG フォントの論理空間は 1024x1024 と巨大ですので、アイコンや通常のテキストとして使う分には目視できる副作用はありません。(2023/08/16 修正)
<p>glyph-name 属性は、先の unicode 属性と同様に文字列操作で削除しました。
<pre class="prettyprint lang-xml"><code><glyph unicode="Windows" glyph-name="Windows" d="M0.35 384l-0.35 312.074 384 52.144v-364.218zM448 757.518l511.872 74.482v-448h-511.872zM959.998 320l-0.126-448-511.872 72.016v375.984zM384-47.836l-383.688 52.594-0.020 315.242h383.708z" />
↓
<glyph unicode="Windows" d="M0 384v312l384 52V384zm448 374 512 74V384H448zm512-438v-448L448-56v376zM384-48 0 5v315h384z"/>
</code></pre>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-28742845202315641562023-07-15T14:44:00.071+09:002024-02-12T16:41:17.065+09:00完全に状況を掌握した CSS の遅延読み込みの実現<div class="note"><p>Wii の Opera 9.30でテストして Opera の B グレードを 9~9.27 → 9~9.30 に修正しました。(2024/02/12)
<p><a href="https://github.com/itozyun/web-doc-base/blob/811c2a11a4c8ffef08322a5402d4406af0e1a159/src/js/8_Library/ExternalCSSLoader.js#L133" target="_blank" rel="me nofollow">現在の実装</a>に沿って動作の記述を変更しています。(2023/07/28)
<p>Gecko が A グレードになるバージョンを特定しました。(2023/07/16)
</div>
<p>本記事の調査結果を元に記述した <a href="https://github.com/itozyun/web-doc-base/blob/5223e9b5758b42d2ba65f51a449d5c8d6535d272/src/js/8_Library/ExternalCSSLoader.js" target="_blank" rel="nofollow">ExternalCSSLoader.js</a> をあわせてご確認ください。
<h2>3行まとめ</h2>
<ol>
<li>A, B, C, Z(動的外部 CSS に非対応) の4つのグレードに分けられる
<li>A グレード(<code><link></code> に <code>onload</code>, <code>onerror</code> を備える)ブラウザの登場は意外に遅め
<li>C グレードでもあまりパフォーマンスを損なわない
</ol>
<h2>はじめに</h2>
<p>本記事のタイトルの「CSS」を「画像」に替えると、皆さんご存知 uupaa 氏による優良記事「<a href="https://uupaa.hatenadiary.org/entry/20080413/1208067631" target="_blank" rel="nofollow">完全に状況を掌握した画像の遅延読み込みの実現</a>」と同じになります。
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1VCkZOXu7bz3CdWlGyOBf3C2jpaVwbrphzUvR0R1bQDyJ8cef5sSOiZ--kBjff6LKNlWkeXn1Dk2bUvGiz0odTQlFkWXyPJNvRapaEHbiQB5wAeQE7czexXuOk5o4_Xl5ti02AzDyyQzfxDJnGAYK01zBc8G7wIVKz_gs7-miWo0ZGi3hl2RSmLGg6xY/s705/check-css-ready.png"><img alt="" data-original-height="705" data-original-width="705" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1VCkZOXu7bz3CdWlGyOBf3C2jpaVwbrphzUvR0R1bQDyJ8cef5sSOiZ--kBjff6LKNlWkeXn1Dk2bUvGiz0odTQlFkWXyPJNvRapaEHbiQB5wAeQE7czexXuOk5o4_Xl5ti02AzDyyQzfxDJnGAYK01zBc8G7wIVKz_gs7-miWo0ZGi3hl2RSmLGg6xY/s160/check-css-ready.png"></a>
<figcaption><a href="https://itozyun.github.io/web-doc-base/test/check-css-ready.html" target="_blank" rel="me nofollow">Check CSS ready</a> 本記事の調査に使用したページ</figcaption>
</figure>
</span>
<p>さて、外部 CSS のロード(からスタイルの適用まで)の成否を掌握したい場合に、最新のブラウザでは <code>onload</code>, <code>onerror</code> が使えます(A グレード)。
<p>しかし旧いブラウザだと、ブラウザ毎に異なるイベントを使用した上で、外部 CSS に仕込んだテスト用のスタイルで要素のサイズの変化を検出して成功判定するひと手間が必要でした。
<p>更に Gecko 0.9.1未満は、そもそも動的な外部 CSS を非サポートであることが分かりました(<a href="#z-grade">Z グレード</a>)。ちょっと寂しいですが、今回は <a href="/search/label/WebFont">Web フォントの読み込みをネットワーク監視ツールなどでブロックされた場合に、Data URI 化して CSS に埋め込んだフォントで迂回する</a>のが目的です。Web フォントに非対応の当該ブラウザでは一旦困りません。Gecko が Web フォントをサポートするのは1.9.1以降になります。
</div>
<h2>テスト結果</h2>
<p>最も省コストで掌握できる <code>onload</code>, <code>onerror</code> を備えるブラウザは意外に後になってから登場したことが分かります。
<p>一方で <code>img.onerror</code> または <code>img.addEventListener('load', ...)</code> を使ってロード完了(ネットワークエラー含む)を検出するハック(C グレード)を組み合わせれば、調査した全てのブラウザで polyfill 出来ることも分かりました。
<p>異常系は存在しないファイルを指定してネットワークエラーを出しているケースです。
<div class="hscroll">
<table>
<thead>
<tr>
<th>ブラウザ<th>バージョン<th>正常系<th>異常系<th>グレード
<tbody>
<tr>
<th rowspan=3>IE<th>11<td colspan=2><code>onload(*1)</code><td>B
<tr>
<th>5~10<td colspan=2><code>onreadystatechange(*1)</code><td>B
<tr>
<th>4<td colspan=2>未チェック<td>-
<tr>
<th>EdgeHTML<th>18<td colspan=2><code>onload(*1)</code><td>B
<tr>
<th rowspan=4>Opera<th>9.5~12.18<td><code>onload, onreadystatechange(*2)</code><td><code>onerror</code><td>A
<tr>
<th>9~9.30<td colspan=2><code>onload, onreadystatechange(*1, *2)</code><td>B
<tr>
<th>7.0~7.1x, 7.5x~8.54<td colspan=2><code>img.onerror(*1)</code><td>C
<tr>
<th>7.2x<td colspan=2><code>img.addEventListener('load')(*1)</code><td>C
<tr>
<th rowspan=3>Gecko<th>9~<td><code>onload</code><td><code>onerror</code><td>A
<tr>
<th>0.9.1~8<td colspan=2><code>img.onerror(*1)</code><td>C
<tr id="z-grade">
<th><a name="z-grade"></a>0.6~0.9.0<td colspan=2>動的外部 CSS が不可<td>Z
<tr>
<th rowspan=2>Chrome<th>19~<td><code>onload</code><td><code>onerror</code><td>A
<tr>
<th>1~18<td colspan=2><code>img.onerror(*1)</code><td>C
<tr>
<th rowspan=2>Safari<th>6~(?)<td><code>onload</code><td><code>onerror</code><td>A
<tr>
<th>3.1~5.1<td colspan=2><code>img.onerror(*1)</code><td>C
</table>
</div>
<ol>
<li>隠し要素のサイズを測る等で可否の判定が可能
<li><code>link.readyState</code> は <code>undefined</code>
</ol>
<h3>B グレードについて</h3>
<p>これらのブラウザは、<code><link></code> の <code>onload</code>, <code>onreadystatechange</code> でロード完了を検出できます。続いて隠し要素のサイズを測る等して、成功とネットワークエラーを判定します。
<h3>C グレードについて</h3>
<p>これらのブラウザは、<code><link></code> の <code>href</code> に加えて <code>Image</code> インスタンスの <code>src</code> に CSS を指定します。続いて <code>img.onerror</code> コールバック内で1秒のタイマーをセットします。(2023/07/28 現在の実装に沿って修正)
<p>Opera 7.2x だけは <code>img.addEventListener('load', ...)</code> を使いました。どんなコードになろうと実現できればオール OK です。
<p>成功の場合、既に CSS はロードされているので、一瞬で CSS をパースしてスタイル適用まで進むはずです。タイマーで繰り返し要素のサイズをチェックします。1秒が経過したらネットワークエラーだと判定します。(2023/07/28 現在の実装に沿って修正)
<p>Chrome 2で <code>img.onerror</code> がコールバックされないケースがあっため、<a href="https://github.com/itozyun/web-doc-base/commit/811c2a11a4c8ffef08322a5402d4406af0e1a159" target="_blank" rel="me nofollow">5秒のタイマーによるバックアップを追加</a>しました。(2023/07/16 追記)
<div class="note">
<p>因みに、タイマーを使わずに <code>onscroll</code> を使う実装を Web フォントのロード監視ライブラリ fontfaceobserver の <a href="https://github.com/bramstein/fontfaceobserver/blob/39f19c41830eac7726e08b09f60d2aa2b74dc38b/src/ruler.js#L126" target="_blank" rel="nofollow">/src/ruler.js</a> ではしています。この為に複数の隠し要素が必要ですが、タイマーよりイベントを使った方がエレガントですね。<a href="https://itozyun.github.io/web-doc-base/test/check-css-ready-width-ruler.html" target="_blank" rel="me nofollow">テスト用のページ</a>を用意しています。
</div>
<h2>未検証の情報</h2>
<p><a href="https://github.com/googlearchive/code-prettify/" target="_blank" rel="nofollow">Google Code Prettify</a> には <code>link.error</code> というプロパティが居るのですが、これをコールバックするブラウザには遭遇していません。
<blockquote title="googlearchive/code-prettify/src/run_prettify.js" cite="https://github.com/googlearchive/code-prettify/blob/e006587b4a893f0281e9dc9a53001c7ed584d4e7/src/run_prettify.js#L177C1-L183C8">
<pre class="prettyprint lang-js"><code>if (i + 1 < n) {
// <a href="https://web.archive.org/web/20220506123333/https://pie.gd/test/script-link-events/" target="_blank" rel="nofollow">http://pieisgood.org/test/script-link-events/</a> indicates that many
// versions of IE do not support onerror on <link>s, though
// <a href="https://web.archive.org/web/20120123144751/http://msdn.microsoft.com/en-us/library/ie/ms535848%28v=vs.85%29.aspx" target="_blank" rel="nofollow">http://msdn.microsoft.com/en-us/library/ie/ms535848(v=vs.85).aspx</a>
// indicates that recent IEs do support error.
link.error = link.onerror = function () { load(i + 1); };
}
</code></pre>
</blockquote>
<h2>参考リンク</h2>
<ul class="icoLink">
<li><a href="https://web.archive.org/web/20220506123333/https://pie.gd/test/script-link-events/" target="_blank" rel="nofollow">Browser CSS/JS loading capabilities</a></li>
<li><code>img.onerror</code> を使うアイデアの元ネタ「<a href="/2022/11/external-script-loader.html">img-JSONP</a>」について
</ul>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-79725901716324514132023-07-01T16:04:00.045+09:002023-08-13T19:09:42.316+09:00svgo を使って SVG フォントを SVG 画像に変換する<h2>はじめに</h2>
<p>このブログなどで使用するアイコンを <a href="/2018/02/PureCssIcon.html">Pure CSS アイコン</a>からベクターアイコンへ置き換えを進めています。新しいベクターアイコンでは、Web フォントと、フォールバックとして JavaScript で SVG を挿入する二段構えとしました。
<div class="note"><p>Web フォントが適用されているか? の検出に関する記事は「<a href="/2018/02/IsWebfontEffective.html">Webフォントがブラウザで有効か?きっちり調べる</a>」を参照ください。
<p>フォールバックの恩恵を享ける環境、つまり SVG に対応するが Web フォントに非対応の環境は Gecko 1.8.1~1.9.0, Opera 9.x, Safari 1.3.2~1.3.3, Safari 2.0.4+ です。SVG Tiny をサポートする PC 版 Opera 8.xの為には、何らかの手段でパスデータの変更が必要です。(追記 2023/08/13)
</div>
<h3>インライン SVG について</h3>
<p>いつの間にか見かけるようになった、HTML への SVG アイコンの直接記述(インライン SVG)は、HTML が大きくなってしまうので採用しませんでした。Web サーバへのリクエスト数は抑えられますが、SVG に非対応な、つまり非力なブラウザにも無駄に SVG 文字列をロードさせてしまうのはイケていませんね。
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhj5GXZ8gDB3zjXotw5sgGFUfrsqb7Ppvm9kvtaWAdkErtlkfhA_8NeSa1FAiJqrCJCVT-cGgiz8qcKNyq4LFDIQYrAkRackC-CuqXGj4OCrhPHg6bDb7vSKO7Vq2f6q2xnGlTE-MDz6q5ZfSGGrcCJe8LkfowvQJrWGG_4VUKk5bs2tacx2yNfruadLM4/s1120/THINK_TANK2022.png"><img alt=""data-original-height="1120" data-original-width="1119" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhj5GXZ8gDB3zjXotw5sgGFUfrsqb7Ppvm9kvtaWAdkErtlkfhA_8NeSa1FAiJqrCJCVT-cGgiz8qcKNyq4LFDIQYrAkRackC-CuqXGj4OCrhPHg6bDb7vSKO7Vq2f6q2xnGlTE-MDz6q5ZfSGGrcCJe8LkfowvQJrWGG_4VUKk5bs2tacx2yNfruadLM4/s160/THINK_TANK2022.png"></a>
<figcaption><a href="https://youtu.be/WkCveSTsnlM">youtube.com</a> のスクリーンショット。Firefox で<samp>スタイルシート使用しない</samp>にチェック。</figcaption>
</figure>
</span>
<span class="caption" style="width:160px">
<figure>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVxMrswWQX5GbyF7eY1nen0Q-fEG54rHOC6YyPJ1hW5dNO6h8BhscXXlsFxOvVfIVcQam6bdvP111OB6mmEFExNVLf20HAyBzKRlRioRomvZaBf6vT6vwyKT-oOoKC6LyzqF7GYbxfTaKYz7DYEEijVHNDWSkbNDpMw5YOiz4GtfiHGcKKHhfXZtB4ALE/s980/twitter-no-css.png"><img alt="" data-original-height="980" data-original-width="980" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVxMrswWQX5GbyF7eY1nen0Q-fEG54rHOC6YyPJ1hW5dNO6h8BhscXXlsFxOvVfIVcQam6bdvP111OB6mmEFExNVLf20HAyBzKRlRioRomvZaBf6vT6vwyKT-oOoKC6LyzqF7GYbxfTaKYz7DYEEijVHNDWSkbNDpMw5YOiz4GtfiHGcKKHhfXZtB4ALE/s160/twitter-no-css.png"></a>
<figcaption>twitter.com のスクリーンショットの比較。Firefox で<samp>スタイルシート使用しない</samp>にチェック。</figcaption>
</figure>
</span>
<p>ところで、この実装をしているサイトの中には、CSS が読み込まれないと、巨大なアイコンが無様に表示されてしまうものがあります。<p>インライン SVG の <code><svg></code> 要素には、きちんと <code>width</code>, <code>height</code> を設定しておきたいところです。
</div>
<h2>SVG フォントから SVG 画像を用意する</h2>
<div class="box"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8tJB22h3HthlPbqRsvaaLSG5oSPBtq87xAtUax2o0tUSAt5VR27ttGeJny-4sgGw6TfMOW1xsjlESTUKKEMtTVgxx63cOsjQ34hoFjMywx9cWD-Usc3esg7-dsu5HyaBnd3dMCZoNqnpVuGV3VGy_xjGpHhMBUGMmnakO5Ppn9N9aq9CWKSRF920eI1s/s1120/glyphs-to-svg.png"><img alt="" data-original-height="1120" data-original-width="1120" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8tJB22h3HthlPbqRsvaaLSG5oSPBtq87xAtUax2o0tUSAt5VR27ttGeJny-4sgGw6TfMOW1xsjlESTUKKEMtTVgxx63cOsjQ34hoFjMywx9cWD-Usc3esg7-dsu5HyaBnd3dMCZoNqnpVuGV3VGy_xjGpHhMBUGMmnakO5Ppn9N9aq9CWKSRF920eI1s/s160/glyphs-to-svg.png"></a>
<p>さて、このフォールバックの SVG 画像ですが、Web フォントの SVG から作ろうとすると上下に反転して上方向にズレた画像になってしまいます。これを svgo で transform してあげる方法をご紹介致します。
<p>併せて1024x1024の論理サイズの <code>viewPort</code> を255x255に変更して、パスデータの少数を丸めてファイルサイズを減らします。ネットワークにも端末のリソースにも優しくなりますね。
</div>
<p><a href="https://github.com/itozyun/web-doc-base/blob/5750bcb5f412942630e2c180ef8473ddbe29a3ea/src/js-vector-icon-compat/insertSVGIcon.js#L25" target="_blank" rel="me nofollow">web-doc-base</a> ではここから更に、パス文字列だけを取り出して、unicode を key にするオブジェクトに格納しています。そして Web フォントに非対応でも SVG をサポートするブラウザに対して、SVG アイコンを挿入します。
<blockquote cite="https://blog.hgrs.me/20191202144656" title="SVG ⇄ グリフ をするときの座標変換"><p>Illustrator と Glyphs を使用すれば特に問題はないですが、Python を使った方法だと、上下が反転しまします。これは SVG が下向きプラスでグリフが上向きプラスだからです。これを修正してあげる必要があります。
</blockquote>
<h2>node.js 用コード</h2>
<pre class="prettyprint lang-js"><code>const fs = require( 'fs' );
const parser = require( 'xml2js' ).Parser();
const svgo = require( 'svgo' );
fs.readFile(
'./.icomoon/fonts/web-doc-base.svg',
function( error, buffer ){
if( error ) throw error;
parser.parseString(
buffer,
function( err, result ){
if( err ) throw err;
const font = result.svg.defs[ 0 ].font[ 0 ];
const fontFace = font[ 'font-face' ][ 0 ].$;
const width = fontFace[ 'units-per-em' ];
const ascent = fontFace[ 'ascent' ];
const descent = fontFace[ 'descent' ];
const glyphList = font.glyph;
const glyphMap = {};
for( let i = 0, l = glyphList.length; i < l; ++i ){
const glyph = glyphList[ i ].$;
// 文字列を1文字ずつ配列化(サロゲートペアを考慮)
// https://qiita.com/sounisi5011/items/aa2d747322aad4850fe7
// 合字を除外しています
if( glyph.d && glyph.unicode && Array.from( glyph.unicode ).length === 1 ){
glyphMap[ glyph.unicode ] = createOptimaizedPath( glyph.d, width, ascent, descent );
};
};
fs.writeFileSync(
'./src/js-vector-icon-compat/vectorIconPathList.generated.js',
Buffer.from(
'// THIS SCRIPT IS GENERATED BY "gulp ico". DO NOT EDIT!\n' +
'var VectorIconCompat_PATH_LIST = \n' + JSON.stringify( glyphMap, null, ' ' ) + ';'
)
);
}
);
}
);
function createOptimaizedPath( path, width, ascent, descent ){
const height = 255;
const scale = height / 1024;
const result = svgo.optimize(
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0,0,' + width * scale + ',' + height + '">' +
'<g transform="matrix(' + scale + ', 0, 0, -' + scale + ', 0, ' + ascent * scale + ')">' +
'<path d="' + path + '"/>' +
'</g>' +
'</svg>',
{
plugins : [
{
name : 'preset-default',
params : {
overrides : {
convertPathData : { floatPrecision : 0 }
}
}
}
]
}
);
return result.data.split( ' d="' )[ 1 ].split( '"' )[ 0 ];
};
</code></pre>
<h3>ポイント</h3>
<ol>
<li>SVG フォントの JavaScript オブジェクトへの変換には、<a href="https://www.npmjs.com/package/xml2js" target="_blank" rel="nofollow">xml2js</a> を使っています。
<li>svgo は 3.0.2 を使用しました。
<li>svgo の <code>transform</code> 属性をパスに apply するオプションはデフォルトで有効です。<a href="https://github.com/svg/svgo/issues/33" target="_blank" rel="nofollow">svgo / apply transforms to Path pata</a>
<li><code>style="transform: ..."</code> は無視されます。<code>transform</code> 属性を使います。
<li><code>matrix</code> の各値は「<a href="https://blog.hgrs.me/20191202144656" target="_blank" rel="nofollow">SVG ⇄ グリフ をするときの座標変換</a>」を参考にしました。
<li>SVG フォントから <code>ascent</code> を取得してズラしてあげます。
</ol>
<p> izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-51587749257697721562022-12-02T23:54:00.299+09:002023-05-11T16:48:04.721+09:00エイプリルフール企画などでレガシーブラウザ対応する場合に覚えておきたい最初期のDHTMLブラウザのJavaScriptの罠たちを回避する<div class="note"><p>執筆時点で未解決だった、<a href="#4">Gecko 0.8.0以下での括弧の下の関数の問題</a>は <a href="https://github.com/ECMAScript2/es2-postprocessor/commit/029416082d750b086493f635971c9f266b33fb89" target="_blank" rel="me nofollow">es2-postprocessor 0.12.0で解決</a>しています。(2023/01/04 追記)
</div>
<p>この記事は、<a href="https://qiita.com/advent-calendar/2022/javascript" target="_blank" rel="nofollow">JavaScript Advent Calendar 2022</a>の3日目です。2日目の記事は martinheidegger さんによる「<a href="https://qiita.com/martinheidegger/items/cfeccfa71c1ea30b9ebe" target="_blank" rel="nofollow">JavaScript を使って DNS データ受け取る。</a>」になります。
<ol>
<li><a href="#1">はじめに</a>
<li><a href="#2">IE5 以下に未実装のビルトインオブジェクトとメソッドを補う</a>
<li><a href="#3">Opera 7.23以下はラベル付きブロックで構文エラー</a>
<ol>
<li><a href="#3-1">ラベル付きブロックを <code>do~while</code> または即時実行関数に書き換える</a>
</ol>
<li><a href="#4">優等生の Gecko 0.8.0以下のややこしめのバグ</a>
<ol>
<li><a href="#4-1">即時実行関数が絡むバグ</a>
</ol>
<li><a href="#5">さいごに</a>
<ol>
<li><a href="#5-1">注釈</a>
<li><a href="#5-2">ご参考リンク</a>
</ol>
</ol>
<a name="1"></a>
<h2 id="1">1. はじめに</h2>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQJhwsLRCQzHuCHBaLu4RgyoADFyCRmD-EeNa050atlmRYabsAYqNEFzpCGc0QlBV2FjaRYSKuVYgBJbG4ZNel1bam5IXy4tTukrqRN1JQk4SkVztM16RaeMHKAKjF70ONttjiwZ_qGF_-ClG-Pac4oOb_Cs-NnBxIH5T6dfSRdgXUkM9ydVHadHDb/s1021/sora-evo-3rd.png"><img alt="" data-original-height="1021" data-original-width="1021" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQJhwsLRCQzHuCHBaLu4RgyoADFyCRmD-EeNa050atlmRYabsAYqNEFzpCGc0QlBV2FjaRYSKuVYgBJbG4ZNel1bam5IXy4tTukrqRN1JQk4SkVztM16RaeMHKAKjF70ONttjiwZ_qGF_-ClG-Pac4oOb_Cs-NnBxIH5T6dfSRdgXUkM9ydVHadHDb/s156/sora-evo-3rd.png"></a>
<figcaption>2016年のエイプリルフール企画の<a href="https://web.archive.org/web/20160401145059/http://www.sora-evo-3rd.com/" target="_blank" rel="nofollow">『英雄伝説 空の軌跡 the 3rd Evolution』公式サイト</a>(アーカイブより)</figcaption>
</figure>
</span>
<p>本記事を一般化して書くと、エイプリルフール企画で0年代前半風の Web サイトを制作する案件が来て「<i>見た目はバイブスでてますけど、コレ、当時のブラウザで動くんスか?</i>」と恐ろしい方向に話が進んだ際に、気配をフェードアウトする暇でこの記事のことを思い出してください。
<p>当時のブラウザを取り出して閲覧してくれるユーザーの手元でバッチリ動いてくれたなら、ハートキャッチですね。
<p>因みに『空の軌跡』のエイプリルフール企画については、Internet Exproler 3.0や Netscape Navigator 3.0で閲覧した報告のツイートを目にした記憶があるので、油断なりません。(<a href="#annotation-1">*1</a>)
</div>
<hr>
<p>さて、0年代前年は DHTML ブラウザが出揃い、後の Ajax(2005年~)の開花を準備します。
<p>Microsoft が IE4 に向けて書いた文書によると <a href="//web.archive.org/web/20100626234859/http://msdn.microsoft.com/ja-jp/library/cc409712.aspx" target="_blank" rel="nofollow">DHTML</a> はダイナミックコンテンツ、ダイナミックスタイル、CSS-P などがその構成技術です。これらに加えて、要素とテキストレンジの計測が正常に実装されているなら、理論上は、新しい CSS の実装を待たずともどんなレイアウトでも可能です。つまり DHTML さえ健全ならどんな表現でも可能なわけです。(<a href="#annotation-2">*2</a>)
<p>そんな素晴らしい能力を秘めたレガシー DHTML ブラウザですが、いざそれらに向けて開発を始めると、不可解なバグと貧弱な開発者ツールに泣くことになります。エラーコンソールがあれば御の字という世界へようこそ。
<p>本記事では未実装とバグの中から印象的なものを3つご紹介します。どれも JavaScript を書き換えるポストプロセッサーを用意してエレガントめに迂回できた問題たちです。
<a name="2"></a>
<h2 id="2">2. IE5 以下に未実装のビルトインオブジェクトとメソッドを補う</h2>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhA_70VLRe7GRdZzRy72qguFLv_WhzXoqKTBpczx7nrBBuOlWc3pjQ171iwafHiY-v2P9Ht-Q9DuJs5xH9TGR9Z5JTH4B8L-y2-pPLx1F2PaDngKBbW5VIZ73tSqOm3I0v9iY_zHlSSlINrRviSngf8KapKJHnOXTVn29e3FQ43UiVzOlT0uc5Ltu8R/s1007/ie5-outcloud.blogspot.com.PNG"><img alt="" data-original-height="1007" data-original-width="1000" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhA_70VLRe7GRdZzRy72qguFLv_WhzXoqKTBpczx7nrBBuOlWc3pjQ171iwafHiY-v2P9Ht-Q9DuJs5xH9TGR9Z5JTH4B8L-y2-pPLx1F2PaDngKBbW5VIZ73tSqOm3I0v9iY_zHlSSlINrRviSngf8KapKJHnOXTVn29e3FQ43UiVzOlT0uc5Ltu8R/s156/ie5-outcloud.blogspot.com.PNG"></a>
<figcaption>IE5 で執筆中の本記事を表示してみる</figcaption>
</figure>
</span>
<p>最初期の DHTML ブラウザ向け開発を始めたらまず入手したいのが、IE5(1999年3月18日)からサポートする jQuery クローン「kQuery」を開発していた ofk 氏による <a href="https://ofk.hatenadiary.org/entry/20080904/1220485969" target="_blank" rel="nofollow" title="?D of K > Function.prototype.applyとかArray.prototype.spliceのIE5用のコード">polyfill 集</a>です。ECMAScript 3未満の IE 4~5 を ES3 のちょい手前くらいまで引き上げる事ができます。
<p>僕の手でいくつかのバグを修正し、他の足りない組み込みオブジェクトとメソッドの polyfill を加えた <a href="https://github.com/ECMAScript2/es2-to-es3" target="_blank" rel="me nofollow">es2-to-es3</a> を公開しています。自動で polyfill を埋め込む gulp プラグインにもしていて <a href="https://www.npmjs.com/package/es2-to-es3" target="_blank" rel="me nofollow">npm からインストール</a>出来ます。
</div>
<a name="3"></a>
<h2 id="3">3. Opera 7.23以下はラベル付きブロックで構文エラー</h2>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUZsMF-3IFfN63DrfBWPe60y3bEjih9WKpARHitwrbKflQMAma0kQjhGlnlCrw8yZNK-m8pN62hMGhD9LoRKRt4Itkt8rQ9TbtaMFJrJj4EDLrtx-tYK6FO5mkUuGBDUR2RAjvvDUGM_Af9UaG49Mq2aBXbaq7c5T7ODOenjOS6ZQk0uSJOLq7fm5i/s1005/opera7-unsupported-labeled-statement-blocks.PNG"><img alt="" height="200" data-original-height="1005" data-original-width="1001" src="//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUZsMF-3IFfN63DrfBWPe60y3bEjih9WKpARHitwrbKflQMAma0kQjhGlnlCrw8yZNK-m8pN62hMGhD9LoRKRt4Itkt8rQ9TbtaMFJrJj4EDLrtx-tYK6FO5mkUuGBDUR2RAjvvDUGM_Af9UaG49Mq2aBXbaq7c5T7ODOenjOS6ZQk0uSJOLq7fm5i/s156/opera7-unsupported-labeled-statement-blocks.PNG"></a>
<figcaption>Opera 7.03のラベル付きブロック非サポートを確認する(<a href="https://itozyun.github.io/web-doc-base/test/javascript-implementation.html#labeled-statement-block" target="_blank" rel="me nofollow">テストページ</a>になります。)</figcaption>
</figure>
</span>
<p>Opera 7.23(<a href="//web.archive.org/web/20160715183827/http://www.opera.com/docs/changelogs/windows" target="_blank" rel="nofollow" title="Opera Changelogs for Windows">7.20は2003年9月23日に公開</a>)以下は、ラベル付きブロックを非サポートで、7.50(2004年5月12日)以降でサポートします。
<p>JavaScript でラベル付きブロックを使うコーディングは寡聞にしてあまり見かけないようですが、僕のケースでは Closure Compiler で ADVANCED コンパイルをすると遭遇しました。「<i>ラベル付きブロックさえなければ動くのに…!</i>」という状況は結構口惜しいですね。
<p>そんなラベル付きブロックを書き換えるツール <a href="https://www.npmjs.com/package/es2-postprocessor" target="_blank" rel="me nofollow">es2-postprocessor</a> を公開しているのでもう大丈夫です。
</div>
<a name="3-1"></a>
<h3 id="3-1">3.1. ラベル付きブロックを <code>do~while</code> または即時実行関数に書き換える</h3>
<p>こんな感じに書き換えます。
<pre class="prettyprint lang-js"><code>a: {
break a;
}
// ↓
do{
break; // <= break a;
} while(false);
// ---------
a: {
b: {
break b;
break a;
}
break a;
}
// ↓
(function(){
do{
break; // <= break b;
return; // <= break a;
} while(false);
return; // <= break a;
})();
</code></pre>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9GvyiCSzOj6iSLoQxYAH1Dc9Lxmssor20w450u1yeV_4wdkPP2Tfn2q9tI4F5W9WDxI4bdFXyigtb_qMi3zZH0JmMWRpzs4OhX41d_mtYcf4RGXxI-vicd-GlMsxqhIkRTHXsOAwLiQRN2WXlDAFL3Xz-VN4x6EoosgFkvuGC7WwhKmFsBvNClloR/s1003/opera7.54-outcloud.blogspot.com.PNG"><img alt="" border="0" data-original-height="1003" data-original-width="1000" src="//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9GvyiCSzOj6iSLoQxYAH1Dc9Lxmssor20w450u1yeV_4wdkPP2Tfn2q9tI4F5W9WDxI4bdFXyigtb_qMi3zZH0JmMWRpzs4OhX41d_mtYcf4RGXxI-vicd-GlMsxqhIkRTHXsOAwLiQRN2WXlDAFL3Xz-VN4x6EoosgFkvuGC7WwhKmFsBvNClloR/s156/opera7.54-outcloud.blogspot.com.PNG"></a>
<figcaption>UI のゴテゴテ感の新鮮な Opera 7.54で表示してみる、<a href="https://github.com/ECMAScript2/es2-code-prettify" target="_blank" rel="me nofollow">Google Code Prettifyの改造版</a>も動作</figcaption>
</figure>
</span>
<p>この書き換えを自動で、あらゆるパターンで漏れなく実施することは、僕の手にはあまりました。そこで、エラーを投げて書き換えを諦める場合があります。但し、僕の使用状況では Closure Compiler の出力するラベル付きブロックは簡素な為、書き替えできなかったことは今のところありません。
<p>それにしても、Opera 7.xは可愛くて良いです。7.0(2003年1月28日)は若干遅めの登場にしては実装状況がやや遅れ気味な気がしますが、可愛いので良しです。
</div>
<a name="4"></a>
<h2 id="4">4. 優等生の Gecko 0.8.0以下のややこしめのバグ</h2>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXfeFSkp12qiZcgeKpzv1r0epWqJV1PRk_bI7FAm9mCDZ9Bs7hSAo5al7It0-Hs7bl3IUjYfbrqdVdHUbu9JPZc0RvvYdBVdhFOo4XO0C0dlWk_1HaLybHCePRdFfpaoJJy7nPnxNKj2KBZyNtThJpltxTg_lM7fHOu84RSJCC_LV0jCbX7BPZqt38/s1005/gecko0.7-outcloud.blogspot.com.PNG"><img alt="" data-original-height="1005" data-original-width="1003" src="//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXfeFSkp12qiZcgeKpzv1r0epWqJV1PRk_bI7FAm9mCDZ9Bs7hSAo5al7It0-Hs7bl3IUjYfbrqdVdHUbu9JPZc0RvvYdBVdhFOo4XO0C0dlWk_1HaLybHCePRdFfpaoJJy7nPnxNKj2KBZyNtThJpltxTg_lM7fHOu84RSJCC_LV0jCbX7BPZqt38/s156/gecko0.7-outcloud.blogspot.com.PNG"></a>
<figcaption>Mozilla ブラウザ(Gecko 0.7)で表示してみる。0.6ではロードが完了しなかった。Google Photoの画像のせいかも。</figcaption>
</figure>
</span>
<p>Netscape Navigator 6(Gecko 0.6)は2000年の11月14日にリリースされたブラウザで IE 5.5(2000年7月17日公開)が同期です。この時点で <code>Object.prototype.__defineGetter__</code>, <code>Object.prototype.__defineSetter__</code> を実装していて頼もしいです。一方の CSS とペイント周りでは、問題がやや多めに感じます。
<p>今回紹介するのは Gecko ~0.8.0で遭遇する JavaScript 実装のバグです。0.8.1では解決したことを確認しました。何年か前に初めて遭遇した時は、訳が分からず頭が白くなりましたが、この11月に条件を特定して解決するところまで漕ぎつけました。(執筆中に発生条件が即時実行関数に留まらないことが判明しました。<del>これへの対処は後日にします。</del>es2-postprocessor 0.12.0 以降で解決しています。2024/01/04 追記)
</div>
<a name="4-1"></a>
<h3 id="4-1">4.1. 即時実行関数が絡むバグ</h3>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhk1oMYHMmbVvd5deKlAjEwKNJvNVPP27d-65wcbywlTkOxgI4XM_zOsJ318vswyKte0BAEFoUuuxRFCRh6gtJNc4rVQ7woOTZVSb-ePR2kgXpxV3O29St9E2R1QWDQ5aBGxc1npng9FvCNKJFf0qZdUvnpx_NPgLM-JO6KEvbDnrPvjOHFg9i7xiM4/s986/gecko-iife-bug.PNG"><img alt="" data-original-height="977" data-original-width="986" src="//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhk1oMYHMmbVvd5deKlAjEwKNJvNVPP27d-65wcbywlTkOxgI4XM_zOsJ318vswyKte0BAEFoUuuxRFCRh6gtJNc4rVQ7woOTZVSb-ePR2kgXpxV3O29St9E2R1QWDQ5aBGxc1npng9FvCNKJFf0qZdUvnpx_NPgLM-JO6KEvbDnrPvjOHFg9i7xiM4/s156/gecko-iife-bug.PNG"></a>
<figcaption>Gecko 0.6での IIFE のテスト結果(<a href="https://itozyun.github.io/web-doc-base/test/javascript-implementation.html#iife" target="_blank" rel="me nofollow">テストページ</a>)</figcaption>
</figure>
</span>
<p>先祖スコープのオブジェクトを参照すると常に <code>undefined</code> になっているバグです。但し、グローバルオブジェクト(<code>window</code> のプロパティ)では問題が起きません。即時実行関数などの括弧で囲まれた無名関数の中からの参照でだけ発生します。そして、これらの関数と同じスコープに関数定義が存在する場合は発生しません。
<p>と、文章にするとややこしいですね。<a href="https://itozyun.github.io/web-doc-base/test/javascript-implementation.html#iife" target="_blank" rel="me nofollow">テストページ</a>でご確認いただけます。
<p>この問題も <a href="https://www.npmjs.com/package/es2-postprocessor" target="_blank" rel="me nofollow">es2-postprocessor</a> に、次のように即時実行関数と括弧で囲まれた(無名)関数を関数定義に書き換えて回避するコードを追加して対処しました。
</div>
<pre class="prettyprint lang-js"><code>function parentScope(){
var a = {};
(function(){
alert(typeof a); // "undefined"
})();
};
// ↓
function parentScope(){
var a = {};
function b(){
alert(typeof a); // "object"
};
b();
b = false;
};
</code></pre>
<a name="5"></a>
<h2 id="5">5. さいごに</h2>
<p>これで0年代風の見た目に留まらず、対応ブラウザも0年代の Web 開発をする下準備が出来ました。
<p>さて、現在では Visual Studio Code などの優れたツールを使って Web 開発が行えます。現代のツールと知見を駆使してチューニングされた Web コンテンツをレガシーブラウザに読み込ませたら、当時には引き出せなかったパワーを引き出すことが出来るかもしれませんね!(<a href="#annotation-3">*3</a>)
<hr>
<p>「この Canvas ゲームですけど、Java アプレットってので出来るんじゃないっスか?」
<p>「… … 、、、」
<pre class="aa"><code>(function(){
obj.filters.alpha.opacity -= 5;
0 < obj.filters.alpha.opacity && setTimeout(arguments.callee, 50);
})();
</code></pre>
<a name="5-1"></a>
<h3 id="5-1">5.1. 注釈</h3>
<ol>
<li id="annotation-1"><a name="annotation-1"></a><div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhyT_DXQBXN_jRpI4HZT82onZkmil434eEfqXbRTGaD9QpyO11gakHNy8s82zH8Wys38AN6z-1e7CM0aUFpNAew6lVlJ4K_RN9EJJVMsyeFEvJr4JhCWiWjSuUe1FwEcmoctVo-Z-IlU6ZMw_x6eIpLONl-F25pFzpdJ58TW1kli42ZnHb4Yki5oQu/s1005/netscape3.04-sora-evo-3rd.com.PNG"><img alt="" data-original-height="1005" data-original-width="1000" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhyT_DXQBXN_jRpI4HZT82onZkmil434eEfqXbRTGaD9QpyO11gakHNy8s82zH8Wys38AN6z-1e7CM0aUFpNAew6lVlJ4K_RN9EJJVMsyeFEvJr4JhCWiWjSuUe1FwEcmoctVo-Z-IlU6ZMw_x6eIpLONl-F25pFzpdJ58TW1kli42ZnHb4Yki5oQu/s156/netscape3.04-sora-evo-3rd.com.PNG"></a>
<figcaption>本記事執筆中に Netscape 3.04でアーカイブの企画サイトを表示してみた</figcaption>
</figure>
</span>
<span class="caption" style="width:160px">
<figure>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6LHXDcRNIeE8fWFQUWCbeEQ3oxtlYLlAt2XdQkQX3vnNyyQcGN-8TszQgaWHrziAKtW8blT0hFJtTJBdmq_MjyEvQtrtLzR-jLwngpExCID6PVDIakoizupnupuC_DCmpibAGJM65i_o6mG0Hc66_bWGMcneM1iWMHVGntjV2eHqImC5unxOTSRd6/s1008/netscape4.8-sora-evo-3rd.com.PNG"><img alt="" data-original-height="1008" data-original-width="1004" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6LHXDcRNIeE8fWFQUWCbeEQ3oxtlYLlAt2XdQkQX3vnNyyQcGN-8TszQgaWHrziAKtW8blT0hFJtTJBdmq_MjyEvQtrtLzR-jLwngpExCID6PVDIakoizupnupuC_DCmpibAGJM65i_o6mG0Hc66_bWGMcneM1iWMHVGntjV2eHqImC5unxOTSRd6/s156/netscape4.8-sora-evo-3rd.com.PNG"></a>
<figcaption>本記事執筆中に Netscape 4.8でアーカイブの企画サイトを表示してみた</figcaption>
</figure>
</span>
<p>Netscape 4.xまでは日本語 UTF-8 に非対応のようです。公開サーバ側で Shift-JIS などで HTML を返す必要があると思います。そして、仮にこのような実装がされていても Web アーカイブには記録されません。
</div>
<li id="annotation-2"><a name="annotation-2"></a>やっぱり、<code>Canvas</code> と <code>WebAudio</code> と <code>GamePad API</code> と <code>Service Worker</code> と <code>IndexedDB</code> は欲しいです。
<li id="annotation-3"><a name="annotation-3"></a>という事象は確認していません。特に Opera 7.xの DHTML は、激しくモッサリです。
</ol>
<a name="5-2"></a>
<h3 id="5-2">5.2. ご参考リンク</h3>
<ol>
<li>「<a href="https://higashidadan.com/web/90s-webdesign.html" target="_blank" rel="nofollow">令和にも残そう、懐かしい90年代WEBデザイン。さよなら平成。</a>」
<li>「<a href="https://wkwkdesign.com/retrodesign_webdesign_torend/" target="_blank" rel="nofollow">レトロブームが、どのようにwebデザインに取り入れられているか</a>」<q cite="https://wkwkdesign.com/retrodesign_webdesign_torend/">「ニュートロ(Newtro)」とは「現在or未来(New)」と「過去(Retro)」を融合させた「新しい過去」を意味する韓国で生まれた新造語です。</q>
<li>「<a href="https://karapaia.com/archives/52295587.html" target="_blank" rel="nofollow">懐かしのインターネット。AppleにGoogle、Amazonなど1999年のサイトデザインはこんな感じだった。</a>」<q cite="https://karapaia.com/archives/52295587.html"> 90年代は、ウェブのグラフィックデザインの可能性が模索された時代でした。当時、ウェブデザイナーの大多数は印刷物のデザインしか手がけたことがありませんでした。だからウェブサイトをどのようにデザインするのか、その方法が試行錯誤されていたのです。</q>
</ol>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-78530495120324258672022-11-04T12:24:00.060+09:002024-02-26T20:27:03.781+09:00Ajax対応ブラウザの下限は?外部Scriptの動的ロードを調べた<div class="note"><p><code>iframe</code> からライブラリのコード文字列を親フレームに渡して、親フレームで <code>eval</code> 等でライブラリを有効化すれば、下で言及している「<code>iframe</code> のリロードでメモリをリフレッシュするテクニック」とバッティングしませんね。(2024/02/26)
<p><code>iframe</code> を使ったスクリプトの動的ロードは JSONP に留めて、ponyfill は <code>document.write</code> で追加するのが良いと思います。<code>iframe</code> でライブラリを含むコードを実行してしまうと <a href="https://thinkit.co.jp/article/116/3?page=0%2C2" target="_blank" rel="nofollow" title="JavaScriptでFREDDYデータを読み込む"><code>iframe</code> のリロードでメモリをリフレッシュするテクニック</a>が(多分)使えない為です。参考記事に追加しました。(2022/11/13)
<p><a href="https://github.com/itozyun/web-doc-base/commit/6d2ae66b228a956efe9d05e10df55caa280ab1bb" target="_blank" rel="me nofollow"><code>iframe</code> の中で行う動的ロードの調査</a>結果を追記。これにより Ajax 対応ブラウザに Gecko 0.6~0.9 が加わりました。タイトルに「Ajax 対応ブラウザの下限は?」を追加しました。検索向け説明を追記しました。(2022/11/05)
</div>
<style>.yes{background:#cfc}.no{background:#fcc}@media handheld, only screen and (prefers-color-scheme:dark), only screen and (max-width: 240px){.yes{background:#030}.no{background:#300}}</style>
<p>RegExp の ponyfill の動的ロードを最初期の DHTML ブラウザ(Opera 7.5x 以下、Gecko 0.9未満)で行ってみたところ、これより後のブラウザと異なったので、<a href="https://itozyun.github.io/web-doc-base/test/dynamic-script.html" target="_blank" rel="me nofollow">テストページ</a>を書いて、表に纏めました。この調査を元に書いたのが <a href="https://github.com/itozyun/web-doc-base/blob/3e264adedf6b30c83284e51ae93de6ba5c83c089/src/js/8_Library/ExternalScriptLoader.js" target="_blank" rel="me nofollow">ExternalScriptLoader.js</a> です。
<h2>調査結果の概要</h2>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyZQiTZiQJV7aiNgxgxmUw-HoSBHM-qFxCVowO6eYuYSJOT4U5CK6dbnfrtGKm1Pl0ITkdkJlHusuNeiphHlVCzJP5Z9-jmUwh02pwY9UcJfdh2JuvLJuxZeFXdnktSF5JIJ8wpE_xbWchbc6MGq0JETNZCoJR6GrqhUGGbz8aUiVP8k8wTXrsNOw-/s756/dynamic-external-script-test-page.png"><img alt="" width="200" data-original-height="755" data-original-width="756" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyZQiTZiQJV7aiNgxgxmUw-HoSBHM-qFxCVowO6eYuYSJOT4U5CK6dbnfrtGKm1Pl0ITkdkJlHusuNeiphHlVCzJP5Z9-jmUwh02pwY9UcJfdh2JuvLJuxZeFXdnktSF5JIJ8wpE_xbWchbc6MGq0JETNZCoJR6GrqhUGGbz8aUiVP8k8wTXrsNOw-/s160/dynamic-external-script-test-page.png"></a>
<figcaption>「<a href="https://itozyun.github.io/web-doc-base/test/dynamic-script.html" target="_blank" rel="me nofollow">動的 Script のテスト</a>」ページ</figcaption>
</figure>
</span>
<p>文書を読み込み中の <code>document.write</code> でしか外部スクリプトを追加できないブラウザ(~Opera 7.1x, <del>~Gecko 0.9</del>)を特定しました。
<p>これ以外のブラウザで一般的な手段をサポートしないものには、<code>iframe</code> 内を <code>contentWindow.document.write()</code> で書き換えて外部スクリプトを追加できるもの(Gecko ~0.9)、<code><script></code> を再利用するパターンだけサポートするブラウザ(Opera 7.2x)がありました。
<p>これらのブラウザは <code>document.createElement('script')</code> が動作するブラウザと同様に追加のタイミングを調整できます。
</div>
<p>動的な外部スクリプトの追加ができる、ということは <a href="https://gihyo.jp/dev/serial/01/crossbrowser-javascript/0011#sec-2" target="_blank" rel="nofollow" title="第11回 JSONP 入門">JSONP</a> が可能です。<code>XMLHttpRequest</code> をサポートしていなくても Ajax が出来る、Ajax 対応ブラウザである、ということです。
<div class="note"><p>モバイル Opera 8.5 を搭載するニンテンドーDSブラウザーは XHR をサポートしないが Ajax 対応と紹介されていたようです。
<blockquote cite="https://ja.wikipedia.org/wiki/%E3%83%8B%E3%83%B3%E3%83%86%E3%83%B3%E3%83%89%E3%83%BCDS%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%83%BC" title="Wikipedia > ニンテンドーDSブラウザー">
<p>一部の記事で Ajax 対応と紹介されたことがあったが、狭義の Ajax で基幹技術とする <code>XMLHttpRequest</code> は実装されていない。
</blockquote>
</div>
<h2>調査結果</h2>
<p><a href="https://itozyun.github.io/web-doc-base/test/dynamic-script.html" target="_blank" rel="me nofollow">テストページ</a>の実行結果が次です。
<div class="hscroll">
<table cellspacing="0">
<thead>
<tr>
<th rowspan=2>ブラウザ<th colspan=3>動的外部スクリプト<th colspan=6>動的インラインスクリプト
<tr>
<th>1. <code>.createElement('script')</code><th>2. <code>.src</code> の変更<th>3. <code>iframe</code><th>4-1. <code>.createTextNode</code><th>4-2. <code>.innerHTML</code><th>4-3. <code>.innerText</code><th>4-4. <code>.textContent</code><th>4-5. <code>.text</code><th>4-6. <code>&nbsp;</code> ハック
<tbody>
<tr>
<th>IE5(Windows 2000)<td class="yes">Yes<td class="yes">Yes<td>?<td class="no">Error<td class="no">Error<td class="no">Error<td class="no">No<td class="yes">Yes<td class="no">Error
<tr>
<th>IE5.5(Windows XP, IE Tester)<td class="yes">Yes<td class="yes">Yes<td>?<td class="no">Error<td class="no">Error<td class="no">Error<td class="no">No<td class="yes">Yes<td class="yes">Yes
<tr>
<th>IE6, 7(Windows XP, IE Tester)<td class="yes">Yes<td class="yes">Yes<td>?<td class="no">Error<td class="no">Error<td class="no">Error<td class="no">No<td class="yes">Yes<td class="no">No
<tr>
<th>Safari 3.1.2(Windows 2000), 3.2.3(Windows XP)<td class="yes">Yes<td class="no">No<td>?<td class="yes">Yes<td class="no">No<td class="yes">Yes<td class="yes">Yes<td class="yes">Yes<td class="no">No
<tr>
<th>Opera 7.03, 7.11(Windows XP)<td class="no">No<td class="no">No<td class="no">No<td class="no">No<td class="no">No<td class="no">No<td class="no">No<td class="no">No<td class="no">No
<tr>
<th>Opera 7.20, 7.23(Windows XP)<td class="no">No<td class="yes">Yes<td class="yes">Yes<td class="yes">Yes<td class="no">No<td class="yes">Yes<td class="no">No<td class="no">No<td class="no">No
<tr>
<th>Opera 7.54u2(Windows XP)<td class="yes">Yes<td class="yes">Yes<td class="yes">Yes<td class="yes">Yes<td class="no">No<td class="yes">Yes<td class="no">No<td class="yes">Yes<td class="no">No
<tr>
<th>Opera 8.02(Windows XP)<td class="yes">Yes<td class="yes">Yes<td>?<td class="yes">Yes<td class="yes">Yes<td class="yes">Yes<td class="no">No<td class="yes">Yes<td class="yes">Yes
<tr>
<th>Gecko 0.6, 0.7, 0.8, 0.9(Windows XP or 2000)<td class="no">No<td class="no">No<td class="yes">Yes<td class="no">No<td class="no">No<td class="no">No<td class="no">No<td class="no">No<td class="no">No
<tr>
<th>Gecko 0.9.1~0.9.9(Windows XP or 2000)<td class="yes">Yes<td class="no">No<td>?<td class="yes">Yes<td class="no">No<td class="no">No<td class="no">No<td class="yes">Yes<td class="yes">Yes
</table>
</div>
<p>動的インラインスクリプトの調査結果も含みますが、スクリプトで組み立てたコード文字列を <code>eval(source)</code> や <code>new Function(source)</code>, <code>execScript()</code> で実行できるので、いまいち使いどころが分かりません。<code>HTMLElement</code> を作って文書ツリーに追加する分、メモリを浪費するだけのように思います。
<h2>参照した記事</h2>
<table class="tl">
<thead>
<tr>
<th>公開日<td>記事タイトル
<tbody>
<tr>
<th>2004?<td><a href="https://web.archive.org/web/20040325075516/http://www.hikksworld.com/loadJSFiles/" target="_blank" rel="nofollow">Dynamically Loading JS Files</a>
<tr>
<th>2006/11/07<td><a href="http://shogo4405.hatenadiary.com/entry/20061107/1162886968" target="_blank" rel="nofollow">script要素のtextプロパティ</a> textプロパティのあるDOM要素, 読取専用のinnerHTML要素を紹介。
<tr>
<th>2006/12/07<td><a href="https://shogo4405.hatenadiary.com/entry/20061207/1165479339" target="_blank" rel="nofollow">innerHTMLでscriptする</a>
<tr>
<th>2007/03/06<td><a href="https://shogo4405.hatenadiary.com/entry/20070306/1173160753" target="_blank" rel="nofollow">script要素のdefer属性の実装</a> <q>あとIEはscript要素にdefer属性をつけるとinnerHTMLに代入したscriptが実行されるという仕様がある。</q>
<tr>
<th>2007/06/05<td><a href="https://labs.cybozu.co.jp/blog/takesako/2007/06/opera_img-jsonp.html" target="_blank" rel="nofollow">Operaでも非同期リクエストが並列処理できる img-JSONP</a> 本件、未実装!
<tr>
<th>2007/10/11<td><a href="http://takuya-1st.hatenablog.jp/entry/20071011/1192119134" target="_blank" rel="nofollow">JavaScriptを動的に書き出す</a>
<tr>
<th>2009/01/28<td><a href="https://web.archive.org/web/20120917100043/http://d.hatena.ne.jp/yuushimizu/20090128/1233146321" target="_blank" rel="nofollow">JSONPのエラーを判断する</a> 本件、未実装!
<tr>
<th>2010/05/28<td><a href="https://fdays.blogspot.com/2010/05/javascript-script.html" target="_blank" rel="nofollow">JavaScriptによって動的に script要素を追加する場合のブラウザごとの挙動の違い</a>
<tr>
<th>2013/02/19<td><a href="https://michigawi.blogspot.com/2013/02/internetexplorerjavascriptinnerhtml.html" target="_blank" rel="nofollow">Internet ExplorerでJavaScriptの動的実行</a>
<tr>
<th>2017/01/07<td><a href="https://support.microsoft.com/ja-jp/topic/iframe-%E8%A6%81%E7%B4%A0%E5%86%85%E3%81%AB%E5%8B%95%E7%9A%84%E3%81%AB-script-%E8%A6%81%E7%B4%A0%E3%82%92%E5%87%BA%E5%8A%9B%E3%81%99%E3%82%8B%E3%81%A8-internet-explorer-%E3%81%8C%E5%BF%9C%E7%AD%94%E3%81%AA%E3%81%97%E3%81%AB%E3%81%AA%E3%82%8B%E5%A0%B4%E5%90%88%E3%81%8C%E3%81%82%E3%82%8B-5a38b82f-e2e1-e78a-0913-823a8962a601" target="_blank" rel="nofollow">iframe 要素内に動的に script 要素を出力すると Internet Explorer が応答なしになる場合がある</a>
</table>
<h2>先行する調査、2004年の Web アーカイブより</h2>
<blockquote title="Dynamically Loading JS Files" cite="https://web.archive.org/web/20040325075516/http://www.hikksworld.com/loadJSFiles/">
<p>Each of the links below attempts to load a .js file dynamically via the method that is named in the link text.
<p>If you click a link and get an alert, then that method worked. If you get no alert, that method does not work :(
</p>
<div class="hscroll">
<table cellspacing="0">
<thead>
<tr>
<th>Browser
<th>Platform
<th>Change Source
<th>Change InnerHTML
<th>Create Element
<th>Load It In A Layer
<tbody>
<tr>
<th class="PC">IE4.0
<th class="PC">Windows
<td class="untested">Untested
<td class="untested">Untested
<td class="untested">Untested
<td class="no">No
<tr>
<th class="PC">IE5.0
<th class="PC">Windows
<td class="yes">Yes
<td class="no">No
<td class="yes">Yes
<td class="no">No
<tr>
<th class="PC">IE5.5
<th class="PC">Windows
<td class="yes">Yes
<td class="no">No
<td class="yes">Yes
<td class="no">No
<tr>
<th class="PC">IE6.0
<th class="PC">Windows
<td class="yes">Yes
<td class="no">No
<td class="yes">Yes
<td class="no">No
<tr>
<th class="PC">Opera 6.06
<th class="PC">Windows
<td class="no">No
<td class="no">No
<td class="no">No
<td class="no">No
<tr>
<th class="PC">Opera 7.23
<th class="PC">Windows
<td class="yes">Yes
<td class="no">No
<td class="no">No
<td class="no">No
<tr>
<th class="PC">K-Meleon 0.8.2
<th class="PC">Windows
<td class="no">No
<td class="no">No
<td class="yes">Yes
<td class="no">No
<tr>
<th class="PC">Mozilla 1.5
<th class="PC">Windows
<td class="no">No
<td class="no">No
<td class="yes">Yes
<td class="no">No
<tr>
<th class="PC">Mozilla 1.6
<th class="PC">Windows
<td class="no">No
<td class="no">No
<td class="yes">Yes
<td class="no">No
<tr>
<th class="PC">Firebird 0.7
<th class="PC">Windows
<td class="no">No
<td class="no">No
<td class="yes">Yes
<td class="no">No
<tr>
<th class="PC">Netscape 4.72
<th class="PC">Windows
<td class="no">No
<td class="no">No
<td class="no">No
<td class="no">No
<tr>
<th class="PC">Netscape 4.77
<th class="PC">Windows
<td class="no">No
<td class="no">No
<td class="no">No
<td class="yes">Yes
<tr>
<th class="PC">Netscape 4.80
<th class="PC">Windows
<td class="no">No
<td class="no">No
<td class="no">No
<td class="yes">Yes
<tr>
<th class="PC">Netscape 6.2.3
<th class="PC">Windows
<td class="no">No
<td class="yes">Yes
<td class="yes">Yes
<td class="no">No
<tr>
<th class="PC">Netscape 7.1 rev 1.4
<th class="PC">Windows
<td class="no">No
<td class="no">No
<td class="yes">Yes
<td class="no">No
<tr>
<th class="MAC">IE5
<th class="MAC">MAC
<td class="yes">Yes
<td class="no">Reports an Error
<td class="no">Reports an Error
<td class="no">Untested
<tr>
<th class="MAC">IE5.2
<th class="MAC">MAC
<td class="no">No
<td class="yes">Yes
<td class="no">No
<td class="no">No
<tr>
<th class="MAC">Safari
<th class="MAC">MAC
<td class="no">No
<td class="no">No
<td class="no">No
<td class="no">No
<tr>
<th class="MAC">Netscape 7.1
<th class="MAC">MAC
<td class="no">No
<td class="no">No
<td class="yes">Yes
<td class="no">No
<tr>
<th class="MAC">iCab 2.9.7
<th class="MAC">MAC
<td class="no">No
<td class="no">No
<td class="no">No
<td class="no">No
<tr>
<th class="Linux">Mozilla 1.4
<th class="Linux">Linux
<td class="no">No
<td class="no">No
<td class="yes">Yes
<td class="no">No
<tr>
<th class="Linux">Galeon 1.3.8
<th class="Linux">Linux
<td class="no">No
<td class="no">No
<td class="yes">Yes
<td class="no">No
<tr>
<th class="Linux">Konqueror 3.1.4
<th class="Linux">Linux
<td class="untested">No
<td class="untested">No
<td class="untested">No
<td class="untested">No
</table>
</div>
<h3>Notes:</h3>
<dl>
<dt>Windows:
<dd>Netscape 7.1: Hangs the loading status bar at 100%
<dd>Why is NS7.1 resizing my buttons?
<dd>Mozilla 1.5: Hangs the loading status bar at 100%
<dd>Opera 7.1: Spoof mode made no difference
<dt>MAC:
</dl>
</blockquote>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-75122711029888287892022-11-01T13:58:00.031+09:002022-12-07T01:31:04.031+09:00es2-postprocessorでOpera8未満、IE5.5未満でも動くJavaScriptを書く<div class="note"><p>「これまでに確認したレガシーな DHTML ブラウザの ES3 サポートと実装のバグ」の各表のタイトルを修正。調査ミスを修正。(2022/11/24)
<p>「これまでに確認したレガシーな DHTML ブラウザの ES3 サポートと実装のバグ」の調査ミスを修正し、調査項目を追加しました。(2022/11/20)
<p>IE5 の「ES3 で追加された構文」の誤りを修正しました。(2022/11/04)
</div>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkTqETJj10fbZEw1O_oBeCtwcxeJ0m5ZJIQ9OHFS3-64dKdHHc2x9PRLVtzJOk41iCmv-vB8W5IK-uSuyjmuMJCaGnvujpTUP-I0zaZVkRwIH9OvLMW8mIl1nbsSohScMDgyd-DBd9R-OnTWpERZ7p2dkJhthVv-ToZ2fY5v0dfVg1kBQD22zvas0Q/s1078/Opera7.54u-syntax-error-with-labeled-break.png"><img alt="" width="200" data-original-height="1077" data-original-width="1078" src="//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkTqETJj10fbZEw1O_oBeCtwcxeJ0m5ZJIQ9OHFS3-64dKdHHc2x9PRLVtzJOk41iCmv-vB8W5IK-uSuyjmuMJCaGnvujpTUP-I0zaZVkRwIH9OvLMW8mIl1nbsSohScMDgyd-DBd9R-OnTWpERZ7p2dkJhthVv-ToZ2fY5v0dfVg1kBQD22zvas0Q/s160/Opera7.54u-syntax-error-with-labeled-break.png"></a>
<figcaption>「<a href="https://twitter.com/itozyun/status/1488876610077954051" target="_blank" rel="me nofollow">Opera 7.54u2 ラベル付きの <code>break</code> で構文エラー</a>」2022年2月2日
のツイート</figcaption>
</figure>
</span>
<p><a href="https://github.com/googlearchive/code-prettify" target="_blank" rel="nofollow">Google Code Prettify</a>(<a href="https://github.com/googlearchive/code-prettify/commit/f395274a5a11597a8875f8d3d7fc796c525d9f82" target="_blank" rel="nofollow">2006年~</a>, IE6+, Gecko 1.8+) は Ajax が登場した時代のライブラリです。これを全ての DHTML ブラウザで動くようにしたいと思い立っていろいろやりました。
<p>全ての DHTML ブラウザとは、IE5(1999年)以上、Gecko 0.6(2000年)以上(マイルストーンまでは頑張っていません…)、Opera7(2003年)以上、WebKit とします。独自な DOM 実装の IE4(1998年)については、ぼちぼち頑張ります。KHTML もおいおい…。
</div>
<p>本件で得られた知見を水平展開すれば、Ajax 時代(<a href="https://ja.wikipedia.org/wiki/Ajax#cite_note-@it-5" target="_blank" rel="nofollow">2005年~</a>)のコード資産の恩恵をよりレガシーなブラウザへもたらすことが出来るでしょう。多分。
<h2>1. これまでに確認したレガシーな DHTML ブラウザの ES3 サポートと実装のバグ</h2>
<p>最初期の DHTML ブラウザの中には、IE6(2001年)をサポートするライブラリが動かないものがあります。これらのブラウザはデバッグ機能も貧弱で対応は困難を極めたりします。あらかじめこのような対応表を参照することで状況は一歩前進します。多分。
<h3>構文エラーが解消するバージョン</h3>
<div class="hscroll">
<table>
<thead>
<tr>
<th colspan=2 rowspan=2>ブラウザのサポートバージョン<th rowspan=2>コード例<th colspan=2>IE<th rowspan=2>Opera<th rowspan=2>Gecko<th rowspan=2>WebKit
<tr>
<th>Mobile<th>PC
<tbody>
<tr>
<th rowspan=2>ES3 で追加された構文<th><td><code>instanceof</code>, <code>try~catch</code>, <code>throw</code>
<td>?<td>5.0(*1)<td>✔<td>✔<td>?
<tr>
<th><code>in</code> オペレーター<td><code>"length" in []</code>
<td>?<td>5.5(*1)<td>✔<td>✔<td>?
<tr>
<th colspan=2>ラベル付きステートメント<td><code>a: {break a}</code>
<td>?<td>✔<td>7.5(*2)<td>✔<td>?
<tr>
<th>Object リテラル<th>数値のプロパティ<td><code>{1 : 1}</code>
<td>?<td>5.5(*3)<td>✔<td>✔<td>?
<tr>
<th rowspan=3>RegExp リテラル(*4)<th><td><code>/./</code>
<td>?<td>✔<td>✔<td>✔<td>?
<tr>
<th>global, ignoreCase<td><code>/./g, /./i</code>
<td>?<td>5<td>✔<td>✔<td>?
<tr>
<th>multiline<td><code>/./m</code>
<td>?<td>5.5<td>✔<td>✔<td>?
</table>
</div>
<ol>
<li>対処法は 2. を参照。
<li><p>「<a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/break#%E3%83%A9%E3%83%99%E3%83%AB%E4%BB%98%E3%81%8D%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B_break">ラベル付きステートメント</a>」を使うコードはほぼ見ませんが、Closure Compiler がアグレッシブにコードの最適化を行った結果、出力されることがあります。
<p><code>do{break}while(false)</code> に書き換えることで構文エラーを回避できます。
<li><p>IE5 以下の Object リテラルのプロパティは数値文字列には対応するので、コードを書き換えます。Closure Compiler は常に Object リテラルの数値文字プロパティを数値に書き換えてしまうので、es2-postprocessor で修正します。
<li><a href="http://www.yaldex.com/javascript_tutorial_2/LiB0178.html#2269" target="_blank" rel="nofollow">JavaScript Object Reference > RegExp (Built-in Object)</a> の各構文の実装状況。
</ol>
<h3>実行時に起きるエラーや問題が解消するバージョン</h3>
<div class="hscroll">
<table>
<thead>
<tr>
<th colspan=2 rowspan=2><th rowspan=2>コード例<th colspan=2>IE<th rowspan=2>Opera<th rowspan=2>Gecko<th rowspan=2>WebKit
<tr>
<th>Mobile<th>PC
<tbody>
<tr>
<th colspan=2>null への for in<td><code>for(key in null)</code>
<td>?<td>✔<td>7.5<td>✔<td>?
<tr>
<th>Object リテラル<th>空文字列のプロパティ<td><code>{"" : "empty"}</code>
<td>?<td>✔<td>8(*1)<td>✔<td>?
<tr>
<th colspan=2>window や DOM プロパティの削除<td><code>delete window.__apply</code>
<td>?<td>9(*2)<td>✔<td>✔<td>?
<tr>
<th colspan=2>空の配列の操作でエラーを投げる<td><code>--array.length</code>
<td>?<td>5.5(*3)<td>8(*4)<td>✔<td>?
</table>
</div>
<ol>
<li>buggy な挙動は「<a href="https://itozyun.github.io/web-doc-base/test/javascript-implementation.html" target="_blank" rel="me nofollow">Javascript 実装状況と深刻なバグ</a>」で確認してください。
<li>未検証ですが <code>ActiveXObject</code> や CSSOM でも起きそうです。ofk 氏による <code>Function.prototype.apply</code> の polyfill からの<a href="https://github.com/ECMAScript2/es2-to-es3/blob/c3fbbb068afaa5637bc8c72c4f18410609f674a3/Function.prototype.apply.js#L42" target="_blank" rel="me nofollow">変更点</a>。
<li>IE5 では空の配列に <code>--this.length</code> の操作を行うと、長さが 4294967296 の配列になってしまう。<a href="https://github.com/ECMAScript2/es2-to-es3/commit/571c755b5816a13b4222dfdc14f6849847d11793" target="_blank" rel="nofollow">shift と pop の polyfill で問題を起こしていました</a>。
<li>Opera 7.x は空の配列に <code>--this.length</code> の操作を行うと、エラーは起きず <code>this.length === 0</code> です。
</ol>
<h2>2. ES3 をよりレガシーな DHTML ブラウザ用に書き換えるポイント</h2>
<h3>2.1. <code>instanceof</code> オペレーター</h3>
<p><code>instanceof</code> の替わりに <code>constructor</code> を調べる。継承クラスの可能性がある場合は、<code>__proto__</code> を使えない為、スーパークラスを辿る仕組みを用意する必要があります。
<p>次のコードは、ブラウザの開発メニューのコンソールで試す為のコードです。
<pre class="prettyprint lang-js"><code>(function(){
function SuperClass(){};
function SubClass(){};
SubClass.prototype = new SuperClass();
SubClass.prototype.__super__ = SubClass.prototype.constructor;
SubClass.prototype.constructor = SubClass;
return (function(instance, Class){
if(instance != null){
var proto = instance;
do{
if(proto.constructor === Class){
return (instance instanceof Class) ? 'Good.' : 'Bad!';
};
proto = proto.__super__ && proto.__super__.prototype;
}while(proto);
};
return (instance instanceof Class) ? 'Bad!' : 'Good.'
})(new SubClass(), SuperClass);
})();
</code></pre>
<p>但し、このような簡単なコードの場合、<code>new SubClass(), Object</code> などの組み込みオブジェクトの調査に失敗します。
<h3>2.2. <code>try~catch</code> ステートメントと <code>throw</code> ステートメント</h3>
<p>そもそも、エラーの出る条件を特定して、条件に合致した場合は、トライしない。
<p>エラーの発生する可能性のあるブラウザオブジェクトに VBScript で触ってエラーをキャッチする(Windows 版 IE のみ, <code>document.activeElement</code> など。)。
<p>または非同期に書き換える事が許されるなら、タイマー(<code>setTimeout</code>)のコールバック内でエラーの可能性のある関数を実行して、エラーが起きた場合は <code>window.onerror</code> ハンドラーでコールバック等の処理をする。(未検証)
<h3>2.3. <code>in</code> オペレーター</h3>
<p><code>in</code> の替わりに <code>this.XX !== undefined</code> か調べる。<code>undefined</code> のプロパティが存在する場合は <code>for in</code> 文を使う。
<pre class="prettyprint lang-js"><code>function isMember(key, obj){
if(obj != null){
if(obj[key] !== void 0){
return true;
};
for(var prop in obj){
if(prop === key) return true;
};
};
return false;
};
</code></pre>
<p>また <code>for(prop in null)</code> は Opera~7.2x でエラーになるので、事前に <code>null</code> のチェックをする事。
<h2>3. es2-postprocessor のご紹介</h2>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsxHTCTel5m6D3X9-PFMqUPPlBHlyHpF68ntdEkjukRB46pJJyJcjYYwSvu3nCCsEBElJpU6fPQp9ZEij4hMi-tsOf8Jl5o1RnvRGR4DwvikTD-efYZkV0n-sqpxYRLNMn0z5RTEWyLCMMnvM8voRqSVlrNC5J5VYVz49nbFIi40nBDZXMQv9U5YvS/s1032/es2-postprocessor.png"><img alt="" border="0" width="200" data-original-height="1032" data-original-width="1032" src="//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsxHTCTel5m6D3X9-PFMqUPPlBHlyHpF68ntdEkjukRB46pJJyJcjYYwSvu3nCCsEBElJpU6fPQp9ZEij4hMi-tsOf8Jl5o1RnvRGR4DwvikTD-efYZkV0n-sqpxYRLNMn0z5RTEWyLCMMnvM8voRqSVlrNC5J5VYVz49nbFIi40nBDZXMQv9U5YvS/s160/es2-postprocessor.png"></a>
<figcaption>npm > <a href="https://www.npmjs.com/package/es2-postprocessor" target="_blank" rel="me nofollow">es2-postprocessor</a></figcaption>
</figure>
</span>
<p>ラベル付きブロックを何度か手動で書き換えた後に、AST ライブラリを使った Javascript の書き換えに初挑戦して制作したポストプロセッサです。<del>まだテストは書いていません。</del>テストも書き始めました。(2022/11/02 追記)
<p>AST ライブラリを使った開発に着手するにあたって「<a href="https://kitak.hatenablog.jp/entry/2014/11/15/233649" target="_blank" rel="nofollow">JS の AST を扱うライブラリをつかって、不要な <code>eval</code> 呼び出しを除くコードを書いてみた</a>」が良い入門記事でした。
<p>本モジュールは <a href="https://github.com/itozyun/rerejs/" target="_blank" rel="me nofollow">ReRE.js for ES2</a> と <a href="https://github.com/ECMAScript2/es2-code-prettify" target="_blank" rel="me nofollow">ES2 Code Prettify</a> のビルドタスクで使っています。
</div>
<!--blockquote cite="https://twitter.com/itozyun/status/1488915866339086336"><p>Closure Compiler によって <code>Parser.prototype.XX</code> が最適化された際に、ラベル付き break(<code>break a;</code>) が出来てしまって、これが Opera 7.x で構文エラーになる。</blockquote>
<blockquote cite="https://twitter.com/itozyun/status/1512690063263428608">
<p>ラベル付き break で Opera 7.x さんが構文エラーになる件。
<p><code>a : { break a; }</code>
<p>↓に書き換えてみるなど。
<p><code>do { break; } while (false)</code>
</blockquote>
https://twitter.com/itozyun/status/1491008302729543686 -->
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-5754190030229069732022-04-08T22:53:00.036+09:002022-11-05T18:01:34.311+09:00MarkdownライブラリmarkedでGoogle Code Prettifyを使う<div class="note"><p>Google Code Prettify についての誤りを訂正しました。次のようなマークアップもサポートしています。<code class="prettyprint" class="language-html"><pre class="prettyprint"><code class="language-js">var a = 0;</code></pre></code>(2022/11/05)
<p><code>language-</code> について追記しています。(2022/04/27)
<p>コードを微修正しました。(2022/04/09)
</div>
<p>Javascript 製マークダウンコンパイラ <a href="https://github.com/markedjs/marked" target="_blank" rel="nofollow">marked</a> のデフォルトのコードブロックの HTML 出力では、Google Code Prettify でハイライト出来ません。
<p>Google Code Prettify 用の HTML を出力するべく marked のレンダラーを上書き設定する方法を紹介します。marked のバージョンは 4.0.12 です。
<p>Google Code Prettify は動作するブラウザの下限が IE6, Firefox2 とご機嫌で使い続けていますが、流石に不満が出てきたので、IE5, Gecko 0.6 対応版を書いています。
<h2>マークアップの確認</h2>
<pre class="aa"><code>~~~js
var a = 0;
~~~
</code></pre>
<p>デフォルト設定の marked は先のマークダウンから次の HTML を出力します。
<pre class="prettyprint lang-html"><code><pre><code class="language-js">
var a = 0;
</code></pre>
</code></pre>
<p>一方で Google Code Prettify が要求する HTML は次の通りです。
<pre class="prettyprint lang-html"><code><pre class="prettyprint lang-js"><code>
var a = 0;
</code></pre>
</code></pre>
<h2>markedのレンダラーの上書き</h2>
<h3>markedの設定をする</h3>
<p>まずはクラス名に記入する言語のプレフィックス部分が異なる為、 <code>langPrefix</code> プロパティで設定します。デフォルトの <code>language-</code> から <code>prettyprint lang-</code> にします。<a href="https://marked.js.org/using_advanced#options" target="_blank" rel="nofollow">オプション</a>に次のパラメータを渡します。
<pre class="prettyprint lang-js"><code>marked.setOptions({langPrefix : 'prettyprint lang-'});
</code></pre>
<h3>レンダラーの上書き</h3>
<p>そもそもクラス名を付す要素が異なりますので、<code>const marked = require('marked').marked;</code> に続けて、<a href="https://github.com/markedjs/marked/blob/3dc35bb7b8281f41a009e8a6c68b1ad2dd48c901/src/Renderer.js#L15" target="_blank" rel="nofollow">コードブロックのレンダラー</a>の上書きをします。
<p>オリジナルのレンダラーは、同一フォルダの <a href="https://github.com/markedjs/marked/blob/3dc35bb7b8281f41a009e8a6c68b1ad2dd48c901/src/helpers.js#L16" target="_blank" rel="nofollow">helper.js から <code class="__prettyprint lang-js">escape(code, true)</code> 関数</a>を使用していました。これを上書き関数でも使いたかったのですが、<code>require</code> してみると marked パッケージが js module だから駄目だよ、と怒られてしまいます。残念ながら、レンダラーが実際に使用している関数群は利用できませんでした。
<p>仕方なくオリジナルのレンダラーの関数そのものを控えておいて、これをコールして、この戻り値を書き換える、という方法を取りました。次がコードの全てになります。
<h3>コード全体</h3>
<pre class="prettyprint lang-js"><code>const marked = require( 'marked' ).marked;
const renderer = new marked.Renderer();
const originalRenderCode = renderer.code;
renderer.code = function(code, infostring, escaped){
const classStart = '<pre><code class="';
var html = originalRenderCode.call(this, code, infostring, escaped);
if(0 <= html.indexOf(classStart)){
const classEnd = html.indexOf('"', classStart.length);
const langClass = html.substring(classStart.length, classEnd);
html = html.replace(
'<pre><code class="' + langClass + '">',
'<pre class="' + langClass + '"><code>'
);
};
return html;
};
marked.setOptions({renderer : renderer, langPrefix : 'prettyprint lang-'});
</code></pre>
<p>以上でマークダウンから出力したコードブロックを Google Code Prettify でハイライト出来るようになりました。デフォルトで <code><code></code> にクラス名を付けるのはやや解せませんが、カスタマイズが出来るので良しです。
<hr>
<p>デフォルトで <code><code></code> にクラス名を付けるのも <code>language-</code> を使うのも、<a href="https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-code-element" target="_blank" rel="nofollow">HTML(WHATWG Living Standard)仕様中で提案</a>されていることでした。<del>Google Code Prettify 側の言語の決定方法を変更した方が良さそうです。</del>(2022/04/27)
<p>Google Code Prettify も提案に対応していました。(2022/11/05)
<blockquote cite="https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-code-element" title="HTML Living Standard > 4.5.15 The code element(翻訳は DeepL)"><p>There is no formal way to indicate the language of computer code being marked up. Authors who
wish to mark <code>code</code> elements with the language used, e.g. so that syntax highlighting
scripts can use the right rules, can use the <code>class</code> attribute, e.g.
by adding a class prefixed with "<code>language-</code>" to the element.
<hr>
<p>マークアップされるコンピュータ・コードの言語を示す正式な方法はありません。例えば、構文強調スクリプトが正しい規則を使用できるように、コード要素に使用言語をマークしたい場合は <code>class</code> 属性を使用することができます。例えば、要素に "<code>language-</code>" を先頭に持つクラスを追加する。
</blockquote>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-16554463743543026832022-03-28T18:40:00.011+09:002022-04-03T16:13:56.713+09:00EdgeHTMLエンジンの検証用にMicrosoft製Javascript Browserをインストール、localhostのアクセス許可をする<div class="note"><p>Javascript Browser には Windows のハイコントラストモードで画面が表示されない症状があった為、他のブラウザアプリをインストールして検証に使っています。(2022/04/03)
</div>
<h2>EdgeHTML の簡易検証環境をゲットする</h2>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4RCTZ8WnGhxvxMxNHkk3KlEjYyBSxw_KM1rsxNN-W6Nj1C3qPffbtDE13BbeJY0umgeBvjW1q-ri4FiALWqT4wlfm_vh7fdUkf-TRG5jgiE9MR9o0D2vS-c_7u1oMqZw-BVh1Y1Mqzq3PjnJ4zcubhzamotk54qYlC14a93c5e7YvyBcKogvCE5z1/s851/Screen%20Shot%202022-03-28%20at%2016.39.09-fullpage.png"><img alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4RCTZ8WnGhxvxMxNHkk3KlEjYyBSxw_KM1rsxNN-W6Nj1C3qPffbtDE13BbeJY0umgeBvjW1q-ri4FiALWqT4wlfm_vh7fdUkf-TRG5jgiE9MR9o0D2vS-c_7u1oMqZw-BVh1Y1Mqzq3PjnJ4zcubhzamotk54qYlC14a93c5e7YvyBcKogvCE5z1/s160/Screen%20Shot%202022-03-28%20at%2016.39.09-fullpage.png"></a>
<figcaption>Microsoft store > <a href="https://www.microsoft.com/ja-jp/p/javascript-browser/9nblggh1z7vx" target="_blank" rel="nofollow">Javascript Browser</a></figcaption>
</figure>
</span>
<p>僕の Windows10 からも EdgeHTML エンジンの Edge ブラウザは消えてしまいましたが、ウェブサイトの検証を続ける為にいろいろやりました。
<p>Windows ストアには、EdgeHTML の WebView を使うブラウザアプリが登録されているので、これをインストールして Web サイトの簡易チェックに使ってみます。
<p>僕のお勧めは Microsoft が WebView アプリ開発の学習用に公開している <a href="https://www.microsoft.com/ja-jp/p/javascript-browser/9nblggh1z7vx" target="_blank" rel="nofollow">Javascript Browser</a> です。公式(デモ)アプリということでサードパーティー製にはない安心感があります。この他のブラウザアプリを使う場合、AppContainer のセキュリティ識別子(SID)を調べるひと手間が必要になります。
<p>早速インストールしてみます。EdgeHTML さん、お久しぶりです。
</div>
<h3>残念な点</h3>
<p>本題に入る前に残念な点を紹介しておきます。
<p>デベロッパーツール、右クリックメニューは利用できません。
<p>デフォルトのブラウザに設定することも出来ませんでした。Chromium が重いので Javascript Browser で Twitter クライアントアプリのリンクを開けたら良かったのですが。
<p><code>forced-colors</code> の検証が出来ません。(2022/04/03)
<h2>localhost にアクセスできない制限を解除する</h2>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1VGzl39Fjbf180kgCSSt-JqIGm2PyC2pQ2jt4qMzVlgRG-F5BzA7r8wpHawcVt6lsg1_dcXUtw64EoX6D1aCSqOzj7UoLWXqUjnrAjMnRPpcVRaLlTZSSvT3QUErVIQ0EMlOjcZOcukk9EzCm3aTraIRjwVnt6mR1B1bwEy68a3LPA87DQoioDP3E/s867/jsbrowser.PNG"><img alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1VGzl39Fjbf180kgCSSt-JqIGm2PyC2pQ2jt4qMzVlgRG-F5BzA7r8wpHawcVt6lsg1_dcXUtw64EoX6D1aCSqOzj7UoLWXqUjnrAjMnRPpcVRaLlTZSSvT3QUErVIQ0EMlOjcZOcukk9EzCm3aTraIRjwVnt6mR1B1bwEy68a3LPA87DQoioDP3E/s160/jsbrowser.PNG"></a>
<figcaption>localhost が表示出来た</figcaption>
</figure>
</span>
<p>さて Javascript Browser をウェブ開発の検証に使うために localhost へのアクセスを許可していきます。Windows ストアアプリの WebView にはデフォルトで localhost(127.0.0.1) にアクセスできない制限があります。
<p>これを管理者権限で起動した PowerShell から次のコマンドで解除します。<code>-p=</code> に続くのが Javascript Browser の SID です。
</div>
<pre class="aa"><samp>PS > CheckNetIsolation.exe LoopbackExempt -a -p=<em>S-1-15-2-2286686099-3699191476-780792926-4103513722-34030058-4079768412-3798828762</em>
</samp></pre>
<p>次のコマンドで現在除外しているアプリケーションのリストを表示できます。
<pre class="aa"><samp>PS > CheckNetIsolation.exe LoopbackExempt -s
リスト ループバックは AppContainer を除外しました
[1] -----------------------------------------------------------------
名前: 62834microsoftwebappdemos.javascriptbrowser_68b04gps0nkf8
SID: S-1-15-2-2286686099-3699191476-780792926-4103513722-34030058-4079768412-3798828762</samp></pre>
<p>これで localhost にアクセス出来ると思います。解除には次のコマンドを使います。
<pre class="aa"><samp>PS > CheckNetIsolation.exe LoopbackExempt -c</samp></pre>
<h3>FiddlerのAppContainer Loopback Utilityを使ってSIDを調べる</h3>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhftVVIcFaRVROfbUPQuyYGxjd0wDvAvBl-1EIT23JMaOQ42bGMJ-rl6wNjKkQYMI1wlgCQcfXMvIoc_FMSEyu9VuNaTBwwdGbtmkzh0Sfv3bLNLkq7h3Qa9fx8gDhVlyeotSl03Kxj5EjwlFlSO5220kPa_lehZVPxkCRANiF05dIrZlTQjRX0ax9J/s1028/fidller.PNG"><img alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhftVVIcFaRVROfbUPQuyYGxjd0wDvAvBl-1EIT23JMaOQ42bGMJ-rl6wNjKkQYMI1wlgCQcfXMvIoc_FMSEyu9VuNaTBwwdGbtmkzh0Sfv3bLNLkq7h3Qa9fx8gDhVlyeotSl03Kxj5EjwlFlSO5220kPa_lehZVPxkCRANiF05dIrZlTQjRX0ax9J/s160/fidller.PNG"></a>
<figcaption><a href="https://www.telerik.com/fiddler/add-ons" target="_blank" rel="nofollow">Windows 8 AppContainer Loopback Utility</a></figcaption>
</figure>
</span>
<p>SID を調べるには Fiddler4 と併せてインストールされる EnableLoopback.exe を使いました。Fiddler.exe と同じ階層に入っています。
<p>ツールを使って除外リストに追加した上で、先のコマンドでリスト表示して SID を取得しました。正直 Windows アプリはサッパリでして、もっと良い方法があるかと思います。
</div>
<h2>最後に</h2>
<p>Javascript Browser は Javascript を使った WebView アプリ開発のデモ用に公開されています。このソースコードは <a href="https://github.com/MicrosoftEdge/JSBrowser" target="_blank" rel="nofollow">github</a> で公開されていて、これを元に自身で機能を追加したブラウザアプリを制作することが出来るようです。
<h3>助けられた記事</h3>
<ul>
<li><a href="https://hebikuzure.wordpress.com/2013/05/12/windows-%E3%82%B9%E3%83%88%E3%82%A2-%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E3%83%AB%E3%83%BC%E3%83%97%E3%83%90%E3%83%83%E3%82%AF%EF%BC%88localhost%EF%BC%89%E3%81%AB%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B/" target="_blank" rel="nofollow">Hebikuzure's Tech Memo > Windows ストア アプリをループバック(localhost)に接続する </a>
<li><a href="https://blog.okazuki.jp/entry/2013/07/23/101939" target="_blank" rel="nofollow">Windows ストア アプリでlocalhostに繋がらない?</a>
</ul>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-66995253441198261392022-03-06T23:51:00.064+09:002023-01-30T05:16:08.854+09:00Webページのサイドバーをいい感じにstickyする、マウスホイールする!タブフォーカスでスクロールする!SidebarFixerを実装した記録<div class="note"><p>「<a href="#1-1">スペック</a>」の表を分割して読みやすくしました。(2022/12/13)
<p><a href="https://github.com/itozyun/web-doc-base/commit/904bcbc3c344a40a1c37b51cfdafd6ba92014091#diff-dd9753a1ccc21572e8647a1b2cd9cfa1c7c1e95f3a6108d3fa9b479b9ebaa3f1L29" target="_blank" rel="me nofollow">タブフォーカスのパッチを修正</a>して Opera 7.xでも動作するようになったため、本機能の下限ブラウザも変わりました。<a href="https://github.com/itozyun/web-doc-base/commit/45b27bff98cd011c1ff9b400226df6649976423f" target="_blank" rel="me nofollow">tabNavigation.js</a> で Gecko 0.9.4以下のタブフォーカスの未実装を補った為、本機能の下限ブラウザも変わりました。(2022/12/03)
<p><code>ScrollEvent</code> について追記。<code>position:fixed</code> は Opera 9以上。(2022/11/29)
<p>その後も <a href="https://github.com/itozyun/web-doc-base/commit/2557d6c2560933b9578d494b1af4acfa94835e15" target="_blank" rel="me nofollow" title="Sticky sidebar when noscript.">JavaScript が無効の際に <code>position:sticky</code> でよしなにする更新</a>を行っています。(2022/11/12)
<p><a href="#5">5. その他の動作</a>の「1. シングルカラムに変化したのを検出してサイドバーの CSS-P をリセットする」にリンクを追記しました。(2022/05/30)
<p><a href="#4-1">4-1.</a> 2. の動作を変更しました。(2022/04/10)
</div>
<p>僕の開発している Web 文書用の<a href="https://github.com/itozyun/web-doc-base/blob/master/src/js/8_Library/SidebarFixer.js" target="_blank" rel="nofollow me">サイドバーをよしなにするスクリプト</a>についてです。同様のスクリプトを実装したい方には結構参考になると思います。
<ol>
<li><a href="#1">はじめに</a>
<ol>
<li><a href="#1-1">スペック</a>
<li><a href="#1-2">最新のChromeで意図しない挙動に遭遇</a>
<li><a href="#1-3">「コンテナの可視部分」について</a>
<li><a href="#1-4">実装にあたって留意事項</a>
</ol>
<li><a href="#2">ドキュメントのスクロールでの動作</a>
<ol>
<li><a href="#2-1">動作の詳細</a>
<li><a href="#2-2">TODO</a>
</ol>
<li><a href="#3">サイドバー上でのマウスホイール動作</a>
<ol>
<li><a href="#3-1">動作の詳細</a>
</ol>
<li><a href="#4"><kbd>Tab</kbd>キーでのリンク要素へのフォーカス移動</a>
<ol>
<li><a href="#4-1">動作の詳細</a>
<li><a href="#4-2">リンクへのフォーカスを Vivaldi で有効化する</a>
<li><a href="#4-3">リンクへのフォーカスを Safari 3.1.2 で有効化する</a>
</ol>
<li><a href="#5">その他の動作</a>
</ol>
<a name="1"></a>
<h2 id="1">1. はじめに</h2>
<p>このブログのテンプレートは僕が2015年から開発を続けています。ブログのサイドバーをスクロールによしなに追従させる <a href="https://github.com/itozyun/web-doc-base/blob/68ff56f0a69c790cf7f6abfe6b188602ab9539ed/js/SidebarFixer.js" target="_blank" rel="nofollow" title="2016年10月時点のコード">SidebarFixer.js</a> を間もなく追加して、機能追加を続けてきました。
<p>当初はスクロールイベントに反応するだけ(<code>position:sticky</code> 相当)でしたが、マウスホイールイベントでサイドバーだけをスライド出来るようにしました。最後にサイドバー内のフォーカス要素がビューポート内に入るようにしました。
<a name="1-1"></a>
<h3 id="1-1">1-1. スペック</h3>
<h4>CSS ポジショニングに使うプロパティ</h4>
<div class="hscroll">
<table>
<thead>
<tr><th>CSS のプロパティ<th>IE<th>Presto<th>Gecko<th>Webkit
<tbody>
<tr>
<th><code>transform3D</code>(*1), <code>transform</code>(*2)<td class=r>9<td class=r>?<td class=r>?<td>Chrome 2, Safari 4
<tr>
<th><code>position:fixed</code><td class=r>7<td class=r>9<td class=r>1<td>Chrome 1, Safari ~3.x(*3)
<tr>
<th><code>position:absolute</code><td class=r>5<td class=r>7.5<td class=r>0.6<td class=r>?
<tr>
<th><code>position:relative</code><td class=r><td class=r>7(*4)<td class=r><td class=r>
</table>
</div>
<ol>
<li><code>transform3D</code> を使わないとアニメーションが著しくガタつく環境があります。Android 3.1
<li><code>transform3D</code> をサポートするがバグの為に描画が乱れる環境には <code>transform</code> を使います。IE, Chrome 2。
<li>初期の WebKit では <code>transform</code> した要素では <code>offsetTop</code> の値が不正です。これらのブラウザでも正しい値の取れる <code>getBoundingClientRect</code> が未実装の Safari 3.x と Chrome 1は <code>position:fixed</code> を使います。(<a href="https://github.com/itozyun/web-doc-base/commit/c1943f5f75419d688b6348eab4583dcdcf39a35a" target="_blank" rel="me nofollow">2022/12/03</a>)
<li><code>position:relative</code> は Opera 7.23 以下用。
</ol>
<h4>サポートするイベント</h4>
<div class="hscroll">
<table>
<thead>
<tr><th colspan=2>イベント<th>IE<th>Presto<th>Gecko<th>Webkit
<tbody>
<tr>
<th rowspan=2><a href="#2">スクロール</a><th><code>scroll</code><td class=r>5<td class=r>7.5<td>1.0~1.1, 1.8<td class=r>?
<tr>
<th>fallback<td class=r><td class=r>7.0(*2)<td class=r>0.6(*2)<td class=r>
<tr>
<th rowspan=4><a href="#3">ホイール</a>
<th><code>wheel</code><td class=r>9<td class=r><td class=r>17<td>Chrome 31, Safari 7
<tr>
<th><code>mousewheel</code><td class=r>6<td class=r>9<td class=r><td>Chrome 1, Safari 3
<tr>
<th><code>MozMousePixelScroll</code><td class=r><td class=r><td class=r>1.9.1<td class=r>
<tr>
<th><code>DOMMouseScroll</code><td class=r><td class=r><td class=r>0.9.7<td class=r>
<tr>
<th rowspan=4><a href="#4">フォーカス</a>
<th><code>focusin</code><td class=r>6<td class=r>11.6(*3)<td class=r>52<td>Chrome 15, Safari 5.1
<tr>
<th><code>DOMFocusIn</code><td class=r><td class=r>8(*3)<td class=r><td class=r>?
<tr>
<th><code>focus</code> + capture phase<td class=r><td class=r>7(*3)<td class=r>0.6(*4)<td class=r>?
<tr>
<th>fallback<td class=r>5(*1)<td class=r><td class=r><td class=r>
</table>
</div>
<ol>
<li>IE5.5 以下は <code>document.activeElement</code> を監視してフォーカスの変化を検出する。(2022/11/19 追記)
<li><code>ScrollEvent</code> をサポートしない Gecko 0.9.x 以下、Gecko 1.2~1.7, Opera 7.2x以下は <code>window.pageYOffset</code> の変化をタイマーで監視する。(2022/11/29 追記)
<li>Opera 12.xまでは、タブフォーカスしたい要素に <code>tab-index</code> 属性が必要です。タブフォーカスさせたくない要素は <code>tab-index="-1"</code> を削除します。(2022/12/03)
<li>Gecko 0.9.4以下はタブフォーカスが不十分で、階層が離れている要素へフォーカス移動しません。<a href="https://github.com/itozyun/web-doc-base/blob/85de4152106caa80ee94c1222c42e2989821234c/src/js/7_Patch/tabNavigation.js" target="_blank" rel="me nofollow">パッチ</a>を追加して本機能のタブフォーカスも動作するようになりました。(2022/12/03)
</ol>
<a name="1-2"></a>
<h3 id="1-2">1-2. 最新の Chrome で意図しない挙動に遭遇</h3>
<p>この<a href="https://twitter.com/itozyun/status/1499655665991970816" target="_blank" rel="nofollow">木曜日に、最新の Chrome で意図したように動かないことに気づいた時はビビりました</a>。(僕は Firefox をメインのブラウザにしています。)
<p>Chrome と Firefox で <code>focus</code> イベントによって発生するフォーカス要素への自動スクロールが異なることが直接の原因だったと思います。しかし問題を見逃してきた大元には、場当たり的に機能追加を続けてきた失敗があると考えました。
<p>ビューポート、コンテナ、サイドバーの位置関係の全ての組み合わせを列挙して、もれなく処理を定義して文書化することをサボったのでした。
<a name="1-3"></a>
<h3 id="1-3">1-3. 「コンテナの可視部分」について</h3>
<div class="box">
<div class="caption" style="width:160px">
<figure>
<a href="https://blogger.googleusercontent.com/img/a/AVvXsEjdM-mCz0pXUOpqmHr4Aao7k_FCASfhhIDfJ-o4Bzmjo0xcD8LQzWpTpokVkYAuW1tmKIAFgTRkk-vwsyf7_ex3OmDnU68tlVbH_QsHCAGg-484VDSWixFz_vlfoB4WU0BU2sfOSPmZ5eYPCq18qGJkXYgEsJOw0zhYzE7dQjP4hnocCvR3VYR9YPax=s1000"><img alt="" src="https://blogger.googleusercontent.com/img/a/AVvXsEjdM-mCz0pXUOpqmHr4Aao7k_FCASfhhIDfJ-o4Bzmjo0xcD8LQzWpTpokVkYAuW1tmKIAFgTRkk-vwsyf7_ex3OmDnU68tlVbH_QsHCAGg-484VDSWixFz_vlfoB4WU0BU2sfOSPmZ5eYPCq18qGJkXYgEsJOw0zhYzE7dQjP4hnocCvR3VYR9YPax=s160"></a>
<figcaption><a href="https://viewer.diagrams.net/?tags=%7B%7D&highlight=0000ff&edit=_blank&layers=1&nav=1&title=SidebarFixer.drawio#R7V1Lc6M4EP41rvIcJmUhXj46Try5TO1UZWofR2IUow1GXoxjZ379SjxsIykT7EWIALkEGiHg%2B1rdrdbDIzhfH36LvU3wjfgoHBkT%2FzCCdyPDANAG9B%2BTvGUSZzrJBKsY%2B3mhk%2BAR%2F0S5sCi2wz7algomhIQJ3pSFSxJFaJmUZF4ck3252DMJy0%2FdeCskCB6XXihK%2F8R%2BEmRSazI5yR8QXgUJd%2BHJW76sYrKL8seNDDhJ%2F7LLa6%2BoKhdsA88n%2BzMRvB%2FBeUxIkh2tD3MUMmgL1LL7Fu9cPb52jKKkyg3rf4jt7R%2BmP8iBfAsmv4fR7u1rXsurF%2B5Q8RnpyyZvBT7pJyJWyWQEb%2FcBTtDjxluyq3uqEVQWJOuQngF6%2BIzDcE5CEqf3QtuGFBQq3yYxeUHFlYhEiBUmUXJWeHG%2FmN2zwvk7oThBh3c%2FFhwhpJqJyBol8Rstkt8ACxpypSx0cn9iGLi5LDhjl9Kba1auVatj1Sdo6UGO7gVIGzUjvX1ByTLIy76HpBz2MkeLhTuZaIbdVIU67CPq0Kiq7apgN%2FXDTq%2Fc3c2AdS9iP5%2Fbdl3Ym7CMPYAi9pYEeuCowt66BHugCvvF4t6ezzns86aQFS6crVUPEUdbUxAhaQTGRMYEUMWE3VHnapltc66ufnuj3szzsOs381P9sDdk5m2njL2r28qDrkbujts24wJ6EUTyuOu3LuCTRJHHjn1NTExBmQlbu63paiAjdJwkZr1pY%2BPoV3oNPdaqwCtLFIBehJA87jbQbuT7E0PyqQLT0m3YC1b7niuQMdFwrsDoajwv9Fr1%2B9gC2m7b%2BquBV%2BZjjV50pHjc9ftY45N0pGoAn8%2FTmJJebMM%2Btqf5eKtCtNO0j%2B1qP1bI3bTAx%2FaiH3s18Op8bC%2F6sTzuLfCx%2FenH8vlJKEnRN%2BtjC1fTNx%2Fr8NGOfh8Lu9qPFVJnjnYfC3vRj70aeHWTyvrTn%2BJzlq7E0TZs67saxAt5gxYYmF4E8VcDr87A9CeY5BM2jgT8Zg2M2dUIRug06TcwZi8imKuBV2ZgzF5k4sWpZLqzBGZ%2FIkc%2BS%2BBonxhv9jQTz2cJZDF8w1kCs0IQjyJ%2Fxpb3ndDxvW1w5OaMhzJp9TaJ27k9NxgRy138emyV2csiX1hZ%2BCEnH2h%2FIYtR6CX4tVy9jIb8Cd8Jpg8%2BTXDgMnQ2R%2BSW7OIlym86cSnUM%2BXz23xFiRevUCJUlCrF8av%2Fh55U6IAMelKbnth8oHetnggVqdaTukc92hKzt26ljdmCrqn6yPFK2JXF6wWdvUJd%2FwoEq%2B5UQHvDdcAFiVXXsbrKsL8oNdCdaJ1fT6x%2FGatVd7Kgpc61BbNmrBbkB5q389onzVgXZQY6Arv%2BOTNW3UN5n8e9Vl37oc69XjS011n32oIZM3YF9yrmOLSmNcrMGJ8h0WGXeZ%2B6ZrmKqpkOviLeOCpOdICLouLP6qmu3QNA3erQYeigLb0R2IuhS3EjNd3BGuxpE%2BDXirZg9KyXs7L0%2B4CeTjLnF3K1wQf0YpGL2AJ0%2BwBzaAJt8QG2mCl8xD568uIRo98O6Rvc7ujBih0E9JVQXIjpA49XaOkk8CJWE97iJ8ri8QuMCXkepfsuJx6O2O0c1RTQhOPzoyaSi7wQryJ6GqJnVgMjBy%2B9cJaL19j32UOk6lNu2KXNlyqpE5Pnu1ADV020Jhk7OTZKWee2fu0Qg7VfaEdI9oNyKFMOzoqbEt0AEt2AynRDzLqOb78o4G9JAaKKoZDBnCkDfMRo%2FllFuYW3xiHj4wGFr4i9mxqqJTGr3SjVYk9hPBuoVjFMK9mkr1mqxXk5YzBQrWRnad1cO2IYPjYGrpV0drVzLU5BGsOBayXJbe1cGyLX5sC1kh3%2FdIdmjjiMMbYGrpXsPKWdazFXM7YHrpXsgKKda9kwWZZZ8fFrkVgZO1%2FO8i1nFwalUGDsXckkn2aVQpJycQcDoCQ1r51rSc5lOnCtZCGrdq5l45CZWQ9AiW%2F73x37nccUnq%2FbFNcZLQAnm8PpYuEE8lT9Ah9KaXlWZeElMuGmyjOALXvGPEAey%2BI%2FBgix%2F8%2BEDQ3coVcUks2aEnJTPOQp5h97ktwydnBCfr7topuzV90o8Gdbqsg4Wo2yUb387AehSn3HNjKXqzuhCvccpioe0GaBogubgFSV%2BUEClbuOWSWNdySjB2AqUXnAL9StTeeLAeeK01WXobfd4mXKsxcnorj6RNaPuIDXzXgVJ7NWmgOLDjj5ix3fWPnZ32dX7g7nJ2%2FFSUQZOLuJnaZ33bipIqWC063pWene7yjGlEZm9j%2FF%2BmJocRabHw%2BvOu1WqGg6vZm65boUT711xUzcHx0cFf3Q4tm%2FaGWh94TC2%2BMPI3OfUIs9dMp6IDOIsqH2K2IAenr6deZMi06%2FgA3v%2FwM%3D" target="_blank" rel="nofollow me">draw.io で編集する</a></figcaption>
</figure>
</div>
<p>ようやく腰を据えて、各要素の位置関係のパターンを網羅する図を描きました。この図を眺めながら各イベントに対する処理を文書化して、処理の漏れが無いか確認していきました。<p>この作業に取り組んだところ「<em>コンテナの可視部分</em>」というキーワードでうまく整理できることが分かりました。
<p>この記事でコンテナとは、メインカラムとサイドバー(サブカラム)を包む <code><div></code> を指します。可視部分とはビューポートのこと。コンテナの可視部分とはビューポートとコンテナの重なり合う部分です。
</div>
<a name="1-4"></a>
<h3 id="1-4">1-4. 実装にあたって留意事項</h3>
<p>ビューポートのリサイズによって、コンテナの高さとサイドバーの高さも変わりうる。またメインカラムとサイドバーの高さの逆転も起こりうる。
<p>2カラムレイアウトからシングルカラムに変化しうる。
<a name="2"></a>
<h2 id="2">2. ドキュメントのスクロールでの動作</h2>
<p><code>position:sticky</code> っぽい動作をします。サイドバーがコンテナの可視部分より高い場合には、常にサイドバーのどこかしらでサブカラム可視部分を覆うようにスクロールに追従します。
<a name="2-1"></a>
<h3 id="2-1">2-1. 動作の詳細</h3>
<ol>
<li>サイドバーの高さ ≧ メインコンテンツの高さ
<ul>
<li>ゼロ位置
</ul>
<li>コンテナはビューポートの外
<ol>
<li>ビューポートのトップより上ならば、サイドバーはコンテナの地へ
<li>ビューポートのボトムより下ならば、ゼロ位置
</ol>
<li>サイドバーの高さ ≦ コンテナの可視部分の高さ
<ul>
<li>サイドバーの天をコンテナの可視部分の天に揃える
</ul>
<li>サイドバーの高さ > コンテナの可視部分の高さ
<ol>
<li>サイドバーの天がコンテナの可視部分の天より下なら、サイドバーの天をコンテナの可視部分の天に揃える
<li>サイドバーの地がコンテナの可視部分の地より上なら、サイドバーの地をコンテナの可視部分の地に揃える
<li>スクロール量 < コンテナのy + サイドバーの高さ - コンテナの可視部分の高さ
<ul>
<li>ゼロ位置
</ul>
<li>これ以外
<ul>
<li>サイドバーの地はコンテナの可視部分の地
</ul>
</ol>
</ol>
<a name="2-2"></a>
<h3 id="2-2">2-2. TODO</h3>
<p>サイドバーのコンテンツの先頭にページ内索引があってリンク集などが続く場合、なるべく索引をビューポートに入れ続けたい。そこでサイドバーの地がコンテナの地と揃うのは、コンテナの地が画面に入っている時とする。
<p>逆に、サイドバーのコンテンツに軽重が無い場合、素早くサイドバー全体を見渡せるように先の動作となる。(4.4.3~4.4.4)
<p>この動作を切り替えられるようにする。
<a name="3"></a>
<h2 id="3">3. サイドバー上でのマウスホイール動作</h2>
<p>文書自体のスクロールをキャンセルして、ホイールスクロール量分だけサイドバーだけがスライドします。文書をスクロールしなくてもサイドバーを見渡すことが出来るので、サイドバーにページ内索引等のメインカラムと連携するコンテンツがある場合には、特に活きる機能です。
<a name="3-1"></a>
<h3 id="3-1">3-1. 動作の詳細</h3>
<ol>
<li>サイドバーの高さ ≦ コンテナの可視部分の高さ
<ul>
<li><code>mousewheel</code> イベントをキャンセルしない
</ul>
<li>サイドバーの高さ > コンテナの可視部分の高さ
<ul>
<li>サイドバーの天の最小値は、コンテナの可視部分の地 - コンテナのy - サイドバーの高さ
<li>サイドバーの天の最大値は、コンテナの可視部分の天 - コンテナのy
</ul>
</ol>
<a name="4"></a>
<h2 id="4">4. <kbd>Tab</kbd>キーでのリンク要素へのフォーカス移動</h2>
<p>サイドバー内のリンク要素等への <code>focus</code> イベントに反応して、要素が画面内に入るように調整します。フォーカスを得た要素が画面外にある場合に起る自動スクロールはブラウザ間で異なりますが、これを共通のルールで調整することで文書の閲覧性を一定にします。
<a name="4-1"></a>
<h3 id="4-1">4-1. 動作の詳細</h3>
<ol>
<li>コンテナはビューポートの外(<code>focus</code> イベント直後のスクロールが起きていないケース、未確認)
<ul>
<li>ビューポートの高さ ≦ サイドバー下のフォーカスを得た要素の高さなら、コンテナのyにスクロールする
<li>コンテナはビューポートの上側なら、コンテナの地 - 要素の高さにスクロールする
<li>コンテナはビューポートの下側なら、コンテナのy + 要素の高さ - ビューポートの高さにスクロールする
</ul>
<code>window.scroll()</code> の呼び出しに対して、同期か非同期でスクロールイベントが起きる場合を想定したコードにする。
<li>サイドバーの高さ ≦ コンテナの可視部分の高さ
<ul>
<li><del>可視部分の天と要素の天を合わせる</del> サイドバーの天をコンテナの可視部分の天に揃える(2022/04/10)
</ul>
<li>サイドバー下のフォーカスを得た要素の高さ ≦ コンテナの可視部分の高さ
<ol>
<li>要素の天をコンテナの可視部分の天に合わせると、サイドバー下に隙間が出来る場合、可視部分の地と要素の地を合わせる
<li>完全に入っている場合
<ul>
<li>サイドバー上に隙間が出来る場合、可視部分の天と要素の天を合わせる
<li>これ以外の場合、何もしない
</ul>
<li>要素の天がコンテナの可視部分に入っている場合、可視部分の地と要素の地を合わせる
<li>要素の地がコンテナの可視部分に入っている場合、可視部分の天と要素の天を合わせる
<li>要素はコンテナの可視部分より上、可視部分の天と要素の天を合わせる
<li>要素はコンテナの可視部分より下、可視部分の地と要素の地を合わせる
</ol>
<li>これ以外
<ul>
<li>コンテナの可視部分の天と要素の天を合わせる
</ul>
</ol>
<a name="4-2"></a>
<h3 id="4-2">4-2. リンクへのフォーカスを Vivaldi で有効化する</h3>
<div class="box"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjFTisUyW_YnW7SU1fMksjFK6uH1CJbKPmXgIE79N_ft_z1puw2TmOs89DgK-mZma-oRCd-nEETG2C1xFYP4BIBudG5SQyi9vvKwEOTL4EdQBcxD2t1KPYqT3cArLUYszKVRMGE2alsLqoWOJJmDvqWvVBF9XgIB0UcCuv7GTd6n-SqNY4V7gdlBUhF"><img src="https://blogger.googleusercontent.com/img/a/AVvXsEjFTisUyW_YnW7SU1fMksjFK6uH1CJbKPmXgIE79N_ft_z1puw2TmOs89DgK-mZma-oRCd-nEETG2C1xFYP4BIBudG5SQyi9vvKwEOTL4EdQBcxD2t1KPYqT3cArLUYszKVRMGE2alsLqoWOJJmDvqWvVBF9XgIB0UcCuv7GTd6n-SqNY4V7gdlBUhF=s160"></a>
<p>Chronium ベースのブラウザである Vivaldi はデフォルトでリンク要素へのフォーカス移動が無効になっています。
<p><samp>ウェブページ > ウェブページのフォーカス > すべてのコントロールとリンクをフォーカスする</samp> にチェックを付けます。
</div>
<a name="4-3"></a>
<h3 id="4-3">4-3. リンクへのフォーカスを Safari 3.1.2 で有効化する</h3>
<div class="box"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhTtNjQH-d2UUzAR37v7patPwVJrwcmd3xdXqg1WKrCKulOzZomcDcHttRuQch4nG-VTlOnJfMRtDMGqGol1-34pU9nyspbyzrhB5X4i8_phen2QUtkmJQBou8GQwYJG-Fr36y_g7NCV9CZJtk3KiilhcxQd6Xz4cDttPivLiT4fg82g_TJy3S_k9yg"><img src="https://blogger.googleusercontent.com/img/a/AVvXsEhTtNjQH-d2UUzAR37v7patPwVJrwcmd3xdXqg1WKrCKulOzZomcDcHttRuQch4nG-VTlOnJfMRtDMGqGol1-34pU9nyspbyzrhB5X4i8_phen2QUtkmJQBou8GQwYJG-Fr36y_g7NCV9CZJtk3KiilhcxQd6Xz4cDttPivLiT4fg82g_TJy3S_k9yg=s160"></a>
<p>Safari 3.1.2 はデフォルトでリンク要素へのフォーカス移動が無効になっています。
<p><samp>編集 > 設定 > 詳細 > Tab キーを押したときに Web ページ上の各項目を強調表示</samp> にチェックを付けます。
</div>
<a name="5"></a>
<h2 id="5">5. その他の動作</h2>
<ol>
<li>シングルカラムに変化したのを検出してサイドバーの CSS-P をリセットする
<ul>
<li><a href="/2016/03/presto.html#2">Opera でスモールスクリーンモードを有効にすると画面サイズに関わらず、handheld メディア用の CSS が適用される</a>ので、ビューポートのサイズを参照するコードでは不適切。メインカラムとサイドバーの <code>offsetTop</code> が一致するか、で判定する。(2020/05/30 追記)
</ul>
<li><code>resize</code> イベント
<ul>
<li>スクロール位置を再取得してサイドバーの位置を調整する
</ul>
<li><code>window.onblur</code> イベント
<ul>
<li><del>何か処理が必要か?不明</del> 不要に思う(2022/12/13)
</ul>
</ol>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-44818459129445344582021-12-07T13:45:00.058+09:002024-01-16T23:08:33.282+09:00対応ブラウザをかなり拡げた場合の最適なCSSの読み込み方法、web-doc-baseのブートシーケンスについて<div class="note"><p>「<a href="#3-4">main.js から CSS を読み込む</a>」に、<code>document.write()</code> での CSS の読み込みについて追記。(2023/08/23)
<p><code><noscript></code> の <code>.textContent</code> から CSS の <a href="https://github.com/itozyun/web-doc-base/commit/ca4a0fe050866ddc858f38cf8b4a754e866b36fd" target="_blank" rel="nofollow me">URL を取得することが出来ないブラウザに AOSP 3未満を追加</a>し、<a href="#3-4">記事にも反映</a>しました。(2023/01/05)
<p><code><noscript></code> の <code>.textContent</code> から CSS の <a href="https://github.com/itozyun/web-doc-base/commit/26e76ef76346d621a0c278283679a6256e993a0f" target="_blank" rel="nofollow me">URL を取得することが出来ないブラウザを修正</a>し、<a href="#3-4">記事にも反映</a>しました。Chrome 2~3 を除外していたのは誤りでした。(2022/05/01)
<p><a href="https://github.com/itozyun/web-doc-base/commit/0967f2973fdf8885484324443412821a3a02c822" target="_blank" rel="nofollow me">ブラウザ毎の CSS の分け方とファイル名の変更</a>を反映。(2022/04/28)
<p><code><noscript></code> の <code>.textContent</code> から CSS の URL を取得することが出来ないブラウザに Chrome 4~7 を加えました。(2022/03/18)
<p>「<q>9~9.2x でも一部の非対応なモードのスタイルが適用</q>」は誤りでした。(2022/03/01)
<p>「<a href="#3-1">javascript を有効にするか Web ブラウザの変更を促す警告メッセージ</a>」の HTML タグに <code></p></code> を追記。(2020/03/01)
<p>「<a href="#3-1">javascript を有効にするか Web ブラウザの変更を促す警告メッセージ</a>」の HTML タグを大幅に修正しました。<a href="https://github.com/itozyun/web-doc-base/commit/c884f91d2fb2ba346ec8f1a981e84f65b4d8db73" target="_blank" rel="nofollow me">github</a>(2022/02/23)
<p><code><noscript></code> の <code>.textContent</code> から CSS の URL を取得することが出来ないブラウザについて調査と<a href="https://github.com/itozyun/web-doc-base/commit/beaf285895c4aebbae69396809365f0e47107338" target="_blank" rel="nofollow me">実装</a>を終えて、追記しました。(2022/02/09)
<p>「<a href="#3-1">javascript を有効にするか Web ブラウザの変更を促す警告メッセージ</a>」の HTML タグを追記しました。<a href="https://github.com/itozyun/web-doc-base/commit/08a5328aafc206a3fc078a9945d4377ccb27ecd4" target="_blank" rel="nofollow me">github</a>(2022/02/03)
<p>記事中でグレースフルデグラデーションとしている部分ですが、レグレッシブ・エンハンスメントと読み替えた方が良いかもしれません。(2021/12/16)
</div>
<p>CSS を一本化しているにも係わらず CSS の読み込み経路が複数になり、やや複雑になってきたので記事化しておくこととしました。
<ol>
<li><a href="#1">はじめに</a>
<ol>
<li><a href="#1-1">プログレッシブエンハンスメントを一部で諦めた件について</a>
</ol>
<li><a href="#2">CSS読み込みのチェックポイント</a>
<ol>
<li><a href="#2-1">ファーストビューのインライン化</a>
<li><a href="#2-2"><code>document.write('<link>')</code> について</a>
<li><a href="#2-3">なるべく外部 javascript からメインの CSS を読み込まない</a>
</ol>
<li><a href="#3">ブラウザ毎の経路の解説</a>
<ol>
<li><a href="#3-1">条件付きコメント非対応ブラウザで javascript が無効の場合</a>
<li><a href="#3-2">IE5~9 の場合</a>
<li><a href="#3-3">インライン javascript から CSS を読み込む</a>
<li><a href="#3-4">main.js から CSS を読み込む</a>
</ol>
</ol>
<a name="1"></a>
<h2 id="1">1. はじめに</h2>
<p>僕の Web 文書用ベースプロジェクト <a href="https://github.com/itozyun/web-doc-base" target="_blank" rel="nofollow me">web-doc-base</a> では、新旧を問わず広範なブラウザで閲覧性を良好にすべく開発を続けています。
<p>この内、プログレッシブエンハンスメントを諦めざるを得ない一部のレガシーブラウザに対しては、各ブラウザ用の CSS を用意して Javascript で読み込むようになりました。javascript が無効の場合は、モダンブラウザ用の CSS が読み込まれてしまうことになります。つまり、グレースフルデグラデーションでの対応です。
<p>併せてモダンブラウザについても Javascript が有効な場合は、Javascript で CSS を読み込むこととなりました。これは、レガシーブラウザが無用なモダンブラウザ用の CSS をロードしない為に、<code><style></code> を <code><noscript></code> で囲んだことによる変更です。
<div class="note">
<a name="1-1"></a>
<h3 id="1-1">1. 1. プログレッシブエンハンスメントを一部で諦めた件について</h3>
<p>長らく <i>javascript の無効なレガシーブラウザについてもある程度の閲覧性を確保したい</i>、と考えてきましたが、Opera 9.5 未満の <code>@media</code> クエリがヤバすぎるので諦めました。<del>以下の記述は 8.5x 以下についてですが、9~9.2x でも一部の非対応なモードのスタイルが適用されました。</del>(この部分は誤りでした。2022/03/01)
<blockquote cite="/2020/11/graceful-degradation.html?#graceful-degradation-1_2" title="Web文書のグレースフルデグラデーションをムキになってやってみる > 2. グレースフルデグラデーションの戦略">
<p>中でも Opera 8 以下には <code>@media</code> 規則に致命的な不備がありました。ダークモードや<a href="/2019/01/howto-high-contrast-mode-support.html">ハイコントラストモード用</a>のスタイルが問答無用に適用されていく様を見て、Javascript に依存しない CSS ハックでの対処を放棄せざるを得ませんでした。
</blockquote>
</div>
<a name="2"></a>
<h2 id="2">2. CSS読み込みのチェックポイント</h2>
<ol>
<li><a href="#2-1">ファーストビューのインライン化</a>
<li><a href="#2-2"><code>document.write('<link>')</code> について</a>
<li><a href="#2-3">なるべく外部 javascript からメインの CSS を読み込まない</a>
</ol>
<a name="2-1"></a>
<h3 id="2-1">2. 1. ファーストビューのインライン化</h3>
<p>ここ何年かで Web 文書のパフォーマンスチェックツールが推奨してくる、<a href="https://developers.gmo.jp/8049/" target="_blank" rel="nofollow" title="Webページの表示高速化:ファーストビューのCSS/JSをインラインで記述する">ファーストビュー部分の CSS のインライン化</a>は未着手です。
<a name="2-2"></a>
<h3 id="2-2">2. 2. <code>document.write('<link>')</code> について</h3>
<p>モダンブラウザでは <code>document.write()</code> での <code><link rel="stylesheet"></code> の追加はページのパフォーマンスの観点から推奨されません。この件については web.dev による解説文の該当箇所を次に引用します。
<p>一方で一部のレガシーブラウザでは <code>document.write('<link>')</code> でないとスタイルの適用が不安定なものがあります。僕が確認しているのは、Opera 9.0 未満と Gecko 1.0 未満です。
<blockquote cite="https://web.dev/no-document-write/" title="Uses document.write() (DeepL で翻訳)"><p>Using <code>document.write()</code> can delay the display of page content by tens of seconds and is particularly problematic for users on slow connections. Chrome therefore blocks the execution of <code>document.write()</code> in many cases, meaning you can't rely on it.
<hr>
<p><code>document.write()</code> を使用すると、ページコンテンツの表示が数十秒遅れることがあり、低速回線のユーザーにとっては特に問題となります。そのため、Chrome は多くの場合、<code>document.write()</code> の実行をブロックしており、<code>document.write()</code> に依存できないようになっています。
</blockquote>
<a name="2-3"></a>
<h3 id="2-3">2. 3. なるべく外部 javascript からメインの CSS を読み込まない</h3>
<p>クロスブラウザ DOM 操作ライブラリ等の組み込まれた、main.js から <code><link rel="stylesheet"></code> を追加していたところ、一度だけですが、この main.js がネットワーク側の理由で読み込まれないケースに遭遇しました。つまり CSS も読み込まれません。
<p>このレアケースに対処する為に、殆んどのブラウザについてはインラインの javascript で <code><link></code> を追加することにしました。ライブラリのサポートが必要等の一部のブラウザでのみ、main.js から <code><link></code> 要素を追加しています。
<a name="3"></a>
<h2 id="3">3. ブラウザ毎の CSS を読み込む経路の解説</h2>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="//1.bp.blogspot.com/-lfBxArKqjgI/YZxlbuwWxyI/AAAAAAAASzw/_A8PfSFEpCEEkjL1nhzsVB8nZimS2LZ-wCLcBGAsYHQ/s600/boot.drawio.png"><img alt="" src="//1.bp.blogspot.com/-lfBxArKqjgI/YZxlbuwWxyI/AAAAAAAASzw/_A8PfSFEpCEEkjL1nhzsVB8nZimS2LZ-wCLcBGAsYHQ/s160/boot.drawio.png"></a>
<figcaption>HTML ファイルから CSS ファイルを読み込むフロー図。<a href="https://viewer.diagrams.net/?tags=%7B%7D&amp;highlight=0000ff&amp;edit=_blank&amp;layers=1&amp;nav=1&amp;title=boot#R7Vvfb%2BI4EP5b%2BpCXSkWxnQTyWCi97en2trqetLtPp5C44G2IaTAt7F9%2FduL8sGMK25IUtAWpjSeO48w333g8Qyw0mq%2F%2FSIPF7DONcGxBO1pb6MqCECDb4%2F%2BEZJNL%2Bj7IBdOURLJTJbgjP7EU2lK6IhFeKh0ZpTEjC1UY0iTBIVNkQZrSZ7XbPY3Vuy6CKW4I7sIgbkq%2FkojNcqln25X8EybTGdNOTILwYZrSVSJvZ0FkZ5%2F89DwohpKC5SyI6HNNhMYWGqWUsvxovh7hWKi20Fp%2B3fWWs%2BW0U5ywfS5I4SMlP%2BOv3u2X0X%2BfV9%2FRpx%2FwQo7yFMQrXDxGNlm2KfTzPCMM3y2CULSfuQ1YaDhj85i3AD%2B8J3E8ojFNs95onH24fMlS%2BoBrZ4bZl58J0lBagWiVarF5YxoHy6U8zlSLI9m6pwmrDQYuxZfL5fxxyvB6q2JAqW5uxZjOMUs3vMtaNURpv75sPlfGgAoMZzVDcAqkA2mA03LkCgV%2BIIH4BVBgA5RepnAdGf7ITAVDVXpCE6whJEVBTKYJb8b4Xowg1Ec4Iy6leE6iSNxkaMJeICHxg6BTnPxdOHlGmFpCCe2mTqHXv4IJjm%2FpkjBChX4nlDE6NyieUY1dnB0LMdgMr4OpuHa4wCnhD4DTSnpbiKDCLk9cnx%2FaPQAcOHD71V8Dkr9O5c6whypHgdMEHwy6RN9poH%2BTxISTC9p%2FBk%2FBMkzJgrXA2JArTGD%2Fas4Cr0vckKvh5jZxcw24obZw806KtbanfvonzVrj0mob0Aetwd83wO8Fc4FfLJh5dnFhuUNyz%2Fuc3Ywt96o8PWWZTuqd%2F%2F5yN%2Frn5vbfl%2Fqc8eFwEvERm2Md23LesWvwe%2B5O84Ae6NA5DE7LOQw83%2FVcCPrI54xx0Gk5h77qHBAyoI8MzmHQFvrFPkB1DhmLI%2FKkmIH3uBLbtkw9Fzkgl7wD6C%2FWuQeQ58U0pR1UwoyltS6ewW3kt9L8xfW55Y7OxUOKQ%2FHPthybzBc0ZeK4HJNgdx6EvZDvpar75COUl8uRjNfP%2BSY%2FTV64PtfKJH2lUsonjuWDZfr12nKLb4%2BZ%2Bl0Sw99NDOAb3GJ7xNgjS3BEfvHEtzraNtcxwd%2FpVgc08xGas5KbHXuZhoonmAck6f1YKtRvNwI6se0RdDWsDdujfpfbI7BHVuNQCcHr7KPw2LdeSAhuw0FF6xCRqat64DLTVw9NHAMs%2FdZgaaYblNAkXzrP5Yp9Iqtqt9lD5Gpcg7DXZJsx4ixYenhY3d1s45vHS1HlEBoXZCChRjfNd3F1pJtv2ULI5y3b36V%2Bs8bVWmltLFO%2BHa8J%2ByZvIY6zEXqubFVDiEYxwvbFU8O1ZH4sooVhWUipQz%2BAY6FJCT2OGkUcDXiuNLpKQ%2FyCuqVvY0E6xWynE2xaUs1OTDmrQpbiOGDkSZ2vyXbkHW4pSVh9%2Fe8rhgo8zavkzymvqiywMRAaaBavFyxyRTQG4uYWbGrdFqLDcvuEHa2AUky4YkY%2BYsWTUqdvoI4pk%2FNW6rzC5lXWHDsDBu9p2ND2e76skWYfTzUbffXc2877W5brA9u5fp%2Bi3a6d75GTajEgA%2FZRRGTaltiF7x6Q%2BQ1Yys3O7x5p%2Beqy4zrvH2gV9nLI1eKIPP%2F7eXTN87qvdOGwwEMn%2BIFduH6fYsKtunC4R%2FrsDVG%2BPUD1MB%2F0bLAj0s9at7Xk2tEFMkceoiMEVHN9dYiuhRQu6CZ0cbsI0QszP5G08YnX2rW0Mdi31u63FSJBUypxS639Zsz%2FnO8ot9dL6fzSj2K6Ukzfib4x4motkQxNGcsjJv9p19I9FX64by29tZoRNGU262SOSfIgJpPi%2B%2Bx0Vbo%2B1%2BrOHyUjBeqBDrWhZGSqDrfH9D1%2BUveRiTP7x%2FfbuA1eSsXpbmH%2FjLNWu24rE6eToJNtXDPjXIB9Yu5o7InvgQIPT91ZIMMvs01vT7TnjpoJ06Y%2F%2Bv1gGqgwQVMGtUuYioFrMKEPmBwtoQZMgVynMDVzV84HTLrTK%2FM%2F7wZTM9UyES8Wcpjw4wonXGtHt0FG0AjZnZwiaBdCvTTexM%2F0u6v2XiZrbpenhM1Wk17Id8LwmjD6c7NK%2BNEznlxENLyYBEuc%2FRb3KHDVgu%2BXCoYFY512AdZ%2BRGF6teAwDOXN6iXePNisXpRG4%2F8B" target="_blank" rel="nofollow">draw.io で閲覧、編集する</a></figcaption>
</figure>
</span>
<p>ブラウザ毎に異なる CSS を読み込む経路について解説します。フロー図の1~4の各経路番号について詳しく記述していきます。
<ol>
<li><a href="#3-1">条件付きコメント非対応ブラウザで javascript が無効の場合</a>
<li><a href="#3-2">IE5~9 の場合</a>
<li><a href="#3-3">インライン javascript から CSS を読み込む</a>
<li><a href="#3-4">main.js から CSS を読み込む</a>
</ol>
</div>
<table>
<caption>ブラウザ毎の CSS ファイルと経路番号</caption>
<thead>
<tr>
<th><th>css<th>js enabled<th>js disabled
<tbody>
<tr>
<th>IE 5, 5.5, 6, 7, 8, 9<td>ie5win.css, ie55.css, ie6.css, ie7.css, ie8.css, ie9.css<td>2<td>2
<tr>
<th>IE10≦, Opera 9.5≦, Gecko 1.9.1≦, Safari 4.0.5≦, Chrome 8≦, AOSP 3≦, !IE && <code>window.addEventListener</code><td>modern.css<td rowspan=3>3<td rowspan=3>1
<tr>
<th>Gecko 1.5~1.9.0<td>gck19.css
<tr>
<th>Mac IE5<td>ie5mac.css
<tr>
<th>Safari ≦4.0.5, Chrome < 8, AOSP < 3, !IE && !Opera && !Gecko && <code>!window.addEventListener</code><td>modern.css<td rowspan=3>4<td rowspan=3>1
<tr>
<th>Opera 9.5 未満<td>opr70.css, opr72.css, opr8.css, opr9.css
<tr>
<th>Gecko 1.5 未満<td>gck07.css, gck08.css, gck09.css, gck12.css, gck13.css, gck19.css
<tr>
<th>IE4<td colspan=3>未対応
</table>
<a name="3-1"></a>
<h3 id="3-1">3. 1. 条件付きコメント非対応ブラウザで javascript が無効の場合</h3>
<p>IE 以外のブラウザ用または Mac IE5 用の CSS が読み込まれます。
<p>このケースでは Gecko 1.9.1 未満、Opera 9.5 未満にも <code>modern.css</code> が読み込まれてしまいます。デザインが崩れるに留まらず、最悪の場合ではブラウザがクラッシュします。
<p>次の HTML タグで「javascript を有効にするか Web ブラウザの変更を促す警告メッセージ」を表示して閲覧者に対処を促します。幸いにクラッシュしなかった場合は、閲覧者側の対処を期待できます。
<p>メッセージはテキストでは無く <code>content</code> で表示しています。これは CSS が無効の場合、IE5~9 以外のブラウザの全てでメッセージが表示されてしまうのを避ける為です。
<pre class="prettyprint lang-html"><code><!--[if !IE]><!-->
<noscript>
<div id="-o-"><!-- 旧いブラウザには noscript p セレクタが効かない! -->
<style>/*<![CDATA[*/
/* common */
#-o- p{border:double 5px #f66;padding:1em;background:#300;color:#fff}
/* Opera 7.20~9.27 */
@media all and(-o-:0),not all and(-o-:0){
html:first-child #-o-{display:block}
:_{top:0} /* Opera ~7.11 skip next rule */
}
/* common */
#-o-{display:none}
#-o- p:after{content:attr(nojs) attr(opr)}
/* Opera 用ルールを先に、Gecko 用を後に書く */
/* Gecko ~1.8 */
@media \0 all{
#-o-{display:block}
#-o- p:after{content:attr(nojs) attr(gck)}
}
@-moz-document url-prefix(){
/* Gecko 1.8~1.9.2 */
_:not(),_:-moz-loading,#-o-{display:block}
_:not(),_:-moz-loading,#-o- p:after{content:attr(nojs) attr(gck)}
/* Gecko 1.9.1~1.9.2 */
_:not(),_:-moz-handler-blocked,#-o-{display:none}
}
/*]]>*/</style>
<p nojs="Please enabled javascript or use new version of browser. At least " opr="Opera 9.5+." gck="Firefox 3.5+."><!-- inline 要素は不可 --></p>
</div>
</noscript>
<!--<![endif]-->
</code></pre>
<p>2022年2月23日に修正済。2022年3月1日に <code></p></code> を追記。<code><noscript></code> 下の <code>p</code> 要素の閉じタグを省略できない。
<h4>短縮版</h4>
<pre class="prettyprint lang-html"><code><!--[if !IE]><!--><noscript><div id="-o-"><style>/*<![CDATA[*/#-o- p{border:double 5px #f66;padding:1em;background:#300;color:#fff}@media all and(-o-:0),not all and(-o-:0){html:first-child #-o-{display:block}:_{top:0}}#-o-{display:none}#-o- p:after{content:attr(nojs) attr(opr)}@media \0 all{#-o-{display:block}#-o- p:after{content:attr(nojs) attr(gck)}}@-moz-document url-prefix(){_:not(),_:-moz-loading,#-o-{display:block}_:not(),_:-moz-loading,#-o- p:after{content:attr(nojs) attr(gck)}_:not(),_:-moz-handler-blocked,#-o-{display:none}}/*]]>*/</style><p nojs="Please enabled javascript or use new version of browser. At least " opr="Opera 9.5+." gck="Firefox 3.5+."></p></div></noscript><!--<![endif]-->
</code></pre>
<p>2022年2月23日に修正済。2022年3月1日に <code></p></code> を追記。<code><noscript></code> 下の <code>p</code> 要素の閉じタグを省略できない。
<a name="3-2"></a>
<h3 id="3-2">3. 2. IE5~9 の場合</h3>
<p>Javascript の死活にかかわらず、条件付きコメントで各ブラウザ用の CSS を読み込みます。
<a name="3-3"></a>
<h3 id="3-3">3. 3. インライン javascript から CSS を読み込む</h3>
<p>殆んどの IE 以外のブラウザ(<code>addEventListener</code> をサポートするもの)と Mac IE 5 用の CSS を読み込ます。
<p>main.js のロードに失敗するケースに備えて、ごく一部のブラウザを除いてインライン javascript で CSS を読み込みます。
<p><code>load</code> または <code>DOMContentLoaded</code> イベントコールバック内で <code><link></code> 要素を追加します。CSS のパスは <code><noscript></code> の <code>textContent</code> から求めます。
<a name="3-4"></a>
<h3 id="3-4">3. 4. main.js から CSS を読み込む</h3>
<p>Presto < 9.5, Gecko < 1.5, Safari < 4.0.5, Chrome < 8, AOSP < 3, IE 以外の <code>addEventListener</code> をサポートしないブラウザは常にここで CSS を読み込みます。
<p>インライン javascript の CSS ローダーを使わないビルド設定の場合、全ての IE 以外のブラウザと Mac IE 5 もここから CSS を読み込みます。
<p><code><script></code> の <code>src</code> からアセットディレクトリを取得します。Gecko < 1, Presto < 9 は、CSS 周りのバグを回避する為に <code>document.write()</code> で <code><link></code> 要素を追加します。(そもそも <a href="/2023/07/check-css-ready.html#z-grade">Gecko 0.6~0.9.0は動的外部スタイルに非対応</a>の為。Presto はスタイルの適用が <code>document.write()</code> でないと不安定だった為。2023/08/23 追記)
<p>Safari < 3 には <code>load</code> イベントがいない為、このフォールバックのある main.js から CSS を読み込みます。
<p>9 ≦ Presto < 9.5, 1 ≦ Gecko < 1.5, 3 ≦ Safari < 4.0.5, Chrome < 8, AOSP < 3 は <code><noscript></code> の <code>.textContent</code> にアクセスして CSS のパスを取得することが出来なかった為、この経路になりました。(2022/02/09, 2022/03/18 追記, 2022/05/01 修正)
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-66185442849966393662021-08-30T00:38:00.042+09:002022-03-01T02:41:05.054+09:00ブロック要素を囲む<a>要素でのFirefox3.5とLynxのバグ回避、閉じタグ省略を辞めるパターン<div class="note"><p>古いFirefoxで遭遇する問題ではありませんでした。<code></p></code> の省略について、より詳しくは <a href="https://triple-underscore.github.io/HTML-writing-ja.html#optional-tags" target="_blank" rel="nofollow">HTML 文書の書き方 > 省略可能なタグ</a>とか。(2022/03/01)
<blockquote cite="https://hail2u.net/documents/html-best-practices.html#dont-omit-closing-tag" title="普通のHTMLの書き方 > 一般 > 終了タグを省略しない"><p>しかし例外もあり、以下の様なケースでは最初の<code>p</code>要素の終了タグは省略できません。
<pre class="prettyprint lang-html"><code><a href="/"><p>ホームページ</a>
<section>...</section></code></pre>
<p>親に<code>a</code>要素を持つ場合は省略できない、というルールがあるからです。</blockquote>
<p>本記事の検証を元に <a href="https://github.com/itozyun/web-doc-base/commit/f0be7d850a6195be0f56264382f797281c02efd6" target="_blank" rel="nofollow">web-doc-base > RichLink</a> を更新しました。(2021/09/03)
</div>
<h2>2行まとめ</h2>
<ol>
<li>Firefox 3.5~3.6では <code><a></code> 要素内のブロック要素の閉じタグを省略した際に、<code><a></code> をコピーして各要素を包んだ独自のツリーをつくります。<a href="https://html.spec.whatwg.org/multipage/syntax.html#optional-tags" target="_blank" rel="nofollow">HTML Living Standard</a> で閉じタグを省略できるとされていても、Firefox 3.5に対応する為には閉じタグの省略を辞めます。
<li>Lynx では <code><a></code> の子に <code><article></code> を置くとハイパーリンクが無効になる。
</ol>
<h2>1. はじめに</h2>
<p><a href="https://www.w3.org/TR/html401/sgml/dtd.html" target="_blank" rel="nofollow">HTML 4.01 Strict</a>(<a target="_blank" rel="nofollow" href="https://www.w3.org/TR/1999/PR-html40-19990824/" title="HTML 4.01 Specification">W3C 勧告は1999年</a>) ではインライン要素である <code><a></code> 内にブロック要素を書くことは invalid です。しかし当時の Web ブラウザはこの不正な文書ツリーを柔軟に解釈します。このおかげで Web デザイナーはブロック要素や <code><img></code> を配置した<strong>リッチなリンク</strong>を制作できました。
<p>このマークアップの際に古めのフルブラウザとテキストブラウザで遭遇した問題とその回避法です。
<p>なお HTML5 の <code><a></code> は、<code><a></code> の親要素によって <code><a></code> の子に出来る要素が変わります。このコンテンツモデルによって valid に記述できます。
<h3>検証前のHTMLタグの例</h3>
<p>古めのフルブラウザ(Firefox 3.5)とテキストブラウザ(Lynx)で不具合が発生します。
<pre class="prettyprint lang-html"><code><a href="https://www.w3.org/TR/1999/PR-html40-19990824/">
<article>
<h2>
<img src="//www.w3.org/Icons/w3c_home">
HTML 4.01 Specification
</h2>
<div>
<span>1999/12/24</span>
</div>
<p>W3C Recommendation 24 December 1999
</article>
</a>
</code></pre>
<h3>対策済のHTMLタグの例</h3>
<pre class="prettyprint lang-html"><code><a href="https://www.w3.org/TR/1999/PR-html40-19990824/">
<h2>
<img src="//www.w3.org/Icons/w3c_home">
HTML 4.01 Specification
</h2>
<div>
<span>1999/12/24</span>
</div>
<p>W3C Recommendation 24 December 1999</p>
</a>
</code></pre>
<h2>2. 古いFirefoxで遭遇する問題を回避する</h2>
<div class="box">
<a href="https://1.bp.blogspot.com/-K1D5ZHC-buc/YStpKQi5c6I/AAAAAAAASw4/4O6U6DQq3yoHHWdVgJ1zWxLhOfK7P8DHACLcBGAsYHQ/s890/richlink_firefox.PNG"><img alt="" src="https://1.bp.blogspot.com/-K1D5ZHC-buc/YStpKQi5c6I/AAAAAAAASw4/4O6U6DQq3yoHHWdVgJ1zWxLhOfK7P8DHACLcBGAsYHQ/s160/richlink_firefox.PNG"></a>
<p>まずは最新の Firefox 91.0.2 で表示した場合を確認します。閉じタグの省略に関わらず意図した表示が得られています。
<p>検証ページは <a href="https://itozyun.github.io/web-doc-base/richlink.html" target="_blank" rel="nofollow">Github pages</a> で公開しています。
</div>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-PEoAO5O_dog/YStpKR3JeUI/AAAAAAAASw8/z4SwLZilKqky8rj0HTRWFSHEsQnlv00uwCLcBGAsYHQ/s854/richlink_firefox3.5.PNG"><img alt="" src="https://1.bp.blogspot.com/-PEoAO5O_dog/YStpKR3JeUI/AAAAAAAASw8/z4SwLZilKqky8rj0HTRWFSHEsQnlv00uwCLcBGAsYHQ/s160/richlink_firefox3.5.PNG"></a>
<figcaption>Firefox 3.5 Beta 4での表示</figcaption>
</figure>
</span>
<p>続いて Firefox 3.5~3.6 で表示した場合です。</dt> や </dd> を省略した場合には、<code><a></code> がコピーされて各要素をラップするツリーが作られてしまいます。不要な下線の出現でその様子が分かります。(画像の2つめ)
<p>また、一度閉じタグのない子を持つ <code><a></code> が出現すると、以降で閉じタグのある子を持つ <code><a></code> が出現しても現象が発生します。<strong><code><a></code> の子は閉じタグを決して省略しないのが良さそうです</strong>。
<p>Firefox 3.1 迄と 4 以降ではこの挙動に遭遇していません。
</div>
<h2>3. Lynxで遭遇する問題を回避する</h2>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-UMJwk1jRIdM/YStpKX92nXI/AAAAAAAASxA/G7Cbmw9aJbUv8YBJOvFEruMszjmCaF61QCLcBGAsYHQ/s821/lynx.PNG"><img alt="" src="https://1.bp.blogspot.com/-UMJwk1jRIdM/YStpKX92nXI/AAAAAAAASxA/G7Cbmw9aJbUv8YBJOvFEruMszjmCaF61QCLcBGAsYHQ/s160/lynx.PNG"></a>
<figcaption>Lynx 2.8.9.1016での表示</figcaption>
</figure>
</span>
<p>Lynx ではハイパーリンクにならない問題が発生しました。<code><a href="#"><article /></a></code> の <a href="https://twitter.com/itozyun/status/1333049479616811013" target="_blank" rel="nofollow"><code><article></code> を外すと解決</a>しました。
<p>また、<code><h2></code> に続く要素がブロック要素とインライン要素では、ハイパーリンクになる範囲が異なることも分かりました。
</div>
<hr>
<p><code><a></code> 周りのデザインでは、タブフォーカス時にビビッドなカラーを要素に適用するのが好きな僕ですが、挙動が把握できていない部分があって悶々としていました。この度、エイヤッとテストして書きあげてホッとしております。Enjoy!izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-40611403080591787532021-08-16T14:06:00.023+09:002022-09-27T12:45:13.914+09:00僕のWeb開発の、変数と関数、ファイル名とフォルダ名の命名ルール<p>俺々命名ルールについてです。
<ol>
<li><a href="#1">前提</a>
<li><a href="#2">ファイル名とフォルダ名の命名</a>
<ol>
<li><a href="#2-1">プロジェクトフォルダの例</a>
<li><a href="#2-2">js scss ファイル名とフォルダ名に数字をつける</a>
<li><a href="#2-3">ドットをフォルダ名の頭に</a>
<li><a href="#2-4"><code>.generated</code> フォルダと <code>.generated</code> ファイル</a>
<li><a href="#2-5">README.md をなるべく全ての階層に用意する</a>
</ol>
<li><a href="#3">変数と関数の命名</a>
<ol>
<li><a href="#3-1">グローバル空間</a>
<ol>
<li><a href="#3-1-1">グローバル空間に公開するオブジェクトの例</a>
<li><a href="#3-1-2">グローバル空間に宣言する定数</a>
<li><a href="#3-1-3">グローバル空間に宣言する Closure Compiler の <code>@define</code></a>
</ol>
<li><a href="#3-2">パッケージのグローバル</a>
<li><a href="#3-3">モジュールのグローバル</a>
<li><a href="#3-4">モジュール下のプライベート空間</a>
</ol>
</ol>
<a name="1"></a>
<h2 id="1">1. 前提</h2>
<ol>
<li><a href="https://github.com/google/closure-compiler" target="_blank" rel="nofollow">Google Closure Compiler</a> でコンパイルします。
<li><code>import</code> 文を使った他モジュールの参照をしません。モジュールバンドラーも使いません。コンパイル結果が開発中のコードと飛躍しないように、自作の gulp プラグイン <a href="/2020/07/gulp-diamond-princess-zoning.html">gulp-diamond-princess-zoning</a> で javascript ファイルを一本化しています。
</ol>
<a name="2"></a>
<h2 id="2">2. ファイル名とフォルダ名の命名</h2>
<a name="2-1"></a>
<h3 id="2-1">2.1. プロジェクトフォルダの例</h3>
<dl>
<dt>.artwork/
<dd>.psd ファイルなどを入れておく
<dt>.generated/
<dd>プロジェクトフォルダ下のビルドツールを走らせた結果得られる生成物を入れる。
<dt>.submodules/
<dd>git の submodule はこの下に配置する。通常の作業時に視界に入れない為。
<dt>js-buildtools/
<dd>プロジェクトの為に書かれたビルドツールの置き場所。僕の場合は gulp プラグインが入る。
<dt>node-modules/
<dd>プロジェクトが依存する npm パッケージ
<dt>src/
<dd>ソースファイルの置き場所
<dd><dl>
<dt>html-templete/
<dd>HTML テンプレートファイルの置き場所。
<dt>js/
<dd>メインの javascript ファイルの置き場所。
<dt>js-common/
<dd>ビルドツール、メインの javascript、インラインの javascript、serviceworker で共通のコードの置き場所。
<dt>js-externs/
<dd>externs.js の置き場所。
<dt>js-inline/
<dd>ビルドタスクによって html ファイルに埋め込まれるインライン javascript ファイルの置き場所。
<dt>js-serviceworker/
<dd>serviceworker 用 javascript のソースファイルの置き場所。
<dt>scss/
<dd>SCSS ファイルの置き場所。SMACSS 等を参考にフォルダとファイルを整理します。
</dl>
</dl>
<a name="2-2"></a>
<h3 id="2-2">2.2. js scss ファイル名とフォルダ名に数字をつける</h3>
<p>数字を添えて、ファイルが実行される順番にファイルとフォルダが並ぶようにする。ファイルやフォルダが追加された場合は頻繁にファイル名とフォルダ名を変更する。
<p>また <a href="/2020/07/gulp-diamond-princess-zoning.html">gulp-diamond-princess-zoning</a> ではファイル名の辞書順にファイルを処理していく。
<a name="2-3"></a>
<h3 id="2-3">2.3. ドットをフォルダ名の頭に</h3>
<p>開発時に触れる頻度の少ないフォルダには <code>.</code> を付けてプロジェクトフォルダ階層の先頭に集める。開発中に視界に入りづらくする。
<a name="2-4"></a>
<h3 id="2-4">2.4. <code>.generated</code> フォルダと <code>.generated</code> ファイル</h3>
<p>ビルドツールによって生成されるファイルには <code>.generated</code> または <code>_generated</code> をファイル名に付与して開発対象ファイルと区別する。<code>.generated</code> なファイルからなるフォルダの名前にも <code>.generated</code> を付与する。
<p>gulp では <code>.</code> で始まるファイル名のファイルを無視する為、<code>_generated</code> を適宜に使用する。
<a name="2-5"></a>
<h3 id="2-5">2.5. README.md をなるべく全ての階層に用意する</h3>
<p>階層の README.md ファイルにフォルダとファイルの説明を書く。各フォルダ階層の README.md ファイルをハイパーリンクで参照するようにする。
<a name="3"></a>
<h2 id="3">2. 変数と関数の命名</h2>
<p>パッケージ(プロジェクトとほぼ同意)、モジュール、グローバル変数、パッケージのグローバル変数、モジュールのグローバル変数といった名称については、僕の書いた gulp プラグイン <a href="/2020/07/gulp-diamond-princess-zoning.html">gulp-diamond-princess-zoning</a> の <a href="https://github.com/itozyun/gulp-diamond-princess-zoning#readme" target="_blank" rel="nofollow me">README.md</a> を参照します。
<a name="3-1"></a>
<h3 id="3-1">2.1. グローバル</h3>
<a name="3-1-1"></a>
<h4 id="3-1-1">3.1.1. グローバルに公開するオブジェクトの例</h4>
<pre class="prettyprint lang-js"><code>window.app = app;
var Debug = { log : function( message ){} };
</code></pre>
<p>Closure Comoiler による名前の短縮から保護する為、<a href="https://developers.google.com/closure/compiler/docs/externs-and-exports#externs" target="_blank" rel="nofollow">js-externs/externs.js</a> ファイルに追記すること。
<a name="3-1-2"></a>
<h4 id="3-1-2">3.1.2. グローバルに宣言する定数</h4>
<p>パッケージに固有の接頭辞も付けておく。パッケージに固有の接頭辞に続けてアンダースコアを2つ繋げる。
<pre class="prettyprint lang-js"><code>var MY_COMMON_PROJECT__EVENT_CLICK = 1,
MY_COMMON_PROJECT__EVENT_FOCUS = 2;
</code></pre>
<p>Closure Compiler の <span class="uc">advanced</span> コンパイルによってコードに埋め込まれるので、グローバル空間に変数が追加されることは無い。
<a name="3-1-3"></a>
<h4 id="3-1-3">3.1.3. グローバル空間に宣言する Closure Compiler の <code>@define</code></h4>
<p><code>DEFINE_</code> を接頭辞に付ける。<a href="https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler#define-type-description" target="_blank" rel="nofollow"><code>@define</code> は、ビルド時に定数に値を埋め込む Closure Compiler のオプションです。</a>
<p>複数のパッケージを組み合わせる場合、パッケージに固有の接頭辞も付けておく。パッケージに固有の接頭辞に続けてアンダースコアを2つ繋げる。
<pre class="prettyprint lang-js"><code>/** @define {boolean} */
var DEFINE_MY_COMMON_PROJECT__DEBUG = true;
</code></pre>
<p>Closure Compiler のバージョンによっては、<code>var</code> 宣言とコメントの位置関係でエラーが起きる場合があった。その場合は次のように記述して回避した。
<pre class="prettyprint lang-js"><code>var
/** @define {boolean} */
DEFINE_MY_COMMON_PROJECT__DEBUG = true;
</code></pre>
<a name="3-2"></a>
<h3 id="3-2">3.2. パッケージのグローバル空間</h3>
<p>変数名や関数名を <code>p_</code> から始める。
<p>複数のパッケージでパッケージグローバル空間を共有する想定のパッケージはパッケージに固有の接頭辞とアンダースコア2つを付けて <code>p_MY_COMMON_PROJECT__XXXXXX</code> とする。
<pre class="prettyprint lang-js"><code>var p_XXXXXX = 1;
var p_MY_COMMON_PROJECT__XXXXXX = "";
</code></pre>
<a name="3-3"></a>
<h3 id="3-3">3.3. モジュールのグローバル空間</h3>
<p>変数名や関数名を <code>m_</code> から始める。
<p>gulp-diamond-princess-zoning の<a href="https://github.com/itozyun/gulp-diamond-princess-zoning#wrapAll" target="_blank" rel="nofollow"><code>wrapAll</code></a> を有効にして得た出力をコンパイルすると、モジュールのグローバル空間に正しく定義されているか?を確認出来ます。
<pre class="prettyprint lang-js"><code>var m_XXXXXX = 1;
</code></pre>
<a name="3-4"></a>
<h3 id="3-4">3.4. モジュール下のプライベート空間</h3>
<p>モジュール内で名称がバッティングしないように冗長な名前にします。例えばファイル名を頭に付けます。このルールで命名された変数や関数は同一ファイル内でしか参照しないようにします。
<pre class="prettyprint lang-js"><code>var AjaxByXHR_apis = {};
function AjaxByXHR_post(){};
</code></pre>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-54038477725928428662021-06-08T14:52:00.003+09:002022-05-08T03:31:17.181+09:00gameEngine(仮)について<section>
<h2>目次</h2>
<ol>
<li>はじめに
<li>課題1:スマートデバイスのニュルニュルするアドレスバーをゲーム中は隠したい
<li>課題2:<abbr title="Progressive Web Apps">PWA</abbr> に取り組む
<li>おまけ:HID 抽象化
</ol>
<h3>話題にする技術や用語</h3>
<p>PWA, SPA, A2HS, <code>ServiceWorker</code>, <code>Cache</code>, <code>IndexedDB</code>, Google Gears の <code>ManagedResourceStore</code>, <code>ApplicatinCache</code>, <code>StorageManager</code>
</section>
<section>
<h2>1. はじめに</h2>
<p>gameEngine ではブラウザをゲーム配信プラットフォームとするにあたっての課題を挙げて解決します。多くの課題は PWA に取り組むことで解決しました。「スマートデバイスのニュルニュルするアドレスバーをゲーム中は隠したい」という課題だけが独自のこだわりでした。
<!--更に言うと、サービスが停止したら遊べなくなるソーシャルゲームではなく、30年近くが経過しても往時のままに遊ぶことの出来る、ファミコンのようなゲームを志向しています。-->
<p>この解決は <abbr title="Single Page Application">SPA</abbr> にも容易に適用され得るものです。一方で例えば Qiita のようなウェブマガジン等への適用は、オフラインキャッシュ戦略等でメディアの特性に合わせた更なる検討が必要です。
</section>
<section>
<h2>2. 課題1:スマートデバイスのニュルニュルするアドレスバーをゲーム中は隠したい</h2>
<ol>
<li>アドレスバー等を隠して Web アプリをネイティブアプリ風にする
<li>アドレスバー等を隠す弊害と回避
<li>STRETCH_BY_SCROLLING の実装
</ol>
</section>
<section>
<h2>2.1. アドレスバー等を隠して Web アプリをネイティブアプリ風にする</h2>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-KLtfiy0lqIw/YK9LH_cKyDI/AAAAAAAASoM/1mOTgumqgTQCqwAFHOmnfZwE5ccvuvJswCLcBGAsYHQ/s1280/STRETCH_BY_SCROLLING.gif"><img alt="" src="https://1.bp.blogspot.com/-VVOAjBwcFC8/YK9LZzOx7TI/AAAAAAAASoQ/5mXKMXQfCwg6X-09xtLU1j-Yg0NP8_3TACLcBGAsYHQ/s160/STRETCH_BY_SCROLLING.jpg"></a>
<figcaption>スクロールでアドレスバーを隠してビューポートを拡げる。灰色のタイルがアドレスバーです。</figcaption>
</figure>
</span>
<p>多くのスマートデバイス用ブラウザは、文書の順方向のスクロールでアドレスバー等を隠してビューポートを拡大します。逆方向のスクロールで再びアドレスバーを表示してユーザーはタブの操作等が出来ます。
<p>gameEngine ではこのギミックを備えるブラウザのリストを持っていて、ビューポートを拡大してからゲームを開始します。
</div>
</section>
<section>
<h2>2.2. アドレスバー等を隠す弊害と回避</h2>
<p>ブラウザの中には、アドレスバー等を隠した状態にするとブラウザを再起動するまでタブの変更等の出来ないものが存在します。
<p>gameEngine では、PAUSE 画面ではスクロールを許可することで弊害を回避しています。しかし一般的な Web コンテンツのフローではない為、ユーザーを混乱させストレスとなるかもしれません。
</section>
<section>
<h2>2.3. STRETCH_BY_SCROLLING の実装</h2>
<p>おそらく各ブラウザで WebView ペーンの扱いが異なる上に、ニュルニュル動くもの(非同期で同時多発で GUI が変化する)を矛盾無く記述することが、人間には不得手。
<p>Android + Presto Opera, Android + Firefox 6x?, それ以外で異なる実装。
</section>
<section>
<h2>3. 課題2:PWA に取り組む</h2>
<ol>
<li><ruby>プログレッシブウェブアプリ<rp> (</rp><rt>Progressive Web Apps</rt><rp>)</rp></ruby> とは?
<ol>
<li>PWA 用例集
<li>「プログレッシブ」な Web サイト
<li>PWA の原則、MDN より
<li>新しい API で実現する PWA の原則
</ol>
<li>gameEngine の PWA 達成状況
<ol>
<li>ホーム画面に追加
<li>オフライン化の効能
<li>オフライン化、<code>ServiceWorker</code> について
<li><code>ServiceWorker</code> 周りの僕の工夫(1)
<li><code>ServiceWorker</code> 周りの僕の工夫(2)
<li>オフライン化、<code>StorageManager</code> について
</ol>
</ol>
</section>
<section>
<h2>3.1. <ruby>プログレッシブウェブアプリ<rp> (</rp><rt>Progressive Web Apps</rt><rp>)</rp></ruby> とは?</h2>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-GGVS4WWoi-w/YKuaEQ0G3-I/AAAAAAAASm0/vPHL9COgMr48ytbFM1liz1FPwH_4Ty32gCLcBGAsYHQ/s975/MDN_PWA.png"><img alt="" src="https://1.bp.blogspot.com/-GGVS4WWoi-w/YKuaEQ0G3-I/AAAAAAAASm0/vPHL9COgMr48ytbFM1liz1FPwH_4Ty32gCLcBGAsYHQ/s200/MDN_PWA.png"/></a>
<figcaption><a href="https://developer.mozilla.org/ja/docs/Web/Progressive_web_apps" target="_blank" rel="nofollow">MDN > プログレッシブウェブアプリ</a></figcaption>
</figure>
</span>
<p>デザインパターン、仕様があるわけでは無い。
</div>
</section>
<section>
<h3>3.1.1. PWA 用例集</h3>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-SwfPgTSiles/YKugUWY7SVI/AAAAAAAASnI/uzPAsxN1VcYwzMPBKLTq7lx7V6X_hffMACLcBGAsYHQ/s1423/nikkei.png"><img alt="" src="https://1.bp.blogspot.com/-SwfPgTSiles/YKugUWY7SVI/AAAAAAAASnI/uzPAsxN1VcYwzMPBKLTq7lx7V6X_hffMACLcBGAsYHQ/s160/nikkei.png"></a>
<figcaption><a href="https://developers.google.com/web/showcase/2018/nikkei?hl=ja" target="_blank" rel="nofollow">日本経済新聞社は複数ページのPWAで新しいレベルの品質とパフォーマンスを実現</a></figcaption>
</figure>
</span>
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-8V3UL7txfxY/YKugUiGSHaI/AAAAAAAASnM/KR2MQQJRjooLiXwPmRwxYNOzaIBq98pNgCLcBGAsYHQ/s1609/tenpoapp.png"><img alt="" src="https://1.bp.blogspot.com/-8V3UL7txfxY/YKugUiGSHaI/AAAAAAAASnM/KR2MQQJRjooLiXwPmRwxYNOzaIBq98pNgCLcBGAsYHQ/s160/tenpoapp.png"></a>
<figcaption><a href="http://tenpoapp.com/tenpolab/archives/1145" target="_blank" rel="nofollow">世界中の多くのサービスでPWAを導入!マーケターが知っておきたい今話題のPWAとは?</a> 2019年4月26日</figcaption>
</figure>
</span>
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-7Pj9PGP0MmU/YKugTiyAdAI/AAAAAAAASm8/PyvoBn3IGSovisoLgnDOM4VpM6CeQCviACLcBGAsYHQ/s1608/digitalidentity.png"><img alt="" src="https://1.bp.blogspot.com/-7Pj9PGP0MmU/YKugTiyAdAI/AAAAAAAASm8/PyvoBn3IGSovisoLgnDOM4VpM6CeQCviACLcBGAsYHQ/s160/digitalidentity.png"></a>
<figcaption><a href="https://digitalidentity.co.jp/blog/creative/progressive-web-apps.html" target="_blank" rel="nofollow">スマートフォンアプリの代わりになる!?グーグルが進めるPWA(Progressive Web Apps)とは</a> 2019年10月31日</figcaption>
</figure>
</span>
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-jcDCQjvAJhk/YKugTmh5XbI/AAAAAAAASnA/WnHW4r9oPKk59E2BZ5p3ECIzYEAP_CExgCLcBGAsYHQ/s1604/ferret-plus.png"><img alt="" src="https://1.bp.blogspot.com/-jcDCQjvAJhk/YKugTmh5XbI/AAAAAAAASnA/WnHW4r9oPKk59E2BZ5p3ECIzYEAP_CExgCLcBGAsYHQ/s160/ferret-plus.png"></a>
<figcaption><a href="https://ferret-plus.com/13564" target="_blank" rel="nofollow">PWA対応サイト5選!アプリ開発よりも導入コストの低いPWAとは?</a> 2019年12月19日</figcaption>
</figure>
</span>
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-Hrqio8cJGaU/YKugTnE_oOI/AAAAAAAASnE/OAKmbLIk2HQLhU7cCO8HY2BPgjNRkQwOwCLcBGAsYHQ/s1609/gpol.png"><img alt="" src="https://1.bp.blogspot.com/-Hrqio8cJGaU/YKugTnE_oOI/AAAAAAAASnE/OAKmbLIk2HQLhU7cCO8HY2BPgjNRkQwOwCLcBGAsYHQ/s160/gpol.png"></a>
<figcaption><a href="https://www.gpol.co.jp/blog/62" target="_blank" rel="nofollow">Webサイトをアプリのようなパフォーマンスに!PWAを導入するメリット</a> 2020年11月20日</figcaption>
</figure>
</span>
</div>
</section>
<section>
<h3>3.1.2. 「プログレッシブ」な Web サイト</h3>
<p>Web サイトにとって「プログレッシブ」とは?MDN を覗いてみると。
<blockquote title="MDN > プログレッシブウェブアプリの構造" cite="https://developer.mozilla.org/ja/docs/Web/Progressive_web_apps/App_structure">
<p>「古き良き基本的なウェブサイト」から始めて、ブラウザーで利用できるかどうかを検出し、サポートが利用できない場合に発生するエラーを適切に処理しながら、新機能を徐々に追加します。 例えば、サービスワーカーの助けを借りたオフラインモードは、ウェブサイトのエクスペリエンスを向上させるための特別な特徴ですが、それがなくても完全に使用可能です。</blockquote>
</section>
<section>
<h3>3.1.3. PWA の原則、MDN より</h3>
<p><em>強調</em>表示は新しい API を使うもの。
<blockquote title="MDN > プログレッシブウェブアプリの紹介" cite="https://developer.mozilla.org/ja/docs/Web/Progressive_web_apps/Introduction">
<p>ウェブアプリが PWA として見なされるために、いくつかの重要な原則があります。
<dl>
<dt>Discoverable<dd>コンテンツを検索エンジンで見つけることができる。
<dt>Installable<dd>アプリは端末の<em>ホーム画面に追加</em>できる。
<dt>Linkable<dd>URL を送るだけでアプリを共有できる。
<dt>Network independent<dd><em>オフライン</em>か、あるいは貧弱なネットワーク環境でも使用できる。
<dt>Progressive<dd>古いブラウザーでも基本的な機能は使用でき、最新のブラウザーではすべての機能が使用できる。
<dt>Re-engageable<dd>新しいコンテンツがあるときには、<em>通知を送る</em>ことができる。
<dt>Responsive<dd>携帯電話やタブレット、ノートパソコン、テレビ、冷蔵庫など、画面とブラウザーを備える全ての端末で使用できる。
<dt>Safe<dd>アプリからの通信が第三者からの攻撃に対して安全であり、機密情報を保護できる。
</dl></blockquote>
</section>
<section>
<h3>3.1.4. 新しい API で実現する PWA の原則</h3>
<ol>
<li>ホーム画面に追加(<ruby>A2HS<rp>(</rp><rt>Add to home screen</rt><rp>)</rp></ruby>)できる
<li>オフラインでも使用できる
<li>通知を送ることができる
</ol>
</section>
<section>
<h2>3.2. gameEngine の PWA 達成状況</h2>
<ol>
<li>ホーム画面に追加(<ruby>A2HS<rp>(</rp><rt>Add to home screen</rt><rp>)</rp></ruby>)できる ⇒ ✔済
<li>オフラインでも使用できる ⇒ ✔済
<li>通知を送ることができる ⇒ 未
</ol>
</section>
<section>
<h3>3.2.1. ホーム画面に追加</h3>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-gA5RsFQxXEY/YK6X36rYVrI/AAAAAAAASn8/Bwpex3-ARFsDjRd2Lp6N5yUIj5lih71MwCLcBGAsYHQ/s1920/prompt.jpg"><img alt="" src="https://1.bp.blogspot.com/-gA5RsFQxXEY/YK6X36rYVrI/AAAAAAAASn8/Bwpex3-ARFsDjRd2Lp6N5yUIj5lih71MwCLcBGAsYHQ/s160/prompt.jpg"></a>
<figcaption>Chrome はプロンプトを表示する。Firefox は画面上のハンバーガーメニューから。</figcaption>
</figure>
</span>
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-8oQw-lycfik/YK50eWBcOWI/AAAAAAAASn0/r_RjWuF8I1kqpVv3GIu3x34Y6JAwJ0PiACLcBGAsYHQ/s1079/a2hs.jpg"><img alt="" src="https://1.bp.blogspot.com/-8oQw-lycfik/YK50eWBcOWI/AAAAAAAASn0/r_RjWuF8I1kqpVv3GIu3x34Y6JAwJ0PiACLcBGAsYHQ/s160/a2hs.jpg"></a>
<figcaption>左は Chrome からホーム画面に追加。右は Firefox。</figcaption>
</figure>
</span>
<p>Android 用ブラウザでは、マニュフェストファイルを設定することで Web アプリケーションをモバイルのホーム画面に追加できるようになる。
<p>Firefox のホームアイコンは <code>"background_color"</code> に設定した緑が意図せず表示されていた為、最終的に <code>"theme_color"</code> と <code>"background_color"</code> を同色の黄色とした。
<p>iOS では Apple 独自の <code><meta></code> タグを使用する。
</div>
</section>
<section>
<h3>3.2.2. オフライン化の効能</h3>
<h4>様々な効能</h4>
<p>SPA の内容によってはオフラインで完全に動作する。オンラインでもギガを節約し高速に起動する。Web サーバの負荷を抑える。
<h4>gameEngine にとって</h4>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-gv52TiJWuh8/YL8DwFShx1I/AAAAAAAASsY/fnlflarKDcAoLzQ4p07mXhsOzgJlhoNGQCLcBGAsYHQ/s1200/famicom.jpg"><img alt="" src="https://1.bp.blogspot.com/-gv52TiJWuh8/YL8DwFShx1I/AAAAAAAASsY/fnlflarKDcAoLzQ4p07mXhsOzgJlhoNGQCLcBGAsYHQ/s160/famicom.jpg" longdesc="http://www.nicheee.com/archives/2255305.html"></a>
<figcaption>画像は『<a href="http://www.nicheee.com/archives/2255305.html" target="_blank" rel="nofollow">時を超えて思い出のソフトに再会!?「名前入りカセット博物館」</a>』より</figcaption>
</figure>
</span><p>ユーザーの所有という側面を強めたい。
</div>
</section>
<section>
<h3>3.2.3. オフライン化、<code>ServiceWorker</code> について</h3>
<p>オフライン化には <code>ServiceWorker</code> という新しい API を使用します(*1)。 <code>ServiceWorker</code> は Web ページの javascript からインストールされ、ローカルウェブサーバーになります。
<p>この <code>ServiceWorker</code> に加えて <code>Cache</code> ストレージや <code>IndexedDB</code> 等を利用してオフライン時にもコンテンツを提供したり、サーバに送るデータをオンラインになるまで保持します。
<div class="note"><p>*1 これに先行して、Google Gears の <code>ManagedResourceStore</code>、<code>ApplicatinCache</code> がありました。
</div>
</section>
<section>
<h3>3.2.4. <code>ServiceWorker</code> 周りの僕の工夫(1)</h3>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-T_K3FFgUeOE/YKuWH2OiaiI/AAAAAAAASms/-diQnDUeBc0bW5SHZ3xmf7o0hLIHkNq0QCLcBGAsYHQ/s1019/firefox_remote_debug.png"><img alt="" src="https://1.bp.blogspot.com/-T_K3FFgUeOE/YKuWH2OiaiI/AAAAAAAASms/-diQnDUeBc0bW5SHZ3xmf7o0hLIHkNq0QCLcBGAsYHQ/s160/firefox_remote_debug.png"></a>
<figcaption><a target="_blank" href="about:debugging#/runtime/this-firefox">Firefox のリモートデバッグ画面で <code>ServiceWorker</code> を確認する</a></figcaption>
</figure>
</span>
<p>ブラウザの開発者ツールを覗くといつの間にか複数の <code>ServiceWorker</code> がインストールされています。ユーザーの同意操作なしにインストールするのはお行儀が良いとは言えません。
<p>gameEngine ではユーザーの操作を経て <code>ServiceWorker</code> をインストール、アンインストールの GUI を提供します。
</div>
</section>
<section>
<h3>3.2.5. <code>ServiceWorker</code> 周りの僕の工夫(2)</h3>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-YLB84qNmy-c/YK5Wq7DhLkI/AAAAAAAASnk/1dSjR9QipSg9owM1VJ0zYg3ZUdz1VMHowCLcBGAsYHQ/s1920/offline.png"><img alt="" src="https://1.bp.blogspot.com/-YLB84qNmy-c/YK5Wq7DhLkI/AAAAAAAASnk/1dSjR9QipSg9owM1VJ0zYg3ZUdz1VMHowCLcBGAsYHQ/s160/offline.png"></a>
<figcaption>ユーザーの操作で <code>ServiceWorker</code> をインストールする</figcaption>
</figure>
</span>
<ol>
<li>ユーザーの操作で <code>ServiceWorker</code> をインストールしてファイルをキャッシュ(通信が発生)
<li>ユーザーの操作で更新(通信が発生)
<li>ユーザーの操作で解除
<li><code>ApplicatinCache</code> でのフォールバック
</ol>
</div>
</section>
<section>
<h3>3.2.6. オフライン化、<code>StorageManager</code> について</h3>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-pQFMAwyFqBM/YK5tMgq_v6I/AAAAAAAASns/fAY1qCy8gxU-IUQYz21iKgpUPKghp13dACLcBGAsYHQ/s1538/StorageManager.png"><img alt="" src="https://1.bp.blogspot.com/-pQFMAwyFqBM/YK5tMgq_v6I/AAAAAAAASns/fAY1qCy8gxU-IUQYz21iKgpUPKghp13dACLcBGAsYHQ/s160/StorageManager.png"></a>
<figcaption>ユーザーの許諾でストレージを永続化する</figcaption>
</figure>
</span>
<p>Web アプリがブラウザ側に保存したデータ(<a href="https://developer.mozilla.org/ja/docs/Web/API/Storage_API" target="_blank" rel="nofollow"><code>IndexedDB</code>, <code>Cache</code>, <code>ServiceWorker</code>, <code>localStorage</code>, <code>ApplicationCache</code> 他</a>)は、<q title="ブラウザーのストレージ制限と削除基準" cite="https://developer.mozilla.org/ja/docs/Web/API/IndexedDB_API/Browser_storage_limits_and_eviction_criteria">ストレージの容量制限に達すると、もっとも過去に使用されたものから削除されます</q>。<code>StorageManager</code> をサポートするブラウザはユーザーの許諾でストレージを永続化することが出来ます。しかしいよいよとなったら削除されます。
</div>
</section>
<section>
<h3>4. おまけ: HID 抽象化</h3>
<div class="box">
<a href="https://1.bp.blogspot.com/-FYLBXTgy27A/YL8BBK_fH5I/AAAAAAAASsI/HDpRxZN7FNoNi8wv2Qn0EKERla55OOw0gCLcBGAsYHQ/s1515/gamepad_config.png"><img alt="" src="https://1.bp.blogspot.com/-FYLBXTgy27A/YL8BBK_fH5I/AAAAAAAASsI/HDpRxZN7FNoNi8wv2Qn0EKERla55OOw0gCLcBGAsYHQ/s160/gamepad_config.png"></a>
<a href="https://1.bp.blogspot.com/-XRldPVGBNj0/YL8BBB_labI/AAAAAAAASsM/GiWvlanhVuYKv020HKQ1mhCxGuAIXEBMACLcBGAsYHQ/s1226/gamepad_added.png"><img alt="" src="https://1.bp.blogspot.com/-XRldPVGBNj0/YL8BBB_labI/AAAAAAAASsM/GiWvlanhVuYKv020HKQ1mhCxGuAIXEBMACLcBGAsYHQ/s160/gamepad_added.png"></a>
</div>
</section>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-90198591549123397552021-06-04T20:15:00.006+09:002022-02-20T09:09:36.081+09:002021年決定版はこれ! スプラッシュ画面("apple-startup-image")編<div class="note"><p>ピクセルサイズの誤りを修正しました。(2022/2/20)
</div>
<ol>
<li><a href="/2021/04/favicon-apple-touch-icon-startup-image.html">2021年決定版はこれ! ICOファビコン、タッチアイコン、スプラッシュ画面をきっちり押さえて圧倒的おもてなし!</a>
<li><a href="/2021/04/understand-the-favicon.html">ファビコン(favicon.ico)編</a>
<li><a href="/2021/04/apple-touch-icon-and-icon-and-icons.html">アイコン編(<code>"apple-touch-icon"</code>と<code>"icon"</code>と<code>"icons"</code>)編</a>
<li>スプラッシュ画面(<code>"apple-startup-image"</code>)編
<ol>
<li><a href="#4.1">はじめに</a>
<li><a href="#4.2">ディスプレイの解像度と <code>device-pixel-ratio</code></a>
<li><a href="#4.3">TODO iOS 3 時代の情報</a>
<li><a href="#4.4">不具合の情報</a>
</ol>
</ol>
<a name="4.1"></a>
<h2 id="4.1">4.1 はじめに</h2>
<p>モバイル Web アプリケーションの為の、Apple の独自実装である <code>"apple-startup-image"</code> がいつ導入されたのかは未調査です。
<p>最新の iPhone 12世代までを集計すると、少なくとも18パターンのスクリーンサイズが存在しました。縦向きと横向きで計36枚のスプラッシュ用画像が必要なわけです。更には後述する、ステータスバーの 20px を引いたサイズが必要なパターンもあるようです。また、iPad のマルチタスクの場合は未調査です。ダークモードも未調査です。
<p>マシンリソースの解放の為に <code>onload</code> 時点で不要と思われる <code><meta></code> を削除するコードを導入したところ、スプラッシュ画面が表示されない問題に遭遇しました。iOS では <code>onload</code> 時点での要素への動的変更が、ホームに追加してそこから起動した際の動作に影響していました。
<a name="4.2"></a>
<h2 id="4.2">ディスプレイの解像度と <code>device-pixel-ratio</code></h2>
<p>ポートレイトの場合を表にします。
<table>
<thead>
<tr>
<th><code>sizes</code><td>device pixel ratio<td>デバイス名
<tbody>
<tr>
<th rowspan="6">320x480<td rowspan="6">1<td>iPod touch 1th
<tr>
<td>iPod touch 2th
<tr>
<td>iPod touch 3th
<tr>
<td>iPhone 1th
<tr>
<td>iPhone 3G
<tr>
<td>iPhone 3GS
<tr>
<th rowspan="3">640x960<td rowspan="3">2<td>iPhone 4
<tr>
<td>iPhone 4S
<tr>
<td>iPod touch 4th
<tr>
<th rowspan="7">640x1136<td rowspan="7">2<td>iPod touch 5th
<tr>
<td>iPod touch 6th
<tr>
<td>iPod touch 7th
<tr>
<td>iPhone 5
<tr>
<td>iPhone 5c
<tr>
<td>iPhone 5s
<tr>
<td>iPhone SE 1th
<tr>
<th rowspan="5">750x1334<del>1134</del><td rowspan="5">2<td>iPhone 6
<tr>
<td>iPhone 6s
<tr>
<td>iPhone 7
<tr>
<td>iPhone 8
<tr>
<td>iPhone SE 2th
<tr>
<th rowspan="3">768x1024<td rowspan="3">1<td>iPad 1
<tr>
<td>iPad 2
<tr>
<td>iPad mini 1
<tr>
<th rowspan="2">828x1792<td rowspan="2">2<td>iPhone XR
<tr>
<td>iPhone 11
<tr>
<th>1080x2340<td>3<td>iPhone 12 mini
<tr>
<th rowspan="3">1125x2436<td rowspan="3">3<td>iPhone X
<tr>
<td>iPhone XS
<tr>
<td>iPhone 11 Pro
<tr>
<th rowspan="2">1170x2532<td rowspan="2">3<td>iPhone 12
<tr>
<td>iPhone 12 Pro
<tr>
<th rowspan="4">1242x2208<td rowspan="4">3<td>iPhone 6 plus
<tr>
<td>iPhone 6s plus
<tr>
<td>iPhone 7 plus
<tr>
<td>iPhone 8 plus
<tr>
<th rowspan="2">1242x2688<td rowspan="2">3<td>iPhone XS Max
<tr>
<td>iPhone 11 Pro Max
<tr>
<th>1284x2778<td>3<td>iPhone 12 Pro Max
<tr>
<th rowspan="11">1536x2048<td rowspan="11">2<td>iPad 3
<tr>
<td>iPad 4
<tr>
<td>iPad 5
<tr>
<td>iPad 6
<tr>
<td>iPad mini 2
<tr>
<td>iPad mini 3
<tr>
<td>iPad mini 4
<tr>
<td>iPad mini 5
<tr>
<td>iPad Pro 1th "9.7"
<tr>
<td>iPad Air 1
<tr>
<td>iPad Air 2
<tr>
<th rowspan="2">1620x2160<td rowspan="2">2<td>iPad 7
<tr>
<td>iPad 8
<tr>
<th rowspan="2">1668x2224<td rowspan="2">2<td>iPad Pro 2th "10.5"
<tr>
<td>iPad Air 3
<tr>
<th>1640x2360<td>2<td>iPad Air 4
<tr>
<th rowspan="2">1668x2388<td rowspan="2">2<td>iPad Pro 3th "11"
<tr>
<td>iPad Pro 4th "11"
<tr>
<th rowspan="4">2048x2732<td rowspan="4">2<td>iPad Pro 1th "12.9"
<tr>
<td>iPad Pro 2th "12.9"
<tr>
<td>iPad Pro 3th "12.9"
<tr>
<td>iPad Pro 4th "12.9"
</table>
<p><a href="https://github.com/onderceylan/pwa-asset-generator/blob/master/src/config/apple-fallback-data.json" target="_blank" rel="nofollow">pwa-asset-generator</a> を参考にしました。
<a name="4.3"></a>
<h2 id="4.3">4.3 TODO iOS 3 時代の情報</h2>
<p>「<a href="https://www.it-swarm-ja.com/ja/ipad/ios-web%e3%82%a2%e3%83%97%e3%83%aa%e7%94%a8%e3%81%ae%e8%a4%87%e6%95%b0%e3%81%ae%e3%80%8cappletouchstartupimage%e3%80%8d%e8%a7%a3%e5%83%8f%e5%ba%a6%ef%bc%88%e7%89%b9%e3%81%abipad%e7%94%a8%ef%bc%89%ef%bc%9f/971959770/" target="_blank" rel="nofollow">「Apple-touch-startup-image」解像度(特にiPad用)?</a>」によると、ステータスバーの 20px を除いた <code>768x1004</code> などのサイズ指定がある。
<p><a href="https://caniuse.com/?search=-webkit-device-pixel-ratio" target="_blank" rel="nofollow">caniuse</a> によると、<code>-webkit-device-pixel-ratio</code> のサポートは iOS 4以降で3.2は不明とのこと。
<a name="4.4"></a>
<h2 id="4.4">4.4 不具合の情報</h2>
<blockquote cite="https://dev.to/ikkou/ios-9-mobile-safari-2-3ok6" title="iOS 9のMobile Safariで消えた2つの機能 ">
<p>本日、03/22にiOS 9.3正式版が公開されました。
早速アップデートして試したところ、iOS 9.2同様に <code>apple-mobile-web-app-status-bar-style</code> は動作するが <code>apple-touch-startup-image</code> は動作しないという挙動に変更はありませんでした。
</blockquote>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com2tag:blogger.com,1999:blog-5003761485377366537.post-71183623414652081412021-06-04T20:05:00.011+09:002021-06-29T02:36:14.421+09:002021年決定版はこれ! アイコン編("apple-touch-icon"と"icon"と"icons")編<ol>
<li><a href="/2021/04/favicon-apple-touch-icon-startup-image.html">2021年決定版はこれ! ICOファビコン、タッチアイコン、スプラッシュ画面をきっちり押さえて圧倒的おもてなし!</a>
<li><a href="/2021/04/understand-the-favicon.html">ファビコン(favicon.ico)編</a>
<li>アイコン編(<code>"apple-touch-icon"</code>と<code>"icon"</code>と<code>"icons"</code>)編
<ol>
<li><a href="#3.1"><code><link rel="apple-touch-icon"></code>と<code><link rel="icon"></code>の概要</a>
<li><a href="#3.2">推奨タグ(暫定版)</a>
<li><a href="#3.3">参考記事</a>
</ol>
<li><a href="/2021/06/apple-startup-image.html">スプラッシュ画面(<code>"apple-startup-image"</code>)編</a>
</ol>
<a name="3.1"></a>
<h2 id="3.1">3.1 <code><link rel="apple-touch-icon"></code>と<code><link rel="icon"></code>の概要</h2>
<h3>タッチアイコン</h3>
<div class="box">
<a href="https://1.bp.blogspot.com/-FJGyf2bMfTA/YLsn9oT5-_I/AAAAAAAASrM/GKnhyImj3noGMkJHacR2CwVz3DzhUxH_wCLcBGAsYHQ/s1081/a2hs.jpg"><img alt="" src="https://1.bp.blogspot.com/-FJGyf2bMfTA/YLsn9oT5-_I/AAAAAAAASrM/GKnhyImj3noGMkJHacR2CwVz3DzhUxH_wCLcBGAsYHQ/s160/a2hs.jpg"></a>
<a href="https://1.bp.blogspot.com/-EruZR_YPLvU/YLsn9qOwbCI/AAAAAAAASrQ/zh0Pnbjyin8mjk-K5Z-_Ycm9ejHC14hjQCLcBGAsYHQ/s1080/android_homescreen.jpg"><img alt="" src="https://1.bp.blogspot.com/-EruZR_YPLvU/YLsn9qOwbCI/AAAAAAAASrQ/zh0Pnbjyin8mjk-K5Z-_Ycm9ejHC14hjQCLcBGAsYHQ/s160/android_homescreen.jpg"></a>
<ol>
<li>Android 9 の Chrome ブラウザからホーム画面に追加する。
<li>Chrome ではタッチアイコンは144pxが使われる。Firefox では512pxが使われる。
</ol>
</div>
<h3>デスクトップショートカット</h3>
<div class="box">
<a href="https://1.bp.blogspot.com/-W1lU0mCu-WU/YLp3OWjCfpI/AAAAAAAASqQ/sW84WMgpCikoMStQSRrTBDxiKxEvD79kwCPcBGAYYCw/s950/Chrome_create_shortcut.png"><img alt="" src="https://1.bp.blogspot.com/-W1lU0mCu-WU/YLp3OWjCfpI/AAAAAAAASqQ/sW84WMgpCikoMStQSRrTBDxiKxEvD79kwCPcBGAYYCw/s160/Chrome_create_shortcut.png"></a>
<a href="https://1.bp.blogspot.com/-jRcV7KcbV0Y/YLp3OW8JwGI/AAAAAAAASqM/uXn0uUGy_jAg1WxSgpgJCkyQhuQLWkyPwCPcBGAYYCw/s899/Chrome_48px_shortcut.png"><img alt="" src="https://1.bp.blogspot.com/-jRcV7KcbV0Y/YLp3OW8JwGI/AAAAAAAASqM/uXn0uUGy_jAg1WxSgpgJCkyQhuQLWkyPwCPcBGAYYCw/s160/Chrome_48px_shortcut.png"></a>
<a href="https://1.bp.blogspot.com/-L2ncWeqyxd4/YLst7zzRysI/AAAAAAAASrc/Vc0S6Q4Jp-IwEPvlvByLy6mb4RXjuyQcACLcBGAsYHQ/s800/IE11_shortcut.png"><img alt="" src="https://1.bp.blogspot.com/-L2ncWeqyxd4/YLst7zzRysI/AAAAAAAASrc/Vc0S6Q4Jp-IwEPvlvByLy6mb4RXjuyQcACLcBGAsYHQ/s160/IE11_shortcut.png"></a>
<a href="https://1.bp.blogspot.com/-FYBIHj-jFsc/YLs6Rvi_jeI/AAAAAAAASrw/KY2dKYe-ve4ty7pIBs8vxQdT5Kjg1CPAwCLcBGAsYHQ/s814/PaleMoon_Firefox.png"><img alt="" src="https://1.bp.blogspot.com/-FYBIHj-jFsc/YLs6Rvi_jeI/AAAAAAAASrw/KY2dKYe-ve4ty7pIBs8vxQdT5Kjg1CPAwCLcBGAsYHQ/s160/PaleMoon_Firefox.png"></a>
</div>
<ol>
<li>Windows 10 の Chrome ブラウザからデスクトップにショートカットを作成する。
<li>Chrome ではタブのアイコンは32pxが表示されている。ダイアログには36pxのアイコンが使われている。
<li>Windows 10 の IE11 でデスクトップにショートカットを作成する。全てのアイコンに32pxが表示されている。
<li>PaleMoon と Firefox のタブのアイコンは16pxが表示されている。Firefox はリロードの後に192pxになることがある。
</ol>
<div class="box">
<a href="https://1.bp.blogspot.com/-NL5QkGkEnpk/YLry8XySJxI/AAAAAAAASqg/vJkiNNcGRVMEi8wHm79bO8fzGpy2TSCHQCLcBGAsYHQ/s512/large_shortcut.png"><img alt="" src="https://1.bp.blogspot.com/-NL5QkGkEnpk/YLry8XySJxI/AAAAAAAASqg/vJkiNNcGRVMEi8wHm79bO8fzGpy2TSCHQCLcBGAsYHQ/s160/large_shortcut.png"></a>
<a href="https://1.bp.blogspot.com/-hOd_MJS2RqQ/YLry8e_1jEI/AAAAAAAASqk/WZ642I-ADWM2rUck2uiFqBeRjUm-Z61UQCLcBGAsYHQ/s473/middle_shortcut.png"><img alt="" src="https://1.bp.blogspot.com/-hOd_MJS2RqQ/YLry8e_1jEI/AAAAAAAASqk/WZ642I-ADWM2rUck2uiFqBeRjUm-Z61UQCLcBGAsYHQ/s160/middle_shortcut.png"></a>
<a href="https://1.bp.blogspot.com/-U8_Y4w7c2aI/YLry8REKqkI/AAAAAAAASqc/MXkUufvV1mM0NfToQePsOBaXVEDs58HFwCLcBGAsYHQ/s464/small_shortcut.png"><img alt="" src="https://1.bp.blogspot.com/-U8_Y4w7c2aI/YLry8REKqkI/AAAAAAAASqc/MXkUufvV1mM0NfToQePsOBaXVEDs58HFwCLcBGAsYHQ/s160/small_shortcut.png"></a>
<a href="https://1.bp.blogspot.com/-6J8y01MPnIk/YLsLjGvxPjI/AAAAAAAASq8/W6Ly0CEzBC8Bo8YQ-yj7lBjsT2vbg9yHgCLcBGAsYHQ/s702/change_icon.png"><img alt="" src="https://1.bp.blogspot.com/-6J8y01MPnIk/YLsLjGvxPjI/AAAAAAAASq8/W6Ly0CEzBC8Bo8YQ-yj7lBjsT2vbg9yHgCLcBGAsYHQ/s160/change_icon.png"></a>
<p>Windows 10 で Chrome ブラウザからデスクトップにショートカットを追加したスクリーンショット。デスクトップ上で右クリックメニューの表示から、大アイコンを選ぶと256pxが、中アイコンを選ぶと48pxが、小アイコンを選ぶと36pxがそれぞれ表示された。
</div>
<h3>スタート画面のタイル</h3>
<div class="box">
<a href="https://1.bp.blogspot.com/-O7cfWDau8io/YLsLiOxO4QI/AAAAAAAASqw/aq7GCaOTbewJ92wxj-u_QgOaG40BoxjhwCLcBGAsYHQ/s966/Edge_add2start.png"><img alt="" src="https://1.bp.blogspot.com/-O7cfWDau8io/YLsLiOxO4QI/AAAAAAAASqw/aq7GCaOTbewJ92wxj-u_QgOaG40BoxjhwCLcBGAsYHQ/s160/Edge_add2start.png"></a>
<a href="https://1.bp.blogspot.com/-RPyoFT3RDHM/YLsLiV91srI/AAAAAAAASq4/HK6yjbggJMcIXgcvpJq9dkGLYic4w-51ACLcBGAsYHQ/s977/Edge_add2start2.png"><img alt="" src="https://1.bp.blogspot.com/-RPyoFT3RDHM/YLsLiV91srI/AAAAAAAASq4/HK6yjbggJMcIXgcvpJq9dkGLYic4w-51ACLcBGAsYHQ/s160/Edge_add2start2.png"></a>
<a href="https://1.bp.blogspot.com/-r5TqMkq35RY/YLsLidXoncI/AAAAAAAASq0/hr5VNH3kDFgFXSPTa0do1vdrcLOBxg0vwCLcBGAsYHQ/s976/Edge_add2start3.png"><img alt="" src="https://1.bp.blogspot.com/-r5TqMkq35RY/YLsLidXoncI/AAAAAAAASq0/hr5VNH3kDFgFXSPTa0do1vdrcLOBxg0vwCLcBGAsYHQ/s160/Edge_add2start3.png"></a>
<a href="https://1.bp.blogspot.com/-mI1BsyB4MK8/YLp3t-X2agI/AAAAAAAASqY/H0fAquxCbGgCjZW0IXhyrOsWumwuJpqdACPcBGAYYCw/s719/StartMenuTile.png"><img alt="" src="https://1.bp.blogspot.com/-mI1BsyB4MK8/YLp3t-X2agI/AAAAAAAASqY/H0fAquxCbGgCjZW0IXhyrOsWumwuJpqdACPcBGAYYCw/s160/StartMenuTile.png"></a>
</div>
<ol>
<li>Microsoft Edge 91.0.864.41 で<samp>その他のツール > スタート画面にピン留めする</samp>を選択。
<li>確認のダイアログでは36pxが使われている。
<li>もう一度、OS の UI で確認が表示される。
<li>スタート画面のタイルは、中サイズ、小サイズ、どちらのサイズでも256pxが表示された。
</ol>
<h3>アプリビュー</h3>
<div class="box">
<a href="https://1.bp.blogspot.com/-UzSOhsirRgM/YLswXe3Z53I/AAAAAAAASro/DOvw2TQ9LfcaLGOjM6xKde9q3iE-g8AkQCLcBGAsYHQ/s535/appview.png"><img alt="" src="https://1.bp.blogspot.com/-UzSOhsirRgM/YLswXe3Z53I/AAAAAAAASro/DOvw2TQ9LfcaLGOjM6xKde9q3iE-g8AkQCLcBGAsYHQ/s160/appview.png"></a>
<a href="https://1.bp.blogspot.com/-JmiLn-ETNbw/YLst742LstI/AAAAAAAASrg/sdjhSHQ2ANkIxOjEFP1RAebDnS2-Y9iaQCLcBGAsYHQ/s835/IE11_AppView.png"><img alt="" src="https://1.bp.blogspot.com/-JmiLn-ETNbw/YLst742LstI/AAAAAAAASrg/sdjhSHQ2ANkIxOjEFP1RAebDnS2-Y9iaQCLcBGAsYHQ/s160/IE11_AppView.png"></a>
<p>Windows 10 の IE11 からアプリビューに追加した場合、32pxが表示されている。Chrome からインストーすると36pxが表示される。
</div>
<h3>サポートの歴史</h3>
<table class="tl">
<thead>
<tr>
<th>リリース日<td>ブラウザとバージョン<td>サポート
<tbody>
<tr>
<th><td>Opera 7<td><code><link rel="icon"></code> をサポート(*5)
<tr>
<th><td>Firefox 2<td><code><link rel="icon"></code> をサポート(*2)
<tr>
<th><td>Safari 3.1, Chrome 4<td><code><link rel="icon"></code> をサポート。<q cite="https://caniuse.com/mdn-html_elements_link_rel_icon">ICO と PNG の両方が利用可能な場合、ICO のマッチしたサイズが適切であれば、PNG よりも ICO を使用します。</q>(*2)
<tr>
<th><td>IE 11<td><code><link rel="icon"></code> をサポート(*2)
<tr>
<th><a href="https://en.wikipedia.org/wiki/IOS_version_history#iPhone_OS_1" target="_blank" rel="nofollow">2007/11/12</a><td>iOS 1.1.3<td><code><link rel="apple-touch-icon"></code> をサポート
<tr>
<th><a href="https://en.wikipedia.org/wiki/IOS_version_history#iPhone_OS_2" target="_blank" rel="nofollow">2008/07/11</a><td>iOS 2.0<td><code><link rel="apple-touch-icon-precomposed"></code> をサポート
<tr>
<th><a href="https://en.wikipedia.org/wiki/Android_version_history#Android_2.0" target="_blank" rel="nofollow">2010/01/12</a><td>Android 2.1<td><code><link rel="apple-touch-icon-precomposed"></code> をサポートする。<q cite="https://www.ravelrumba.com/blog/android-apple-touch-icon/">(stackoverflowに関する一部の話では、一部のHTCスマートフォンではまったく機能しない可能性があります)</q>(*1)
<tr>
<th><a href="https://en.wikipedia.org/wiki/Android_version_history#Android_2.2" target="_blank" rel="nofollow">2010/03/20</a><td>Android 2.2<td><code><link rel="apple-touch-icon"></code> をサポートする。
<tr>
<th><a href="https://en.wikipedia.org/wiki/IOS_version_history#iOS_4" target="_blank" rel="nofollow">2010/11/22</a><td>iOS 4.2<td><code>sizes</code> 属性をサポートする。
<tr>
<th>2012/06/27?<td>Chrome for Android 18?<td>AOSP が 2.x からサポートしていることから、Android 版で最初の18から <code>"apple-touch-icon"</code> をサポートしているかもしれない。ちなみに4.0以降にインストールできる。
<tr>
<th><a href="https://en.wikipedia.org/wiki/IOS_version_history#iOS_7" target="_blank" rel="nofollow">2013/09/18</a><td>iOS 7<td>タッチアイコンの特殊効果の廃止。
<tr>
<th><a href="https://en.wikipedia.org/wiki/Google_Chrome_version_history" target="_blank" rel="nofollow">2013/11/14</a><td>Chrome for Android 31<td>標準の <code><link rel="icon"></code> をサポートする。A2HS をサポートする。
<tr>
<th><td>Android 4.4<td><q cite="https://caniuse.com/link-icon-png">複数のフォーマットが利用可能な場合、サイズに関係なく、最後にロードされたフォーマットを使用します(事実上ランダムに選択します)。</q>(*4)
<tr>
<th><td>Chrome 39<td>ウェブマニュフェストの <code>"icons"</code> をサポート(*3)
</table>
<ol>
<li><a href="https://www.ravelrumba.com/blog/android-apple-touch-icon/" target="_blank" rel="nofollow">Getting Android to Recognize Apple Touch Icons</a>
<li><a href="https://caniuse.com/mdn-html_elements_link_rel_icon" target="_blank" rel="nofollow">Can I Use > HTML element: link: rel: icon</a>
<li><a href="https://caniuse.com/mdn-html_manifest_icons" target="_blank" rel="nofollow">Can I Use > manifest: icons</a>
<li><a href="https://caniuse.com/link-icon-png" target="_blank" rel="nofollow">Can I Use > PNG favicons</a>
<li><a href="https://web.archive.org/web/20190518060358/http://www.jonathantneal.com:80/blog/understand-the-favicon/" target="_blank" rel="nofollow">Jonathan T. Neal > Understand the Favicon</a>
</ol>
<a name="3.2"></a>
<h2 id="3.2">3.2 推奨タグ(暫定版)</h2>
<h3>PNG アイコン</h3>
<p><code><link rel="icon"></code> では、最初に指定されていたアイコンを使用するブラウザ、最期に指定されていたアイコンを使用するブラウザが、それぞれある為、妥当なサイズを最初と最後で指定します。
<pre class="prettyprint lang-html"><code><!-- Other browsers -->
<link rel="icon" type="image/png" href="icon/032x032.png" sizes="32x32">
<link rel="icon" type="image/png" href="icon/192x192.png" sizes="192x192">
<link rel="icon" type="image/png" href="icon/048x048.png" sizes="48x48">
<link rel="icon" type="image/png" href="icon/096x096.png" sizes="96x96">
<link rel="icon" type="image/png" href="icon/016x016.png" sizes="16x16">
<!-- for iOS 4.2+ -->
<link rel="apple-touch-icon" href="icon/180x180.png" sizes="180x180">
<link rel="apple-touch-icon" href="icon/167x167.png" sizes="167x167"> <!-- *1 -->
<link rel="apple-touch-icon" href="icon/152x152.png" sizes="152x152">
<link rel="apple-touch-icon" href="icon/144x144.png" sizes="144x144">
<link rel="apple-touch-icon" href="icon/120x120.png" sizes="120x120">
<link rel="apple-touch-icon" href="icon/114x114.png" sizes="114x114">
<link rel="apple-touch-icon" href="icon/076x076.png" sizes="76x76">
<link rel="apple-touch-icon" href="icon/072x072.png" sizes="72x72">
<link rel="apple-touch-icon" href="icon/060x060.png" sizes="60x60">
<link rel="apple-touch-icon" href="icon/057x057.png" sizes="57x57">
<!-- for iOS 2.0+, AOSP 2.1+ -->
<link rel="apple-touch-icon-precomposed" href="icon/057x057.png">
<!-- for iOS 1.2.2+, AOSP 2.2+ -->
<link rel="apple-touch-icon" href="icon/057x057.png">
</code></pre>
<ol>
<li>167サイズは「<a href="https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html#//apple_ref/doc/uid/TP40002051-CH3-SW3" target="_blank" rel="nofollow">Safari Web Content Guide</a>」でだけ記述を見つけた。
</ol>
<h3><code>manifest.json</code>の<code>"icons"</code>プロパティ</h3>
<pre class="prettyprint lang-js"><code>{
"name" : "/*__APP_TITLE__*/",
"short_name" : "/*__APP_TITLE_SHORT__*/",
"start_url" : "./?a2hs=1",
"display" : "fullscreen",
"theme_color" : "/*__THEME_COLOR__*/",
"background_color" : "/*__BACKGROUND_COLOR__*/",
"description" : "/*__DESCRIPTION__*/",
"icons" : [
{
"src" : "icon/512x512.png",
"sizes" : "512x512",
"type" : "image/png"
},{
"src" : "icon/384x384.png",
"sizes" : "384x384",
"type" : "image/png"
},{
"src" : "icon/256x256.png",
"sizes" : "256x256",
"type" : "image/png"
},{
"src" : "icon/192x192.png",
"sizes" : "192x192",
"type" : "image/png"
},{
"src" : "icon/144x144.png",
"sizes" : "144x144",
"type" : "image/png"
},{
"src" : "icon/096x096.png",
"sizes" : "96x96",
"type" : "image/png"
},{
"src" : "icon/072x072.png",
"sizes" : "72x72",
"type" : "image/png"
},{
"src" : "icon/048x048.png",
"sizes" : "48x48",
"type" : "image/png"
},{
"src" : "icon/036x036.png",
"sizes" : "36x36",
"type" : "image/png"
}
]
}
</code></pre>
<a name="3.3"></a>
<h2 id="3.3">3.3 参考記事</h2>
<p>本記事執筆の際に参考にしたオリジナルは英文の<a href="https://mathiasbynens.be/notes/touch-icons" target="_blank" rel="nofollow">記事</a>です。
<blockquote cite="https://mathiasbynens.be/notes/touch-icons" title="Everything you always wanted to know about touch icons">
<h1>タッチアイコンについて知りたいこと全て</h1>
<p>2011年3月2日
<p>「タッチアイコン」は、モバイルデバイスやタブレットのファビコンです。それらを Web ページに追加するのは簡単で、HTML を使用してこれがどのように機能するかをすでに知っていると思います。
<pre class="prettyprint lang-html"><code><!-- In its simplest form: -->
<link rel="apple-touch-icon" href="apple-touch-icon.png">
</code></pre>
<p>Apple が標準の <code><link rel=icon></code> を実装しないだけでなく、代わりにもっと冗長な独自のリンク関係を考え出すことを選択したのは残念です。<ins>ただし、Android 用 Chrome v31+ はこの構文をサポートしています。次のように使用します。</ins>
<pre class="prettyprint lang-html"><code><link rel="icon" sizes="196x196" href="apple-touch-icon.png"></code></pre>
<p>そのような HTML が見つからない場合、Chrome for Android は代わりに Apple タッチアイコンにフォールバックします。<strong>更新:</strong><a href="https://code.google.com/p/chromium/issues/detail?id=259681" target="_blank" rel="nofollow">Chrome 30+では</a>、これは当てはまりません。通常返される404ページが<a href="https://bugs.webkit.org/show_bug.cgi?id=104585" target="_blank" rel="nofollow">すべてのモバイル帯域幅使用量の3〜4%を消費していたため</a>、<code>apple-touch-icon-*</code> が自動的にフェッチされなくなりました。ただし、当面は、適切な <code><link></code> HTML が存在する場合でもダウンロードされます。
<p>Apple は、iOS 1.1.3以降タッチアイコンをサポートしています。 奇妙なことに、<a href="http://www.ravelrumba.com/blog/android-apple-touch-icon/" target="_blank" rel="nofollow">Android 2.1以降でも <code>apple-touch-icon</code> をサポートしています</a>(いくつかの癖があります)。
<p>カスタムタッチアイコンを指定していない Web ページの場合、代わりにページのサムネイルスクリーンショットが使用されます。Android にはデフォルトのアイコンがあり、一部のシステムでは、ファビコンが利用可能な場合はファビコンにフォールバックします。
<h2>ファンシーな効果</h2>
<p>iOS は、アイコンにいくつかの視覚効果を自動的に追加して、ホーム画面の組み込みアイコンと調整します(アプリケーションアイコンの場合と同様)。 具体的には、iOS は次を追加します。
<ul>
<li>丸い角
<li>影を落とす
<li>反射する輝き
</ul>
<p>iOS 2.0以降では、<code>precomposed</code> キーワードを使用して、これらの効果の追加を防ぐことができます。
<pre class="prettyprint lang-html"><code><link rel="apple-touch-icon-precomposed" href="apple-touch-icon-precomposed.png"></code></pre>
<p><a href="https://html.spec.whatwg.org/multipage/semantics.html#attr-link-rel" target="_blank" rel="nofollow"><code>rel</code> 属性</a>は HTML でスペースで区切られた値のリストを受け入れるため、理論的には、追加の <code><link></code> 要素を必要とせずに iOS 1のエフェクトを追加して通常のアイコンにフォールバックできるはずです。
<pre class="prettyprint lang-html"><code><link rel="apple-touch-icon-precomposed apple-touch-icon" href="apple-touch-icon-precomposed.png"></code></pre>
<p>しかし、実際にはそのようには機能しません。スペースで区切られた値の手法を使用している場合、iOS 4.2は宣言全体を無視しているようです。
<p>常に事前に作成されたアイコンを使用することをお勧めします。アイコンを完全に制御でき、Android 2.1がサポートする唯一の種類のアイコンです。iOS 7以降、タッチアイコンに特殊効果は適用されなくなったため、iOS 7以降のみを気にする場合は、<code>precomposed</code> を使用する必要はありません。
<h2>さまざまなアイコンサイズ</h2>
<p><a href="https://developer.apple.com/library/ios/documentation/userexperience/conceptual/mobilehig/IconMatrix.html" target="_blank" rel="nofollow">iOS ヒューマンインターフェイスガイドラインの[アイコンと画像サイズ]セクション</a>には、次のアイコンを作成する必要があると記載されています。
<ul>
<li>1×ディスプレイを備えた iPad および iPad Mini モデルの76×76ピクセルのサイズのもの。
<li>iPhone 4s、iPhone 5、iPhone 6(2倍のディスプレイを備えている)の場合、120×120ピクセルのサイズのもの。
<li>2倍ディスプレイを備えた iPad および iPad Mini モデルの場合は152×152ピクセルのサイズのもの。
<li>iPhone 6 Plus(3倍のディスプレイ)用に180×180ピクセルのサイズのもの。
</ul>
<div class="note"><p><strong>更新(2013年6月):</strong>iOS 7の時点で、Retina ディスプレイ iPhone の推奨タッチアイコンサイズは114×114ピクセルから120×120ピクセルに増加しました。Retina ディスプレイ iPad のアイコンサイズは、144×144ピクセルから152×152ピクセルに増加しました。この投稿はそれを反映するように更新されました。
<p><strong>更新(2014年9月):</strong>iOS 8とiPhone 6 Plus がリリースされたため、この投稿はもう一度更新されました。
</div>
<p>1つの高解像度アイコンを作成し、それをすべてのデバイスに使用することは完全に可能です。実際、<a href="http://www.apple.com/apple-touch-icon.png" target="_blank" rel="nofollow">これは Apple がそれを行う方法です</a>。画面が小さい、またはディスプレイの解像度が低いデバイスは、アイコンのサイズを自動的に変更します。欠点は、これらのデバイスが大きな高品質の画像をロードする一方で、はるかに小さなファイルでも同様に機能することです。これは帯域幅を浪費し、サイトがホーム画面に追加されるたびにエンドユーザーのパフォーマンスに悪影響を及ぼします。
<p>幸い、iOS 4.2では、<code>sizes</code> 属性を使用して、<a href="https://developer.apple.com/library/safari/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html" target="_blank" rel="nofollow">デバイスの解像度ごとに複数のアイコン</a>を指定できます。
<pre class="prettyprint lang-html"><code><!-- For non-Retina (@1× display) iPhone, iPod Touch, and Android 2.1+ devices: -->
<link rel="apple-touch-icon-precomposed" href="apple-touch-icon-precomposed.png"><!-- 57×57px -->
<!-- For the iPad mini and the first- and second-generation iPad (@1× display) on iOS ? 6: -->
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="apple-touch-icon-72x72-precomposed.png">
<!-- For the iPad mini and the first- and second-generation iPad (@1× display) on iOS ? 7: -->
<link rel="apple-touch-icon-precomposed" sizes="76x76" href="apple-touch-icon-76x76-precomposed.png">
<!-- For iPhone with @2× display running iOS ? 6: -->
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="apple-touch-icon-114x114-precomposed.png">
<!-- For iPhone with @2× display running iOS ? 7: -->
<link rel="apple-touch-icon-precomposed" sizes="120x120" href="apple-touch-icon-120x120-precomposed.png">
<!-- For iPad with @2× display running iOS ? 6: -->
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="apple-touch-icon-144x144-precomposed.png">
<!-- For iPad with @2× display running iOS ? 7: -->
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="apple-touch-icon-152x152-precomposed.png">
<!-- For iPhone 6 Plus with @3× display: -->
<link rel="apple-touch-icon-precomposed" sizes="180x180" href="apple-touch-icon-180x180-precomposed.png">
<!-- For Chrome for Android: -->
<link rel="icon" sizes="192x192" href="touch-icon-192x192.png"></code></pre>
<p>ここでは、いくつかの簡単なルールが適用されます。
<ul>
<li>デバイスの推奨サイズに一致するアイコンがない場合は、推奨サイズよりも大きい最小のアイコンが使用されます。
<li>推奨サイズよりも大きいアイコンがない場合は、最大のアイコンが使用されます。
<li>複数のアイコンが適切な場合は、<code>precomposed</code> キーワードを持つアイコンが使用されます。
</ul>
<p>しかし、それはより複雑になります。iOS の4.2未満は、単に <a href="https://mathiasbynens.be/demo/touch-icon" target="_blank" rel="nofollow"><code>sizes</code> 属性を無視する</a>ため、上記のコードスニペットは次のように解釈されます。
<pre class="prettyprint lang-html"><code><link rel="apple-touch-icon-precomposed" href="apple-touch-icon-precomposed.png"><!-- 57×57px -->
<link rel="apple-touch-icon-precomposed" href="apple-touch-icon-72x72-precomposed.png">
<link rel="apple-touch-icon-precomposed" href="apple-touch-icon-76x76-precomposed.png">
<link rel="apple-touch-icon-precomposed" href="apple-touch-icon-114x114-precomposed.png">
<link rel="apple-touch-icon-precomposed" href="apple-touch-icon-120x120-precomposed.png">
<link rel="apple-touch-icon-precomposed" href="apple-touch-icon-144x144-precomposed.png">
<link rel="apple-touch-icon-precomposed" href="apple-touch-icon-152x152-precomposed.png">
<link rel="apple-touch-icon-precomposed" href="apple-touch-icon-180x180-precomposed.png"></code></pre>
<p>これらのシステムでは、ドキュメントの最後の値のみが使用されます。この場合、それが最大のアイコンです。見方によっては、アイコンの順序を逆にした方がよい場合があります。
<pre class="prettyprint lang-html"><code><!-- For Chrome for Android: -->
<link rel="icon" sizes="192x192" href="touch-icon-192x192.png">
<!-- For iPhone 6 Plus with @3× display: -->
<link rel="apple-touch-icon-precomposed" sizes="180x180" href="apple-touch-icon-180x180-precomposed.png">
<!-- For iPad with @2× display running iOS ? 7: -->
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="apple-touch-icon-152x152-precomposed.png">
<!-- For iPad with @2× display running iOS ? 6: -->
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="apple-touch-icon-144x144-precomposed.png">
<!-- For iPhone with @2× display running iOS ? 7: -->
<link rel="apple-touch-icon-precomposed" sizes="120x120" href="apple-touch-icon-120x120-precomposed.png">
<!-- For iPhone with @2× display running iOS ? 6: -->
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="apple-touch-icon-114x114-precomposed.png">
<!-- For the iPad mini and the first- and second-generation iPad (@1× display) on iOS ? 7: -->
<link rel="apple-touch-icon-precomposed" sizes="76x76" href="apple-touch-icon-76x76-precomposed.png">
<!-- For the iPad mini and the first- and second-generation iPad (@1× display) on iOS ? 6: -->
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="apple-touch-icon-72x72-precomposed.png">
<!-- For non-Retina iPhone, iPod Touch, and Android 2.1+ devices: -->
<link rel="apple-touch-icon-precomposed" href="apple-touch-icon-precomposed.png"><!-- 57×57px --></code></pre>
<p>このように、古い iOS バージョンは、最大のアイコンではなく最小のアイコンをダウンロードします。そのため、<code>sizes</code> 属性(iOS 4.2以降)をサポートしていない限り、すべてのデバイスに最大のアイコンを強制する代わりに、<code>@sizes</code> がサポートされていない限り最小のアイコンを提供するようになりました。つまり、現在、グレースフルデグラデーションではなくプログレッシブエンハンスメントを使用しています:)
<p><strong>疑わしい場合は、常にこのスニペットを使用してください。</strong>ほぼすべての iOS バージョンとデバイス、および可能な限り多くの異なる Android バージョンをサポートしているため、サイトにタッチアイコンを追加するための最も堅牢な方法です。
<p>Android 2.3(Gingerbread)を実行している Nexus One でこれをテストしてもらいましたが、<code>@sizes</code> もサポートされていないようです。ただし、動作は古い iOS バージョンとは異なります。最後の <code><link></code> 要素の <code>@href</code> 値を使用する代わりに、<code>rel="apple-touch-icon"</code> または <code>rel="apple-touch-icon-precomposed"</code> で最初の <code><link></code> 要素の値を使用します。上記のコードスニペットの場合、これが利用可能な最大のアイコンです。
<div class="note"><p><strong>更新(2013年3月):</strong>Android デバイスでさらにいくつかのテストをクラウドソーシングしました。提案されたスニペットを使用すると、Galaxy Nexus の Android 4.1.xと4.2.xはどちらも、デフォルトの Android ブラウザを使用してブックマークを追加している限り、57×57pxのアイコンを取得します。<del>Chrome 内からブックマークすると、<a href="https://code.google.com/p/chromium/issues/detail?id=125076" target="_blank" rel="nofollow">タッチアイコンが無視されます</a>。</del><ins>これは Chrome 27で修正されています。</ins>このバグは、Android 4.0.xを実行している Samsung I9100 Galaxy SII デバイスにも存在します。
<strong>更新(2013年7月):</strong><a href="http://src.chromium.org/viewvc/blink?view=revision&revision=154413" target="_blank" rel="nofollow">このコミット</a>の時点で、Chrome for Android はデフォルトで <code>apple-touch-icon(-precomposed).png</code> を要求しなくなりました(つまり、そのようなアイコンが HTML ソースから参照されていない場合)。
</div>
<h2>HTMLは見ません</h2>
<p>HTML でアイコンが指定されていない場合、iOS Safari は Web サイトのルートディレクトリで、<code>apple-touch-icon</code> または <code>apple-touch-icon-precomposed</code> プレフィックスが付いたアイコンを検索します。たとえば、デバイスの適切なアイコンサイズが57×57ピクセルの場合、iOS は次の順序でファイル名を検索します。
<ol>
<li><code>apple-touch-icon-57x57-precomposed.png</code>
<li><code>apple-touch-icon-57x57.png</code>
<li><code>apple-touch-icon-precomposed.png</code>
<li><code>apple-touch-icon.png</code>
</ol>
<p>そうです。iOS の場合、解像度固有のアイコンを複数使用する場合でも、HTML を使用してサイトにタッチアイコンを追加する必要はありません。すべての HTML ページにある独自の <code><link rel="apple-touch-icon"></code> 要素のボートロードにアディオスと言ってください。 アイコンのさまざまなバージョンを作成し、正しいファイル名を使用してルートに配置するだけです。(<a href="https://mathiasbynens.be/notes/rel-shortcut-icon" target="_blank" rel="nofollow">favicon.ico</a>、誰か?)
<p>では、何が必要ですか?
<ul>
<li>非 Retina iPhone および iPod Touch(@1xディスプレイ)の場合は、<code>apple-touch-icon-57x57-precomposed.png</code> または <code>apple-touch-icon-57x57.png</code>。
<li><del>iPad mini および iOS≦6 の第1世代および第2世代 iPad(@1xディスプレイ)の場合は、<code>apple-touch-icon-72x72-precomposed.png</code> または <code>apple-touch-icon-72x72.png</code></del>。
<li><ins>iPad mini および iOS≧7 の第1世代および第2世代 iPad(@1xディスプレイ)の場合は、<code>apple-touch-icon-76x76-precomposed.png</code> または <code>apple-touch-icon-76x76.png</code>。</ins>
<li><del><code>apple-touch-icon-114x114-precomposed.png</code> または <code>apple-touch-icon-114x114.png</code> for iPhone 4 +(@2xディスプレイ付き)iOS≦6;</del>
<li><ins>iOS≧7 の iPhone 4 +(@2xディスプレイ付き)の場合は、<code>apple-touch-icon-120x120-precomposed.png</code> または <code>apple-touch-icon-120x120.png</code>。</ins>
<li><del>iPad 3+の場合は <code>apple-touch-icon-144x144-precomposed.png</code> または <code>apple-touch-icon-144x144.png</code>(@2xディスプレイ付き)。</del>
<li><ins>iPad 3+の場合は <code>apple-touch-icon-152x152-precomposed.png</code> または <code>apple-touch-icon-152x152.png</code>(@2xディスプレイ付き)。</ins>
<li>iPhone 6 Plus の場合は <code>apple-touch-icon-180x180-precomposed.png</code> または <code>apple-touch-icon-180x180.png</code>(@3xディスプレイ付き)。
<li><code>touch-icon-192x192.png</code> for Chrome for Android;
<li>他のすべて(おそらく Apple 以外のデバイスを含む)のフォールバックとしての <code>apple-touch-icon-precomposed.png</code> および <code>apple-touch-icon.png</code>。
</ul>
<p>互換性を最大化するために、<code>apple-touch-icon.png</code> と <code>apple-touch-icon-precomposed.png</code> の両方を含めることをお勧めします。iOS 1と BlackBerry OS 6は、事前に作成されたアイコンをサポートしていません。(Android 2.1は合成済みアイコンのみをサポートしていることに注意してください。)ファイルを複製する必要がないように、書き換えルールを使用できます。
<p>残念ながら、HTML なしのアプローチは、ネイティブの Android ブラウザ(2.3 Gingerbread, 3 Honeycomb, 4.1 Jelly Bean でテスト済み)では機能しませんが、<a href="https://twitter.com/puntlino/status/312289586736951296" target="_blank" rel="nofollow">4.2 Jelly Bean のデフォルトブラウザで機能するとの報告があります</a>。 私はまだ BlackBerry OS 6をテストすることができませんでした。必要に応じて、私の Web サイトでこの手法をテストできます。このページのブックマークをホーム画面に保存して、カスタムタッチアイコンが表示されるかどうかを確認します。<a href="https://mathiasbynens.be/notes/touch-icons#comments" target="_blank" rel="nofollow">あなたが見つけたものを私に知らせてください</a>!
<h2>概要</h2>
<p>では、どのテクニックを使用するのでしょうか?それはあなた次第です。
<ul>
<li>Android のサポートが必須の場合は、HTML を使用する必要があります。「さまざまなアイコンのサイズ」セクションにある最後のコードスニペットを使用することをお勧めします。
<li>iOS だけが気になる場合は、HTML を使用しないアプローチを使用することを強くお勧めします。
<li>怠惰で、Android、レガシー iOS バージョン、またはパフォーマンスをあまり気にしない場合は、180×180pxのアイコンを1つ使用して、<code>apple-touch-icon-precomposed.png</code> という名前を付けて、あなたのウェブサイトのルートに配置します。
</ul>
</blockquote>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-3818508400667429792021-06-04T19:52:00.004+09:002021-06-29T02:36:04.554+09:002021年決定版はこれ! ファビコン(favicon.ico)編<ol>
<li><a href="/2021/04/favicon-apple-touch-icon-startup-image.html">2021年決定版はこれ! ICOファビコン、タッチアイコン、スプラッシュ画面をきっちり押さえて圧倒的おもてなし!</a>
<li>ファビコン(favicon.ico)編
<ol>
<li><a href="#2.1">3行まとめ</a>
<li><a href="#2.2">マルチサイズな ICO</a>
<li><a href="#2.3">PNGもサポートする環境でICOを避けたい理由</a>
<li><a href="#2.4">参考記事</a>
</ol>
<li><a href="/2021/04/apple-touch-icon-and-icon-and-icons.html">アイコン編(<code>"apple-touch-icon"</code>と<code>"icon"</code>と<code>"icons"</code>)編</a>
<li><a href="/2021/06/apple-startup-image.html">スプラッシュ画面(<code>"apple-startup-image"</code>)編</a>
</ol>
<a name="2.1"></a>
<h2 id="2.1">2.1 3行まとめ</h2>
<ul>
<li><code>favicon.ico</code> は Internet Exproler 5からサポートする。Chrome, Safari もサポートする。
<li><code>favicon.ico</code> は 16px, 24px, 36px, 48px, 64px のマルチサイズとする。
<li><code>favicon.ico</code> の画像データは非圧縮なのでファイルサイズが輪をかけて大きい。よって条件付きコメントと js で IE だけに読み込ませて、他のブラウザは <abbr title="Portable Network Graphics">PNG</abbr> アイコンを使用する。
</ul>
<a name="2.2"></a>
<h2 id="2.2">2.2 マルチサイズな ICO</h2>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-lA5kQmILRwU/YI-rM5h5b6I/AAAAAAAASlk/x173mvlmdKc6qFniB-gZuEYn0G55h_WVQCLcBGAsYHQ/s906/2021-05-03.png"><img alt="" src="https://1.bp.blogspot.com/-lA5kQmILRwU/YI-rM5h5b6I/AAAAAAAASlk/x173mvlmdKc6qFniB-gZuEYn0G55h_WVQCLcBGAsYHQ/s160/2021-05-03.png"></a>
<figcaption>「<a href="https://ao-system.net/alphaicon/" target="_blank" rel="nofollow">半透過マルチアイコン favicon.icoを作ろう!</a>」で作成した検証用マルチアイコン</figcaption>
</figure>
</span>
<p>ICO 画像形式では、ひとつのファイルに複数のサイズの画像を格納することが出来ます。
<p>Internet Exproler 限定にする場合、次の画像サイズが必要となっています。
</div>
<h3>Internet Exproler 用の各サイズと用途</h3>
<table>
<thead>
<tr>
<th>縦横サイズ<td>用途
<tbody>
<tr>
<th>16px<td>アドレスバー、タブ、またはブックマークビュー
<tr>
<th>24px<td>Internet Explorer 9で固定されたサイト
<tr>
<th>32px<td>Internet Explorer の新しいタブページ、Windows 7以降のタスクバーボタン
<tr>
<th>48px<td>Windows デスクトップショートカット
<tr>
<th>64px<td>高解像度の Windows デスクトップショートカット
</table>
<ul>
<li><a href="https://kubogen.com/web-design-011/" target="_blank" rel="nofollow">ファビコン(favicon)のサイズはどれが必要?作り方や設置方法も紹介</a>
</ul>
<a name="2.3"></a>
<h2 id="2.3">2.3 PNGもサポートする環境でICOを避けたい理由</h2>
<p>PNG ファビコンと ICO ファビコン、両方をサポートするブラウザに対しては PNG が適用されるようにします。これは、PNG 形式ではビットマップデータが可逆圧縮されているのに対して、ICO が非圧縮なのでファイルサイズが大きいためです。
<p>加えて先に述べたマルチサイズな ICO の場合、更にファイルサイズが大きくなってしまいます。
<p>条件付きコメントで IE ブラウザにだけ適用させているのは、以上の理由からです。
<h3>TODO</h3>
<p>この他に ICO が必要なブラウザは?マルチサイズから適切に画像を選んでデスクトップショートカットにする Windows のバージョンは?
<a name="2.4"></a>
<h2 id="2.4">2.4 参考記事</h2>
<p>本記事執筆の際に参考にした英文記事の一つです。オリジナルは<a href="https://web.archive.org/web/20190518060358/http://www.jonathantneal.com:80/blog/understand-the-favicon/" target="_blank" rel="nofollow">インターネットアーカイブ</a>に収録されてます。
<blockquote cite="https://web.archive.org/web/20190518060358/http://www.jonathantneal.com:80/blog/understand-the-favicon/" title="Jonathan T. Neal > Understand the Favicon">
<h1>ファビコンについて理解する</h1>
<p>written by jonathantneal, 2013年1月16日
<p><a href="//twitter.com/AlecRust" target="_blank" rel="nofollow">Alec Rust</a> が <a href="//html5boilerplate.com/" target="_blank" rel="nofollow">HTML5 Boilerplate</a> プロジェクトに <a href="//github.com/h5bp/html5-boilerplate/issues/1285" target="_blank" rel="nofollow">HiDPI ファビコンに切り替える</a>ように依頼したとき、<a href="//www.w3.org/2005/10/howto-favicon" target="_blank" rel="nofollow">お気に入りのアイコン</a>、<a href="//developer.apple.com/library/ios/#documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html" target="_blank" rel="nofollow">タッチアイコン</a>、<a href="http://blogs.msdn.com/b/ie/archive/2012/06/08/high-quality-visuals-for-pinned-sites-in-windows-8.aspx" target="_blank" rel="nofollow">タイルアイコン</a>についてほとんど知らなかったことに気づきました。もう少し深く潜ることにしたとき、物事は面白くなりました。
<p>1999年に Internet Explorer によって最初に導入されて以来、ファビコンについてはほとんど何も変わっていません。それらはほとんど常に <a href="//en.wikipedia.org/wiki/ICO_%28file_format%29" target="_blank" rel="nofollow">ICO ファイル</a>であり、ドメインのルートに <code>/favicon.ico</code> としてネストされているか、CMS によってテーマまたは画像ディレクトリにオーガナイズされて次のように表示されます。
<pre class="prettyprint lang-html"><code><link rel="shortcut icon" href="/path/to/favicon.ico">
</code></pre>
<div class="box"><img src="https://1.bp.blogspot.com/-hG4NkOfaly4/YIOozsIptEI/AAAAAAAASg8/2LnBdqWhz4k9qxBt5VfBplHdtWqyYV9MgCLcBGAsYHQ/favicon-16.png">
<img src="https://1.bp.blogspot.com/-tm2evV_6zws/YIOozopiM3I/AAAAAAAAShE/lCkq3wOQN6gG7X-KUqFsBrh-Y8beR2mMgCLcBGAsYHQ/favicon-32.png"></div>
<p>従来の favicon.ico は16×16の ICO ファイルであり、多くの場合、16色または24ビットのアルファ透明フォーマットで提供されます。最近では、ファビコンは32×32として提供されており、すべての主要で人気のあるレガシーブラウザで適切に縮小されています。 IE10 Metro では、32×32アイコンがアドレスバーで使用されます。
<img alt="" src="https://1.bp.blogspot.com/-1jxa6MVmjIc/YIOo09WNYlI/AAAAAAAAShM/sQoW_gzyF-IfiHEHzEk9A-ag3UX2eO2ewCLcBGAsYHQ/ie10-address-bar.png">
<p>ファビコンの <code>rel</code> 属性は、進化の産物です。 Internet Explorer 5は、<code>shortcut icon</code> がページとアイコンの関係を表すことを意図していましたが、仕様で関係がスペースで区切られている場合、理論的には <code>shortcut</code> と <code>icon</code> の2つの関係が作成されました。 HTML5 仕様で <code>icon</code> のみが標準の識別子であると宣言されたのは2010年のことでした。 IE 以外のブラウザでは、<code>shortcut</code> プロパティなしでファビコンを提供できます。
<pre class="prettyprint lang-html"><code><!-- IE6-10 -->
<link rel="shortcut icon" href="path/to/favicon.ico">
<!-- Everybody else -->
<link rel="icon" href="path/to/favicon.ico"></code></pre>
<p>ファビコンの <strong>type</strong> 属性は、<a href="//www.w3.org/html/wg/drafts/html/master/scripting-1.html#attr-script-type" target="_blank" rel="nofollow"><code><script></code> の <code>type</code> 属性</a>とほぼ同じくらい便利です。 2013年1月16日の時点で、<a href="//en.wikipedia.org/wiki/Favicon" target="_blank" rel="nofollow">ウィキペディア</a>は<a href="//en.wikipedia.org/wiki/Favicon#How_to_use" target="_blank" rel="nofollow">ファビコンの type 属性</a>が Internet Explorer が正しく表示するかどうかに影響を与える可能性があることを示唆しています。実際には、Internet Explorer は ICO ファイルのサーバー mime のみを考慮し、それ以外の場合は type 属性を無視します。type 属性は何でもかまいませんし、何でもありません。
<pre class="prettyprint lang-html"><code><!-- Still works in IE6+ -->
<link rel="shortcut icon" href="path/to/favicon.ico" type="image/vnd.microsoft.icon">
<!-- Still works in IE6+ -->
<link rel="shortcut icon" href="path/to/favicon.ico" type="image/x-icon">
<!-- Still works in IE6+ -->
<link rel="shortcut icon" href="path/to/favicon.ico"></code></pre>
<blockquote>
<div class="box">
<a href="https://1.bp.blogspot.com/-yc4sSBMS-pg/YIOozhJDFVI/AAAAAAAAShk/Q983L1a2kE89KdiQofy8yNB1rCB6hG1OACPcBGAYYCw/happy-doctor.png"><img alt="" src="https://1.bp.blogspot.com/-yc4sSBMS-pg/YIOozhJDFVI/AAAAAAAAShk/Q983L1a2kE89KdiQofy8yNB1rCB6hG1OACPcBGAYYCw/s160/happy-doctor.png"/></a>
<p>皆さん、朗報です!優れたブラウザは PNG ファビコンを使用できます。
</div>
<div class="box">
<a href="https://1.bp.blogspot.com/-cii0fMqvDng/YIOo1c3KBaI/AAAAAAAAShg/j6v2805TvAk3aYzaM68OMX1_6-FUy_imwCPcBGAYYCw/sad-doctor.png"><img alt="" src="https://1.bp.blogspot.com/-cii0fMqvDng/YIOo1c3KBaI/AAAAAAAAShg/j6v2805TvAk3aYzaM68OMX1_6-FUy_imwCPcBGAYYCw/s160/sad-doctor.png"/></a>
<p>悪いニュース、みんな! Chrome と Safari はとにかく ICO ファビコンを使用します。
</div>
</blockquote>
<p>Chrome, Firefox, Opera 7以降、Safari 4以降はすべて PNG ファビコンを受け入れるため、これは本当に気のめいることですが、Chrome と Safari は、宣言されている順序に関係なく、両方が提供されたときに ICO ファビコンを使用することを選択します。一方、Internet Explorer は PNG ファビコンをサポートしていませんが、宣言されている順序に関係なく、PNG ファビコンを無視して ICO ファビコンを使用します。
<pre class="prettyprint lang-html"><code><!-- Chrome, Safari, IE -->
<link rel="shortcut icon" href="path/to/favicon.ico">
<!-- Firefox, Opera (Chrome and Safari say thanks but no thanks) -->
<link rel="icon" href="path/to/favicon.png">
</code></pre>
<p>PNG ファビコンファイルには ICO ファビコンのような複数の解像度が含まれていないため、いくつかのファビコン宣言を書き出し、<strong>sizes</strong> 属性を使用して各解像度をターゲットにすることができます。
<pre class="prettyprint lang-html"><code><link rel="icon" href="favicon-16.png" sizes="16x16">
<link rel="icon" href="favicon-32.png" sizes="32x32">
<link rel="icon" href="favicon-48.png" sizes="48x48">
<link rel="icon" href="favicon-64.png" sizes="64x64">
<link rel="icon" href="favicon-128.png" sizes="128x128">
</code></pre>
<p>これらの PNG ファビコン互換ブラウザは、どのファビコンを使用するかをどのように決定しますか?Firefox と Safari は、最後に来るファビコンを使用します。Chrome for Mac は、ICO 形式のファビコンを使用します。それ以外の場合は32×32ファビコンを使用します。 Chrome for Windows は、16×16の場合は最初に記述されるファビコンを使用し、それ以外の場合は ICO を使用します。前述のオプションのいずれも使用できない場合、両方の Chrome は、Firefox や Safari とは正反対に、最初に記述されるファビコンを使用します。実際、Chrome for Mac は16×16ファビコンを無視し、Retina 以外のデバイスで16×16に縮小する場合にのみ32×32バージョンを使用します。Opera は、一方に加担したくないので、利用可能なアイコンから完全にランダムに選択します。私はこの Opera の挙動が大好きです。
<p>そして、ここ迄は序章に過ぎません。次に、Internet Explorer の警告について学習します。
<div class="box"><a href="https://1.bp.blogspot.com/-4WvBaVhKKc8/YIOo1cDD0ZI/AAAAAAAAShg/IOQZiB2oS68dy7So-hH1gXM_RJn9VZuPgCPcBGAYYCw/lqIAj.jpg"><img alt="" src="https://1.bp.blogspot.com/-4WvBaVhKKc8/YIOo1cDD0ZI/AAAAAAAAShg/IOQZiB2oS68dy7So-hH1gXM_RJn9VZuPgCPcBGAYYCw/s160/lqIAj.jpg"/></a>
<p>IEはトロールになる可能性があります。IE8-10 はページの最初の読み込み時にファビコンを表示しますが、IE7 は最初の読み込みをスキップし、繰り返しアクセスするときにファビコンを表示します。さらに悪いことに、IE6 は、サイトがブックマークされてブラウザーで再度開かれた場合にのみファビコンを表示します。 IE6 は、ブラウザのキャッシュがクリアされるたびにファビコンをドロップし、サイトが再ブックマークされるか、ファビコンが何らかの方法で再ロードされるまで、ファビコンを再度表示しません。 IE6 とファビコンがあなたにとって大きな意味を持つ場合は、できれば条件付きコメントでラップした小さな JavaScript スニペットを使用してこのリロードを強制できます。
</div>
<pre class="prettyprint lang-html"><code><!-- I "support" IE6 -->
<!--[if IE 6]><script>(new Image).src="path/to/favicon.ico"</script><![endif]-->
</code></pre>
<a href="https://jonneal.bandcamp.com/track/bye-bye-hacker" target="_blank" rel="nofollow"><img alt="" src="https://1.bp.blogspot.com/-QsSoF-eaG0g/YIOo27RTf7I/AAAAAAAAShk/dgAP4G16NQosvZsX41z1Tphx-SteRPuBgCPcBGAYYCw/YVKiF.png"/></a>
<p>HiDPI に戻って、この自問を既にしましたか?
<blockquote><p>すべての優れたブラウザが PNG ファビコンをサポートし、IE が ICO ファビコンを必要としているが、ICO ファビコンが Chrome と Safari を振り落とす場合、IE 条件付きコメントで ICO ファビコンをラップしてみませんか?</blockquote>
<p>それは素晴らしい質問であり、それは素晴らしいアイデアにつながります。 PNG ファイルは ICO ファイルの数分の1のサイズです。クラシックな32×32 ICO ファビコンを IE に提供し、非常に洗練された96×96 PNG ファビコンを他のすべての人に提供できます。
<pre class="prettyprint lang-html"><code><!-- Just IE? -->
<!--[if IE]><link rel="shortcut icon" href="path/to/favicon.ico"><![endif]-->
<!-- Everybody else? -->
<link rel="icon" href="path/to/favicon.png"></code></pre>
<p>ある大問題。IE10 は条件付きコメントをサポートしておらず、PNG ファビコンもサポートしていません。はい、上記のコードを使用すると、レガシー IE は Microsoft の最も優れたフラッグシップよりも優れたエクスペリエンスを得ることができます。
<blockquote><p>ねえ、ねえ、ルートディレクトリに ICO ファビコンを貼り付け、<code><link rel="icon"></code> を使用して PNG ファビコンを割り当てるとどうなりますか?</blockquote>
<p>君は。勝つ。インターネット! Chrome, Safari, IE の制限を考えると、この方法はすべてのブラウザに最高のファビコンエクスペリエンスを提供します。 IEは <code><link rel="icon"></code> を無視し、ドメインのルートにある ICO ファビコンを <code>/favicon.ico</code> として使用します。他のすべてのブラウザは、次のように表示される PNG ファビコンを使用します。
<pre class="prettyprint lang-html"><code><link rel="icon" href="path/to/favicon.png"></code></pre>
<blockquote><p>しかし、複数のファビコンが必要な場合、または CMS がこの方法を好まない場合はどうなりますか?…別の方法はありますか?</blockquote>
<p>ええ、でもあなたはそれを気に入らないでしょう。
<pre class="prettyprint lang-html"><code><!-- I "support" IE -->
<script>
navigator.appName == "Microsoft Internet Explorer" && (function (i, d, s, l) {
i.src = "favicon.ico";
s = d.getElementsByTagName("script")[0];
l = s.parentNode.insertBefore(d.createElement("link"), s);
l.rel = "shortcut icon";
l.href = i.src;
})(new Image, document);
</script>
<!-- Everybody else -->
<link rel="icon" href="path/to/favicon.png"></code></pre>
<p>どちらの解決策にも満足していませんか?すべてが失われるわけではありません。IE10 ユーザーは今のところほとんどが Windows8 ユーザーであり、Windows8 では Web サイト用の新しい種類の表示アイコンであるタイルアイコンが導入されています。
<div class="box"><img alt="" src="https://1.bp.blogspot.com/-tDHkFW9wNpY/YIOr4v0ngoI/AAAAAAAASho/VK9j1T2k0Zk-m-wOASYQPkxGpNXmz2-0ACLcBGAsYHQ/tile-icon.png"></div>
<p>IE10 Metro を使用すると、訪問者がサイトをスタート画面に固定したときに、一意のタイルアイコンを表示できます。これらのタイルアイコンは144×144の PNG ファイルであり、最良の結果を得るには、透明な背景を使用します。背景タイルの色は、16進RGB色(6文字の #RRGGBB 表記を使用)、CSS 色名、または CSS rgb()関数を使用して指定できます。マークアップは非常に簡単です。
<pre class="prettyprint lang-html"><code><meta name="msapplication-TileColor" content="#D83434">
<meta name="msapplication-TileImage" content="path/to/tileicon.png"></code></pre>
<div class="box"><a href="https://1.bp.blogspot.com/-3kwTNL5YELA/YIOsQOA292I/AAAAAAAAShw/lJQxLoMAFxw99Q9x_fONt7I7abFsC5rgACLcBGAsYHQ/tile-icon-pinnning.png"><img alt=""src="https://1.bp.blogspot.com/-3kwTNL5YELA/YIOsQOA292I/AAAAAAAAShw/lJQxLoMAFxw99Q9x_fONt7I7abFsC5rgACLcBGAsYHQ/s160/tile-icon-pinnning.png"/></a></div>
<p>では、IE10 の潜在的な制限を受け入れ、他のすべての正常な部分を維持しながら、すべてをまとめましょう。
<pre class="prettyprint lang-html"><code><link rel="apple-touch-icon" href="path/to/touchicon.png">
<link rel="icon" href="path/to/favicon.png">
<!--[if IE]><link rel="shortcut icon" href="path/to/favicon.ico"><![endif]-->
<!-- or, set /favicon.ico for IE10 win -->
<meta name="msapplication-TileColor" content="#D83434">
<meta name="msapplication-TileImage" content="path/to/tileicon.png">
</code></pre>
<p>少なくとも、これが最初の一歩です。
<p>ファビコンの作成について詳しく知りたい場合は、Jon Hicks の『<a href="//www.fivesimplesteps.com/products/the-icon-handbook" target="_blank" rel="nofollow">The Icon Handbook</a>』から<a href="//web.archive.org/web/20130916141114/https://www.netmagazine.com/features/create-perfect-favicon" target="_blank" rel="nofollow">完璧なファビコンを作成</a>し、Jonathan Snook による『<a href="//snook.ca/archives/design/making_a_good_favicon" target="_blank" rel="nofollow">Making a good favicon</a>』をお勧めします。また、タイルアイコンについて教えてくれた <a href="//twitter.com/alrra" target="_blank" rel="nofollow">@alrra</a> に感謝します。
<h2>待って、私はタッチアイコンのためにここに来ました。</h2>
<p>タッチアイコンの埋め込みについて詳しく知りたい場合は、Mathias Bynens の『<a href="//mathiasbynens.be/notes/touch-icons" target="_blank" rel="nofollow">タッチアイコンについて常に知りたいことのすべて</a>』をお読みください。または、彼の記事のこの要約に従ってください。
<blockquote><p>高解像度のアイコンを1つだけ作成することは完全に可能です。ディスプレイの解像度を低くすると、アイコンのサイズが自動的に変更されます。欠点は、サイトがホーム画面に追加されるたびに、パフォーマンスに悪影響を与えることです。
<p>2013年3月の時点で、サイトがホーム画面に追加されたときに怠惰でパフォーマンスをあまり気にしない場合は152×152のアイコンを1つだけ使用してください。</blockquote>
<p>そして、そのアイコンのマークアップは次のとおりです。
<pre class="prettyprint lang-html"><code><link rel="apple-touch-icon-precomposed" href="apple-touch-icon-152x152-precomposed.png"></code></pre>
<p>すべての BlackBerry ~ Android ~ iOS(7) の夢が叶いますように。
</blockquote>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-43249616143120110572021-06-04T19:30:00.009+09:002022-05-22T20:59:08.479+09:002021年決定版はこれ! ICOファビコン、タッチアイコン、スプラッシュ画面をきっちり押さえて圧倒的おもてなし!<ol>
<li>2021年決定版はこれ! ICOファビコン、タッチアイコン、スプラッシュ画面をきっちり押さえて圧倒的おもてなし!
<ol>
<li><a href="#1.1">はじめに</a>
<li><a href="#1.2">僕が採用したタグ</a>
<li><a href="#1.3">参考記事</a>
</ol>
<li><a href="/2021/04/understand-the-favicon.html">ファビコン(favicon.ico)編</a>
<li><a href="/2021/04/apple-touch-icon-and-icon-and-icons.html">アイコン編(<code>"apple-touch-icon"</code>と<code>"icon"</code>と<code>"icons"</code>)編</a>
<li><a href="/2021/06/apple-startup-image.html">スプラッシュ画面(<code>"apple-startup-image"</code>)編</a>
</ol>
<a name="1.1"></a>
<h2 id="1.1">1.1 はじめに</h2>
<p>自身の <abbr title="Single Page Application">SPA</abbr> フレームワークでは、テンプレートから index.html を書き出すこととしました。SPA だけあって <code><body></code> 下は <code><noscript></code> が入っているだけでほぼ空なのですが、<code><head></code> 下などに思いの他、大量の要素が必要なことが判りました。しかもこの <code><head></code> 下の内容は時代とともに更新を迫られます。
<ul>
<li>検索エンジンの変化への対応。<code><meta name="keywords"></code> の有無等。
<li><abbr title="Progressive web apps">PWA</abbr> 過渡期の iOS の独自拡張、現在も使用されていて新端末のディスプレイサイズが増えるごとに増える。
<li>各ブラウザの独自拡張タグ。詳しくは <a href="https://github.com/joshbuchea/HEAD" target="_blank" rel="nofollow">joshbuchea/HEAD</a> を参照ください。
<li><abbr title="Social networking service">SNS</abbr> 用に <a href="http://ogp.me/" target="_blank" rel="nofollow">Open Graph protocol</a> と <a href="https://dev.twitter.com/cards/getting-started" target="_blank" rel="nofollow">Twitter Card</a>。
<li>検索のリッチリザルト用の <a href="https://json-ld.org/" target="_blank" rel="nofollow">JSON-LD</a>。
<li>Windows 8.1 + モダン IE 11 のライブタイルに関する指定。僕は大好きで Windows 10 でサポートしないのはややショックでした。
</ul>
<p>本記事シリーズではこの内の、ファビコン、タッチアイコン、Web マニフェストに書くアイコン、スプラッシュ画面といった、<code><body></code> の外の画像について纏めます。また調査にあたってのサポートブラウザのポリシーにつては『<a href="/2020/11/graceful-degradation.html">Web文書のグレースフルデグラデーションをムキになってやってみる</a>』を確認ください。
<p><code><head></code> 下に入れるべき内容について詳しくは <a href="https://github.com/joshbuchea/HEAD" target="_blank" rel="nofollow">joshbuchea/HEAD</a> が頼りになります。また HEAD が参照している「UCBrowser_U3_API.doc」の<a href="/2021/04/UCBrowser-U3-API-doc.html">翻訳</a>を当ブログで公開しています。
<a name="1.2"></a>
<h2 id="1.2">僕が採用したタグ</h2>
<h3><code>favicon.ico</code></h3>
<p>次の <code><link></code> に加えて、条件付きコメントと <code>rel="icon"</code> に非対応の IE 10用に javascript が必要です。
<pre class="prettyprint lang-html"><code><!-- Just Microsoft Internet Explorer -->
<!--[if IE]><link rel="shortcut icon" href="icon/multi.ico"><![endif]-->
</code></pre>
<pre class="prettyprint lang-js"><code><script>
if( document.documentMode === 10 ){
document.write( '<link rel="shortcut icon" href="icon/multi.ico">' );
};
</script>
</code></pre>
<h3>PNG アイコン(<code>rel="icon"</code>)、タッチアイコン(<code>rel="apple-touch-icon"</code>)、ウェブマニフェストの <code>"icons"</code></h3>
<p>要素の記述順の背景や、対応ブラウザについては後の記事で。
<h4>PNG アイコン</h4>
<pre class="prettyprint lang-html"><code><!-- Other browsers -->
<link rel="icon" type="image/png" href="icon/032x032.png" sizes="32x32">
<link rel="icon" type="image/png" href="icon/192x192.png" sizes="192x192">
<link rel="icon" type="image/png" href="icon/048x048.png" sizes="48x48">
<link rel="icon" type="image/png" href="icon/096x096.png" sizes="96x96">
<link rel="icon" type="image/png" href="icon/016x016.png" sizes="16x16">
<!-- for iOS 4.2+ -->
<link rel="apple-touch-icon" href="icon/180x180.png" sizes="180x180">
<link rel="apple-touch-icon" href="icon/167x167.png" sizes="167x167">
<link rel="apple-touch-icon" href="icon/152x152.png" sizes="152x152">
<link rel="apple-touch-icon" href="icon/144x144.png" sizes="144x144">
<link rel="apple-touch-icon" href="icon/120x120.png" sizes="120x120">
<link rel="apple-touch-icon" href="icon/114x114.png" sizes="114x114">
<link rel="apple-touch-icon" href="icon/076x076.png" sizes="76x76">
<link rel="apple-touch-icon" href="icon/072x072.png" sizes="72x72">
<link rel="apple-touch-icon" href="icon/060x060.png" sizes="60x60">
<link rel="apple-touch-icon" href="icon/057x057.png" sizes="57x57">
<!-- for iOS 2.0+, AOSP 2.1+ -->
<link rel="apple-touch-icon-precomposed" href="icon/057x057.png">
<!-- for iOS 1.2.2+, AOSP 2.2+ -->
<link rel="apple-touch-icon" href="icon/057x057.png">
</code></pre>
<h4>ウェブマニフェスト</h4>
<pre class="prettyprint lang-js"><code>{
"name" : "/*__APP_TITLE__*/",
"short_name" : "/*__APP_TITLE_SHORT__*/",
"start_url" : "./?a2hs=1",
"display" : "fullscreen",
"theme_color" : "/*__THEME_COLOR__*/",
"background_color" : "/*__BACKGROUND_COLOR__*/",
"description" : "/*__DESCRIPTION__*/",
"icons" : [
{
"src" : "icon/512x512.png",
"sizes" : "512x512",
"type" : "image/png"
},{
"src" : "icon/384x384.png",
"sizes" : "384x384",
"type" : "image/png"
},{
"src" : "icon/256x256.png",
"sizes" : "256x256",
"type" : "image/png"
},{
"src" : "icon/192x192.png",
"sizes" : "192x192",
"type" : "image/png"
},{
"src" : "icon/144x144.png",
"sizes" : "144x144",
"type" : "image/png"
},{
"src" : "icon/096x096.png",
"sizes" : "96x96",
"type" : "image/png"
},{
"src" : "icon/072x072.png",
"sizes" : "72x72",
"type" : "image/png"
},{
"src" : "icon/048x048.png",
"sizes" : "48x48",
"type" : "image/png"
},{
"src" : "icon/036x036.png",
"sizes" : "36x36",
"type" : "image/png"
}
]
}
</code></pre>
<h3>スプラッシュ画面(<code>rel="apple-startup-image"</code>)</h3>
<p>iOS 端末でホームに追加された Web サイトの起動時に表示される全画面画像です。詳しくは後の記事で。
<pre class="prettyprint lang-html"><code><!-- iPhone 1th, 3G, 3GS, iPod touch 1~3th, 320x480 -->
<link rel="apple-touch-startup-image" href="startup-img/320x480.png" media="(device-width: 320px) and (device-height: 480px) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/480x320.png" media="(device-width: 480px) and (device-height: 320px) and (orientation: landscape)">
<!-- iPhone 4, 4S, iPod touch 4th, 640x960 -->
<link rel="apple-touch-startup-image" href="startup-img/640x960.png" media="(device-width: 320px) and (device-height: 480px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/960x640.png" media="(device-width: 480px) and (device-height: 320px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<!-- iPod touch 5~7th, iPhone 5, 5C, 5s, SE 1th, 640x1136 -->
<link rel="apple-touch-startup-image" href="startup-img/640x1136.png" media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/1136x640.png" media="(device-width: 568px) and (device-height: 320px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<!-- iPhone 6, 6s, 7, 8, SE 2th, 750x1334 -->
<link rel="apple-touch-startup-image" href="startup-img/750x1334.png" media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/1334x750.png" media="(device-width: 667px) and (device-height: 375px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<!-- iPad 1, 2, mini 1, 768x1024 -->
<link rel="apple-touch-startup-image" href="startup-img/768x1024.png" media="(device-width: 768px) and (device-height: 1024px) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/1024x768.png" media="(device-width: 1024px) and (device-height: 768px) and (orientation: landscape)">
<!-- iPhone XR, 11, 828x1792 -->
<link rel="apple-touch-startup-image" href="startup-img/828x1792.png" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/1792x828.png" media="(device-width: 896px) and (device-height: 414px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<!-- iPhone 12 mini, 1080x2340 -->
<link rel="apple-touch-startup-image" href="startup-img/1080x2340.png" media="(device-width: 360px) and (device-height: 780px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/2340x1080.png" media="(device-width: 780px) and (device-height: 360px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
<!-- iPhone X, XS, 11 Pro, 1125x2436 -->
<link rel="apple-touch-startup-image" href="startup-img/1125x2436.png" media="(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/2436x1125.png" media="(device-width: 812px) and (device-height: 375px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
<!-- iPhone 12, 12 Pro, 1170x2532 -->
<link rel="apple-touch-startup-image" href="startup-img/1170x2532.png" media="(device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/2532x1170.png" media="(device-width: 844px) and (device-height: 390px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
<!-- iPhone 6 plus, 6s plus, 7 plus, 8 plus, 1242x2208 -->
<link rel="apple-touch-startup-image" href="startup-img/1242x2208.png" media="(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/2208x1242.png" media="(device-width: 736px) and (device-height: 414px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
<!-- iPhone XS Max, 11 Pro Max, 1242x2688 -->
<link rel="apple-touch-startup-image" href="startup-img/1242x2688.png" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/2688x1242.png" media="(device-width: 896px) and (device-height: 414px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
<!-- iPhone 12 Pro Max, 1284x2778 -->
<link rel="apple-touch-startup-image" href="startup-img/1284x2778.png" media="(device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/2778x1284.png" media="(device-width: 926px) and (device-height: 428px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
<!-- iPad 3~6, mini 2~5, iPad Pro 1th "9.7", iPad Air 3, 4, 1536x2048 -->
<link rel="apple-touch-startup-image" href="startup-img/1536x2048.png" media="(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/2048x1536.png" media="(device-width: 1024px) and (device-height: 768px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<!-- iPad 7~8, 1620x2160-->
<link rel="apple-touch-startup-image" href="startup-img/1620x2160.png" media="(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/2160x1620.png" media="(device-width: 1080px) and (device-height: 810px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<!-- iPad Pro 2th "10.5", iPad Air 3, 1668x2224 -->
<link rel="apple-touch-startup-image" href="startup-img/1668x2224.png" media="(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/2224x1668.png" media="(device-width: 1112px) and (device-height: 834px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<!-- iPad Air 4, 1640x2360 -->
<link rel="apple-touch-startup-image" href="startup-img/1640x2360.png" media="(device-width: 820px) and (device-height: 1180px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/2360x1640.png" media="(device-width: 1180px) and (device-height: 820px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<!-- iPad Pro 3~4th "11", 1668x2388 -->
<link rel="apple-touch-startup-image" href="startup-img/1668x2388.png" media="(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/2388x1668.png" media="(device-width: 1194px) and (device-height: 834px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<!-- iPad Pro 1~4th "12.9", 2048x2732 -->
<link rel="apple-touch-startup-image" href="startup-img/2048x2732.png" media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="startup-img/2732x2048.png" media="(device-width: 1366px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
</code></pre>
<h3>この他のアイコン関連</h3>
<p>本記事シリーズでは扱いませんでしたが IE 10~11 用のスタート画面用のアイコン指定と、Mac OSX 用 Safari のタブアイコン指定もお忘れなく。
<pre class="prettyprint lang-html"><code><meta name="msapplication-TileImage" content="icons/png_144.png">
<link rel="mask-icon" color="orange" href="icon/safari-pinned-tab.svg">
</code></pre>
<a name="1.3"></a>
<h2 id="1.3">参考記事</h2>
<p>本記事執筆にあたって参考にした英文記事の一つです。オリジナルは<a href="https://web.archive.org/web/20130916141114/https://www.netmagazine.com/features/create-perfect-favicon" target="_blank" rel="nofollow">インターネットアーカイブに収録</a>されてます。
<blockquote cite="https://web.archive.org/web/20130916141114/https://www.netmagazine.com/features/create-perfect-favicon" title="Create the perfect favicon">
<h1>完璧なファビコンを作成する</h1>
<p>written by jonathantneal, 2013年1月16日
<h2>本日、Five Simple Steps から出版された Jon Hicks の待望の『Icon Handbook』が発売されます。ファビコンの作成に関する独占的な抜粋を提示します</h2>
<p><em>これは、Jon Hicks による『The Icon Handbook』の第3章からの編集された抜粋です。</em>
<p>これまでに他の種類のアイコンを作成したことがない場合でも、これを読んでいるすべての人がいつかファビコンを作成したことは間違いありません。大多数の人にとって、それはおそらく通常の作業です。小さなサイズで pixel-crisp なアートワークと鮮明さを実現する方法を検討できるため、これらは開始するのに理想的な場所です。
<p>「ロゴは旗、署名、護衛、道路標識です。ロゴは(直接)販売されません、それは識別します。」<br>Paul Rand
<p>ファビコン(ショートカットアイコンとも呼ばれます)は、Internet Explorer 5で最初に登場しました。HTML を必要とせずに favicon.ico アイコンを Web サイトのルートに配置すると、アドレスバーとブックマークリストの URL の横に16ピクセルの正方形の画像が表示されます。当初、これにはファビコンのリクエストをカウントすることでサイトがブックマークされた回数を推定するという追加の利点がありましたが、ブラウザがブックマーク以外のファビコンをサポートし始めたため、これは信頼できなくなりました。
<p>ファビコンと、アプリケーションアイコンの章で取り組むアイコンの種類との違いは、ここでは正しいメタファーについての議論がないことです。彼らの目的は、行動を要約したり、言語の壁を克服したりすることではなく、サイトを道標として表現し、そのブランドをブラウザに拡張することです。そのため、ほとんどの場合、サイトのロゴの小さいバージョンになります。幸い、一般的に、アプリケーションアイコンよりも16ピクセルでロゴを再作成する方が簡単です。
<p>最近でははるかに大きなサイズも使用できますが、アイコンのデザインに慣れていない場合は、16ピクセルバージョンが不可欠であり、開始するのに理想的な場所です。それらを作成することで習得したスキルは、後で検討する他のタイプの基礎として役立ちます。このサイズで透明度を達成できれば、残りは所定の位置に収まります!
<p>この本で説明されている他の種類のアイコンを作成したことがない場合でも、これを読んでいるすべての人がいつかファビコンを作成し、大多数の人にとっては通常の作業であることは間違いありません。
<h2>始める前に</h2>
<p>アイコンの作成を開始する前に、アイコンの作成方法と展開方法に影響を与えるため、アイコンの使用方法と使用場所を知る必要があります。以下のサブセクションでは、さまざまな考慮事項について説明します。
<ul>
<li>コンテキストは何ですか?
<li>どのサイズが必要ですか?
<li>どのフォーマットが必要ですか?
</ul>
<h3>コンテキストは何ですか?</h3>
<p>ファビコンはさまざまな背景に表示される可能性があるため、すべてに適合する最適なオプションを取得するには、透明度を使用する必要があります。常に白いアドレスバーの背景に表示されるとは限りません。Windows Aero ガラス、灰色の Mac OS X UI、または暗いブラウザテーマに表示される場合があります。 Firefox 4は、アドレスバーのファビコンに灰色のボタンの背景も追加します。少し大きく設定されているため、常にファビコンに隣接します。
<h3>どのサイズが必要ですか?</h3>
<p>考えられるすべての用途にファビコンを作成する場合、作成する必要のあるサイズは次のとおりです。
<dl>
<dt>16px<dd>すべてのブラウザで一般的に使用するために、アドレスバー、タブ、またはブックマークビューに表示できます。
<dt>24px<dd>Internet Explorer 9で固定されたサイト
<dt>32px<dd>Internet Explorer の新しいタブページ、Windows 7以降のタスクバーボタン、Safari の[後で読む]サイドバー
<dt>57px<dd>標準の iOS ホーム画面(iPod Touch、iPhone 第1世代から 3G)
<dt>72px<dd>iPad のホーム画面アイコン
<dt>96px<dd>GoogleTV プラットフォームで使用されるファビコン
<dt>114px<dd>iPhone 4+のホーム画面アイコン(Retina ディスプレイの標準サイズの2倍)
<dt>128px<dd>Chrome ウェブストア
<dt>195px<dd>Opera スピードダイヤル
</dl>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-VOTDtnthc3c/YIULBvMT_6I/AAAAAAAASjo/t9U0lMwDMBInsrXzQoenAVib2maCBnoqACLcBGAsYHQ/195px%2BOpera%2BSpeed%2BDial.png"><img alt="" src="https://1.bp.blogspot.com/-VOTDtnthc3c/YIULBvMT_6I/AAAAAAAASjo/t9U0lMwDMBInsrXzQoenAVib2maCBnoqACLcBGAsYHQ/s160/195px%2BOpera%2BSpeed%2BDial.png"></a>
<figcaption>Opera スピードダイヤル</figcaption>
</figure>
</span>
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-ErmDdw32D6I/YIULmmnhCiI/AAAAAAAASjw/-OJmxYt3g84bYsFL5_TBFrgIdj4ZoMANgCLcBGAsYHQ/128px%2BChrome%2BWeb%2BStore.png"><img alt="" src="https://1.bp.blogspot.com/-ErmDdw32D6I/YIULmmnhCiI/AAAAAAAASjw/-OJmxYt3g84bYsFL5_TBFrgIdj4ZoMANgCLcBGAsYHQ/s160/128px%2BChrome%2BWeb%2BStore.png"></a>
<figcaption>Chrome ウェブストア</figcaption>
</figure>
</span>
</div>
<p>本当にこれらすべてを供給する必要がありますか?いつものように、それは文脈に依存します。 Mac および iOS ソフトウェア会社のサイトは、さまざまな iPad および iPhone 固有のアイコンの恩恵を受けますが、Internet Explorer でのみ表示されるイントラネットサイトは、マルチ解像度の ICO ファイルを使用した方がよいでしょう。モバイルとデスクトップで表示するように設計された Web アプリは、これらすべてのサイズの作成に時間を費やすことでメリットが得られます。
<p>50%縮小して16pxにできる32pxアイコンを使用することは可能ですが(たとえば、2pxストロークを使用して1pxにきれいに縮小することにより)、これはブラウザに依存して拡大縮小し、代わりにトリミングする場合があります。また、ファイルが大きくなるため、ファビコンファイルはできるだけ小さくしたいと考えています。
<p>ただし、本当に良い妥協案は、16pxのアイコンと128pxなどの1つの大きなサイズのアイコンを提供することです。これは、Chrome ウェブストアや Opera のスピードダイヤルなどの大規模な用途に最適です。57pxにサイズ変更された128pxの画像は、特注の最適化された57pxの画像ほど見栄えがよくありませんが(均等に縮小されないため –44.5%)、ニーズには十分かもしれません。実際、これはまさに Apple が行っていることです。ファビコン以外のアイコンをもう1つだけ提供します。これは、129pxのサイズの <code>apple-touch-icon.png</code> アイコンです。Apple にとって何が十分か...
<p>何をするにしても、ブラウザのデフォルトアイコンを回避するには、少なくとも16pxのアイコンが不可欠です。 Safari は魅力的な青い地球を表示しますが、ほとんどの場合、空白のドキュメントアイコンが表示されます。
<p>基本的な16pxのファビコンを含めないと、ページ自体を超えてサイトのブランドを拡張する機会が失われます。サーバーが最初のリクエストごとに404エラーを生成するため、favicon.ico ファイルが欠落していると、トラフィックの多いサイトでも問題が発生します。 Firefox は、ファビコンが欠落しているサイトを記憶し、それらを再要求しませんが、これを行う唯一のブラウザです。
<h3>どのようなフォーマットが必要ですか?</h3>
<p>Windows ICO 形式がサポートされている唯一のファイルタイプであった初期の頃は、ファビコンを16×16 GIF として保存し、名前を変更して <code>.ico</code> ファイル拡張子を付けるという、少し時間を節約するトリックがありました。それはハックでしたが、うまくいきました!ICO ファイルを作成するためのツールがオンラインでより簡単かつ自由に利用できるようになったため、現在、この方法を使用する必要はなく、使用すべきではありません。さらに、ファビコンの使用では他の形式がサポートされるようになりましたが、検討する価値のある形式は基本的に2つだけです。
<ul>
<li>ICO ファイルは今でも最も広くサポートされています。 PNG とは異なり、複数の解像度とビット深度を含めることができます。これは Windows で非常に便利です。Internet Explorer は、Windows 7タスクバーの32ピクセルアイコンなど、さまざまなサイズのファビコンを使用します。これらを提供する唯一の方法は ICO です。 また、<code><link></code> 要素を使用せずに検出される唯一の形式です。
<li>PNG の方が便利ですが、作成に特別なツールを必要としないため、アルファ透明度をサポートし、ファイルサイズを可能な限り小さくします。その唯一の欠点は、Internet Explorer がそれをサポートしていないことです(ICO のみを受け入れます)。
</ul>
<p>他のオプションについて:
<ul>
<li>GIF とアニメーション GIF には、非常に古いブラウザのサポート以外の利点はありません。
<li>画像が写真であっても、JPG が選択される可能性はほとんどありません。 それは PNG の鮮明さを欠いており、そのような小さなサイズでのより良いブレンドからの利益は見られません。
<li>より多くのブラウザがファビコンの使用のために SVG をサポートしていれば、SVG は優れていますが、現在は Opera のみがサポートしています。
<li>Firefox と Opera でサポートされている PNG の生意気な小さなサブフォーマットである APNG(アニメーション PNG)もありますが、その有用性には疑問があります。アニメーション化されたファビコンは、イライラして困窮しているように見えます!
</ul>
<h2>16ピクセルで描画</h2>
<p>これで、ファビコンを作成するための背景情報と準備について見てきました。手を汚して、いくつかのアイコンを描き始めましょう。
<h3>ツール</h3>
<div class="box"><a href="https://1.bp.blogspot.com/-l2l8roauY-o/YIUMNOyFwAI/AAAAAAAASj4/Q6Gl0DGronMCeVZI7U2dOgfbfJPGCUjrwCLcBGAsYHQ/s962/3_4%2Bsharp%2Band%2Bfuzzy%2Bpixels-1.png"><img alt="" src="https://1.bp.blogspot.com/-l2l8roauY-o/YIUMNOyFwAI/AAAAAAAASj4/Q6Gl0DGronMCeVZI7U2dOgfbfJPGCUjrwCLcBGAsYHQ/s160/3_4%2Bsharp%2Band%2Bfuzzy%2Bpixels-1.png"></a>
<p>ツールは非常に個人的な選択であるため、このハンドブックでは、使用するグラフィックエディタを想定していません。私にとってうまくいくことは、必ずしもあなたにとってうまくいくとは限りません!ただし、どのアプリを使用する場合でも、高解像度をスムーズにするだけでなく、ピクセルプレビューを使用してベクターアートワークを作成できる必要があります。また、ピクセルグリッドを表示して、アイコンの描画と計画を簡単に行えるようにすると便利です。特に16pxのアイコンの場合、途中でアイコンがぼやけて見えるため、直線のエッジがグリッド内に保持されていることを確認する必要があります。
</div>
<h2>ケーススタディ:Five Details のファビコン</h2>
<div class="box"><a href="https://1.bp.blogspot.com/-QxBAIiXqx4M/YIUMec5l2CI/AAAAAAAASkA/o5PvHKpImgYconsLITO-D98_8eiSfj98gCLcBGAsYHQ/3_13%2BFavicon%2Bon%2Bwhite.png"><img alt="" src="https://1.bp.blogspot.com/-QxBAIiXqx4M/YIUMec5l2CI/AAAAAAAASkA/o5PvHKpImgYconsLITO-D98_8eiSfj98gCLcBGAsYHQ/s160/3_13%2BFavicon%2Bon%2Bwhite.png"/></a>
<p>Five Details は、Mac, iPhone, iPad用のソフトウェアを設計および開発しています。Flow と Seamless のユーザーが10万人を超え、Apple Design Award を受賞したこの会社のために、Hicksdesign は Five Details のロゴ、ブランド、ウェブサイトを作成しました。
<p>ワークフローの例では、元のベクターファイルを取得し、そこから16pxのファビコンと、ウェブサイトの他のサイズを作成します。Five Details は Mac ソフトウェアに焦点を当てているため、このコンテキストは Mac デスクトップブラウザと iOS モバイルデバイスに重点を置くことを意味します。したがって、時間をかけて、最適化された Apple Touch アイコンの全範囲も作成されていることを確認してください。iPhone と iPod Touch の場合は57ピクセル、iPad の場合は72ピクセル、iPhone4 の Retina ディスプレイの場合は114ピクセルです。
</div>
<p>Illustrator では、アイコンサイズごとにアートボードを設定しました。それぞれに個別のファイルを用意するよりも、各サイズを並べて表示できる方が好きです。アートボードには、goodies パックに含まれているスクリプトを使用してエクスポートするときに使用されるため、目的のファイル名(「favicon」や「apple-touch-icon-114x114-precomposed」など)で名前が付けられます。
<p>まず、アートワークのサイズを16ピクセルに変更し、何が得られるかを確認します。オリジナルが16のきちんとした倍数である場合は、良いスタートを切ることができますが、おそらくピクセルアート(各ピクセルを個別に描画する)としても、微調整するか、最初から再描画する必要があります。明確にするために。ただし、それは思ったほど難しくも時間もかかりません。
<p>画像に背景を含める必要がある場合([Five Details]アイコンのように)、必要なパディングにより、実際のロゴのサイズがさらに小さくなります。アイコンには背景は必要ありませんが、さまざまな環境でアイコンのコントラストを制御するのに役立つ場合があります。シンプルな灰色のファビコンは、白いアドレスバー(右下)では見栄えがよく微妙に見えますが、Firefox などの Mac ブラウザの灰色のタブに表示すると簡単に失われます(右上)。
<p>これに対する2つの解決策は、(灰色ではなく)透明な黒を使用して、背景に比例して暗くするか、すべての状況に合うようにファビコンに色付きの背景を追加することです。この場合、明るい灰色のボックスの背景の上に、両側に3ピクセルのパディングがあり、実際のロゴサイズがわずか10ピクセルに縮小されるため、強度が増すと感じました。
<div class="box"><a href="https://1.bp.blogspot.com/-XzOtwWlT_mY/YIT1crANiZI/AAAAAAAASh4/hqseDtblfxERSLZSbpICNr3FlNCAhfoaQCLcBGAsYHQ/3_9%2BReduced%2Bto%2B10px.png"><img alt="" src="https://1.bp.blogspot.com/-XzOtwWlT_mY/YIT1crANiZI/AAAAAAAASh4/hqseDtblfxERSLZSbpICNr3FlNCAhfoaQCLcBGAsYHQ/s160/3_9%2BReduced%2Bto%2B10px.png"></a>
</div>
<p>残念ながら、エッジは完全なピクセルにきちんと収まらず、ロゴの2つの部分の間のギャップはほぼ閉じられています。場合によっては、パスのアンカーポイントを微調整して、パスがピクセルグリッド上に適切に配置されるようにすることができます。 選択したグラフィックエディタがピクセルスナップ(編集中のパスをピクセルグリッドにスナップする)をサポートしている場合は、さまざまなタスクでこれをオンとオフに切り替える必要があることがわかります。直線エッジをスナップする場合は非常に便利ですが、カーブ(ロゴの右側など)をオフにすると、編集が簡単になります。曲線だけでなく、シャドウなどの要素のエッジを意図的に柔らかくするために、パスをピクセルの中間に配置したい場合があります。
<p>ただし、この場合、単純な形状を最初からベクトルで再作成する方が簡単です。これにより、少なくとも、再現に役立つ適切な比率が得られます。縮小したアートワークを別々のレイヤーに配置してロックすると、ガイドとして使用し、その上で作業することができます。
<div class="box"><a href="https://1.bp.blogspot.com/-W5sPwn7_C8s/YIT2dZmCyxI/AAAAAAAASiA/uFlUwe6SliU2dXNrullPeUMHoDMtJKwzQCLcBGAsYHQ/3_10%2Bredrawing%2Bon%2Btop.png"><img alt="" src="https://1.bp.blogspot.com/-W5sPwn7_C8s/YIT2dZmCyxI/AAAAAAAASiA/uFlUwe6SliU2dXNrullPeUMHoDMtJKwzQCLcBGAsYHQ/s160/3_10%2Bredrawing%2Bon%2Btop.png"></a></div>
<p>それを機能させるには、ロゴの比率にある程度の自由を持たなければならないかもしれませんが、16pxは非常に寛容であり、鮮明なアートワークは精度よりも見栄えがします。それでも形状が機能しない場合は、鉛筆などのビットマップツールを使用するか、できればベクトル長方形を使用して、単一ピクセルで再描画し、単一ピクセルの不透明度を変更して独自のアンチエイリアシングを作成できます(この場合)。必要な場所に1pxの正方形のベクトル長方形)
<p>滑らかなエッジ:
<div class="box"><a href="https://1.bp.blogspot.com/-BC61bYipHnY/YIT3A960CrI/AAAAAAAASiI/wMfEDLkupKcH4d58FDH1cFbx19gSgcxUQCLcBGAsYHQ/3_11%2BSingle%2BPixel%2BDrawing%2B%2528with%2Blabels%2Bfor%2Breference%2529.png"><img alt="" src="https://1.bp.blogspot.com/-BC61bYipHnY/YIT3A960CrI/AAAAAAAASiI/wMfEDLkupKcH4d58FDH1cFbx19gSgcxUQCLcBGAsYHQ/s160/3_11%2BSingle%2BPixel%2BDrawing%2B%2528with%2Blabels%2Bfor%2Breference%2529.png"></a></div>
<p>これにより、曲線の滑らかさを非常に細かく制御できますが、明らかにかなり面倒です。 効果が実際のサイズでどのように見えるかを確認するには、頻繁にズームアウトする必要があります。 これで、くっきりとしたシルエットができました。次に、内側のシャドウや下端の白いハイライトなど、他の微妙な要素を追加して、エッジを視覚的にシャープにすることができます。
<div class="box"><a href="https://1.bp.blogspot.com/-dwMmxTOlkbo/YIT3jR2SVSI/AAAAAAAASiQ/uryydCueu8Y3d8NAXOjGwXBai-61ubtIACLcBGAsYHQ/3_12%2BCompleted%2BFavicon.png"><img alt="" src="https://1.bp.blogspot.com/-dwMmxTOlkbo/YIT3jR2SVSI/AAAAAAAASiQ/uryydCueu8Y3d8NAXOjGwXBai-61ubtIACLcBGAsYHQ/s160/3_12%2BCompleted%2BFavicon.png"></a></div>
<p>内側のハイライトを追加することで境界線が強調されています。50%の白いストロークはコントラストを提供するのに十分であり、エッジをより鮮明に感じさせます。 Illustrator や Opacity などの一部のアプリケーションでは、同じベクターオブジェクトに複数のストロークを追加できます。そうでない場合は、それに合わせて角の丸い半径を小さくする必要があります。 たとえば、外側の境界線の半径が4pxの場合、正しく表示するには、内側のハイライトの半径を3pxにする必要があります。
<p>ICO ファイルと PNG ファイルの両方が透明性をサポートしているため、透明性は検討する価値があります。このファビコンが常に白い背景で表示されると仮定すると、Five Details ファビコンに明るい灰色の境界線を指定することを意味します。
<div class="box"><a href="https://1.bp.blogspot.com/-K2KR1jbS2mU/YIT4SBl-EcI/AAAAAAAASiY/XSxURhIEHygCPwnCV40uGeydck7KPmewACLcBGAsYHQ/Comparison-of-addressbar-and-tab.jpg"><img alt="" src="https://1.bp.blogspot.com/-K2KR1jbS2mU/YIT4SBl-EcI/AAAAAAAASiY/XSxURhIEHygCPwnCV40uGeydck7KPmewACLcBGAsYHQ/s160/Comparison-of-addressbar-and-tab.jpg"/></a></div>
<p>ボーダーの明るさは、それが主要な要素であるロゴからあまりにも気を散らさないようにします。ただし、これを常に白い背景で表示するとは限りません。他の背景で表示すると、境界線がひどく震えます。
<p>20%の灰色の代わりに、20%の不透明度で黒を使用すると、境界線が背景に溶け込み、より快適に座ることができます。
<h3>その他のファビコンの落とし穴</h3>
<p>これでファビコンアートワークは完成しましたが、避けるべき他の落とし穴があります。アイコンの視覚的な重みを減らし、アンチエイリアス処理されたピクセルを増やす必要があり、エッジがくっきりと見えなくなるため、遠近法を再現しようとしないことをお勧めします。Reeder アプリの Web サイトが、ファビコンにサイドオンパースペクティブを使用するようにアイソメボックスのロゴを変更する方法に注目してください。明確でありながら、Reeder アプリとして認識されています。
<div class="box"><a href="https://1.bp.blogspot.com/-lr717lbKkrg/YIT5YVGkaVI/AAAAAAAASig/kkAud3fvdIkhiNVkBdM8clh80kc_air-gCPcBGAYYCw/3_16%2BReeder%2BFavicon%2Bin%2Bsitu.png"><img alt="" src="https://1.bp.blogspot.com/-lr717lbKkrg/YIT5YVGkaVI/AAAAAAAASig/kkAud3fvdIkhiNVkBdM8clh80kc_air-gCPcBGAYYCw/s160/3_16%2BReeder%2BFavicon%2Bin%2Bsitu.png"/></a>
<a href="https://1.bp.blogspot.com/-xajhvqUQGgg/YIT5ZZYIY3I/AAAAAAAASik/XHySZMc_9VQXPEd2lUe0VBmtL5C5yCqBACPcBGAYYCw/3_16%2BReeder%2BLogo.jpg"><img alt="" src="https://1.bp.blogspot.com/-xajhvqUQGgg/YIT5ZZYIY3I/AAAAAAAASik/XHySZMc_9VQXPEd2lUe0VBmtL5C5yCqBACPcBGAYYCw/s160/3_16%2BReeder%2BLogo.jpg"/></a></div>
<div class="box"><a href="https://1.bp.blogspot.com/-5QjlWt7eMUw/YIT5aHTN55I/AAAAAAAASio/eS07JFTD_YIZBcwcbsMHdFg6aaJx4-oegCLcBGAsYHQ/chimp.jpg"><img alt="" src="https://1.bp.blogspot.com/-5QjlWt7eMUw/YIT5aHTN55I/AAAAAAAASio/eS07JFTD_YIZBcwcbsMHdFg6aaJx4-oegCLcBGAsYHQ/s160/chimp.jpg"></a>
<p>ロゴの比率が正方形ではなく16pxで再現するには複雑すぎる場合もあります。これを回避するには、全体を表示するのではなく、ロゴの強力な要素を選択します。Mailchimp は、チンパンジー全体やロゴタイプではなく、チンパンジーの頭のフレディに焦点を当ててこれを行います。
</div>
<div class="box"><a href="https://1.bp.blogspot.com/-U1hcxK_XjtY/YIT6mQZ8WlI/AAAAAAAASi4/gR2yG0H6GNQVd0oTtJMPufT96WPFILY9ACLcBGAsYHQ/bbc.jpg"><img alt="" src="https://1.bp.blogspot.com/-U1hcxK_XjtY/YIT6mQZ8WlI/AAAAAAAASi4/gR2yG0H6GNQVd0oTtJMPufT96WPFILY9ACLcBGAsYHQ/s160/bbc.jpg"/></a>
<p>ただし、常に例外があり、最善の努力にもかかわらず、ロゴと制限されたサイズは最初からあなたに反対です。BBC は、ファビコンに簡単に拡大縮小できないロゴの良い例ですが、ブランドを失うことなく、選択した要素に縮小することもできません。 上部と下部の空白は、他のファビコンと比較して視覚的な重みを減らし、それによってその重要性を薄めます。
</div>
<p>ただし、この特定のファビコンは、複数の ICO ファイルに関する別の潜在的な問題を浮き彫りにします。 favicon.ico ファイルには16pxと32pxの両方の最適化されたアイコンが含まれていますが、Safari や Chrome などの Webkit ブラウザーは32pxアイコンのみを表示し、16pxに縮小して、認識できないマッシュを作成します。
<figure>
<img alt="" src="https://1.bp.blogspot.com/--JRMJ-pRTSM/YIT7c-pgQTI/AAAAAAAASjA/HqOLg-fcR7E3yAcXYkWYRL2JGuqXVzp-QCLcBGAsYHQ/Mushy-BBC-Favicon-in-Safari.jpg">
<figcaption><p>ただし、Safari は32pxバージョンを16pxアイコンとして表示しようとします。</figcaption>
</figure>
<figure>
<img alt="" src="https://1.bp.blogspot.com/-xrUFvaL7N1A/YIT7lG1DdxI/AAAAAAAASjE/y8KysB3CVAQ9rvprihz0WZqPogAM2Bl-gCLcBGAsYHQ/Crisp-BBC-Favicon-in-Firefox.jpg">
<figcaption><p>Firefox は正しいサイズのファビコンが表示される</figcaption>
</figure>
<p>これを回避する唯一の方法は、16pxの PNG ファビコンも追加し、HTML に <code><link></code> 要素を追加することです。
<h2>エクスポート</h2>
<p>PNG を作成するだけの場合、この段階は簡単ですが、ICO の作成にはさらにいくつかの手順が必要です。 PNG を取得して ICO を作成する無料のオンラインツールが多数あります(付録を参照)。または、Photoshop から直接エクスポートすることもできます。
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-ICgRu6_F3fQ/YIT9VELU3tI/AAAAAAAASjQ/Jjj6yoG-AQUK99zEpusi-gs_p5DtmKr0QCLcBGAsYHQ/Iconbuilder-Windows.jpg"><img alt="" src="https://1.bp.blogspot.com/-ICgRu6_F3fQ/YIT9VELU3tI/AAAAAAAASjQ/Jjj6yoG-AQUK99zEpusi-gs_p5DtmKr0QCLcBGAsYHQ/s160/Iconbuilder-Windows.jpg"></a>
<figcaption>Iconbuilder Windows テンプレートには、アプリケーションアイコンに必要なすべてのサイズが付属していますが、これらを削除して、16pxと(オプションで)32pxを使用することができます。</figcaption>
</figure>
</span>
<p>ただし、Windows 7がタスクバーに使用する32pxなど、複数の解像度で ICO を作成する場合は、Photoshop や Fireworks で使用する Iconfactory のプラグインである Iconbuilder などのより専門的なソフトウェアが必要になります。Iconbuilder には、画像の Windows のように、アートワークを配置する準備ができたテンプレートが付属しています。
<p>アイコンレイヤーの正しいボックスにすべてのアートワークが表示されたら、(フィルターを介して)Iconbuilder に移動し、Windows プリセットを選択できます。 [ビルド]を押して、プレビューウィンドウで各サイズが正しく表示されることを確認します。
</div>
<div class="box"><a href="https://1.bp.blogspot.com/-5j8Ri6mSP6A/YIT-oIOuKOI/AAAAAAAASjY/OxdgBcW_UVMVJkTxtaSgt4iPXGns-dmpwCLcBGAsYHQ/3_21%2BIconbuilder%2BWindow.png"><img alt="" src="https://1.bp.blogspot.com/-5j8Ri6mSP6A/YIT-oIOuKOI/AAAAAAAASjY/OxdgBcW_UVMVJkTxtaSgt4iPXGns-dmpwCLcBGAsYHQ/s160/3_21%2BIconbuilder%2BWindow.png"></a>
<p>不要なサイズや色深度は、サイドバーで削除できます。すべてが良さそうな場合は、ICO として保存できます。Iconbuilder は、解像度ごとの PNG のセットなど、他の形式で同時にエクスポートすることもできます。これは非常に便利です。
</div>
<h2>実装</h2>
<p>ICO 以外の形式の場合、各ページの <code><head></code> にある <code><link></code> 要素を使用して、適切な <code>rel</code> 属性と <code><type></code> 属性を使用してそれを指す必要があります。
<pre class="prettyprint lang-html"><code><link rel="icon" type="image/png" href="/pathto/favicon.png" />
</code></pre>
<p>これにより、Tumblr や Blogger など、ホストしていないサイトのファビコンを変更することもできます。ファビコンに favicon.ico という名前を付けたり、サイトやアプリケーションのルートに保持したりする必要はありませんが、必ず <code><link></code> 要素を使用してください。そうしないと、ブラウザが複数のリクエストを送信して検索を試みます。
<h2>他のタイプのファビコンを作成する</h2>
<p>ファビコンは最後の最後まで残される傾向があるため、リストに大きなサイズを作成する時間はないと感じるかもしれません。ただし、ファビコンを大きくすることでメリットを得るプラットフォームが増えているため、少なくとももう1つ追加することを検討する価値があります。このセクションでは、16ピクセルのファビコンを超える方法について説明し、Five Details の例のケーススタディ用に拡張されたアイコンセットを完成させます。
<h3>Apple タッチアイコン</h3>
<p>最初の iPhone 以来、iOS(iPhone / iPod / iPad オペレーティングシステムが知られるようになった)は、サイトがホーム画面に追加されるときに使用されるより大きなファビコンである Apple タッチアイコンをサポートしてきました。
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-ue-QilXOYKU/YIUBEayq-kI/AAAAAAAASjg/F-j6ufRw3lcQNVDP2cta2Fue6x1Jk82cgCLcBGAsYHQ/apple.jpg"><img alt="" src="https://1.bp.blogspot.com/-ue-QilXOYKU/YIUBEayq-kI/AAAAAAAASjg/F-j6ufRw3lcQNVDP2cta2Fue6x1Jk82cgCLcBGAsYHQ/s160/apple.jpg"/></a>
<figcaption>Apple タッチアイコン、デフォルト(左)および合成済み(右)で光沢オーバーレイを防止</figcaption>
</figure>
</span>
<p>サイトに1つを指定しない場合、iOS は代わりにページの縮小スクリーンショットを使用するだけであり、これはほとんど望ましくありません。
<p>favicon.ico ファイルの場合と同様に、<code>apple-touch-icon.png</code> という名前のファイルをサイトのルートに追加できます。iOSは、<code><link></code> 要素を介した参照を必要とせずにファイルを検出します。また、<code>apple-touch-icon-precomposed.png</code> という名前のアイコンをルートに追加することもできます。そうすれば、iOS は光沢オーバーレイを追加せずにそれを使用し、より多くの制御を可能にします。
</div>
<p>iOSは、最初にデバイスに適したサイズのアイコンも探します。 iPad のモバイル Safari は、次のような名前のアイコンを探します。
<pre class="aa"><code>apple-touch-icon-72x72-precomposed.png
apple-touch-icon-72x72.png</code></pre>
<p>時間があれば、これらのアイコンを提供する必要があります。
<p>したがって、追加の HTML を使用せずに、さまざまな iOS デバイスにさまざまなサイズのアイコンを指定できます。 Android OS(2.1以降)はこれをサポートしていませんが、<code><link></code> 要素を使用してそれらを指すと、合成済みの Apple タッチアイコンを利用できます。
<pre class="prettyprint lang-html"><code><link rel="apple-touch-icon-precomposed" href="apple-touch-icon-precomposed.png">
</code></pre>
<p>Android 2.2以降は、合成済みだけでなく、すべての Apple タッチアイコンをサポートしています。
<p>ここでの <code>rel</code> 属性の値は Apple 独自のものですが、他のすべての人はアイコンのみを使用します。<code>sizes</code> 属性と並行して、iPad および iPhone4 の Retina ディスプレイに他のサイズを指定することもできます。
<pre class="prettyprint lang-html"><code><!-- For iPhone 4 Retina display: -->
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="apple-touch-icon- 114x114-precomposed.png”>
<!-- For iPad: -->
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="apple-touch-icon- 72x72-precomposed.png”></code></pre>
<p>アイコンは最初に最も大きく表示されるため、バージョン4.2より前の iOS(<code>sizes</code> 属性をサポートしていません)は正しいアイコンを取得します。Android 以外にも、Apple タッチアイコンは iPad の Reeder などのアプリでも使用されています。
<h2>Opera スピードダイヤル</h2>
<p>Apple タッチアイコンの使用をサポートするアプリの別の例は、Opera ブラウザのスピードダイヤル機能です。Opera は、ユーザーが新しいタブを開いたときに、ユーザーのお気に入りの Web サイトのサムネイルを表示する最初のブラウザーでした(デフォルトでは9つですが、設定を変更してさらに表示することができます)。
<p>バージョン11では、これがさらに拡張され、Web サイトの所有者は、<code><link></code> タグとファイル名を使用して、最小114×114pxから最大256×160pxまでの任意のサイズのアイコンを指定できるようになりました(横向きの形状を使用)。
<pre class="prettyprint lang-html"><code><!-- Opera speed dial icon -->
<link rel="icon" type="image/png" href="195x195image.png"></code></pre>
<p>繰り返しになりますが、これはサイトのサムネイルよりも望ましい場合があり、見事に見えます。最後に、テストするときは、スピードダイヤルを右クリックし、[再読み込み]を選択して、Opera に最新バージョンを取得できることを知っておく価値があります。常に白い枠線で表示され、ウィンドウサイズとスピードダイヤルの数によっては、アイコン自体が常にフルサイズで表示されるとは限りません。
<h2>大きなアイコンを描く</h2>
<p>Illustrator のアートボードに戻り、最大のものから始めて、114pxのアイコンを作成します。これは、iPhone 4の Retina ディスプレイの半分のサイズで表示されます。これは、元の iPhone 画面の2倍の解像度ですが、物理的な寸法は同じです。したがって、ストロークを画面上で1ピクセルとして表示する場合は、2ピクセルとして描画する必要があります。ただし、1pxは引き続き表示されるため、状況によっては線の太さを薄くすることをお勧めします。または、Photoshop で作業している場合は、Photoshop を1pxに保ち、ストロークカラーの50%の内側の輝きを追加して、妥協点を見つけることができます。
<p>確認する唯一の方法は、デバイスでテストすることです。これを簡単にテストするには、iOS アプリのレビューをお勧めしますが、画像のキャンバスサイズを640×960pxに増やし、組み込みの写真アプリを介して iPhone にインポートすることでもテストできます。
<p>アートワークの透明な領域は黒く表示されることにも注意してください(したがって、カスタム iOS の背景は透けて見えません)。これらは iOS によって追加されるため、アートワークに丸みを帯びた角を含めないでください。ただし、コーナーの半径とそれらがコーナーにどのように影響するかを知っておくと役立つ場合があります。さまざまなサイズについては、付録のアイコン参照チャートを参照してください。ダウンロード可能なパックの iOS アイコンテンプレートを参照して、角が丸く、光沢のあるオーバーレイでアイコンをプレビューしてください。
<p>このアートワークは、50%にサイズ変更して、57pxのアートワークのベースとして使用できます。計算が正しければ、これを最適化する必要はなく、ピクセルグリッドに正確に当てはまるはずです。伝統的に、アイコンのサイズは互いにきちんと2倍になっています:16px→32px(×2)→64px(×2)など。これは、72pxの iPad アイコンには当てはまりません。繰り返しになりますが、最良の結果を得るには、最大サイズを使用し、これをサイズ変更して最適化します。その逆ではありません。
<p>プロセスのこの部分は、さまざまな OS のアプリケーションアイコンを作成する部分と似ています。これについては、第7章で詳しく説明します。
<p>最後に、各アートボードを PNG としてエクスポートするには、goodies パックで提供されているスクリプトを使用します。これで、サイトのルートに4つの正しい名前とサイズの PNG ファイルができました。
<h2>概要</h2>
<p>最低限、デフォルトのアイコンを使用するためにブラウザに任せるのではなく、常に16pxの favicon.ico ファイルを Web サイトに含める必要があります。 見た目が良いだけでなく、ブランディングも強化され、ICO 形式に固執することで、Internet Explorer がアイコンを利用できるようになります。
<p>16pxファビコンが含まれていないということは、ブラウザのデフォルトが代わりにサイトに関連付けられていることを意味し、HTTP リクエストが増加します。これは、トラフィックの多いサイトで増幅される問題です。
<p>この章で提案されているすべてのアイコンサイズを作成する必要はないかもしれませんが、128pxなどの大きなバージョンのファビコンも作成する価値があります。ファビコンのサイズを変更して、iPhone 4などのさまざまなデバイスにアイコンを提供することもできます。 Chrome ウェブストアや Opera のスピードダイヤルなどの適切な用途として。
</blockquote>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-46062947975677756972021-04-25T22:52:00.009+09:002021-05-14T17:04:50.461+09:00Webブラウザの動的Audioサポートの下限バージョンを探る<p>DHTML が登場し <strong>Web ブラウザがゲームのプラットフォームになる</strong>事が知られてからも、ブラウザ側でサウンドを動的に生成する API の提供は遅れました。
<p>mp3 などの静的なオーディオファイルの再生ではなく、javascript 等でインタラクティブにサウンドコンテンツを生成できたら、ブラウザはゲームのプラットフォームとして一層魅力的になります。また一般的に、オーディオファイルに比べて、オーディオを生成するコードの方がファイルサイズが小さい点も Web 配信ではとても有利です。
<p>WebAudio API の登場によってこの不満は完全に解消されますが、API をサポートしないブラウザでもプラグインを利用したり、ハック的に動的オーディオを実現している先例があります。
<p>これらの手法を表にまとめて、チップチューンプレイヤ等に使用できるブラウザの下限を探ってみます。
<p>本記事はバージョンのあたりを付けるに留め、検証環境を用意しての実装はいずれまた頑張ります。
<table>
<caption>デスクトップ用ブラウザ</caption>
<thead>
<tr>
<th>ブラウザ<th><code>WebAudio</code><th><code>mozWriteAudio</code>(*1)<th>HTMLAudio(*3)<th><a href="https://internet.watch.impress.co.jp/cda/news/2008/10/15/21187.html" target="_blank" rel="nofollow">Flash 10</a>~<th><a href="https://www.adobe.com/support/documentation/en/flashplayer/9/releasenotes.html" target="_blank" rel="nofollow">Flash 9</a>(*2)
<tbody>
<tr>
<th>IE, Edge<td>12<td><td>(*4)<td>6<td>5
<tr>
<th>Firefox<td>23(25)<td>4~27<td>3.5<td>Gecko 1.8.1<td>Gecko 1.7.5
<tr>
<th>Presto Opera<td><td><td>11<td>9.5<td>?
<tr>
<th>Chrome<td>10(14)<td><td>8<td>1?<td>1?
<tr>
<th>Safari<td>6<td><td>4<td>3<td>1.3
</table>
<table>
<caption>スマートデバイス用ブラウザ</caption>
<thead>
<tr>
<th>ブラウザ<th><code>WebAudio</code><th><code>mozWriteAudio</code>(*1)<th>HTMLAudio(*3)<th><a href="https://internet.watch.impress.co.jp/cda/news/2008/10/15/21187.html" target="_blank" rel="nofollow">Flash 10</a>~<th><a href="https://www.adobe.com/support/documentation/en/flashplayer/9/releasenotes.html" target="_blank" rel="nofollow">Flash 9</a>(*2)
<tbody>
<tr>
<th>Safari Mobile<td>6.1<td><td>4<td><td>
<tr>
<th>IE Mobile, Edge Mobile, Modern IE<td>12?<td><td>10?(*4)<td><td>
<tr>
<th>Presto Opera Mobile<td><td><td>12(*5)<td colspan="2">11(Opera Mobile 11 for Android and Symbian 参照)
<tr>
<th>Firefox Mobile<td>23(25)<td>8~27?<td>8<td rowspan="2" colspan="2"><a href="https://en.wikipedia.org/wiki/Adobe_Flash_Player#Mobile_platforms" target="_blank" rel="nofollow">Android 2.2–4.1</a>
<tr>
<th>AOSP, Chrome WebView<td>5<td><td>2.3
<tr>
<th>Chrome Mobile<td>28(29)<td><td>18?<td colspan="2"><a href="https://en.wikipedia.org/wiki/Adobe_Flash_Player#Mobile_platforms" target="_blank" rel="nofollow">Android 4.0–4.1</a>
<tr>
<th><a href="https://en.wikipedia.org/wiki/BlackBerry_10" target="_blank" rel="nofollow">BlackBerry 10</a>.0–10.3.1<td><td><td><td>○ 11.1<td>
<tr>
<th><a href="https://en.wikipedia.org/wiki/BlackBerry_Tablet_OS" target="_blank" rel="nofollow">BlackBerry Tablet OS</a><td><td><td><td>○ 11.1<td>
<tr>
<th><a href="https://en.wikipedia.org/wiki/Maemo_%28operating_system%29" target="_blank" rel="nofollow">Maemo</a><td><td><td><td><td><a href="https://en.wikipedia.org/wiki/Adobe_Flash_Player#cite_note-103" target="_blank" rel="nofollow">○ 9.4</a>
<tr>
<th><a href="https://en.wikipedia.org/wiki/PlayStation_3" target="_blank" rel="nofollow">PlayStation 3</a><td><td><td><td><td>Firmware 2.50, 9.1(update 3)
<tr>
<th>Symbian OS<td><td><td><td>○ <a href="https://en.wikipedia.org/wiki/Adobe_Flash_Player#cite_note-105" target="_blank" rel="nofollow">Flash Lite 4.0</a><td>
<tr>
<th>webOS (Palm and HP)<td><td><td><td>○<td>
</table>
<ol>
<li>Firefox 4~27 では <a href="https://caniuse.com/mdn-api_htmlaudioelement_mozwriteaudio" target="_blank" rel="nofollow">Audio Element 拡張</a>が使えました。
<li>FlashPlayer 9 で動的サウンド生成を実現している <a href="https://code.google.com/archive/p/popforge/downloads" target="_blank" rel="nofollow">popforge</a> を参照。
<li><code>HTMLAudioElement</code> の <code>src</code> 属性に動的に生成した Data URI スキームな wav を設定している <a href="https://gist.github.com/mohayonao/1342081" target="_blank" rel="nofollow">pico.js</a> を参照。
<li>wav をサポートしない IE の為に <a href="https://github.com/zhuker/lamejs" target="_blank" rel="nofollow">javascript 製 mp3 encoder</a> を追加する必要がある。Flash Player 等プラグインの使えない Modern IE と IE Mobile 10+ 用に検討する。IE 10 では <code>Worker</code> も使用可能になる。
<li><a href="/2015/10/audiosprite3.html">Android1.6 + Opera12 は <code>new Audio</code> でクラッシュ</a>
</ol>
<blockquote cite="https://web.archive.org/web/20110325012353/http://my.opera.com/operamobile/blog/opera-mobile-11-for-android-and-symbian" title="Opera Mobile 11 for Android and Symbian">
<p>You can now click links and activate Flash content in overview mode, without having to zoom in first (yes, that's right, the Android version now supports Flash).
<ul>
<li>Adobe Flash support (Android only, Flash player available separately in Android Market)
<li>Click-to-play, load Flash content on demand only
</ul></blockquote>
<p>IE9 + Windows Media Player + data URI スキームな MIDI の検討。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-75844339411809690602021-04-18T18:20:00.030+09:002021-08-30T15:54:36.688+09:00翻訳『U3カーネル拡張インターフェースの定義』(UCBrowser_U3_API.doc)<h2>本記事の投稿者より</h2>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/--2q2h8O0Wpg/YHv4ofsJFTI/AAAAAAAASgs/zFbdHyE_EfE4j3yHM3REIEL_PDgJAsTZwCLcBGAsYHQ/s857/UCBrowser_U3_API.PNG"><img alt="UCBrowser_U3_API.doc 書影" src="https://1.bp.blogspot.com/--2q2h8O0Wpg/YHv4ofsJFTI/AAAAAAAASgs/zFbdHyE_EfE4j3yHM3REIEL_PDgJAsTZwCLcBGAsYHQ/s160/UCBrowser_U3_API.PNG"/></a>
<figcaption>『U3内核扩展接口定义』の表紙</figcaption>
</figure>
</span>
<p>この文書は、UC ブラウザの独自拡張に関する文書『U3カーネル拡張インターフェースの定義』、原題『U3内核扩展接口定义』、ファイル名「<a href="https://web.archive.org/web/20180820180411/http://www.uc.cn/download/UCBrowser_U3_API.doc" target="_blank" rel="nofollow">UCBrowser_U3_API.doc</a>」を Web アーカイブから取得した上で、Google 翻訳で翻訳し、僕のフィーリングでマークアップしたものです。
<p>ごく一部で Google 翻訳の結果のブレを僕がフィーリングで修正しています。また<strong>元文書の誤記と思われる点を、僕のフィーリングで書き換えています</strong>。
<p>僕に中国語の素養が無い点、翻訳文書の公開にあたって作者 ucweb の許可を得ていない点をご承知ください。ついでに、ucweb による最終の文書を元にしたのかもイマイチ不明です。
<p>本記事を参照したことによる如何なる損害についても僕は免責とさせていただくことをご承知の上で以降を閲覧ください。Enjoy!
</div>
<h2>目次</h2>
<ul>
<li>1. <a href="#ucbrowser_u3_apidoc_1">執筆目的</a>
<ul>
<li>1.1. <a href="#ucbrowser_u3_apidoc_1_1">背景</a>
</ul>
<li>2. <a href="#ucbrowser_u3_apidoc_2">機能拡張の概要</a>
<li>3. 機能拡張
<ul>
<li>3.1. <a href="#ucbrowser_u3_apidoc_3_1">画面の向き(screen orientation)</a>
<li>3.2. <a href="#ucbrowser_u3_apidoc_3_2">フルスクリーンコントロール(full screen)</a>
<li>3.3. <a href="#ucbrowser_u3_apidoc_3_3">ジェスチャースイッチ</a>
</ul>
<li>4. 組版拡張
<ul>
<li>4.1. <a href="#ucbrowser_u3_apidoc_4_1">XHTML は画面レイアウトに適応します</a>
<li>4.2. <a href="#ucbrowser_u3_apidoc_4_2">組版モード</a>
<li>4.3. <a href="#ucbrowser_u3_apidoc_4_3">ナイトモード</a>
<li>4.4. <a href="#ucbrowser_u3_apidoc_4_4">画像表示を強制する</a>
<li>4.5. <a href="#ucbrowser_u3_apidoc_4_5">速度モード制御</a>
</ul>
<li>5. その他
<ul>
<li>5.1. <a href="#ucbrowser_u3_apidoc_5_1">デスクトップに送信</a>
<li>5.2. <a href="#ucbrowser_u3_apidoc_5_2">アプリケーションモード</a>
</ul>
<li>6. <a href="#ucbrowser_u3_apidoc_6">ブラウザのバージョン認識</a>
</ul>
<h3>修正記録</h3>
<table class="tl">
<thead>
<tr>
<th>修正日<td>概要<td>作者
<tbody>
<tr>
<th>2012年6月26日<td>初稿<td>ucweb
<tr>
<th>2012年8月10日<td>バージョン8.6に従ってドキュメントの内容を調整します<td>ucweb
<tr>
<th>2012年8月27日<td>ブラウザ認識の手順を追加しました<td>ucweb
<tr>
<th>2012年10月8日<td><p>次のコンテンツを追加します。
<ul>
<li>画像表示を強制する
<li>ナイトモードコントロール
<li>アプリケーションモード
<li>植字モード制御
</ul>
<p>以下を変更します。
<p>フルスクリーンモードには、他のモードコントロールは含まれていません<td>ucweb
</table>
<a name="ucbrowser_u3_apidoc_1"></a>
<h2 id="ucbrowser_u3_apidoc_1">1. 執筆目的</h2>
<p>この文書では、U3 カーネルに基づくさまざまな拡張機能について説明します。この文書の読者は、開発に U3 を使用するフロントエンド開発者と、拡張機能を実装する開発者です。
<a name="ucbrowser_u3_apidoc_1_1"></a>
<h3 id="ucbrowser_u3_apidoc_1_1">1.1. 背景</h3>
<p>モバイルゲームやモバイルアプリケーションの急速な発展に伴い、これらのアプリケーションはモバイルブラウザのあらゆる面で新しい要件を提唱しています。これらの新しい要件は必ずしも既存のプロトコル仕様で定義されているわけではないため、U3 の機能を拡張する必要があります。これらの要件を満たすためのカーネル。アプリケーションはサポートを提供します。このドキュメントでは、U3 カーネルによって追加されたすべての固有の、または未定義の拡張機能をまとめています。これは、開発に U3 カーネルを使用するフロントエンド開発者にとって便利です。
<a name="ucbrowser_u3_apidoc_2"></a>
<h2 id="ucbrowser_u3_apidoc_2">2. 機能拡張の概要</h2>
<table>
<thead>
<tr>
<th>拡張機能分類<th>機能詳細<th><code>meta</code> サポート<th>js サポート<th>補足事項
<tbody>
<tr>
<th><a href="#ucbrowser_u3_apidoc_3_2">フルスクリーン</a><td><td>8.6<td>将来のバージョン<td>
<tr>
<th><a href="#ucbrowser_u3_apidoc_3_1">画面の向き</a><td><td>8.6<td>将来のバージョン<td>
<tr>
<th rowspan=4><a href="#ucbrowser_u3_apidoc_3_3">ジェスチャースイッチ</a><td>longpressMenu<td>无<td>8.6<td>
<tr><td>gesture<td>无<td>8.6<td>
<tr><td>flipbutton<td>无<td>将来のバージョン<td>
<tr><td>menu<td>无<td>将来のバージョン<td>
<tr>
<th>画面レイアウトに合わせる<td><td>8.5patch<td>无<td>
<tr>
<th><a href="#ucbrowser_u3_apidoc_5_1">デスクトップに送信</a><td><td>8.6<td>无<td>
<tr>
<th><a href="#ucbrowser_u3_apidoc_6">ブラウザのバージョン認識</a><td><td><td>8.2<td>
</table>
<h2>3. 機能拡張</h2>
<a name="ucbrowser_u3_apidoc_3_1"></a>
<h3 id="ucbrowser_u3_apidoc_3_1">3.1. 画面の向き(screen orientation)</h3>
<h4>3.1.1 仕様状況</h4>
<p><a href="http://www.w3.org/TR/screen-orientation/" target="_blank" rel="nofollow">http://www.w3.org/TR/screen-orientation/</a>
<h4>3.1.2 定義</h4>
<p>以下を含む、画面の向きの特性の判断、イベント、および操作を提供します。
<ul>
<li>現在の画面の方向を読み取ることができる <code>screen</code> オブジェクトを定義します。
<li>画面の向きは、<code>screen</code> オブジェクトを介して設定できます。
<li>画面の向きが変わったときのイベントハンドラー関数を定義します。
</ul>
<pre class="aa"><code>interface screen {
readonly attribute DOMString orientation;
boolean lockOrientation (DOMtring orientation);
void unlockOrientation ();
attribute Function onorientationchange;
};
</code></pre>
<h4>3.1.3. 例</h4>
<pre class="prettyprint lang-html"><code><!DOCTYPE html>
<html>
<script>
function show() {
alert("Screen orientation state is " + screen.orientation);
}
screen.addEventListener("orientationchange", show, false);
show();
screen.lockOrientation("portrait");
</script>
</html>
</code></pre>
<h4>3.1.4 <code>Meta</code>タグ</h4>
<p>呼び出しを単純化するために、画面の向きは <code>meta</code> を介して設定でき、効果は js を使用して関連するインターフェースを呼び出すのと同じです。
<pre class="prettyprint lang-html"><code><meta name="screen-orientation" content="portrait/landscape"></code></pre>
<p>次に相当。
<pre class="prettyprint lang-js"><code>screen.lockOrientation("portrait/landscape");
</code></pre>
<h4>3.1.5 操作設計</h4>
<h5>タブ切り替え</h5>
<p>アニメーションは現在の方向にあり、切り替え後にページがクリックされます
<h5>前後</h5>
<p>現在のページの方向にアニメーションを表示し、切り替え後はページの方向に応じてページを切り替えて表示します。
<h5>システム回転画面設定</h5>
<p>この機能は、画面設定を1回だけ変更し、永続的に有効になることはありません。ユーザーがブラウザ->設定->画面設定をオンにして画面を設定すると、設定の変更に応じて画面が変化し、それに応じて画面の向きのイベントがトリガーされます。
<h4><del>3.1.6 バージョン変更履歴</del></h4>
<a name="ucbrowser_u3_apidoc_3_2"></a>
<h3 id="ucbrowser_u3_apidoc_3_2">3.2. フルスクリーンコントロール(fullscreen)</h3>
<h4>3.2.1 仕様状況</h4>
<p><a href="http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html" target="_blank" rel="nofollow">http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html</a>
<h4>3.2.2 定義</h4>
<p>以下を含むフルスクリーンの操作を提供します。
<ul>
<li><code>element</code> オブジェクトで定義されたフルスクリーン(<code>requestFullscreen</code>)関数を入力します
<li><code>document</code> オブジェクトで定義された <code>exitFullscreen</code> 関数
<li><code>document</code> オブジェクトの全画面状態と現在の全画面要素を読み取るように定義します
<li>フルスクリーン切り替えイベントを定義する
</ul>
<pre class="aa"><code>
partial interface Element{
void requestFullscreen();
}
partial interface Document {
readonly attribute boolean fullscreenEnabled;
Readonly attribute Element fullscreenElement;
void exitFullscreen();
}
</code></pre>
<h4>3.2.3 例</h4>
<pre class="prettyprint lang-html"><code><!DOCTYPE html>
<html>
<script language="text/javascript">
var docElm = document.documentElement;
if (docElm.requestFullscreen) {
docElm.requestFullscreen();
}
If (docElm.fullscreenEnabled){
docElem.exitFullscreen();
}
</script>
</html>
</code></pre>
<h4>3.2.4 <code>Meta</code>タグ</h4>
<pre class="prettyprint lang-html"><code><meta name="full-screen" content="yes"></code></pre>
<p>次と機能的に同等。
<pre class="prettyprint lang-js"><code>var docElm = document.documentElement;
docElem.requestFullscreen();
</code></pre>
<h4>3.2.5 操作設計</h4>
<p>フルスクリーン機能現在定義されているインタラクションおよび操作機能は、アプリケーションのフルスクリーンと一致しています。
<h4>3.2.6 バージョン変更履歴</h4>
<dl>
<dt>8.8変更
<dd>バージョン8.6/8.7で定義されているフルスクリーン機能の <code>meta</code> タグに含まれる禁止ジェスチャを削除し、サスペンションフレームを禁止し、長押しメニューのデザインを禁止しました。
<dd>Apple 独自の <code>meta</code> サポートを削除しました
</dl>
<div class="note"><h4>僕による追記</h4>
<p><a href="https://web.archive.org/web/20130203183134/http://www.uc.cn/download/UCBrowser_U3_API.doc" target="_blank" rel="nofollow">2012年8月27日版</a>の 3.2.4 <code>Meta</code>タグ セクションは次の記述となっていて、バージョン8.6/8.7と8.8で異なる挙動となっていることが分かる。
<blockquote title="2012年8月27日版" cite="https://web.archive.org/web/20130203183134/http://www.uc.cn/download/UCBrowser_U3_API.doc">
<pre class="prettyprint lang-html"><code><meta name="full-screen" content="yes"></code></pre>
<p>このタグは、次のジェスチャ動作も暗黙的に定義します。
<ul>
<li>一本指での操作は禁止されています
<li>フローティングフレームを禁止する
<li>メニューキーはメニューをポップアップできます
<li>長押しメニューの禁止
<li>ページめくりボタンを表示しない
</ul>
<p>次と機能的に同等
<pre class="prettyprint lang-js"><code>Var docElm = document.documentElement;
docElem.requestFullscreen();
navigator.control.gesture(false);
navigator.control.float_button(false);
navigator.control.longpressMenu(false);</code></pre></blockquote>
</div>
<a name="ucbrowser_u3_apidoc_3_3"></a>
<h2 id="ucbrowser_u3_apidoc_3_3">3.3. ジェスチャースイッチ</h2>
<h3>3.3.1 仕様状況</h3>
<p>暂无
<h3>3.3.2 定義</h3>
<p>U3 は、モバイルブラウザ用のいくつかの独自の操作方法を定義しています。これらの操作方法には次のものがあります。
<ul>
<li>ジェスチャー:1本の指で前後に動かし、2本の指で操作します(追加/削除/タブ切り替え)
<li>長押しメニュー
<li>全画面表示のフローティングボタン(まだ提供されていません)
<li>ページめくりボタン
<li>物理メニューキー
</ul>
<p>次のようなジェスチャの制御機能を提供します。
<ul>
<li>ブラウザ制御オブジェクトを定義します:<code>navigator.control</code>
<li><code>navigator.control</code> にジェスチャー、フローティングボタン、その他の操作を提供します
</ul>
<pre class="aa"><code>Interface control{
Boolean gesture(boolean enable/disable);
Boolean longpressMenu(boolean enable/disable);
Boolean flipbutton()
Boolean menu(boolean enable/disable);
}</code></pre>
<h4><del>3.3.3 例</del></h4>
<h4>3.3.4 <code>Meta</code>タグ</h4>
<p>利用不可
<h4>3.3.5 操作設計</h4>
<p>すべての設定は現在のページに対してのみ有効であり、順方向リストと逆方向リストのページには影響しません。
<p>ジェスチャが禁止されている場合、現在のページのジェスチャイベントを Web ページに渡して処理する必要があります。次の方法でこのページにアクセスすると、操作を使用できなくなります。
<ul>
<li>2本の指を使用して、別のタブからジェスチャーイベントが禁止されている現在のページに切り替えます
<li>1本の指を使用して前後に移動するときにジェスチャイベントが禁止されている現在のページ
</ul>
<h2>4. 組版拡張</h2>
<a name="ucbrowser_u3_apidoc_4_1"></a>
<h3 id="ucbrowser_u3_apidoc_4_1">4.1. XHTML は画面レイアウトに適応します</h3>
<h4>4.1.1 定義</h4>
<p>画面レイアウトへの適応は、大多数のユーザーに愛されている UC ブラウザの大きな特徴であり、左右のスクロールバーを効果的に回避し、ユーザー操作の回数を減らすことができます。ただし、XHTML の場合、小さな画面でのズームは、ズームインして表示領域を縮小することで実現されるため、画面に適応して視覚効果を向上させることはできません。
<p>標準の植字効果の実現に基づいて、UC ブラウザは、画面に適応する植字方法を提供します。これにより、画面を拡大および縮小したときに XHTML ページが左右のスクロールバーに表示されなくなります。
<p>この機能を使用するには、<code>uc-fitscreen</code>を使用して <code>viewport</code> に設定するだけです。デフォルト値は <code>uc-fitscreen=no</code> です。つまり、この機能は有効になっていません。現時点では、ブラウザのズーム動作は次のとおりです。標準と一致しています。 <code>uc-fitscreen=yes</code> に設定すると、ズーム操作を実行するときに、画像やテキストなどのページ要素のみが拡大されますが、画面幅は拡大されないため、左右のスクロールバーの生成が回避されます。
<h4>4.1.2 例</h4>
<pre class="prettyprint lang-html"><code><meta name="viewport" content="width=device-width, uc-fitscreen=yes"/>
<meta name="viewport" content="initial-scale=1.0, uc-fitscreen=yes"/></code></pre>
<h4>4.1.3 <code>Meta</code>タグ</h4>
<pre class="prettyprint lang-html"><code><meta name="viewport" content="uc-fitscreen=yes"/></code></pre>
<p>ページの要件に応じて、ビューポートの他の属性と一緒に使用してください。
<h4>4.1.4 操作設計</h4>
<p>この拡張機能は、画面幅にズームするときに有効な表示領域を制限するだけで、レイアウトとルールを調整しません。したがって、ズームが最大に達すると、一部のテーブル行でフォントが少し重なる場合があります。このとき、倍率が大きくなりすぎないように <code>maximum-scale</code> を設定することで回避できます。
<p>設計上の考慮事項に基づいて、複数の <code>viewport</code> 定義がページに表示される場合、後の <code>viewport</code> が前の定義を上書きします。したがって、 <code>uc-fitscreen=no</code> 属性を定義して、ページ上の他の <code>viewport</code> 属性と一緒に使用する必要があり、単独で使用することはできません。例えば、
<pre class="prettyprint lang-html"><code><!DOCTYPE html '-//WAPFORUM//DTD XHTML Mobile 1.0//EN' 'http://www.wapforum.org/DTD/xhtml-mobile10.dtd'>
<meta name="viewport" content="width=device-width,uc-fitscreen=yes"/></code></pre>
<p>または
<pre class="prettyprint lang-html"><code><!DOCTYPE html '-//WAPFORUM//DTD XHTML Mobile 1.0//EN' 'http://www.wapforum.org/DTD/xhtml-mobile10.dtd'>
<meta name="viewport" content="initial-scale=1.0,uc-fitscreen=yes"/></code></pre>
<a name="ucbrowser_u3_apidoc_4_2"></a>
<h3 id="ucbrowser_u3_apidoc_4_2">4.2. 組版モード</h3>
<h4>4.2.1 定義</h4>
<p>UC ブラウザには、画面フィッティングモードと標準モードの2種類のレイアウトモードがあります。画面フィッティングモードは、一部のページの処理を簡素化し、ページコンテンツをページの読み取りに適したものにし、トラフィックを節約し、応答を高速化します。標準モードでは、標準仕様に従ってページを植字およびレンダリングできます。新しく定義されたタグと js api インターフェイスを介して、Web デザイナは、ユーザーにページを表示するために使用するレイアウト方法を決定できます。
<h4>4.2.2 标签</h4>
<h5><code>Meta</code>タグ</h5>
<pre class="prettyprint lang-html"><code><meta name="layoutmode" content="fitscreen/standard"/></code></pre>
<h5>Javascript APIインターフェース</h5>
<p>現在の植字モードの属性値を定義します
<pre class="aa"><code>interface layout{
readonly attribute DOMString layoutmode;
};</code></pre>
<h5>定義済み</h5>
<p><code>layoutmode</code> の値は、<code>fitscreen</code>(画面に適応するために対応)または <code>standard</code>(標準モードに対応する)です。
<p><code>onlayoutchange</code> 関数は、ユーザーがメニューからレイアウトモードを切り替えると呼び出され、各ウィンドウに Web ページのレイアウトが変更されたことを通知します。
<p>メタタグを使用してページのレイアウトを定義した後、ページのレイアウトは、ユーザーが選択したメニューレイアウトの影響を受けなくなります。
<h4>4.2.3 例</h4>
<h5>ページレイアウトを標準モードに設定する</h5>
<pre class="prettyprint lang-html"><code><html>
<meta name="layoutmode" content="standard"/>
<body>
このページは標準モードでフォーマットされ、ユーザーメニューでのズーム/フィット画面の選択は無効です
</body>
</html></code></pre>
<h5>組版モードの切り替えを検出し、ユーザーにプロンプトを表示します</h5>
<pre class="prettyprint lang-html"><code><html>
<meta name="layoutmode" content="fitscreen"/>
<body>
<script type="text/javascript>
function handlelayout(newmode)
{
confirm("現在のページレイアウトは画面表示モードに固定されています。標準モードに切り替えるには、xxxリンクをクリックしてください。");
}
layout.onlayoutchange = handlelayout;
</script>
</body>
</html>
</code></pre>
<h4>4.2.4 説明</h4>
<p><code>layoutmode</code> が設定されていない場合、レイアウトモードはユーザーが設定したブラウザオプションによって決定され、ユーザーのメニューの変更に応じて変更できます。
<p><code>meta</code> 設定は、現在のページに従属する <code>iframe/frame</code> を含む現在のページで有効になりますが、前方ページと後方ページには影響しません。
非現在のウィンドウのイベントコールバック関数はリアルタイムで生成されます
<p>ページの <code>frame/iframe</code> のレイアウトメタ属性は有効になりません。
<p>組版切り替えイベントは、ページ内の <code>frame/iframe</code> に通知されます
<a name="ucbrowser_u3_apidoc_4_3"></a>
<h3 id="ucbrowser_u3_apidoc_4_3">4.3. ナイトモード</h3>
<h4>4.3.1 定義</h4>
<p>ナイトモードは UC ブラウザの特徴的な機能であり、ユーザーが低輝度または暗い状態でより快適にページを閲覧するのに役立ちます。 Web ベースのアプリケーションがますます複雑になるにつれて、ブラウザによって実装されるシングルナイトモードはすべての状況(ゲームアプリケーションなど)に適応できない場合があります。したがって、UC ブラウザでは、Web デザイナがブラウザのナイトモードを無効にすることができます。ページを設計し、ユーザーにより適した独自のナイトモードを設計します。
<h4>4.3.2 标签</h4>
<h5><code>Meta</code>タグ</h5>
<pre class="prettyprint lang-html"><code><meta name="nightmode" content="enable/disable"/></code></pre>
<h6><code>content=disable</code> の場合の意味</h6>
<p>このページは、UC ブラウザによってカスタマイズされたナイトモードの使用を禁止されており、ナイトモードに入ったときのパフォーマンスはデイモードと同じです。
<h6><code>content=enable</code> の場合の意味</h6>
<p><code><meta name="nightmode" content="disable"/></code> の効果をキャンセルするために使用される UC ブラウザのカスタムナイトモードの使用をページに許可する。
<h5>js インターフェース</h5>
<ul>
<li>ナイトモードのイベントハンドラー関数を定義する
<li>ナイトモードの属性値を定義する
</ul>
<pre class="aa"><code>interface layout{
readonly attribute DOMString displaymode;
Function onnightmodechange(DOMString newmode);
};
</code></pre>
<p><code>displaymode</code> はページを単位とする変数で、値は <code>day/night</code> で、それぞれデイモードとナイトモードに対応し、ブラウザ全体のナイトモードと同じ値になります。
<p>ブラウザがナイトモードに入る、または終了すると、イベントがすべてのウィンドウに送信され、<code>onnightmodechange</code> 関数が呼び出され、着信パラメータは変更される <code>displayMode</code> 値です。
<h4>4.3.3 例</h4>
<h5>ナイトモードへの移行を禁止する</h5>
<pre class="prettyprint lang-html"><code><!DOCTYPE html>
<html>
<meta name="nightmode" content="disable"/>
<body>
<p>このページはナイトモードにはなりません。
<body>
</html></code></pre>
<h5>ユーザーにナイトモードに入るように促す</h5>
<pre class="prettyprint lang-html"><code><!DOCTYPE html>
<html>
<body>
<p>現在のナイトモード:<div id="isNight"><script>document.write(layout.displaymode)</script></div>
<script language="text/javascript">
function handlenightmode(newmode)
{
ret_val = true;
//現在のモードはオフです。つまり、ナイトモードに変換されています。
if (newmode == "night"){
alert("ナイトモードに入った");
}
document.getElementById("isNight").innerHTML= layout.displaymode;
}
layout.onnightmodechange = handlenightmode;
</script>
</body>
</html></code></pre>
<h5>カスタムナイトモード</h5>
<pre class="prettyprint lang-html"><code><!DOCTYPE html>
<html>
<meta name="nightmode" content="disable"/>
<body>
<p>現在のナイトモード:<div id="isNight"><script>document.write(layout.nightmode)</script></div>
<script language="text/javascript">
function handlenightmode(newmode)
{
ret_val = false;
//デイモードからナイトモードに切り替えます
if (layout.nightmode == "night")
{
alert("ページのカスタマイズにナイトモードを使用する");
//カスタムナイトモードスタイルシートのページに切り替える
}
else //ナイトモードからデイモードに切り替えます
{
//ページのカスタマイズのためにナイトモードスタイルシートをキャンセルする
}
}
layout.onnightmodechange = handlenightmode;
document.getElementById("isNight").innerHTML= layout.nightmode;
</script>
</body>
</html></code></pre>
<h4>4.3.4 説明</h4>
<p>ページの <code>frame/iframe</code> のナイトモード <code>meta</code> は有効になりません。
<p>ユーザーのナイトモード切り替えイベントは、ページの <code>frame/iframe</code> に通知されます
<a name="ucbrowser_u3_apidoc_4_4"></a>
<h3 id="ucbrowser_u3_apidoc_4_4">4.4. 画像表示を強制する</h3>
<h4>4.4.1 定義</h4>
<p>トラフィックを節約し、速度を上げるために、UC はユーザーに画像なしモードを提供します。実際の使用では、確認コードや地図など、ページ上の画像が不可欠です。強制画像表示の機能により、画像表示がユーザーの設定に影響されないようにすることができます。
<p>この機能は、ページの全画像の強制表示と単一画像の強制表示の2つの部分に分かれています。
<p>ページ全体に画像の表示が強制され、<code>meta</code> タグを介して、ページ上のすべての画像を読み込む必要があることがブラウザに通知されます。ユーザーが設定した画像なしオプションは無効です。
<p>単一の画像が強制的に表示されます。属性が <code>img</code> タグに追加されます。これにより、ユーザーが設定した画像なしオプションは無視され、対応する画像オブジェクトが強制的に読み込まれますが、他の画像オブジェクトの処理には影響しません。
<h4>4.4.2 标签</h4>
<h5><code>meta</code>タグ</h5>
<pre class="prettyprint lang-html"><code><meta name="imagemode" content="force"/></code></pre>
<h5><code>img</code>タグ</h5>
<pre class="prettyprint lang-html"><code><img src="..." show="force"></code></pre>
<h4>4.4.3 例</h4>
<h5>ページの全画像の強制表示</h5>
<pre class="prettyprint lang-html"><code><html>
<meta name="imagemode" content="force"/>
<body>
<img src="sample1.jpg"/>
<img src="sample2.jpg"/>
<img src="sample3.jpg"/>
<p>上記の画像は画像なしモードの影響を受けず、表示する必要があります
</body>
</html></code></pre>
<h5>単一の画像の強制表示</h5>
<pre class="prettyprint lang-html"><code><html>
<body>
<img src="sample1.jpg"/>
<p>この画像は画像なしモードでは表示されません
<img src="sample2.jpg" show="force"/>
<p>この画像は、画像なしモードでも表示されます
<img src="sample3.jpg" id=testimg/>
<a href="javascript:document.getElementById("testimg").show="force";">強制表示を設定する</a>
<p>この画像は、ボタンをクリックすると強制的に表示されます
</body>
</html></code></pre>
<h4>4.4.3 説明</h4>
<p>アプリケーションモードでは、ページの全画像は強制的に表示されます。
<p>ページの全画像の強制表示は、現在のページにのみ有効であり、ページ内の <code>iframe/frame</code> には有効ではなく、前後のページには影響しません。
<a name="ucbrowser_u3_apidoc_4_5"></a>
<h3 id="ucbrowser_u3_apidoc_4_5"><del>4.5. 速度モード制御</del></h3>
<h2>5. その他</h2>
<a name="ucbrowser_u3_apidoc_5_1"></a>
<h3 id="ucbrowser_u3_apidoc_5_1">5.1. デスクトップに送信</h3>
<p>次のタグの場合、ユーザーがブックマークを追加するとき->デスクトップショートカットに送信するときに、対応する画像をオンラインで取得し、この画像を使用してデスクトップに表示します(safariモバイルブラウザーの定義と互換性があります)
<pre class="prettyprint lang-html"><code><link rel="apple-touch-icon-precomposed" sizes="57x57" href="images/icon.png" />
<link rel="apple-touch-icon" sizes="72x72" href="images/icon.png" /></code></pre>
<p>ユーザーが“デスクトップに送信”メニュー操作をトリガーすると、ネットワークがトリガーされ、最大サイズの画像が取得されます。画像を取得する前に、デフォルトの画像を最初に表示できます。取得が完了すると、取得した画像がデスクトップに更新されます。この特別なラベルを取得できない、または取得できない場合でも、デフォルトのデスクトップブックマークアイコンが引き続き使用されます。
<a name="ucbrowser_u3_apidoc_5_2"></a>
<h3 id="ucbrowser_u3_apidoc_5_2">5.2. アプリケーションモード</h3>
<h4>5.2.1 定義</h4>
<p>アプリケーションモードは、Web アプリケーションとゲーム開発者の便宜のために設定された包括的なスイッチであり、<code>meta</code> タグを介して開くように指示されます。アプリケーションモードに入ると、ブラウザは次のパラメータを自動的に調整します。
<table>
<thead>
<tr>
<th>パラメータ<th>状態
<tbody>
<tr>
<th>全画面表示<td>効果的に、<code>meta</code> または js api 呼び出しを介して全画面を終了できます。
<tr>
<th>長押しメニュー<td>無効です。js api 呼び出しで再検証できます。
<tr>
<th>ブラウザのデフォルトのジェスチャー<td>無効です。js api 呼び出しで再検証できます。
<tr>
<th>組版モード<td>標準モード、他の植字モードは、<code>meta</code> または js api を呼び出すことで設定できます。
<tr>
<th>画像表示を強制する<td><del>無効です。</del><ins>有効が正しいと思われる。(僕)</ins>
<tr>
<th>ナイトモード<td>無効です。<code>meta</code> または js api 呼び出しを介して有効にできます。
</table>
<h4>5.2.2 标签</h4>
<h5>アプリケーションモードは <code>meta</code> タグを介して呼び出すことができます</h5>
<pre class="prettyprint lang-html"><code><meta name="browsermode" content="application"/></code></pre>
<h4>5.2.3 例</h4>
<h5>アプリケーションモードに入る</h5>
<pre class="prettyprint lang-html"><code><html>
<meta name="browsermode" content="application"/>
<body>
アプリケーションモードはこのページで設定され、デフォルトは全画面表示、長押しメニューは禁止、ジェスチャーは禁止、標準の植字、画像表示は必須です。
</body>
</html></code></pre>
<h5>アプリケーションモードに入り、長押しメニューを有効にし、ナイトモードを禁止します</h5>
<pre class="prettyprint lang-html"><code><html>
<meta name="browsermode" content="application"/>
<meta name="nightmode" content="disable"/>
<script language="text/javascript">
navigator.control.longpressMenu(true);
</script>
<body>
このページではアプリケーションモードが設定されていますが、ナイトモードは禁止されており、長押しメニューは許可されています
</body>
</html></code></pre>
<h4><del>5.2.4 説明</del></h4>
<a name="ucbrowser_u3_apidoc_6"></a>
<h2 id="ucbrowser_u3_apidoc_6">6. ブラウザのバージョン認識</h2>
<p>UC ブラウザの認識方法は他のブラウザと同じです。<code>navigator.appVersion</code> 変数を使用して、UC ブラウザと対応するバージョンを識別することができます。次の例を参照してください。
<pre class="prettyprint lang-html"><code><html>
<body>
<script type="text/javascript">
document.write(navigator.appVersion);
if (navigator.appVersion.indexOf("UC")!= -1)
{
document.write("this is uc browser");
}
</script>
</body></html></code></pre>
<p>UC ブラウザ(デフォルトは UA)を使用している場合、ページには次のように表示されます。
<pre class="aa"><samp>5.0 (Linux; U; Android 2.3.3; zh-cn; samsung Build/GINGERBREAD) UC AppleWebKit/534.31 (KHTML,like Gecko) Mobile Safari/534.31 UC/8.6.0.174
This is uc browser</samp></pre>
<!-- p>子フレーム内のすべての <code>meta</code> が有効になるわけではありません
<p>イベントは子フレームに配信されます -->
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-27755647012343860322020-12-06T01:30:00.015+09:002024-02-13T00:26:48.867+09:00【画像スプライト編】Web文書のグレースフルデグラデーションをムキになってやってみる<div class="note"><p>Wii インターネットチャンネル(Opera 9.30)について追記しました。テストページの URL 変更に追従。(2024/02/13)
</div>
<p>『<a href="/2020/11/graceful-degradation.html">Web文書のグレースフルデグラデーションをムキになってやってみる</a>』と『<a href="/2020/11/ultimate-clearfix.html">clearfix 編</a>』の続きです。
<h2>3行まとめ</h2>
<ol>
<li>CSS Generated Content が CSS-P をサポートするのは Opera 7.20 以降、Firefox 3.5 以降、Internet Exproler 8 以降。
<li>インラインブロック要素に対して <code>content : url()</code> で画像スプライト出来るのは、Opera 9.50 以降、Firefox 3.5 以降(ベータ版を含めるなら3.1 Beta 1以降)、Internet Exproler 8 以降。
<li>この他にも細かい挙動の差異があるので Nintendo DS ブラウザ(Opera 8.5 相当)で見れる HTML を書きたい人は良く見ていってね。
</ol>
<hr>
<ol>
<li><a href="/2020/11/graceful-degradation.html">Web文書のグレースフルデグラデーションをムキになってやってみる</a>
<li><a href="/2020/11/ultimate-clearfix.html">clearfix 編</a>
<li>CSS Generated Content 編
<ol>
<li><a href="#1">CSS Generated Contentと画像スプライトの変遷</a>
<li><a href="#2">先行する記事</a>
<li><a href="#3">検証ページ</a>
<li><a href="#4">検証結果</a>
</ol>
</ol>
<h2 id="1">1. CSS Generated Contentと画像スプライトの変遷</h2>
<p>僕が開発しているとある CSS ライブラリでは、画像スプライトによってコンテンツを提供しています。まずそもそもとして、コンテンツの画像スプライトでの提供は推奨されません。<code><img></code> タグで提供されるのが本筋です。
<p>しかしものによっては CSS とマークアップを注意深く設計することで、画像や CSS の無効な環境に対しては HTML とテキストで情報を伝えることが出来ます。併せてコンテンツ毎に画像の準備が不要なのも便利です。
<p>幸いに <a href="/2019/01/howto-high-contrast-mode-support.html#background"><code>content : url()</code> を使って画像スプライトにまつわる諸問題を回避しつつ、その利便性を享受できるテクニックもある</a>ので活用します。
<p>しかしこのテクニックでは <code>background-image : url()</code> による画像スプライトより対応ブラウザの下限が上がってしまいます。<a href="/2020/11/graceful-degradation.html#2-1">先の記事</a>で挙げた Opera 9.50 と Firefox 3.5.0 に加えて Internet Exproler 8 がその分水嶺です。
<p>非対応の Internet Exproler 8 未満は脇に置くとして、Opera と Firefox の CSS Generated Content と画像スプライトに纏わる挙動が羽陽曲折だったので記録しておきます。
<h2 id="2">2. 先行する記事</h2>
<p>MDN の次の記述のおかげで、実装状況に差異があることを知りました。
<blockquote title="::before (:before) - CSS: カスケーディングスタイルシート | MDN" cite="https://developer.mozilla.org/ja/docs/Web/CSS/::before"><p>Before Firefox 3.5, only the CSS level 2 behavior of <code>:before</code> was supported, which disallowed <code>position</code>, <code>float</code>, <code>list-style-*</code> and some <code>display</code> properties.</blockquote>
<h2 id="3">3. 検証ページ</h2>
<div class="box"><a href="https://1.bp.blogspot.com/-a1LIrdZzP2g/X8uxIEodXCI/AAAAAAAASbw/W7e6JK_5hzYbGZgRo-yeICnYPFsMOY-jQCLcBGAsYHQ/s1080/mozilla1.3.1.PNG"><img alt="" src="https://1.bp.blogspot.com/-a1LIrdZzP2g/X8uxIEodXCI/AAAAAAAASbw/W7e6JK_5hzYbGZgRo-yeICnYPFsMOY-jQCLcBGAsYHQ/s160/mozilla1.3.1.PNG"/></a>
<p>検証ページは <a href="https://itozyun.github.io/web-doc-base/test/cssGeneratedContent.html" target="_blank" rel="me nofollow">github ページで公開</a>しています。要素と <code>:before</code>, <code>:after</code> 疑似要素に異なる背景画像を表示するテストになっています。
</div>
<h2 id="4">4. 検証結果</h2>
<ol>
<li>CSS Generated Content の CSS-P 対応は Opera 7.20 以降、Firefox 3.5.0 以降。
<li>インラインブロック要素に対する <code>content : url()</code> の画像スプライトは Opera 9.50 以降、Firefox 3.5.0 以降。
</ol>
<h3>background-image</h3>
<div class="hscroll">
<table>
<thead>
<tr>
<th rowspan="2">browser<th rowspan="2">CSS-P<td colspan="3">Block element<td colspan="3">Inline block element
<tr>
<td>both<td><code>:before</code><td><code>:after</code><td>both<td><code>:before</code><td><code>:after</code>
<tbody>
<tr>
<th>Opera 7.0x~7.1x(*1)<td>x<td>△(*2)<td>〇<td>△(*3)<td>x(*5)<td>△(*3)<td>△(*3)
<tr>
<th>Opera 7.20<td>〇<td>〇<td>〇<td>〇<td>x(*4,*5)<td>△(*3,*4)<td>△(*3,*4)
<tr>
<th>Opera 7.23~9.27<td>〇<td>〇<td>〇<td>〇<td>x(*5)<td>△(*3)<td>△(*3)
<tr>
<th>Wii Opera 9.30<td>△(*7)<td>△(*7)<td>△(*7)<td>△(*7)<td>△(*7)<td>△(*7)<td>△(*7)
<tr>
<th>Opera 9.5x~<td>〇<td>〇<td>〇<td>〇<td>〇<td>〇<td>〇
<tr>
<th>Gecko 0.9.4.1(Netscape 6.2.3)<td>x<td>△(*2)<td>〇<td>△(*3)<td>△(*2,*6)<td>〇(*6)<td>△(*3,*6)
<tr>
<th>Gecko 1.0.2~1.8.1.12<br>(Netscape 7.02~9.0.0.6)<td>x<td>△(*2)<td>〇<td>△(*3)<td>x(*5)<td>△(*3)<td>△(*3)
<tr>
<th>Firefox 3.0.9, Gecko 1.9.0.9<td>x<td>△(*2)<td>〇<td>〇<td>△(*2)<td>〇<td>〇
<tr>
<th>Firefox 3.5 beta4, Gecko 1.9.1b4<td>〇<td>〇<td>〇<td>〇<td>〇<td>〇<td>〇
</table>
</div>
<ol>
<li>gif がアニメーションしない。
<li><code>:after</code> のみ表示される。<code>:before</code> と要素のコンテンツが欠落する。
<li>要素のコンテンツが欠落する。
<li>インラインブロック要素で text-indent で飛ばした文字列が画面に残る
<li><code>:after</code>, <code>:before</code> どちらも欠落する。
<li>インラインブロックに非対応でブロック要素のレイアウトになる
<li><code>:after</code>・<code>:before</code> と <code>content</code> の組み合わせで文書の下に大きな余白ができる。
</ol>
<div class="note"><h4>古いOpera, Geckoでgifの透過が黒色になる問題を回避する</h4>
<p>今回の調査中に Opera ~9.64, Gecko 0.9.4.1 で、ImageReady で書き出したア二メーション gif を圧縮すると透過色が無視されて背景が黒色になる問題に遭遇しました。
<p><a href="https://www.compresss.com/jp/compress-gif.html" target="_blank" rel="nofollow">compresss.com</a> を使って圧縮レベルに0を選択すると回避できました。今回使用したファイルでは、最高レベルの圧縮でのファイルサイズは250バイトだったのに対し、圧縮レベル0では272バイトでした。
</div>
<h3>content:url()</h3>
<div class="hscroll">
<table>
<thead>
<tr>
<th rowspan="2">browser<th rowspan="2">CSS-P<td colspan="3">Block element<td colspan="3">Inline block element
<tr>
<td>both<td><code>:before</code><td><code>:after</code><td>both<td><code>:before</code><td><code>:after</code>
<tbody>
<tr>
<th>Opera 7.0x~7.1x<td>x<td colspan="6">x
<tr>
<th>Opera 7.20<td>〇<td>〇<td>〇<td>〇<td>x(*1,*2)<td>x(*1,*2)<td>x(*1,*2)
<tr>
<th>Opera 7.23~8.54<td>〇<td>〇<td>〇<td>〇<td>x(*2)<td>x(*2)<td>x(*2)
<tr>
<th>Opera 9.0~9.27<td>〇<td>〇<td>〇<td>〇<td>x<td>x<td>x
<tr>
<th>Wii Opera 9.30<td>△(*3)<td>△(*3)<td>△(*3)<td>△(*3)<td>△(*3)<td>△(*3)<td>△(*3)
<tr>
<th>Opera 9.5x~<td>〇<td>〇<td>〇<td>〇<td>〇<td>〇<td>〇
<tr>
<th>Firefox ~3.0.9(Gecko 1.9.0.9)<td>x<td colspan="6">x
<tr>
<th>Firefox 3.5 beta4~(Gecko 1.9.1b4)<td>〇<td>〇<td>〇<td>〇<td>〇<td>〇<td>〇
</table>
</div>
<ol>
<li>インラインブロック要素で <code>text-indent</code> で飛ばした文字列が画面に残る
<li>インラインブロック要素で <code>content:url()</code> が文書の頭に描画されてしまう
<li><code>:after</code>・<code>:before</code> と <code>content</code> の組み合わせで文書の下に大きな余白ができる。
</ol>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-48253173625449488652020-12-05T20:06:00.057+09:002022-03-09T10:41:48.725+09:00【clearfix編】Web文書のグレースフルデグラデーションをムキになってやってみる<div class="note"><p>テスト用の HTML では不要でしたが実際の Web 文書用には Gecko 0.9.4.1 の為に <code>.ultimate-clearfix {position : relative;}</code> が必要でした。<a href="https://github.com/itozyun/web-doc-base/commit/22d26edddfe47d1d3722a357c59273feda568a65" target="_blank" rel="nofollow me">github で確認する</a>。(2022/03/09)
</div>
<p>『<a href="/2020/11/graceful-degradation.html">Web文書のグレースフルデグラデーションをムキになってやってみる</a>』の続きです。『<a href="/2020/12/graceful-image-sprite.html">CSS Generated Content 編</a>』に続きます。
<h2>3行でまとめ</h2>
<ol>
<li>最初期の clearfix の <code>content : "."</code> は Gecko 1.3~1.5 用。この他にも初期 Gecko 限定の指定があります。
<li>モダンな clearfix の <code>content : " "</code> は Opera 9~11 と <code>contentEditable</code> 要素の組み合わせで発生する隙間を回避する。<code alia-label="ドット">"."</code> でも回避できるがより副作用の少ないこちらが採用されている。但し <code>height:0</code> などでも隙間は消える。
<li>ここまでの調査を踏まえた究極の clearfix を紹介します。
</ol>
<hr>
<ol>
<li><a href="/2020/11/graceful-degradation.html">Web文書のグレースフルデグラデーションをムキになってやってみる</a>
<li>clearfix 編
<ol>
<li><a href="#1">究極のclearfixを探る</a>
<li><a href="#2">先行する記事</a>
<li><a href="#3">検証ページ</a>
<li><a href="#4">検証結果</a>
<li><a href="#5">ここまでを元にした僕的究極 clearfix</a>
<li><a href="#6">リンク集</a>
</ol>
<li><a href="/2020/12/graceful-image-sprite.html">CSS Generated Content 編</a>
</ol>
<h2 id="1">1. 究極のclearfixを探る</h2>
<p>clearfix には最初期のものから、時々の主要ブラウザにターゲットを絞って記述量をスリム化したものまで、複数のバージョンが紹介されています。
<p>僕が今回求める clearfix は対応ブラウザを最大にしつつ、初期のブラウザで発生した問題を回避する為の <code>content : "."</code> や <code alia-label="スペース">" "</code> が不要なブラウザについては <code alia-label="空文字列">""</code> を使用するものです。
<p>このような着眼で <code alia-label="ドット">"."</code>, <code alia-label="スペース">" "</code> が必要なブラウザと、これを上書きする CSS ハックを調査しました。
<div class="note">
<h3>EdgeHTMLで遭遇した問題</h3>
<p>僕には EdgeHTML で文書をコピペした際に CSS Generated Content な <code alia-label="ドット">"."</code> が含まれた経験があります。デベロッパーツールを立ち上げて検証を繰り返していた時で、これ以降は再現していません。この経験から <code alia-label="空文字列">""</code> で動作する環境では <code alia-label="空文字列">""</code> を指定したい、と考えるようになりました。</div>
<h2 id="2">2. 先行する記事</h2>
<p>まずは次の先行する記事のお陰で <code alia-label="ドット">"."</code> と <code alia-label="スペース">" "</code> の由来が判明しました。
<h3><code alia-label="ドット">"."</code>の由来は古いGeckoエンジン</h3>
<blockquote title="スタイルシートをめぐる冒険: clearfixの決定版を作る -モダンブラウザ編-" cite="http://norisfactory.com/stylesheetlab/000038.php">
<p><code>content</code> がスペースや空だと <code>float</code> をクリアできないのは、Netscapeだった。7.1で確認しているので、それより古いバージョンでも同様だろう。ただし、ここで検証したような親ボックスに <code>border</code> または <code>padding</code> を設定したケースでは、<code>float</code> がクリアされてしまうため見逃してしまったのだ(<a href="http://norisfactory.com/stylesheetlab/sample_html/clearfix_for_NS.html" target="_blank" rel="nofollow">検証ページはこちら</a>)。
</blockquote>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-hbkuZQw3J0c/X7petZVXNMI/AAAAAAAASaw/WDL0uAgmmb8OYwXpuyKuBLxDLYzDDL65ACLcBGAsYHQ/s717/netscape7.1.png"><img src="https://1.bp.blogspot.com/-hbkuZQw3J0c/X7petZVXNMI/AAAAAAAASaw/WDL0uAgmmb8OYwXpuyKuBLxDLYzDDL65ACLcBGAsYHQ/s160/netscape7.1.png"></a>
<figcaption><a href="https://web.archive.org/web/20040615034349/http://wp.netscape.com/ja/downloads/index.html" target="_blank" rel="nofollow">Netscape 7.1 Download のアーカイブ</a></figcaption>
</figure>
</span>
<p><code alia-label="ドット">"."</code> は古い Gecko エンジン用の指定でした。しかも親ボックスのスタイルによって問題の発生の有無が異なるとのことです。先人の検証が無ければ、とても自力で見つける自信はありません。
</div>
<h3><code alia-label="スペース">" "</code>の由来はPrestoエンジン</h3>
<blockquote title="A new micro clearfix hack" cite="http://nicolasgallagher.com/micro-clearfix-hack/"><ol><li>The space content is one way to avoid an Opera bug when the contenteditable attribute is included anywhere else in the document. Otherwise it causes space to appear at the top and bottom of elements that are clearfixed.</ol>
<hr>
<p><p>The use of <code>content:" "</code> (note the space in the content string) avoids an
<a href="http://codepen.io/anon/full/9454/4">Opera bug</a> that creates space around
clearfixed elements if the <code>contenteditable</code> attribute is also present
somewhere in the HTML. Thanks to Sergio Cerrutti for spotting this fix. An
alternative fix is to use <code>font:0/0 a</code>.</p>
</blockquote>
<p><code alia-label="スペース">" "</code> で回避できる問題は Presto Opera でテキスト編集機能をトリガーに発生するとのことでした。Opera のテキスト編集機能は9以降でサポートする為、比較的新しいブラウザで起きている問題です。テキスト編集機能にはほとんど触っていない為、こちらも先人の検証が無ければとても自力で見つける自信はありません。
<h2 id="3">3. 検証ページ</h2>
<p>検証ページは <a href="https://itozyun.github.io/web-doc-base/clearfix.html" target="_blank" rel="me nofollow">github ページで公開</a>しています。また検証ページの当該 CSS は次になります。
<h3>モダンブラウザ用clearfix</h3>
<pre class="prettyprint lang-css"><code>#clearfix-general:after {
content : "";
height : 0; /* for Gecko 0.9~1.7.5 & Opera 9~11 */
display : block; /* for Gecko ~0.9 & Opera */
visibility : hidden;
clear : both;
}
</code></pre>
<h3>レガシーブラウザ用clearfix</h3>
<h4>Gecko ~1.2.1用</h4>
<pre class="prettyprint lang-css"><code>#iclearfix-gecko12
position : relative; /* for Gecko 1.0.2 */
}
#clearfix-gecko12:after {
content : "";
clear : both;
}
</code></pre>
<h4>Gecko 0.6~0.9, 1.3~1.7用</h4>
<pre class="prettyprint lang-css"><code>#clearfix-gecko17:after {
content : "."; /* for Gecko 1.3~1.5 */
height : 0; /* for Gecko 0.9~1.7.5 */
display : block; /* for Gecko & Opera */
visibility : hidden;
clear : both;
}
</code></pre>
<h2 id="4">4. 検証結果</h2>
<p><code>:after</code> 疑似要素に <code>content:"."</code> を要求するのは Gecko 1.3~1.5 迄でした。ちなみに先に挙がった Netscape 7.1 は Gecko 1.4 になります。この他にも特定の環境で必要なプロパティがありました。詳しくは続くコード中のコメントで確認ください。
<div class="box"><a href="https://1.bp.blogspot.com/-OB8ohInZIwI/X7o3-LI9MPI/AAAAAAAASac/dmSJrJ95ubUZttiCECewppD2L-2HTSNIwCLcBGAsYHQ/s1053/opera_clearfix.png"><img alt="" src="https://1.bp.blogspot.com/-OB8ohInZIwI/X7o3-LI9MPI/AAAAAAAASac/dmSJrJ95ubUZttiCECewppD2L-2HTSNIwCLcBGAsYHQ/s160/opera_clearfix.png"></a>
<a href="https://1.bp.blogspot.com/-nbvDYXhvuVo/X7o3-HP_14I/AAAAAAAASag/NhAUm0CCM405xD6ynCfoAK3j8i5dcap7wCLcBGAsYHQ/s1032/opera_clearfix_bug.png"><img alt="" src="https://1.bp.blogspot.com/-nbvDYXhvuVo/X7o3-HP_14I/AAAAAAAASag/NhAUm0CCM405xD6ynCfoAK3j8i5dcap7wCLcBGAsYHQ/s160/opera_clearfix_bug.png"></a>
<p>Opera 9~11 と <code>contentEditable</code> 要素の組み合わせで親ボックスに隙間ができる問題も確認できました。これはモダンブラウザ用の clearfix に既にある <em><code>height:0</code> で解消できたので <code>content:" "</code> は不要</em>でした。
</div>
<table>
<caption>clearfix</caption>
<thead>
<tr>
<th>browser<th>モダンブラウザ用<td>レガシーブラウザ用
<tbody>
<tr>
<th>Opera 7~<td>〇<td>〇
<tr>
<th>Gecko 0.6~1.5<td>x <code>:after</code> 疑似要素の <code>content:""</code> の為 Gecko 1.3~1.5 で親ボックスの高さが不正になります。<td>〇
<tr>
<th>Gecko 1.8~(Mozilla 1.8)<td>〇<td>〇
<tr>
<th>Safari 3.0~<td>〇<td>〇
</table>
<h2 id="5">5. ここまでを元にした僕的究極clearfix</h2>
<p>僕的究極 clearfix に登場するプロパティは <code>position:relative;</code> を除いて先の引用した『<a href="http://norisfactory.com/stylesheetlab/000038.php" target="_blank" rel="nofollow">clearfixの決定版を作る</a>』で紹介されている Movable Type のデフォルトスタイルシートと同じです。但し、ある環境で必要な指定が他の環境で悪影響するケースがあるため、CSS ハックを駆使しています。
<h3>モダンブラウザ用clearfix</h3>
<p>Internet Explorer 8 以上、Gecko 1.6 以降、Opera 7.0 以降、Safari 3.0 以降であればこれでいけます。
<pre class="prettyprint lang-css"><code>.ultimate-clearfix:after {
content : "";
height : 0; /* for Gecko 0.9~1.7.5 & Opera 9~11 */
display : block; /* for Gecko and Opera */
visibility : hidden;
clear : both;
}
</code></pre>
<h3>Gecko 1.5 以下用のclearfix追加コード</h3>
<p>Gecko 1.5 以下に対応する場合には次の CSS ハックで上書きしていく。Gecko 1.6~1.7 にも <code alia-label="ドット">"."</code> が当たりますが丁度よい CSS ハックが無いので一旦諦めます。ちなみに Firefox 1.0 は Gecko 1.7 です。
<div class="hscroll">
<pre class="prettyprint lang-css"><code>/* override Gecko ~1.8.1 */
@media \0 all {
.ultimate-clearfix {
position : relative; /* for Gecko 1.0.2 , or absolute */
}
.ultimate-clearfix:after {
display : inline; /* 1.0.2 で隙間が出来るのを回避 */
}
/* override Gecko 1.2~1.8.1 */
_:lang(x), .ultimate-clearfix:after {
content : "."; /* (1) for Gecko 1.3~1.5 */
display : block; /* (2) for Gecko 1.3~1.5 */
font-size : 1px; /* (3) for Gecko 1.2.1 (1)(2) で発生する隙間を小さく */
line-height : 0; /* for Gecko 1.2.1 (1)(2) で発生する隙間を小さく */
height : 0.1px; /* for Gecko 1.4 (3) で高さが消えるのを回避 1.4.2 では発生しない */
}
/* override Gecko 1.8~ */
@-moz-document url-prefix() { .ultimate-clearfix:after { content : "" } }
}
</code></pre>
</div>
<h3>おまけでOpera 6.2.3用のclearfix追加コード</h3>
<p>Opera 6.06 で頭にできる隙間を小さくする。Opera 9.54~, Safari 3.2 で隙間が出来るので注意が必要です。
<pre class="prettyprint lang-css"><code>.ultimate-clearfix:before {
content : "";
display : table;
}
</code></pre>
<h2 id="6">6. リンク集</h2>
<ol>
<li><a href="https://ja.wikipedia.org/wiki/Gecko#Gecko%E3%82%92%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2" target="_blank" rel="nofollow">Gecko バージョンとアプリバージョンの対照表</a>
<li><a href="https://browserstrangeness.github.io/css_hacks.html" target="_blank" rel="nofollow">browser strangeness</a> 大量の CSS ハックの検証ページ
</ol>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-34383966032591419932020-12-05T19:56:00.026+09:002023-09-21T10:03:49.086+09:00Web文書のグレースフルデグラデーションをムキになってやってみる<div class="note"><p>文章の微修正をしています。(2023/09/20)
<p>2点追記しました。(2022/05/03)
</div>
<div class="box"><a href="https://1.bp.blogspot.com/-HqYZ6nAt5TU/X8tk3XD0lEI/AAAAAAAASbc/qEki622sOdYZbfLKikT73XFNj2BdyQssQCLcBGAsYHQ/s864/vm.PNG"><img alt="" src="https://1.bp.blogspot.com/-HqYZ6nAt5TU/X8tk3XD0lEI/AAAAAAAASbc/qEki622sOdYZbfLKikT73XFNj2BdyQssQCLcBGAsYHQ/s160/vm.PNG"/></a><p>フワッとした理解が気持ち悪かったので、古いブラウザを Virtual Machine にインストールしまくって、結構調べました。今回の調査でフワッとしない Web ドキュメント開発のアウトラインが見えてきた手応えを感じます。
</div>
<ol>
<li>Web文書のグレースフルデグラデーションをムキになってやってみる
<ol>
<li><a href="#graceful-degradation-1_1">はじめに</a>
<li><a href="#graceful-degradation-1_2">グレースフルデグラデーションの戦略</a>
<li><a href="#graceful-degradation-1_3">次回に続きます</a>
</ol>
<li><a href="/2020/11/ultimate-clearfix.html">clearfix 編</a>
<li><a href="/2020/12/graceful-image-sprite.html">CSS Generated Content 編</a>
</ol>
<a name="graceful-degradation-1_1"></a>
<h2 id="graceful-degradation-1_1">1. はじめに</h2>
<p>妙なスイッチが入ったので次のブラウザバージョン迄遡って、このブログ等で使っている HTML と CSS、ささやかな javascript についてチェックを行いました。僕が HTML を生業にしたのは2008年からですので、当時の推奨ブラウザよりずっと古いものに触れたことになります。
<table class="tl">
<thead>
<tr>
<th>リリース日<td>ブラウザ
<tbody>
<tr>
<th>1999年3月18日<td>Internet Exproler 5.0
<tr>
<th>2000年11月14日<td>Netscape 6.0(Mozilla Milestone 18ベース)
<tr>
<th>2003年1月28日<td>Opera 7.0
<tr>
<th>2004年11月4日<td>Firefox 1.0(Gecko 1.7)
<tr>
<th>2007年6月11日<td>Windows 版 Safari 3.0
</table>
<!--ol>
<li><a href="https://web.archive.org/web/20130226080051/http://aol-4.vo.llnwd.net/pub/netscape7/japanese/7.1/windows/win32/sea/NSSetup-Full.exe" target="_blank" rel="nofollow">日本語版 Netscape 7.1 フルインストーラ</a>
</ol-->
<a name="graceful-degradation-1_2"></a>
<h2 id="graceful-degradation-1_2">2. グレースフルデグラデーションの戦略</h2>
<p>この調査によって、ダークモードや<a href="/2019/01/howto-high-contrast-mode-support.html">強制カラーモード</a>などをサポートする新しいブラウザと同一の CSS を読み込むことが出来るブラウザの下限バージョンを決定できました。CSS の実装状況がある程度に達したことで、JavaScript のサポートが無くとも閲覧性が保たれる、バージョンに応じた体験を提供できるようになるブラウザのスタート地点です。(2023/09/20 文章修正)
<p>Opera 9.50, Firefox 3.5 を境に大きく <a href="https://developer.mozilla.org/ja/docs/Web/CSS/CSS_Generated_Content" target="_blank" rel="nofollow" title="MDN > CSS Generated Content">CSS Generated Content</a> のスペックが変化していた為、ここに線を引く判断が出来ました。これより古いブラウザについては JavaScript が有効な場合に限って閲覧性を保つ戦略とします。(2023/09/20 文章修正)
<p>中でも Opera 8.5x 以下には <code>@media</code> 規則に致命的な不備がありました。ダークモードや<a href="/2019/01/howto-high-contrast-mode-support.html">ハイコントラストモード用</a>のスタイルが問答無用に適用されていく様を見て、JavaScript に依存しない CSS ハックでの対処を放棄せざるを得ませんでした。
<p>また Opera 9.27 以下には <code>:not()</code> セレクタと <code>@media</code> 規則の組み合わせで不具合に遭遇しました。この件についてはいずれ記事化します。(2022/05/03)
<a name="2-1"></a>
<h2 id="2-1">2.1. Javascriptが無効でもそれなりの閲覧性を維持できるブラウザ</h3>
<table class="tl">
<thead>
<tr>
<th>リリース日<td>ブラウザ
<tbody>
<tr>
<th>1999年3月18日<td>Windows 版 Internet Exproler 5.0(*1)
<tr>
<th>2007年6月11日<td>Windows 版 Safari 3.0(*2)
<tr>
<th>2008年6月12日<td>Opera 9.50
<tr>
<th>2009年3月20日<td>Internet Exproler 8.0(*1)
<tr>
<th>2009年6月30日<td>Firefox 3.5(Gecko 1.9.1)
</table>
<ol>
<li>Internet Exproler が CSS Generated Content をサポートするのは8からですが、Windows 版 5.0 は条件付きコメントで専用 CSS だけを設定できるため、Javascript が無効でも閲覧性を維持できています。
<li>Mac OSX 用 Safari 2 以下では未検証です。
</ol>
<h3>2.2. Javascriptが有効の場合に専用CSSに差し替えるブラウザ</h3>
<p>CSS Generated Content と画像スプライトを使うサイトでは、Firefox 3.5 未満と Opera 9.50 未満で専用 CSS に差し替えます。また Javascript が無効の場合のメッセージを <code><noscript></code> と CSS ハックを使って当該端末だけに表示します。
<hr>
<p>以下のコードは正しく動作しません。最新のコードは「<a href="https://outcloud.blogspot.com/2021/12/loading-css-in-webdocbase.html#3-1">対応ブラウザをかなり拡げた場合の最適なCSSの読み込み方法、web-doc-baseのブートシーケンスについて</a>」に紹介されています。(2022/05/03 追記)
<pre class="prettyprint lang-html"><code><noscript>
<style>
#noscript { display : none; border : double 5px #f66; padding: 1em; background: #300;color : #fff; }
/* Gecko ~1.8 */
@media \0 all {
#noscript { display : block; }
}
@-moz-document url-prefix() {
/* Gecko 1.8~1.9.2 */
_:not(), _:-moz-loading, #noscript { display : block; }
/* Gecko 1.9.1~1.9.2 */
_:not(), _:-moz-handler-blocked, #noscript { display : none; }
}
/* Opera 7.20~9.27 */
@media all and (-webkit-min-device-pixel-ratio:10000),not all and (-webkit-min-device-pixel-ratio:0) {
html:first-child #noscript { display : block; }
}
/* Opera ~7.10 */
#noscript, x:not(\){ display : block; }
</style>
<p id="noscript">Javascript disabled! Please enabled javascript or use new version of browser. At least Opera 9.50+ or Firefox 3.5+.
</noscript>
</code></pre>
<a name="graceful-degradation-1_3"></a>
<h2 id="graceful-degradation-1_3">3. 次回に続きます</h2>
<p>Javascript が無効のケースで対応を諦めるブラウザのバージョンをカチッと特定できたことは大きな一歩でした。
<p>続く記事ではバージョンによる変化が際立った <a href="/2020/11/ultimate-clearfix.html">clearfix</a> と <a href="/2020/12/graceful-image-sprite.html">CSS Generated Content</a> の挙動について調査結果を紹介します。
<p>ところで、当ブログはレイアウトの為に Flexbox などの新機能は使わず、<code>float</code> や <code>position</code> を使っている為、この部分で閲覧性を損なうことはありませんでした。僕がコントロールできる開発では、新しい機能は WebView アプリ等の、エンジンとエンジンバージョンの範囲を限定できる条件でしか使わないと思います。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-52259882664039559232020-09-06T06:59:00.026+09:002022-12-26T18:07:14.278+09:00【2020年版】ハイコントラストモード対応で圧倒的おもてなし!Chromium Edge含む4ブラウザ対応はこれでバッチリ<div class="note"><p>Qiita の投稿記事『<a href="https://qiita.com/feo52/items/b01fa93b1ddf16f19649" target="_blank" rel="nofollow">::-ms-clear & ::-ms-reveal & -ms-high-contrast-adjust on Edge(Chromium) of Windows</a>』からリンクを頂戴していたのでメモ。(2022/03/28)
<p>Firefox のハイコントラストモードサポートは Gecko 1.8 からです。<code>prefers-contrast</code> との混同がありますが、未だ修正できていません。(2022/03/16)
<p>Firefox 73 からは、ハイコントラストモード時に背景画像を表示する設定が可能とのこと。(2020/09/21)
<blockquote cite="https://news.mynavi.jp/article/20200217-976093/" title="「Firefox 73」を試す - ズーム一括設定やハイコントラスト時の背景画像表示が可能に "><p>Firefox 73では新たに、readability backplateという仕組みが導入された。この機能を使うと、背景画像はそのままで、テキストの背後にバックプレートが敷かれ、テキストのコントラストを高める。</blockquote>
</div>
<p>Chromium エンジンの Edge が僕のパソコンにも降って来ていました。これ以前に Microsoft が開発していた EdgeHTML エンジンは<q cite="https://ja.wikipedia.org/wiki/Microsoft_Edge">「現代的なウェブとの相互運用性」を重視し</q>たといいます。しかしどうしてもシェアで先行する Chrome との差異はあって <a href="https://twitter.com/fladdict/status/1070837743368863745" target="_blank" rel="nofollow">Web 開発者らの支持が得られなかった</a>のだと思われます。しかし<a href="https://www.atmarkit.co.jp/ait/articles/1606/22/news097.html" target="_blank" rel="nofollow">省電力性の高さ</a>などユーザーにユニークな選択肢を提供してきた点は、もっと顧みられて良い筈です。
<h2>Chromium Edge がハイコントラストモードをサポート</h2>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-qGSvyG26EA0/X1H1TwNTXwI/AAAAAAAASYE/CjF0v1RRQdIxdRPs4HAuUHFq23mXbDNsQCLcBGAsYHQ/s1040/PaleMoon28.6.0.1.png"><img alt="" src="https://1.bp.blogspot.com/-qGSvyG26EA0/X1H1TwNTXwI/AAAAAAAASYE/CjF0v1RRQdIxdRPs4HAuUHFq23mXbDNsQCLcBGAsYHQ/s200/PaleMoon28.6.0.1.png"></a>
<figcaption><a href="https://twitter.com/itozyun/status/1301645950838951937" target="_blank" rel="me nofollow">Gecko からフォークした Windows 版 Pale Moon 28.6.0.1 もハイコントラストモードをサポートする</a></figcaption>
</figure>
</span>
<p>さて、エンジンが Chrome と同じになって全く食指が動かなかった Edge ですが、Microsoft が開発するハイコントラストモードサポートを先行して提供している事を知りました。
<p>ユーザーのハイコントラストで表示して欲しい、という要請を Web 文書に反映するこの機能は、アクセシビリティの点で重要です。これとは別に<em>自身の Web サイトがマイコン画面のようなビビッドな配色になる</em>のも、僕は結構気に入っています。
<p>現在、ハイコントラストモードをサポートする環境は多くなく、IE, EdgeHTML エンジンの Edge, Windows 版の Firefox、そして Gecko からフォークした Goanna エンジンの Pale Moon があります。これに Chromium Edge が加わわりました。
<p>ゆくゆくは <code><a href="https://drafts.csswg.org/mediaqueries-5/#descdef-media-prefers-contrast" target="_blank" rel="nofollow">prefers-contrast</a></code> メディア特性として広範なブラウザに実装されるようで楽しみですね。
</div>
<h3>ハイコントラストモードをオンする</h3>
<div class="box">
<a href="https://blogger.googleusercontent.com/img/a/AVvXsEj3aGIthzBwZM2_cEfZGCXwXylmrtbzzc8g3n2EZvi5_Zz6hHORs1DhlDXBX34pOq-563vEBw1-uQzT5_gTWMqqGvyHNjGJr5dLR7Sk72P96OikoC6IXHGnhUx9s0kIdTBy8JM2w3aZd10Ib7dHHy8tBgZuW9__fCFgSn_OpFC7XuIBpBngaaUukuM6=s1079">
<img alt="" src="https://blogger.googleusercontent.com/img/a/AVvXsEj3aGIthzBwZM2_cEfZGCXwXylmrtbzzc8g3n2EZvi5_Zz6hHORs1DhlDXBX34pOq-563vEBw1-uQzT5_gTWMqqGvyHNjGJr5dLR7Sk72P96OikoC6IXHGnhUx9s0kIdTBy8JM2w3aZd10Ib7dHHy8tBgZuW9__fCFgSn_OpFC7XuIBpBngaaUukuM6=s160"></a>
<ul>
<li><kbd>shift</kbd> + <kbd>alt</kbd> + <kbd>print screen</kbd> を同時に押す。ハイコントラストのオフも同じ。
<li>Windows の設定 > 簡単操作 > ハイ コントラスト > ハイ コントラストをオンにする
</ul>
<p>画像は、Windows XP でハイコントラストモードを有効にしている。<samp>コントロールパネル > アクセシビリティ > ディスプレイ</samp> から変更します。先に紹介したショートカットキーでも切り替え出来ます。(2022/03/16 スクリーンショットと併せて追記)
</div>
<h2>ハイコントラストモードの独特の挙動を把握する</h2>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-TJ6HSkmahv8/X1HlrT0Fy1I/AAAAAAAASX4/VxIWY0xrXHAx7l8PdEtFkKoBpCB0wk8EwCLcBGAsYHQ/s1875/highContrastMode.png"><img alt="" src="https://1.bp.blogspot.com/-TJ6HSkmahv8/X1HlrT0Fy1I/AAAAAAAASX4/VxIWY0xrXHAx7l8PdEtFkKoBpCB0wk8EwCLcBGAsYHQ/s160/highContrastMode.png"></a>
<figcaption><a href="https://twitter.com/itozyun/status/1301644824538300416" target="_blank" rel="me nofollow">左から Firefox80, Edge85, IE11, Windows のハイコントラスト設定画面</a></figcaption>
</figure>
</span>
<p>ハイコントラストモードでは貴方の Web サイトのスタイルが大きく変化します。この際もデザインを損なわない為には、独特の挙動を理解するのが最初の一歩です。
<p>この変化は一見すると各ブラウザで似た感じなのですが、よく見ていくと IE+Edge と Gecko+Goanna では結構異なります。IE のバージョン、EdgeHTML と Chromium Edge、Firefox と Pale Moon でも細々と異なり、僕は計5種類に分類したのでした。
</div>
<h3>ブラウザ別ハイコントラストモードの違い</h3>
<table>
<thead>
<tr>
<th>グレード<th>ブラウザ<th><code>-ms-high-contrast</code><th>モード切替の反映<th>ユーザー設定の色の反映
<tbody>
<tr>
<th>A<th>IE10, 11, Edge18-<td>◎<td>〇<td>だいたい OS 側で設定した色。メディアクエリ内で自由な色に上書き可能。
<tr>
<th>B<th>Windows 版 Chromium Edge85<td>〇<td>〇<td>だいたい OS 側で設定した色。(*2)メディアクエリ内でシステムカラー限定で上書き可能。(2022/03/17)
<tr>
<th>C<th>IE9 以下<td>×<td>〇<td>だいたい OS 側で設定した色。
<tr>
<th>D<th>Windows 版 Firefox(新しめ *1)<td>×<td>〇<td rowspan=2>背景色と選択テキストの色のみ OS 側で設定した色。リンク色はブラウザ側で<del>固定の模様</del>設定する。
<tr>
<th>E<th>Windows 版 Pale Moon, Firefox(<del>古め</del>Gecko 1.8+ *1)<td>×<td><code>onload</code> 時のみ
<tr>
<th>Z<th>非サポート<td colspan=3>×
</table>
<ol>
<li>Windows 版 Firefox がどのバージョンで D<del>, E</del> グレードへ移るのかは未調査です。E グレートを Gecko 1.8 からサポートします。(2022/03/16)
<li>Edge85 で <code>:before</code>, <code>:after</code> 疑似要素の背景色が維持するバグがある。Edge84 では起きていない。
</ol>
<h3>ハイコントラスト色設定のWeb文書への反映</h3>
<p>ハイコントラスト設定画面のプリセットやユーザー設定がどう Web 文書に反映するのか、詳しく見ていきます。
<h4>背景色</h4>
<p>Windows の設定がドキュメント全体、全要素に適用されます。<code><blockquote></code>, <code><pre></code> 等を背景色でスタイリングしている場合は枠線等で囲みます。
<p>あらかじめ背景色と同色の枠線で囲んでおくと後述する Javascript によるフォールバックに失敗した場合も安全です。
<h4 id="background">背景画像</h4>
<p>非表示になるので、コンテンツを背景画像で提供している場合に不味いです。
<p>この対策には <code>:before</code>, <code>:after</code> 疑似要素と <code>content:url()</code> を使う方法が『<a target="_blank" rel="nofollow" href="https://developer.paciellogroup.com/blog/2010/01/high-contrast-proof-css-sprites/">High Contrast Proof CSS Sprites</a>』で紹介されています。<em>背景を無効にした印刷でもコンテンツが欠落しないのでハイコントラストモード対応に関わらず導入をお勧めします</em>。
<h4>テキスト色</h4>
<p>ハイパーリンクを除いて一色になります。色は背景色に対して自動で黒か白を割り当てられるようです。<code><strong></code>, <code><em></code> 等の強調をテキスト色の違いでスタイルしている場合は太字や下線等を設定します。
<h4>ボーダー色</h4>
<p>テキストと同じ色になります。要素に薄色の線を入れている場合は鮮やかな色になってしまいます。五月蠅い印象になるならハイコントラストモード時は線を消したり点線にするのも手です。
<h4>ハイパーリンクのテキスト色とボーダー色</h4>
<div class="box">
<a href="https://blogger.googleusercontent.com/img/a/AVvXsEjr7ZFUHy-W8isK1--KvJZUpOMLpRmXlH289n9GKklqm8WeBNXB6ANEoUfo0Z0eBDfJvV_dpgaTyO9YidCNm3iuTQRQ5YjKmQAl7p5h5IapbJlHPh08L27pbGVUXS0ZZTiiNZham5tdD5s_jkhCjSLQiEdzq5HNzGiCO2y73cubES8A_xcaVNn76fUU=s1152">
<img alt="" src="https://blogger.googleusercontent.com/img/a/AVvXsEjr7ZFUHy-W8isK1--KvJZUpOMLpRmXlH289n9GKklqm8WeBNXB6ANEoUfo0Z0eBDfJvV_dpgaTyO9YidCNm3iuTQRQ5YjKmQAl7p5h5IapbJlHPh08L27pbGVUXS0ZZTiiNZham5tdD5s_jkhCjSLQiEdzq5HNzGiCO2y73cubES8A_xcaVNn76fUU=s160"></a>
<p>IE と Edge で Windows の設定が反映されました。Firefox, Goanna ではアプリ側<del>の固定の</del>で設定します。デフォルトは暗い青と暗い紫で、背景が黒の場合ですとコントラストが足らず見辛いです。(2022/03/16 修正)
<p>Firefox 6では <samp>オプション > コンテンツ > 配色</samp>からリンクの色を設定します(2022/03/16 スクリーンショットと併せて追記)
</div>
<h4>フォーム部品の色</h4>
<p>“淡色表示のテキスト”が IE ではテキストとボーダーに、Chromium Edge はテキストだけに配色されました。Firefox, Goanna ではフォーム部品もテキスト色と同じでした。
<h4>選択テキストの色</h4>
<p>上記全ての環境で Windows の設定が適用されました。
<h2>ハイコントラストモード対応のポイント</h2>
<ol>
<li><a href="#1"><code>-ms-high-contrast</code>メディア特性と JavaScript でフォールバック</a>
<li><a href="#2">IE10+, Edge18 以下に比べて機能の劣る Chromium Edge だけに CSS ハック</a>
<li><a href="#3"><code>border-color</code> に <code>transparent</code> を使って三角形を作っている場合</a>
<li><a href="#4">腰を据えて各部品を再デザインする、将来の新機能に備える体制を</a>
<li><a href="#5">ここ一番で使える!色の反転がハイコントラストモードでも有効</a>
</ol>
<h3 id=1>1. <code>-ms-high-contrast</code>メディア特性とJavaScriptでフォールバック</h3>
<p>IE10 以上と Edge はハイコントラストモード用の <code><a target="_blank" rel="nofollow" href="https://developer.mozilla.org/ja/docs/Web/CSS/-ms-high-contrast">-ms-high-contrast</a></code> メディア特性が用意されています。
<p>この IE10 以上と Edge18 以下の <code>-ms-high-contrast</code> メディア特性は強力で、このメディアクエリ内では各種色の指定も可能です。Web サイト全体のスタイル指定をこの中に書いてしまえば、通常と全く同じ見た目にも出来そうです。もちろんハイコントラストモードを選んだ閲覧者の意図に沿って抑制的に使用します。
<pre class="prettyprint lang-css"><code>@media (-ms-high-contrast:none){ /* IE10, 11 のみ */ }
@media (-ms-high-contrast:active){ /* */ }
@media (-ms-high-contrast:white-on-black){ /* 黒地に白文字 */ }
@media (-ms-high-contrast:black-on-white){ /* 白地に黒文字 */ }
</code></pre>
<p>これ以外の IE9 以下と Firefox, Goanna では javascript でハイコントラストモードを判定して文書のスタイルを変化させます。僕は『<a href="https://developer.paciellogroup.com/blog/2011/10/detecting-if-images-are-disabled-in-browsers/" target="_blank" rel="nofollow">Checking for Windows High Contrast</a>』を元にした<a href="https://github.com/itozyun/web-doc-base/blob/master/src/js/4_EventModule/forcedColors.js" target="_blank" rel="me nofollow">コード</a>を使ってハイコントラストモード専用の .css を追加で読み込むことにしました。専用 CSS の切り出しには <a href="https://github.com/itozyun/web-doc-base/blob/master/gulp-finalize-css.js" target="_blank" rel="me nofollow">postCSS を使った gulp タスク</a>を書いています。
<h3 id=2>2. IE10+, Edge18に比べて機能の劣るChromium EdgeだけにCSSハック</h3>
<p>IE や EdgeHTML ではサポートされなかった <code>prefers-color-scheme</code> と組み合わせることで、Chromium Edge だけにスタイルを当てることが出来ます。次のボーダーを使った三角形などで、Edge18 以下用スタイルの上書きが必要になります。
<p>印刷メディアにも適用されるのを避けるために <code>only screen</code> も付けておきます。<code>prefers-color-scheme:dark</code> だけを指定すると印刷メディアにも効いてしまうことは Chrome でも起こります。併せてチェックしておくのが良いでしょう。
<pre class="prettyprint lang-css"><code>@media only screen and (-ms-high-contrast:active) and (prefers-color-scheme:dark),
only screen and (-ms-high-contrast:active) and (prefers-color-scheme:light) {
/* 今のところ Chromium Edge only */
}
</code></pre>
<h3 id=3>3. <code>border-XXX-color:transparent</code> を使って三角形を作っている場合</h3>
<p>ボーダー色がテキスト色と同じになってしまう為に、一部の辺の色を <code>transparent</code> 等にして作る三角形が、ハイコントラストモードでは四角形になってしまいます。<code>-ms-high-contrast</code> メディア特性の中で自在に色指定が出来る IE10+, Edge18 以下は次のようにすれば OK です。
<pre class="prettyprint lang-css"><code>@media (-ms-high-contrast:active){
border-top-color : transparent;
border-bottom-color : transparent;
}
</code></pre>
<p>しかし Chromium Edge, IE9 以下と Firefox、Goanna ではどうすればよいのでしょう?
<h4><code>forced-colors:active</code> をサポートする Chromium Edge 79+, Chrome 89+, Fireox 89+ ではシステムカラーの背景色を使う</h4>
<p>Chromium Edge ではシステムカラーの背景色を指定します。透明色では無く背景色なので、やや使い勝手が悪いです。(2022/03/17 追記)
<pre class="prettyprint lang-css"><code>@media (forced-colors:active){
border-top-color : Window; /* or Canvas */
border-bottom-color : Window;
}
</code></pre>
<h4>IE9以下とFirefox89未満、Goannaでは要素の回転で表現する</h4>
<p>次の記事では <code>border-color:transparent</code> では無く <code>transform:rotate</code> を使った三角形の作り方を紹介しています。ブラウザが要素の回転をサポートしていれば三角形は可能です。SVG や VML でのフォールバックは未検証です。
<dl>
<dt><a href="https://kuzlog.com/2017/09/20/1549/#i-4" target="_blank" rel="nofollow">【2017年版】CSSのみで三角形を作る方法を解説するよ|ついでに台形や扇形も作ってみるよ</a>
<dd>僕が採用した方法はこの記事を元にしました
<dt><a href="http://webrocketsmagazine.com/entry/20120213/how-to-triange-in-css3.html" target="_blank" rel="nofollow">CSS3を極めたいなら知っておきたい三角形を作る3つの方法</a>
<dd><code>transform:rotate</code> と併せて <code>clip:rect</code> を使う方法。こちらの方が元々の <code>border-color:transparent</code> を使った三角に近い表現になる。
</dl>
<h3 id=4>4. 腰を据えて各部品を再デザインする、将来の新機能に備える体制を</h3>
<p>コントラストモード別に <code>:hover</code>, <code>:focus</code>, <code>:hover:focus</code> 等のインタラクションを、サイトの各部品に設定するにあたってアドホックに取り組んでしまうと、コードが散らかってスタイルの一貫性も損なわれ易いです。ハイコントラストモードの挙動を把握した上で、部品の一覧を用意して腰を据えて取り組むのが良いです。
<p><code>-ms-high-contrast</code> の姉妹の <code>prefers-color-scheme:dark</code> メディア特性も Chrome, Safari, Firefox で提供されています。これらを合わせて対応していけたら良いですね。
<p>僕は自身の小さなブログプロジェクトですが、仕切り直してやり遂げる事ができました。そうそう Web サイトへのインタラクションの設定については『<a href="/2016/10/link-interaction.html">リンクテキストのインタラクションを整理する</a>』も参照ください。
<h3 id=5>5. ここ一番で使える!色の反転がハイコントラストモードでも有効</h3>
<p>スタイルの自由度が低くて困った時に最期に頼りになったのが <code>filter:invert(1)</code> と <code>outline:solid invert</code> でした。アイコン画像の色を反転させたい場合など、追加の画像と、ユーザーのネットワークへの負荷を避けることが出来ました。太いボーダーを背景色でくり抜くことも出来て重宝しました。
<p>特に <code>outline:solid invert</code> は <code>-ms-filter</code> が無効な IE8 でも反転効果が使えてパワフルです。このテクニックについて解説した記事『<a href="https://lea.verou.me/2011/04/invert-a-whole-webpage-with-css-only/" target="_blank" rel="nofollow">Invert a whole webpage with CSS only</a>』に助けられました。
<h2>おわりに</h2>
<p>ハイコントラストモードの存在を遅ればせながら2018年の暮れに知った僕はブログの対応に着手しました。
<p>特殊な挙動に戸惑ったり、フォールバック用の javascript を書いたり。試行錯誤を通して Web サイトの各部品に対してハイコントラストモード用を加えたデザインポリシーの再定義から取り組む必要があることにも気づかされました。
<p>やることは決して少なくは無かったですが自身の Web サイトが晴れてハイコントラストモードに対応し、一定のデザイン性を維持している様子を眺めるのは愉しいものです。Web 屋の端くれとして多様なアクセス手段を提供していく地力を養えたことは収穫でした。
<h2>お勧め記事</h2>
<dl>
<dt><a href="https://saneyukis.hatenablog.com/entry/2018/12/10/005530" target="_blank" rel="nofollow">saneyuki_s log > EdgeHTMLを悼む</a>
<dd>Gecko エンジン元コントリビューターによる記事。必読です!
<dt><a target="_blank" rel="nofollow" href="https://frasco.io/writing-css-with-accessibility-in-mind-4fc82b26aecb">アクセシビリティを意識した CSS の書き方 > Windows でのハイコントラストモード</a>
<dd>ハイコントラストモードについてアクセシビリティの思想側から。
<dt><a href="https://www.atmarkit.co.jp/ait/articles/2009/04/news013.html" target="_blank" rel="nofollow">勝手にChromium版になったMicrosoft Edgeをアンインストールする</a>
<dd>Chromium Edge をアンインストールして EdgeHTML を再使用する方法など。
<dt><a target="_blank" rel="nofollow" href="https://accessible-usable.net/2018/04/entry_180405.html">ブランド訴求と「ハイコントラスト」モード</a>
<dd>Web ドキュメント側の実装だけでハイコントラストバージョンを提供しているブランドの例。
<dt><a target="_blank" rel="nofollow" href="https://blog.jxck.io/entries/2018-11-10/dark-mode-via-prefers-color-scheme.html" target="_blank" rel="nofollow">prefers-color-scheme を用いた Dark Mode 対応と User Preference Media Features</a>
<dd>ダークモード対応に関する記事。ハイコントラストモードとポイントは異なりますが良記事です。
</dl>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-70987300105576159432020-08-23T11:17:00.005+09:002022-11-02T21:23:33.055+09:00尋常でないレベルでブラウザを判定するライブラリ、what-browser-am-iをnpmに公開しました<div class="box">
<div class="caption" style="width:160px">
<figure>
<a href="https://1.bp.blogspot.com/-I9qK8ydaTIs/X0HMdqs7jpI/AAAAAAAASWI/8eOPQXodvR4in5sTrGVGfL42SOLrb5YAwCLcBGAsYHQ/s1600/what-browser-am-i.png"><img src="//1.bp.blogspot.com/-I9qK8ydaTIs/X0HMdqs7jpI/AAAAAAAASWI/8eOPQXodvR4in5sTrGVGfL42SOLrb5YAwCLcBGAsYHQ/s160/what-browser-am-i.png"></a>
<figcaption><a href="https://www.npmjs.com/package/what-browser-am-i" target="_blank">npm > what-browser-am-i</a></figcaption>
</figure>
</div>
<p>クライアントサイド専用の Web ブラウザ判定用ライブラリ<a href="https://github.com/itozyun/what-browser-am-i" target="_blank">what-browser-am-i</a> を npm に公開しました。
<p>頻繁に偽装される <code>userAgent</code> に惑わされず、可能な限りビルトインオブジェクトを使ってバージョン等を判定するように実装しています。新旧を問わず、広範な DHTML ブラウザでの動作を目標に開発を続けます。
<p>フワッとしたブラウザ判定をしてしまうと、これ以降に書かれるクロスブラウザ用コードもフワッとしてしまって、精神衛生上宜しくありません。この点が改善されるようになってきた、と個人的には感じています。Enjoy!
</div>
<h2>ブラウザエンジンはおろかブランド名まで判定してUXをアゲアゲする</h2>
<p>ブラウザ判定というとブラウザエンジンと OS の判定がまず念頭に浮かびます。EdgeHTML の開発中止や Windows Phone の撤退など、エンジンと OS の多様性は失われていく傾向です。Web 開発者はクロスブラウザ対応から解放されつつある、と考えてよいのでしょうか?
<p>ところで Android や iOS の組み込み WebView をラップした各種ブラウザアプリケーションは独自の変更が加えられています。つまりユーザーに最良の体験を提供したい場合、先の2点に加えてブランド(アプリケーション名)を判定する必要があります。
<p>エンジンと OS は減少傾向ですがブランドとなると際限がなく、長らく二の足を踏んでいました。しかしある時、一年発起してコードを書き始めました。Web 開発の一丁目一番地はブラウザ判定、コードを書いて本当に良かったです。
<p>クロスブラウザに頭を悩ます状況は変わりませんが、<em>ユーザーの多様な選択肢を保証する</em>ため知見とコードを積み上げていきましょう。
<h3>ブラウザ判定でブランドを知りたい理由</h3>
<p>モバイル用ブラウザには、<em>スクロール操作でアドレスバーの高さが低くなり表示エリアが拡大する</em>ギミックを備えるものが多くあります。ややこしいことに変化しないものもあります!この際に取れる表示エリアのサイズが各ブラウザ(ブランド)で異なることに業を煮やしたのでした。
<p>また Facebook, Line などの提供する in App ブラウザを使用中の場合、これを検出してフォローリンクを表示することも考えられますね。
<h3>リンク</h3>
<dl>
<dt><a href="https://en.wikipedia.org/wiki/Comparison_of_web_browsers">Comparison of web browsers</a>
<dd>Web ブラウザを網羅する Wikipedia のページ。Amaya 等の非ダイナミック HTML ブラウザ、w3m 等のテキストブラウザも含まれる。
</dl>
<hr>
<p><strong>以降のテーブルは、開発を進めながら加筆・修正して参ります</strong>。悪しからず!
<h2>ua.PLATFORM プラットフォーム</h2>
<table>
<caption>デスクトップOS</caption>
<thead>
<tr>
<th>プロパティ<th>値の例<th>メモ
<tbody>
<tr>
<th>Win16<td><td>
<tr>
<th>Win32<td>6.1, 10<td>64bit CPU でも多くの場合で Win32 と判定される。
<tr>
<th>Win64<td><td>
<tr>
<th>MacPPC<td><td>
<tr>
<th>Mac68K<td><td>
<tr>
<th>MacIntel<td><td>
<tr>
<th>ChromeOS<td><td>
<tr>
<th>SunOS<td><td>
<tr>
<th>FreeBSD<td><td>
<tr>
<th>OpenBSD<td><td>
<tr>
<th>NetBSD<td><td>
<tr>
<th>Ubuntu<td><td>
<tr>
<th>Mint<td><td>
<tr>
<th>Fedora<td><td>
<tr>
<th>Gentoo<td><td>
<tr>
<th>Linux<td><td>
</table>
<table>
<caption>モバイルOSとスマートデバイス用OS</caption>
<thead>
<tr>
<th>プロパティ<th>値の例<th>メモ
<tbody>
<tr>
<th>WinCE<td><td>
<tr>
<th>WindowsMobile<td><td>
<tr>
<th>WindowsPhone<td><td>
<tr>
<th>Android<td><td>
<tr>
<th>BlackBerry<td><td>
<tr>
<th>iOS<td><td>
<tr>
<th>FireOS<td><td>
<tr>
<th>FirefoxOS<td><td><a href="https://developer.mozilla.org/ja/docs/Tools/Firefox_OS_Simulator_clone#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">Firefox OS シミュレータのインストール</a>
<tr>
<th>webOS<td><td>
<tr>
<th>Tizen<td><td>
<tr>
<th>MeeGo<td><td>
<tr>
<th>Maemo<td><td>
</table>
<table>
<caption>モバイル機器</caption>
<thead>
<tr>
<th>名前<th>値の例<th>メモ
<tbody>
<tr>
<th>FeaturePhone<td><td>
<tr>
<th>Mylo<td><td>
<tr>
<th>kobo<td><td>
<tr>
<th>SonyReader<td><td>
<tr>
<th>Kindle<td><td>
</table>
<table>
<caption>ゲーム機</caption>
<thead>
<tr>
<th>プロパティ<th>値の例<th>メモ
<tbody>
<tr>
<th>NDS<td><td>Nintendo DS
<tr>
<th>NDSi<td><td>Nintendo DSi
<tr>
<th>N3DS<td><td>Nintendo 3DS
<tr>
<th>New3DS<td><td>New 3DS
<tr>
<th>Wii<td><td>
<tr>
<th>WiiU<td><td>
<tr>
<th>Switch<td><td>
<tr>
<th>PSP<td><td>
<tr>
<th>PSVita<td><td>
<tr>
<th>PSPGo<td><td>
<tr>
<th>PS3<td><td>
<tr>
<th>PS4<td><td>
<tr>
<th>XBox360<td><td>
<tr>
<th>XBoxOne<td><td>
</table>
<h2>ua.ENGINE ブラウザエンジン</h2>
<table>
<caption>PC用ブラウザエンジン</caption>
<thead>
<tr>
<th>プロパティ<th>値の例<th>メモ
<tbody>
<tr>
<th><a href="https://en.wikipedia.org/wiki/Trident_(software)">Trident</a><td>4, 5, 5.5, 6, 7, 8, 9, 10, 11<td>
<tr>
<th><a href="https://en.wikipedia.org/wiki/Tasman_(layout_engine)">Tasman</a><td>5.2<td>
<tr>
<th><a href="https://en.wikipedia.org/wiki/EdgeHTML">EdgeHTML</a><td>12, 13, 14, 15, 16, 17, 18<td>
<tr>
<th><a href="https://en.wikipedia.org/wiki/Presto_(browser_engine)">Presto</a><td>7.2, 7.5, 8, 8.6, 9, 10, 11, 12.1<td>
<tr>
<th><del><a href="https://en.wikipedia.org/wiki/Netscape_Navigator">NetscapeNavigator</a></del><td>4.06<td>未実装。
<tr>
<th><a href="https://en.wikipedia.org/wiki/Firefox_version_history">Gecko</a><td><td>Quantum も含む。5以降でGeckoとFirefoxのナンバリングが一致
<tr>
<th><a href="https://en.wikipedia.org/wiki/Goanna_(software)">Goanna</a><td><td>Quantum に切り替わる直前に Gecko から分岐したエンジン。
<tr>
<th>FennecPC<td><td>Mobile 用 Gecko の開発中にリリースされたPC向けのベータ版。
<tr>
<th><a href="https://en.wikipedia.org/wiki/KHTML">KHTML</a><td><td>
<tr>
<th><a href="https://en.wikipedia.org/wiki/WebKit">WebKit</a><td><td>Webkit2 を含む
<tr>
<th><a href="https://en.wikipedia.org/wiki/Chromium_(web_browser)">Chromium</a><td><td>Blink も含む。
<tr>
<th><del><a href="https://en.wikipedia.org/wiki/WebKit#Ports">QtWebKit</a></del><td><td>
<tr>
<th><del><a href="https://doc.qt.io/qt-5/qtwebengine-overview.html">QtWebEngine</a></del><td><td>Chromium がベース。Chromium と判定。
<tr>
<th><a href="https://en.wikipedia.org/wiki/ICab">iCab</a><td><td>iCab 3.x までが独自エンジン。以降は WebKit。
</table>
<table>
<caption>スマートデバイスとゲーム用のブラウザエンジン</caption>
<thead>
<tr>
<th>プロパティ<th>値の例<th>メモ
<tbody>
<tr>
<th><a href="https://en.wikipedia.org/wiki/Internet_Explorer_Mobile#Internet_Explorer_Mobile">TridentMobile</a><td>4, 5, 6, 7, 9, 10, 11<td>
<tr>
<th><del><a href="https://en.wikipedia.org/wiki/Internet_Explorer_Mobile#Pocket_Internet_Explorer">TridentPocket</a></del><td>4<td>未実装。W-ZERO3 等に搭載された <code>XMLHttpRequset</code> が追加されて、css-p がサポートが無効の IE4。
<tr>
<th>EdgeMobile<td>12<td>
<tr>
<th><a href="https://en.wikipedia.org/wiki/Opera_Mobile">PrestoMobile</a><td>12.1<td>
<tr>
<th><a href="https://ja.wikipedia.org/wiki/NetFront_Browser">NetFront</a><td>3.4, 4. 4.2<td>
<tr>
<th>SafariMobile<td><td>iOSの標準ブラウザ
<tr>
<th>iOSWebView<td><td>iOS用の WebView をラップしたブラウザや in App ブラウザのエンジン。Safari Mobile から一部に機能制限がある。
<tr>
<th>AOSP<td>1.5, 2, 2.1, 2.2, 2.3, 3, 4, 4.1, 4.2, 4.3, 4.4<td>AOSP stock browser。Android OS のバージョンと一致。
<tr>
<th>ChromiumMobile<td><td>Blink も含む。
<tr>
<th>ChromeWebView<td>4.4, 以降は Chromium のバージョン<td><a href="https://qiita.com/DriftwoodJP/items/1916d5519857295622b2" title="Android 標準ブラウザに関する情報の整理">Chrome ベースの AOSP の後継 WebView</a>。Android 5 移行で、OS のアップデートと分離した。
<tr>
<th><a href="https://en.wikipedia.org/wiki/Firefox_for_Android">Fennec</a><td><td>Mobile 用 Gecko。Quantum も含む。
<tr>
<th><a href="https://developers.whatismybrowser.com/useragents/explore/software_name/samsung-browser/">Samsung</a><td>0.9, 1, 1.5, 1.6, 2...<td>『<a href="/2019/06/studySamsungInternet.html">サムスンによる魔改造Webブラウザ、Samsung Internet の判定</a>』
<tr>
<th>Sony<td><td>『<a href="https://www.itmedia.co.jp/news/articles/0807/28/news016.html">ITmedia NEWS > PS3のWebブラウザ、独自エンジンだからできること</a>』
</table>
<table>
<caption>サーバサイドレンダリングエンジン</caption>
<thead>
<tr>
<th>プロパティ<th>値の例<th>メモ
<tbody>
<tr>
<th><a href="https://en.wikipedia.org/wiki/Opera_Mini">OperaMini</a><td><td>
<tr>
<th>UCWEB<td><td><a href="http://www.ucweb.com/download/UCBrowser_User_Agent_en.pdf">User-Agent and X-UCBrowser-UA Specification of UC Browser</a>
</table>
<dl>
<dt><a href="https://qiita.com/takanamito/items/8c2b6bc24ea01381f1b5">インドネシアの特殊なブラウザ事情(Opera Mini,UC Browser Mini)</a>
<dd>UserAgent を用いた判定と、Web アプリのサーバサイドレンダリングブラウザ対応について。
<dt><a href="https://qiita.com/takanamito/items/c412556856c7d027a747">シェアの少ないJS殺しブラウザ対応の話</a>
<dd>Web アプリのサーバサイドレンダリングブラウザ対応について。
</dl>
<h2>ua.BRAND ブランド</h2>
<p>NetFront などエンジンと同名がブランドになるケースもある。
<table>
<caption>エンジン開発社提供のブラウザブランド</caption>
<thead>
<tr>
<th>プロパティ<th>値の例<th>メモ
<tbody>
<tr>
<th>NetFront<td><td>NetFront エンジン。
<tr>
<th>Safari<td><td>WebKit, SafariMobile エンジン。
<tr>
<th>Chrome<td><td>Chromium, ChromiumMobile
<tr>
<th>Edge<td><td>EdgeHTML, EdgeMobile, Chromium(Windows, MacOS X), ChromeWebView(Android, iOS)
<tr>
<th>IE<td><td>Trident エンジン。
<tr>
<th>IEHost<td><td>Trident エンジン。IE8 以上でシュミレータを使用した場合。
<tr>
<th>ModernIE<td><td>Windows 8.x のモダンUI用ブラウザ。Live タイルが使用できる。アドレスバーの挙動がモバイルブラウザと同じ。
<tr>
<th>MacIE<td><td>Trident, Tasman エンジン。
<tr>
<th>Opera<td><td>Presto, PrestoMobile, Chromium, ChromeWebView エンジン。
<tr>
<th>Silk<td><td>ChromeWebView エンジン。
<tr>
<th>Firefox<td><td>Gecko, Fennec, FennecPC
<tr>
<th>Focus<td><td>Klar 含む。但し FireTV 版は ChromiumMobile。
<tr>
<th>Klar<td><td>Fennec エンジン。
<tr>
<th>PaleMoon<td><td>Goanna エンジン。
<tr>
<th>Samsung<td><td>Samsung エンジン。
<tr>
<th>Konqueror<td><td>KHTML, Webkit エンジン。
<tr>
<th>iCab<td><td>iCab, Webkit エンジン。
<tr>
<th>unknown<td><td>
</table>
<table>
<caption>カスタムブラウザ</caption>
<thead>
<tr>
<th>プロパティ<th>値の例<th>メモ
<tbody>
<tr>
<th>NN<td><td>Gecko エンジン。
<tr>
<th>NetFrontNX<td><td>WebKit エンジン。
<tr>
<th>Coast<td><td>ChromeWebView エンジン。
<tr>
<th>OperaTouch<td><td>ChromeWebView エンジン。
<tr>
<th>Yahoo<td><td>AOSP, ChromiumMobile エンジン。
<tr>
<th>UC<td><td>
<tr>
<th>Vivaldi<td><td>
<tr>
<th>QQ<td><td>
<tr>
<th>Yandex<td><td>
<tr>
<th>coccoc<td><td>
<tr>
<th>Camino<td><td>
<tr>
<th>Sogou<td><td>
<tr>
<th>AOL<td><td>Trident エンジン。
<tr>
<th>IceDragon<td><td>
<tr>
<th>Iceweasel<td><td>
<tr>
<th>ITenFourFox<td><td>
<tr>
<th>Waterfox<td><td>
<tr>
<th>GNUzilla<td><td>
<tr>
<th>SeaMonkey<td><td>
<tr>
<th>Basilisk<td><td>
<tr>
<th>Maxthon<td><td>
<tr>
<th>Avant<td><td>
<tr>
<th>Lunascape<td><td>
<tr>
<th>Midori<td><td>
<tr>
<th>OmniWeb<td><td>
<tr>
<th>Roccat<td><td>
<tr>
<th>Epiphany<td><td>
<tr>
<th>WebPositive<td><td>
<tr>
<th>Iron<td><td>
<tr>
<th>ComodoDragon<td><td>
<tr>
<th><del>Brave</del><td><td>特徴無し、Chrome として判定される。
<tr>
<th>Rockmelt<td><td>
<tr>
<th>Sleipnir<td><td>
<tr>
<th>Puffin<td><td>
<tr>
<th>Dooble<td><td>
<tr>
<th>Flock<td><td>
<tr>
<th>Galeon<td><td>
<tr>
<th>Falkon<td><td>
<tr>
<th>Iceape<td><td>
<tr>
<th>KMeleon<td><td>
<tr>
<th>Iris<td><td>WebKit
<tr>
<th>DuckDuckGo<td><td>
</table>
<table>
<caption>In app ブラウザ</caption>
<thead>
<tr>
<th>プロパティ<th>値の例<th>メモ
<tbody>
<tr>
<th>LINE<td><td>
<tr>
<th>Facebook<td><td>
</table>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-60009555431755428782020-07-01T18:43:00.002+09:002021-09-07T03:47:59.460+09:00gulpプラグインのgulp-diamond-princess-zoningを公開しました<div class="box">
<div class="caption" style="width:160px">
<figure><a href="https://2.bp.blogspot.com/-Res5_bucV5M/Xvw4uXrxz0I/AAAAAAAASTg/V8mIEjVD-1MyeZG0IP_rwNN3jlYCiuhrwCLcBGAsYHQ/s1600/gulp-diamond-princess-zoning.png"><img src="https://2.bp.blogspot.com/-Res5_bucV5M/Xvw4uXrxz0I/AAAAAAAASTg/V8mIEjVD-1MyeZG0IP_rwNN3jlYCiuhrwCLcBGAsYHQ/s160/gulp-diamond-princess-zoning.png"></a>
<figcaption><a href="https://www.npmjs.com/package/gulp-diamond-princess-zoning" target="_blank" rel="nofollow me">npm gulp-diamond-princess-zoning</a></figcaption>
</figure>
</div><p>javascript ファイルのビルドに関する gulp プラグインを npm に公開しました。
<p>プラグインは複数の javascript ファイルを一本化します。併せて、パスを元に適宜に即時無名関数 <code>(function(){/* */})();</code> で囲みます。
<p>これによりパス名にもとづくコーディングルールを強制し、Closure Compiler 等で違反が検出できます。またモジュール毎に関数スコープをつくることで、実行時に動的に解決する変数や関数の参照が高速になります、多分。
</div>
<p>レガシーでプアな環境でも動くようにコンパイル結果を意識する、僕のコーディングスタイルでは抜群に貢献してくれています。モダンなモジュールローダー等を利用できるプロジェクトとの相性は悪いと思います。
<hr>
<p>Closure Compiler の advanced ビルドの出力はかなり素晴らしいのですが、この出力を更に最適化したいという欲求からいくつかツールが欲しいと考えています。その最初の一つになります。
<p>この他には SCSS ファイルと javascript ファイルで変数を共有するツール、BEM で冗長になったクラス名や json ファイルのプロパティ名を短縮するツールを準備中です。Enjoy!izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-64769084506843542082020-02-07T02:49:00.002+09:002020-10-11T14:34:30.711+09:00textareaを使った疑似リッチテキストエディタ<div class="box">
<div class="caption" style="width:160px">
<figure>
<a target="_blank" rel="nofollow noopener" href="https://4.bp.blogspot.com/-fY2annlheZo/XjkVevMEhTI/AAAAAAAASJw/hM8nqPcmVFgQGbJok3Bq2GbRBuHTIKqPwCLcBGAsYHQ/s1600/textarea_rte.png"><img src="//4.bp.blogspot.com/-fY2annlheZo/XjkVevMEhTI/AAAAAAAASJw/hM8nqPcmVFgQGbJok3Bq2GbRBuHTIKqPwCLcBGAsYHQ/s160/textarea_rte.png"></a>
<figcaption><a href="https://pettanr.github.io/webframework/RichTextEditor/textarea.html" target="_blank" rel="nofollow noopener me">github で動作を確認する</a></figcaption>
</figure>
</div>
<p>フルスタックの Javascript 製テキストエディタには VSCode で採用されている <a target="_blank" rel="nofollow noopener" href="https://microsoft.github.io/monaco-editor/">Monaco Editor</a> や先駆のひとつといえる <a target="_blank" rel="nofollow noopener" href="https://ace.c9.io/">Ace</a>, Github の開発した <a target="_blank" rel="nofollow noopener" href="https://github.com/atom/atom">Atom</a> といった優れた実装があります。
<p>これらの隙間を縫って、より広範なブラウザに対してそこそこの編集環境をグレイスフルデグラデーションしつつ提供する、という方針でエディタの開発について検討してみます。
<hr>
<p>さて、DOM がなんだかんだいいつつその初期から安定していたのに比してテキスト編集関連の API である <code><textarea></code>, <code>[contentEditable="true"]</code>, <code>iframe.contentDocument.designMode="on"</code> の実装状況は様々であり、その上必ずしも最も古い API の実装が最も充実しているわけでも無いようです。
この記事シリーズでは各 API について愚直に実装しテストすることで、ふんわりと語るしかなかった実装状況をなるべく明らかにしていきたいです。
<p>最初の記事では最も古くからある <code><textarea></code> を使ってエディタを実装しました。この実装では <code><textarea></code> の制約から要素の編集中は HTML ソースが表示されます。この為、<em>疑似</em> WYSIWYG エディタとしています。
</div>
<div class="note">
<p>実は、<a href="/2016/12/textarea-caret-position.html">調査</a>と<a href="/2018/03/pettanR-TextRange.html">ライブラリ化</a>はかなり昔から少しづつ行っていて、実装もかなり以前に終えて記事も書きかけたまま放置していました。
</div>
<table>
<thead>
<tr>
<th><th>クロスブラウザ対応の戦略<th>テキスト編集能力
<tbody>
<tr>
<th>フルスタックエディタ<td>低レベルな API を駆使してフルスクラッチしているので、ブラウザの差異に<em>あまり</em>遭遇しないと思われる<td>数万行の文書の編集でもパフォーマンスを落とさないのは、DOM の再利用やワーカーを駆使しているから、と思われる。
<tr>
<th>そこそこのエディタ<td>ビルトインの編集 API の実装状況のリストを持って、基本的にそれを使う。時には一部機能を諦める。<td>ビルトインの編集 API に頼った実装になるので、ネイティブのスピードが出たり、その限界に拘束されたりする。小~中規模の文書をそこそこ扱えれば良しとする。
</table>
<h2>実装済</h2>
<h3>編集開始</h3>
<ul>
<li>クリックした要素が <code><a target="_blank" rel="nofollow noopener me" href="https://github.com/pettanR/webframework/blob/master/docs/RichTextEditor/data/ddtd.js">DDTD</a></code> に一致する場合、編集エリア化する。
<li>この際のクリック位置が、編集エリアのカーソル位置になる。
<li>この際に選択していたら、編集エリアに反映される。
<li>要素を跨いで選択した場合、ポインターアップ時の要素が編集エリア化する。選択範囲は編集中要素に切り詰められる。
</ul>
<h3>編集エリアの移動</h3>
<ul>
<li>編集エリアの最初にカーソルがある状態で <kbd>←</kbd> を押すと、直前の <code>DDTD</code> に一致する要素に編集を移る。カーソルは行末。
<li>逆。カーソルは先頭。
<li>上下キーによる編集エリアの移動。(要素の行数と各行に存在する文字数から意図した移動が可能)
</ul>
<h3>編集</h3>
<ul>
<li>改行文字の入力で <code><P></code> タグの分割、複数の改行を持つテキストのペーストにも対応
<li>行頭で <kbd>BS</kbd> キーで前の要素と結合、行末で <kbd>DEL</kbd> キーで後の要素と結合
<li>空文字の状態でカーソルを失った際に、その要素は削除する
</ul>
<h2>気づき</h2>
<ul>
<li>IME 変換中のキーイベント(方向キー)は発生しない?
<li>Windows 10 の Firefox と Chrome はカーソルが行末にある場合と次の行頭にある場合で <code>offset</code> 値が同じ… そもそも IE は途中の行の行末にはカーソルがいかない
<li>IE は1行目でカーソル上を押したときカーソルがホーム位置に行かない、最終行でカーソル下を押した場合にカーソルがエンド位置に行かない
<li>IE8 以下では <code>textarea</code>, <code>input[type=text]</code> にフォーカスする際にタイマーを挟む必要がある
<li>IE では9以上でサポートした <code>selection</code> を使うとクリックで編集をはじめた際に1文字が選択される
<li>IE では rect の補正が必要。その補正法は IE11 の IE8 モードと IE7 モードでも差異がある。
<li><code>.select()</code> 出来ない問題、iOS, Android の Firefox Chrome では <code>click</code> イベント内で <code>focus()</code> を与える。
</ul>
<h2>未実装</h2>
<ul>
<li>キー入力時に編集エリアのカーソル位置が画面外なら、スクロールする。但し Firefox 58 はブラウザ側でスクロールした。<code><textarea></code> 内のカーソル位置からピクセル座標を取得するには隠し要素による測定が必要。
<li>初期の Chromium で <code><textarea></code> に対して CSS が無視される。(Iron 5 で確認。)<code>width</code> でなく <code>cols</code> 等を使う。
</ul>
<h2>メモ</h2>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="http://d.hatena.ne.jp/zariganitosh/20110530/textedit_bookmarklet">ザリガニが見ていた...。『テキスト編集を強力にサポートするブックマークレット作り』</a>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/hrdaya/items/6488d8dd3962cf35c0a0">jQueryでIME入力確定時にイベントを発行する</a>
<li><a target="_blank" rel="nofollow noopener" href="http://tanishiking24.hatenablog.com/entry/ime-event-handling-javascript">JavaScript とクロスブラウザでの IME event handling (2017年)</a>
<li><a target="_blank" rel="nofollow noopener" href="http://d.hatena.ne.jp/dayflower/20080423/1208941641">選択範囲の取得について調べた</a>
</ul>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-3773000604863367822019-12-27T14:07:00.001+09:002020-07-01T18:44:03.008+09:00何故かVSCode拡張だった汎用プリプロセッサをgulpプラグインに移行しました<p><a href="/2016/10/iz-preprocessor.html">VSCode 拡張として開発していた</a>コメントベースの汎用プリプロセッサ iz-preprocessor は gulp プラグインに移行しました。<a target="_blank" rel="nofollow noopener me" href="https://github.com/itozyun/iz-preprocessor/commit/a5c2a8da4eeda45bc713868c012d67adb24cdb98">今月に見つかったバグを修正</a>したものを Visual Studio マーケットプレイスに登録したのを最後に、VSCode 拡張での更新は提供されないと思います。
<h2>gulp プラグイン化と npm への登録</h2>
<div class="box">
<div class="caption" style="width:160px">
<figure>
<a target="_blank" rel="nofollow noopener me" href="https://3.bp.blogspot.com/-fsJD69gGOK0/XgWCuNqLpbI/AAAAAAAASEs/P6UL9tquXI4sgLZ9YKii0ovj07hKSQNPQCLcBGAsYHQ/s1600/npm-gulp-iz-preprocessor.png"><img src="//3.bp.blogspot.com/-fsJD69gGOK0/XgWCuNqLpbI/AAAAAAAASEs/P6UL9tquXI4sgLZ9YKii0ovj07hKSQNPQCLcBGAsYHQ/s160/npm-gulp-iz-preprocessor.png"></a>
<figcaption><a target="_blank" rel="nofollow noopener me" href="https://www.npmjs.com/package/gulp-iz-preprocessor">gulp-iz-preprocessor</a> npm</figcaption>
</figure>
</div>
<p>Qiita の記事『<a target="_blank" rel="nofollow noopener" href="https://qiita.com/ousttrue/items/7f19291b8cee110a947a">gulpでスタティックなサイトを生成する</a>』を参考に gulp プラグインの作法で書き換えたところ、コードが短くなり、ビルド作業が楽になる、といい事ずくめでした。
<p>何よりも <strong>Visual Studio Code とその拡張が不要になったことで他の開発者にも触ってもらいやすくなった</strong>のが大きいです。今にしたら、何故 VSCode 拡張で実装してしまったのか、不思議です。
</div>
<h3>若干の不満、ファイルが欠落する</h3>
<div class="box">
<div class="caption" style="width:160px">
<figure>
<a target="_blank" rel="nofollow noopener me" href="https://3.bp.blogspot.com/--2dl8Qw-l9I/XgWCvLCQfQI/AAAAAAAASEw/bIXx8S-UTzYd7zUg0u3Kd7-gK1EBcl99gCLcBGAsYHQ/s1600/visualstudio-marketplace-iz-preprocessor.png"><img src="//3.bp.blogspot.com/--2dl8Qw-l9I/XgWCvLCQfQI/AAAAAAAASEw/bIXx8S-UTzYd7zUg0u3Kd7-gK1EBcl99gCLcBGAsYHQ/s160/visualstudio-marketplace-iz-preprocessor.png"></a>
<figcaption><a target="_blank" rel="nofollow noopener me" href="https://marketplace.visualstudio.com/items?itemName=itozyun.iz-preprocessor">iz-preprocessor</a> Visual Studio Marketplace</figcaption>
</figure>
</div>
<p>まれに <code>gulp.src()</code> でピックアップされるファイルが欠落するようで、<code>gulp-sass</code> でコケる時があります。この場合は、再実行すると成功します。
<p>このような問題は VSCode 拡張では、<code>fs</code> をラップして常に非同期で処理できるようにした <code><a target="_blank" rel="nofollow noopener me" href="https://github.com/itozyun/iz-preprocessor/blob/master/libs/izFS.js">izFS</a></code> を使いだしてからは遭遇していませんでした。その点だけが不便です。
<p>しかし再実行の手間と、以前のように拡張機能を実行してから gulp タスクを実行する手間を比べれば、僕は前者に軍配を上げます。gulp のアップデートで将来に改善されることを期待します。
</div>
<hr>
<p>続いても Qiita の記事『<a target="_blank" rel="nofollow noopener" href="https://qiita.com/TsutomuNakamura/items/f943e0490d509f128ae2">初めてのnpm パッケージ公開</a>』を参考に npm の登録も終え version 1.0.0 を公開することが出来ました。
<h2>gulp-util の注意</h2>
<p>先に紹介した gulp プラグイン作成の記事では、<code>gulp-util</code> を <code>reguire</code> してプラグイン作成を進めていますが、現在 gulp-util は <samp>Deprecated</samp> です。最終の 3.0.8 が公開されたのは2016年12月となっています。しかし現在の週間ダウンロード数は75万です。
<blockquote cite="https://www.npmjs.com/package/gulp-util" title="gulp-util npm"><h3>This package has been deprecated<br>
Author message:</h3>
<p>gulp-util is deprecated - replace it, following the guidelines at <a target="_blank" rel="nofollow noopener" href="https://medium.com/gulpjs/gulp-util-ca3b1f9f9ac5">https://medium.com/gulpjs/gulp-util-ca3b1f9f9ac5</a></blockquote>
<p>僕は 1.0.0 の公開直後に気が付いて、提示されている記事を元にプラグインを書き換えました。gulp-util はパッケージを纏めて名前空間を付けているだけのようで、プラグインに必要なパッケージだけを <code>reguire</code> するように書き換えました。<a target="_blank" rel="nofollow noopener me" href="https://github.com/itozyun/gulp-iz-preprocessor/commit/7544be5aa3b89b3830528714f2aa6355133df85c">依存パッケージが減って</a>満足です。これを version 1.0.1 として公開しました。
<p>本件に関する日本語の記事『<a target="_blank" rel="nofollow noopener" href="https://ohbarye.hatenablog.jp/entry/2017/12/30/203317">gulp-util の問題、deprecation warning と migration path について</a>』がこの文書の執筆にあたって理解を助けてくれました。ありがとうございます。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-61528578531911534202019-06-25T13:48:00.002+09:002021-04-19T13:47:16.464+09:00サムスンによる魔改造Webブラウザ、Samsung Internet の判定<h2>Samsung Internet 2.0 未満の闇</h2>
<p>サムスンが自社のスマートフォンに AOSP stock browser に替えてインストールしていた Samsung Internet には、めくるめくバグが存在したようです。この判定を正しくしたいと思い立って調べました。
<p>残念ながら、未だ実機は手元にありません。
<blockquote title="おや… S Browser 三銃士 の様子が…" cite="https://gist.github.com/uupaa/b25c9cf47bbeedea5a7f">
<ul>
<li>サムスンが Chromium を魔改造して創りだしたブラウザ
<li>Android Browser の代わりに docomo や au の端末に搭載されている
<li>S Browser は Canvas API の描画が壊滅的。全くマトモじゃない
</ul>
<p>(中略)
<ul>
<li>Chrome なら本来サポートしている機能が、S Browser では OFF にされているとか、I/Fはあるけど実装が空っぽとかがある
<li>Chrome for Android は更新されるが、S Browser はアップデートされない
</ul>
<p>(中略)
<p>Android 4.4 から Android Browser は Chrome WebView をベースにしているとのことなので、ちょっと古めの Chrome という扱いで良さそうです。
</blockquote>
<p>uupaa氏による上記文書には、<q cite="https://gist.github.com/uupaa/b25c9cf47bbeedea5a7f">S Browser が初めて登場したのは、Galaxy S4 (SC-04E) です</q>、とあります。SC-04E は<a href="https://ja.wikipedia.org/wiki/SC-04E">2013年5月23日の発売</a>、4.2.2 が出荷時の Android OS のバージョンでした。また Galaxy S4 の世界で最初の発売は<a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_S4">2013年4月27日</a>でした。
<p>しかし、サムスンの開発者向けサイトによると、2012年から Galaxy の標準ブラウザを Samsung Internet に置き換えました、とザックリと書かれていて焦りました。<a href="https://en.wikipedia.org/wiki/Samsung_Galaxy">英語版 Wikipedia によると</a>、2012年にサムスンは実に25モデルの Galaxy 端末を発売しています。一体、どのデバイスから、或いはどの Android バージョンから Samsung Internet が使われているのでしょう?
<blockquote title="Samsung Internet | SAMSUNG Developers > Overview for Android" cite="https://developer.samsung.com/internet"><p>It has replaced the stock Android browser on Samsung Galaxy devices since 2012, to provide a browser highly optimized for our devices.</blockquote>
<h2>Samsung Internet のバージョンを知る</h2>
<p>uupaa氏の<a href="https://gist.github.com/uupaa/b25c9cf47bbeedea5a7f">先の文書</a>によるとSC-04Eの <code>userAgent</code> 文字列中の <samp>Version/</samp> に続く数字が Samsung Internet のバージョンを示しているらしいことが分かります。
<p>幸いに Android 4.4.4 以降の Galaxy の <code>userAgent</code> には、<samp>SamsungBrowser/</samp> が登場します。4.4.4 にプリインストールされている Samsung Internet のバージョンは 2.0 になるようです。
<p>そして、2013年4月より前に発売された Galaxy の標準ブラウザの <code>userAgent</code> には、<samp>Version/</samp> がありませんが、1.0未満のバージョンの Samsung Internet となるようです。
<h3>2012年から2013年4月のいつから Samsung Internet になった?</h3>
<p>公式のドキュメントが無い以上は、あたりをつけて端末を手に入れて、不具合の変化を Android 標準ブラウザと比較するほかありません。などと考えていたところ、<a href="https://gist.github.com/NielsLeenheer/4daa6a9ce7f4a0f4733d">凄いまとめドキュメント</a>が存在しました。
<p>NielsLeenheer 氏によるドキュメントによって、同時代のサムスンスマートフォンでありながら Samsung Internet がインストールされていないものがあることが分かります。フラッグシップモデルに対しては早くから Samsung Internet がインストールされていた一方で、廉価なモデルには AOSP がインストールされていたようです。他の Android 端末と同じブラウザを備えた廉価版の方がUXが良かったのでは、と想像されいろいろ業が深いです。
<p>ところで NielsLeenheer 氏がどうやってこの表を作成したのか?解説を見つけることが出来ませんでした。おそらくは HTML5 Test のスコアを元に、Samsung Internet の判定を行ったと想像します。もちろん HTML5 Test の公開するデータは偽装されたユーザーエージェントから送られたものである可能性もあるため、必ずしも正確なものではありません。
<h2>Samsung Internet 2.0 未満の表</h2>
<p>次は NielsLeenheer 氏のドキュメントを表にまとめたものです。ユーザーエージェント文字列には各デバイスの型番が書かれているケースが多いです。この型番を利用することで、Samsung Internet の判定の可能性が見えてきました。
<table>
<thead>
<tr>
<th rowspan=3>Device<th>Samsung Version<th>?<th>?<th>1.0<th colspan=3>1.5<th>1.6
<tr>
<th>HTML5 Test Score<th>326<th>346<th>402<th>420<th>425<th>430<th>460
<tr>
<th>Based Engine<th colspan=2>Webkit 534.30<th>Chromium 18<th colspan=4>Chromium 28
<tbody>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_S_III">S III</a><td>4.0.4<td>4.1.2, 4.3<td><td><td><td><td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Ace_2">Ace 2</a><td><td>4.1.2<td><td><td><td><td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Core">Core</a><td><td>4.1.2<td><td><td>4.3<td><td>4.4.2
<tr>
<th colspan=2><a href="https://www.gsmarena.com/samsung_galaxy_core_plus-5842.php">Core Plus</a><td><td>4.2.2<td><td><td><td><td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Note_(original)">Note</a><td><td>4.1.2<td><td><td><td><td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Note_II">Note II</a><td><td>4.1.2, 4.3<td><td><td><td><td>4.4.2
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Note_8.0">Note 8.0</a><td><td>4.1.2<td><td><td><td><td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Note_10.1">Note 10.1</a><td><td>4.1.2<td><td><td><td><td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_S_II">S II</a><td><td>4.1.2<td><td><td><td><td>
<tr>
<th colspan=2><a href="https://www.gsmarena.com/samsung_i9105_galaxy_s_ii_plus-5213.php">S II Plus</a><td><td>4.2.2<td><td><td><td><td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_S_III_Mini">S III Mini</a><td><td>4.1.2<td><td><td><td><td>
<tr>
<th colspan=2><a href="https://www.gsmarena.com/samsung_i8200_galaxy_s_iii_mini_ve-6190.php">S III Mini VE</a><td><td>4.1.2<td><td><td><td><td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Tab_2_7.0">Tab 2 (7.0)</a><td><td>4.1.2, 4.2.2<td><td><td><td><td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Tab_2_10.1">Tab 2 (10.1)</a><td><td>4.1.2, 4.2.2<td><td><td><td><td>
<tr>
<th colspan=2><a href="https://ameblo.jp/povtc/entry-11621797582.html">Trend 3</a><td><td>4.3<td><td><td><td><td>
<tr>
<th colspan=2><a href="https://www.gsmarena.com/samsung_galaxy_s_duos_2_s7582-5876.php">Trend Plus</a> <q cite="https://www.gsmarena.com/samsung_galaxy_s_duos_2_s7582-5876.php">Also known as Samsung Galaxy Trend Plus S7580</q><td><td>4.2.2<td><td><td><td><td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Young">Young</a><td><td>4.1.2<td><td><td><td><td>
<tr>
<th colspan=2><a href="https://www.gsmarena.com/samsung_galaxy_ace_3-5479.php">Ace 3</a><td><td><td>4.2.2<td><td><td><td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Mega">Mega 5.8</a><td><td><td>4.2.2<td><td><td><td>
<tr>
<th colspan=2>Mega 5.8 Plus<td><td><td>4.2.2<td><td><td><td>
<tr>
<th colspan=2>Mega 6.3<td><td><td>4.2.2<td><td><td>4.4.2<td>
<tr>
<th colspan=2>S4<td><td><td>4.2.2<td><td>4.3<td>4.4.2 or 4.4.4<td>4.4.2
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_S4_Mini">S4 Mini</a><td><td><td>4.2.2<td><td><td>4.4.2 or 4.4.4<td>4.4.2
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Win">Win</a><td><td><td>4.2.2<td><td><td><td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Note_3">Note 3</a><td><td><td><td>4.3<td><td>4.4.2 or 4.4.4<td>4.4.2
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Grand_2">Grand 2</a><td><td><td><td><td>4.3<td>4.4.2<td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Note_3_Neo">Note 3 Neo</a><td><td><td><td><td>4.3<td>4.4.2<td>
<tr>
<th colspan=2><a href="https://www.gsmarena.com/samsung_galaxy_note_10_1_(2014)-5677.php">Note 10.1 (2014)</a><td><td><td><td><td>4.3<td>4.4.2<td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_S_III">S3 Neo</a><td><td><td><td><td>4.3<td>4.4.2 or 4.4.4<td>
<tr>
<th colspan=2><a href="https://www.gsmarena.com/samsung_galaxy_light-5786.php">Light</a><td><td><td><td><td><td>4.4.2<td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Note_Pro_12.2">Note Pro</a><td><td><td><td><td><td>4.4.2<td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_S4_Active">S4 Active</a><td><td><td><td><td><td>4.4.2<td>
<tr>
<th colspan=2><a href="https://www.gsmarena.com/samsung_i9506_galaxy_s4-5542.php">S4 Advance</a><td><td><td><td><td><td>4.4.2<td>
<tr>
<th colspan=2><a href="https://www.gsmarena.com/samsung_i9505_galaxy_s4-5371.php">S4 VE(Neo)</a><td><td><td><td><td><td>4.4.2<td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Tab_4_7.0">Tab 4 (7.0)</a><td><td><td><td><td><td>4.4.2<td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Tab_4_8.0">Tab 4 (8.0)</a><td><td><td><td><td><td>4.4.2<td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Tab_4_10.1">Tab 4 (10.1)</a><td><td><td><td><td><td>4.4.2<td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Tab_Pro_8.4">Tab Pro 8.4</a><td><td><td><td><td><td>4.4.2<td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Tab_Pro_10.1">Tab Pro 10.1</a><td><td><td><td><td><td>4.4.2<td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Tab_S_8.4">Tab S 8.4</a><td><td><td><td><td><td>4.4.2<td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Tab_S_10.5">Tab S 10.5</a><td><td><td><td><td><td>4.4.2 or 4.4.4<td>
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_A3_(2015)">A3</a><td><td><td><td><td><td><td>4.4.4
<tr>
<th colspan=2><a href="https://www.gsmarena.com/samsung_galaxy_a5-6761.php">A5</a><td><td><td><td><td><td><td>4.4.4
<tr>
<th colspan=2><a href="https://www.gsmarena.com/samsung_galaxy_alpha-6573.php">Alpha</a><td><td><td><td><td><td><td>4.4.4
<tr>
<th colspan=2><a href="https://www.gsmarena.com/samsung_galaxy_k_zoom-6210.php">K Zoom</a><td><td><td><td><td><td><td>4.4.2
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_Mega_2">Mega 2</a><td><td><td><td><td><td><td>4.4.4
<tr>
<th colspan=2><a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_S_III_Neo">S III Neo</a><td><td><td><td><td><td><td>4.4.2
<tr>
<th colspan=2><a href="https://www.gsmarena.com/samsung_galaxy_s5-6033.php">S5</a> <a href="https://www.gsmarena.com/samsung_galaxy_s5_lte_a_g906s-6450.php">LTE</a><td><td><td><td><td><td><td>4.4.2 or 4.4.4
<tr>
<th colspan=2><a href="https://www.gsmarena.com/samsung_galaxy_s5_active-6356.php">S5 Active</a><td><td><td><td><td><td><td>4.4.2 or 4.4.4
<tr>
<th colspan=2><a href="https://www.gsmarena.com/samsung_galaxy_alpha_(s801)-6580.php">S5 Alpha</a>(?)<td><td><td><td><td><td><td>4.4.4
<tr>
<th colspan=2>S5 Mini<td><td><td><td><td><td><td>4.4.2
</table>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-9326783289087515892018-10-06T13:27:00.000+09:002021-07-13T15:02:31.784+09:00貴方のBloggerの閲覧性を爆上げする!テンプレート式でデスクトップ版(m=0)を判定するには?<h2>Bloggerのテンプレートでレイアウトバージョン2を使い続ける理由</h2>
<p>Google のブログサービス“Blogger”はユーザーの手でブログテンプレートに様々なカスタマイズを施すことが出来る点が大きな魅力の一つです。本記事のテーマに係るカスタマイズ項目では、デスクトップ用のテンプレートに条件分岐を追加してモバイル用に最適化したページを用意することができます。
<p>訪問者に表示させるのはデスクトップ版か、モバイル版か?この判断は通常、 Blogger 側で行います。そして URL パラメータ(<code>?m=1</code>)を付与することで、訪問者側からデスクトップ版またはモバイル版を強制することができます。
<p>しかし、この機能は最新のレイアウトバージョン3(<code>b:layoutsVersion='3'</code>)では削除されています。より高度な機能が利用できるバージョン3ですが、これが理由でバージョン2を使い続けています。</p>
<table>
<thead>
<tr>
<th>種類<td>urlの例<td>テンプレート式
<tbody>
<tr>
<th>Blogger が判断<td><code>outcloud.blogspot.com</code><td>
<tr>
<th>モバイル版を表示<td><code>outcloud.blogspot.com?m=1</code><td><code>data:blog.isMobile</code>
<tr>
<th>デスクトップ版を表示<td><code>outcloud.blogspot.com?m=0</code><td>以下で紹介
</table>
<h2>デスクトップ版の判定が必要になるケース</h2>
<p>訪問者が所望の版で閲覧し続ける為には、ページ内の各リンクに対し適宜に<code>m</code>パラメータが付与されている必要があります。
<p><code>m</code>パラメータは基本的に、各ウィジェットのアイテムの url にあらかじめ付与されています。このためテンプレート開発者はほとんどの場面で、Blogger が判断か?モバイル版か?デスクトップ版か?意識することはありません。
<p>しかし次のケースでは、テンプレート内でデスクトップ版の要求を判定して<code>m</code>パラメータを付与する必要がありました。
<ul>
<li>ウィジェットに依らずに独自のリンクを設定している
<li>検索ウィジェットはパラメータを付与しないので追加してあげる
</ul>
<h2>デスクトップ版を調べるテンプレート式</h2>
<p>次がデスクトップ版を判定するテンプレート式になります。レイアウトバージョン2、デフォルトウィジェットバージョン2(<code>b:defaultwidgetversion='2'</code>)で動作確認しています。
<div class="note">デフォルトウィジェットバージョン1で、Blog ウィジェット内限定であれば、<a href="/2016/09/search-box.html"><code><data:mobileLinkUrl/></code> が真ならデスクトップ版</a>でした。</div>
<p><code>data:blog.homepageUrl.http</code> と <code>data:blog.homepageUrl.canonical.http</code> の文字数の差を調べる、という手法です。各所に混乱を招いていた国別ドメインへのリダイレクトがいつの間にか終わっていたので、4文字差の判定だけをすればOKでした。
<p><code>m</code>以外の一文字パラメータが実は存在していたり、今後追加された場合には動作が保証されないという歯がゆい手管です。
<div class="hscroll">
<pre class="prettyprint lang-xml"><code><b:with var='isDesktop' value='!data:blog.isMobile and ((data:blog.homepageUrl.http.length - data:blog.homepageUrl.canonical.http.length) == 4)'>
<b:if cond='data:isDesktop'>
Desktop version requested.
</b:if>
</b:with>
</code></pre>
</div>
<h3>BlogSearchウィジェットが<code>m=0</code>を付与する改造</h3>
<p>直前で <code>data:blog.isMobile</code> の条件分岐をしているため、上記コードから <code>!data:blog.isMobile</code> を省いています。併せて <a href="/2016/09/search-box.html">【Blogger改造】完璧な検索窓設置のためのポイント2つ</a> もご参考に。
<div class="hscroll">
<pre class="prettyprint lang-xml"><code><b:widget id='BlogSearch1' locked='true' type='BlogSearch' visible='true' mobile='yes'>
<b:includable id='main'>
<form expr:action='data:blog.searchUrl' method='get'>
<b:if cond='data:blog.isMobile'>
<input name='m' type='hidden' value='1'/>
<input name='max-results' type='hidden' value='10'/>
<b:elseif cond='(data:blog.homepageUrl.http.length - data:blog.homepageUrl.canonical.http.length) == 4'/>
<input name='m' type='hidden' value='0'/>
<input name='max-results' type='hidden' value='20'/>
<b:else/>
<input name='max-results' type='hidden' value='20'/>
</b:if>
<input type='text' name='q' autocomplete='off' autocapitalize="off" expr:placeholder='data:title' expr:title='data:title' expr:value='data:blog.searchQuery'/>
<input expr:value='data:messages.search' type='submit'/>
</form>
</b:includable>
</b:widget>
</code></pre>
</div>
<h3>動かなかったコード片</h3>
<p>以下、動かなかったコードです。url を文字列として扱っても、何故か上手くいきません。
<div class="hscroll">
<pre class="prettyprint lang-xml"><code><b:eval expr='( data:blog.url.jsEscaped contains &quot;?m\x3d0&quot; )' />
<b:eval expr='( data:blog.url.jsonEscaped contains &quot;?m\u003d0&quot; )' />
<b:eval expr='( data:blog.url.cssEscaped contains &quot;?m=0&quot; )' />
<b:eval expr='( data:blog.url == appendParams( data:blog.url, { m : &quot;0&quot; } ) )' />
<b:eval expr='( ( &quot;&quot; + data:blog.homepageUrl.jsEscaped ) contains &quot;?m\x3d0&quot; ) or ( ( &quot;&quot; + data:blog.homepageUrl.jsEscaped ) contains &quot;\x26m\x3d0&quot; )'>
</code></pre>
</div>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-33990543918478378532018-09-20T12:32:00.001+09:002021-07-13T15:04:03.306+09:00CleanCSSとmerge-media-queryでCSSのminifyを徹底的にやってみた<div class="note">
<p>"Data URI スキームで埋め込んだテスト用のWebフォント"の温存が変わったか、誤っていたため修正しました。(2019/12/11, gulp-clean-css@4.2.0)
<p><code>clean-css ignore:start</code>指定について追記しました。(2018/10/4)</div>
<p>当ブログでは CSS の minify に <a title="Bloggerのファイル置き場をGoogle DriveからDropboxへ、CSSのブラウザ別ビルド、SMACSS導入など" href="/2016/08/goodbye-gdrive.html">CleanCSS</a> を使用しています。この度はまだまだ minify 出来ることに気づいたので腰を据えて設定を詰めました。
<p>併せて導入した <a target="_blank" rel="nofollow" href="https://www.npmjs.com/package/gulp-merge-media-queries">gulp-merge-media-queries</a> のお陰で冗長な <code>@media</code> をゼロにできました。その上、これまでは同一の <code>@media</code> 毎に拡張コメントで囲んで独自ツールで並び替えていましたが、これが不要なことが分かりました。
<ol>
<li>CleanCSS の minify 設定がデフォルトだったのを最高レベルに。
<li>gulp-merge-media-queries を導入して冗長な <code>@media</code> を無くす。
</ol>
<p>これにより<strong>ファイルサイズを2割近く削減</strong>することが出来ました。
<h2>CleanCSSの最高レベルのminify設定</h2>
<p>最高レベルの minify 結果を得るために、パラメータを書き換えつつ出力結果を確認する、を繰り返す必要がありました。詳しいパラメータは <a target="_blank" rel="nofollow" href="https://github.com/jakubpawlowicz/clean-css#optimization-levels">CleanCSS@Github</a> に掲載されています。
<h3>gulp.js の一部</h3>
<p>この度、到達した設定は次の通りです。
<div class="hscroll">
<pre class="prettyprint lang-js"><code>cleanCSS({
level: {
1: {
// rounds pixel values to `N` decimal places; `false` disables rounding; defaults to `false`
roundingPrecision : 3
},
2: {
// controls duplicate `@font-face` removing; defaults to true
removeDuplicateFontRules: true,
// controls duplicate `@media` removing; defaults to true
removeDuplicateMediaBlocks: true,
// controls duplicate rules removing; defaults to true
removeDuplicateRules: true,
// controls semantic merging; defaults to false
mergeSemantically: true,
// controls unused at rule removing; defaults to false (available since 4.1.0)
removeUnusedAtRules: true,
// controls rule restructuring; defaults to false
restructureRules: true
}
}
});
</code></pre>
</div>
<!--p><del>ところで、レガシーブラウザの為に敢えて重複させているプロパティの保護(<code>/* clean-css ignore:start */ ... /* clean-css ignore:end */</code>)が必要かと考えていましたが、上記設定でも意図したようにプロパティは残りました。</del-->
<h3>1. ignore 指定の追加</h3>
<p>CleanCSS の <code>level:2</code> では重複する CSS プロパティを削除し、複数のプロパティをマージします。レガシーブラウザ向けに敢えて重複させたり、冗長にしているプロパティを保護するため、<code>clean-css ignore:start</code>~<code>clean-css ignore:end</code> を追加しました。今回この指定が必要だったのは本件では次のプロパティに対してでした。
<h4>-webkit-transition</h4>
<p>古い WebKit ブラウザ用に -webkit-transition-property を分けたのをマージから保護します。
<div class="hscroll">
<pre class="prettyprint lang-css"><code>a:link, a:visited {
background-color : rgba( 0, 0, 0, 0 );
/* clean-css ignore:start */
-webkit-transition-property : background-color, color, border-color;
-webkit-transition : 0.3s ease-in;
/* clean-css ignore:end */
-moz-transition : background-color 0.3s ease-in, color 0.3s ease-in, border-color 0.3s ease-in;
-o-transition : background-color 0.3s ease-in, color 0.3s ease-in, border-color 0.3s ease-in;
transition : background-color 0.3s ease-in, color 0.3s ease-in, border-color 0.3s ease-in;
}
</code></pre>
</div>
<h4>Data URI スキームで埋め込んだテスト用のWebフォント</h4>
<p><del>Webフォントの可否を調べるために小さな Web フォントを Data URI スキームで埋め込んでいました。この Web フォントは javascript で利用するため、.scss 中ではどこからも <code>font-family:</code> で参照されていませんでした。この為に Web フォントが削除されてしまうのを保護しました。</del>
<p><ins><code>level : { 2 : { removeUnusedAtRules: false } }</code></ins>をオプション設定することで回避しました。
<h3>2. リンクのインタラクションの副作用</h3>
<p>CleanCSS では適宜に指定を纏めて出現順を入れ替えます。この為にリンクのインタラクション周りで、<em>出現順に依存する曖昧な指定</em>を行っていた場合、不具合に遭遇しやすいようです。
<p><code>:link</code>, <code>:visited</code> それぞれに、<code>:hover</code>, <code>:focus</code>, <code>:active</code>, <code>:focus:hover</code>, <code>:active:hover</code> を設定していきます。本ブログの記事『<a href="/2016/10/link-interaction.html">リンクテキストのインタラクションを整理する</a>』もご参考に、タブフォーカスなど突き詰めていくと結構冗長なコードが必要になります。
<div class="hscroll">
<pre class="prettyprint lang-css"><code>:link, :visited { text-decoration : underline; }
:link:hover , :visited:hover,
:link:focus , :visited:focus,
:link:active, :visited:active { text-decoration : none; }
:link:focus:hover, :visited:focus:hover,
:link:active:hover, :visited:active:hover { text-decoration : underline !important; }
</code></pre>
</div>
<h2>gulp-merge-media-queriesで<code>@media</code>の重複を無くす</h2>
<p>CleanCSS でも <code>@media</code> をマージしてくれますが完全ではありませんでした。今回 merge-media-queries を導入すると <code>@media</code> の重複を完全に無くすことができました。
<p>単位を統一することでメディアクエリを正しく並び替えてくれます。<code>(max-width: ...)</code>, <code>(min-width: ...)</code> が混在していても大丈夫でした。メディアクエリは通常は px 単位が使われますが、当ブログではフォントサイズベースのレイアウトの為、em を使用しています。
<pre class="prettyprint lang-css"><code>handheld, projection, tv, only screen and (min-width: 801px){...}
↓
handheld, projection, tv, only screen and (min-width: 50.06em){...}
</code></pre>
<p>当初、merge-media-queries を CleanCSS の前に実行しましたが、冗長な <code>@media</code> が残ってしまいました。CleanCSS である程度マージしたものを merge-media-queries に渡すフローにすると冗長の無い CSS が得られました。
<p>この段階では空白文字が残るため、CleanCSS をもう一度使ってこれを除きました。この際には <code>level:1</code> で空白文字だけを除去する設定にします。
<h3>gulp.js の全体、最初の cleanCSS() のパラメータは省略してある</h3>
<pre class="prettyprint lang-js"><code>var gulp = require('gulp'),
sass = require("gulp-sass"),
cleanCSS = require("gulp-clean-css"),
plumber = require("gulp-plumber"),
mmq = require("gulp-merge-media-queries");
gulp.task('sass', function() {
return gulp.src(['R:/precompiled/*.scss'])
.pipe(plumber())
.pipe(sass())
.pipe(cleanCSS({
level: {
1: {...},
2: {...}
}
}))
.pipe(mmq())
.pipe(cleanCSS({
level: {
1: {
// set all values to `false`
all: false,
// controls removing unused whitespace; defaults to `true`
removeWhitespace: true
}
}
}))
.pipe(gulp.dest('./dest'));
});
</code></pre>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-84670521108927492782018-08-25T14:05:00.002+09:002018-09-22T12:07:35.215+09:00大阪で保管中のパソコン用ハードの記録<p>大掃除を経て棚卸もできたので、ここでリストを制作しておきます。部品よりもパソコンが多いあたり、闇が深いです…</p>
<div class="hscroll">
<table>
<caption>マザーボード</caption>
<thead>
<tr>
<th>型番<th>ソケット<th>規格<th>メモ
<tbody>
<tr>
<th>PCA-6145B/45L<td><td>PCI<td>Intel DX4付。
<tr>
<th>V75M<td>Socket7<td>Micro ATX<td><!-- ハードオフにて108円で購入。-->
<tr>
<th>AX59PRO<td>Socket7<td>ATX<td><!-- ハードオフにて108円で購入。-->
<tr>
<th>P55VP3<td>Socket7<td>ATX<td>日本橋にて1480円で購入。K6-2+ 533Mhz付。
<tr>
<th>P/I-P55T2P4 rev.3.0<td>Socket7<td>AT<td>日本橋にて500円で購入。K6 200ALR付。
<tr>
<th><del>MX46-533V</del><td>socket478<td>Micro ATX<td>会社の廃棄を貰う。Celeron 1.7GHz + DDR400 1GB 付。現在は実家?
<tr>
<th><a href="https://www.gigabyte.com/Motherboard/GA-586SG#sp" rel="nofollow" target="_blank" title="gigabyte.com">GA-586SG</a><td>Socket7<td>AT<td><a href="https://akiba-pc.watch.impress.co.jp/hotline/980124/sis5591.html" rel="nofollow" target="_blank" title="秋葉ホットライン">1998年1月に発売</a>。日本橋で購入。
<tr>
<th>IQ77T<td>LGA775<td><td>Think Centre M92p Tiny 専用。
<tr>
<th>P5B-V<td>LGA775<td>ATX<td>会社の廃棄をフルATXのケース目当てで貰う。壊れてる?
</table>
</div>
<div class="hscroll">
<table>
<caption>ビデオカード</caption>
<thead>
<tr>
<th>型番<th>スロット<th>メモ
<tbody>
<tr>
<th>Tornedo GeForce4 MX440 128MB<td>PCI<td>
<tr>
<th>Radeon 7000 64MB<td>PCI<td>
<tr>
<th>ASUS AGP-V9570/TD 256M<td>AGP<td>でっかいヒートシンク付。日本橋で300円で購入。
<tr>
<th>型番不明<td>AGP<td>でっかいヒートシンク付。日本橋で300円で購入。
<tr>
<th>Voodoo3 3500TV<td>AGP<td>
<tr>
<th>NX6600-VTD256EH<td>PCI Express<td><a href="/2013/03/blog-post.html">GA-965P-DQ6 機に刺していたもの</a>。
<tr>
<th>MSI N260GTX T2D896-OC BATMAN<td>PCI Express<td>GA-965P-DQ6 機に搭載。
</table>
</div>
<div class="hscroll">
<table>
<caption>パソコン</caption>
<thead>
<tr>
<th>型番<th>タイプ<th>CPU<th>メモ
<tbody>
<tr>
<th>DELL Think Centre M92p Tiny<th rowspan=4>デスクトップ<td>Core i5-3470T<td>
<tr>
<th>GA-965P-DQ6 機<td>Core 2 Duo<td>
<tr>
<th>Sony VAIO MXS1<td>Pentium 4<td><a href="https://youtu.be/fy1vYxY5Y3Y" target="_blank" rel="nofollow" title="YouTube 分解清掃1">分解清掃1</a> <a href="https://youtu.be/I4Pg3ufBHlA" target="_blank" rel="nofollow" title="YouTube 分解清掃2">2</a> <a href="https://youtu.be/rAGXHUYvdqA" target="_blank" rel="nofollow" title="YouTube 分解清掃3">3</a>
<tr>
<th>EPSON Endeavor ST100<td>Core 2 Duo<td><a href="/search/label/PC%3AST100">実家の母が使っていたが不調のため現在は大阪</a>。
<tr>
<th>SOTEC AFiNA Style AFS270TX2-M<th rowspan=2>モニタ一体型<td><td>モニタ割れ。
<tr>
<th>DAEWOO Qrium CM6570-JPAT<td>Pentium 3<td>
<tr>
<th>HP Compaq t5720 HSTNC-001L-TC<th rowspan=2>シンクライアント<td>Geode<td>2台。
<tr>
<th><a href="http://www.mintwave.co.jp/download/pdf/cute40U_StartupGuide.pdf" rel="nofollow" target="_blank" title="pdf MiNT-ACC cute-40U
スタートアップガイド">MiNT-ACC cute-40U</a><td>VIA Eden 400Mhz<td>4台。<a href="http://www.keyman.or.jp/nw/20024131/" target="_blank" rel="nofollow" title="ミントウェーブ、各種SBC対応のノート型シンクライアント等発売">2008年11月5日発売</a>。
<tr>
<th>Dell Latitude D420 PP09S<th rowspan=2>ノート<td>Core Duo<td><a href="/search/label/D420">大型モバイルバッテリー</a>。
<tr>
<th>iBook G3 M2453<td>PowerPC G3<td>2台。<a href="/search/label/iBookG3 366MHz">一台には Air Mac カード挿入済</a>。
<tr>
<th>VAIO P VPCP11ALJ<th rowspan=3>ネットブック<td>Atom<td><a href="/search/label/VAIO P">Windows10 インストール済</a>。
<tr>
<th>DELL Inspiron 910<td>Atom<td>バッテリー死亡。
<tr>
<th>ネットブック<td>Atom<td>1500円で購入。
</table>
</div>ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-15234493697243424132018-08-20T22:39:00.001+09:002020-12-06T21:40:31.115+09:00ブラウザネイティブの録音APIのサポート状況の調査<p>仕事でWebブラウザの録音機能を使うことになり、サポート状況を調査しました。
<p>録音した音声データを取り出すには、<code>MediaDevices</code> または <code>navigator.getUserMedia</code> と <code>Worker</code>, <code>Blob</code> を組み合わせる必要があるため、各APIのサポート時期を調べて纏めます。
<p>変わり種として同様に録音機能を提供する <code>MediaRecorder</code> なる別の API があったようです。こちらは詳しく見れていません。
<table>
<thead>
<tr>
<th>ブラウザ
<th>サポートするバージョン
<tbody>
<tr>
<th>IE<td>12
<tr>
<th>Opera<td>?
<tr>
<th>Firefox<td>23
<tr>
<th>Chrome<td>21
<tr>
<th>Safari<td>11
<tr>
<th>iOS<td>11(WebView では不可)
<tr>
<th>Android ブラウザ<td>5
<tr>
<th>Android Chrome<td>?
<tr>
<th>Android Firefox<td>?
<tr>
<th>Android Opera<td>?
</table>
<div class="hscroll">
<table>
<caption>各APIを提供するバージョン</caption>
<thead>
<tr>
<th>ブラウザ
<th>Web Audio
<th><a target="_blank" rel="nofollow" title="can i use" href="http://caniuse.com/#search=getUserMedia">getUserMedia</a>
(<a target="_blank" rel="nofollow" title="MDN" href="https://developer.mozilla.org/ja/docs/Web/API/MediaDevices/getUserMedia">MediaDevices</a>)
<th><a target="_blank" rel="nofollow" title="MDN" href="https://developer.mozilla.org/ja/docs/Web/API/URL/createObjectURL">createObjectURL</a>(*2) (worker)
<th><a target="_blank" rel="nofollow" title="can i use" href="http://caniuse.com/#search=Worker">Worker</a>
<th><a target="_blank" rel="nofollow" title="can i use" href="http://caniuse.com/#search=Blob">Blob</a>
<th><a target="_blank" rel="nofollow" title="MDN" href="https://developer.mozilla.org/en-US/docs/Web/API/MediaStream_Recording_API/Using_the_MediaStream_Recording_API">MediaRecorder</a>
<tbody>
<tr>
<th>IE<td>12<td>12(<a href="https://blogs.windows.com/msedgedev/2015/05/13/announcing-media-capture-functionality-in-microsoft-edge/">12</a>)<td>10(11)<td>10<td>10<td>
<tr>
<th>Opera<td>15<td>12(*1),18<td>15(15)<td>11.5<td>12.1<td>
<tr>
<th>Firefox<td>23(25)(4-27 *4)<td>17(36)<td>4(21)<td>3.5<td>6<td>25
<tr>
<th>Chrome<td>10(14)<td>21<td>8(10)<td>4<td>8<td>47
<tr>
<th>Safari<td>6<td>11<td>6(6)<td>4<td>6<td>
<tr>
<th>iOS<td>6.1<td>11(*3)<td>6(6)<td>5.1<td>6.1<td>
<tr>
<th>Android ブラウザ<td>5<td>5<td>4<td>2.1, 4.4+<td>3<td>
<tr>
<th>Android Chrome<td>28(29)<td>61?<td>18(18)<td>61?<td>61?<td>47
<tr>
<th>Android Firefox<td>23(25)<td>?(36)<td>14(14)<td>56?<td>56?<td>25
<tr>
<th>Android Opera<td><td><td>15(15)<td><td>12.1<td>
</table>
</div>
<ol>
<li><a target="_blank" rel="nofollow" title="qiita" href="https://qiita.com/iw3me/items/c16da9e06c6e079204e6">WebRTCのgetUserMediaでビデオ出力</a><q title="qiita" cite="https://qiita.com/iw3me/items/c16da9e06c6e079204e6">Opera 12では映像のみ出力され、音声は出力されませんでした。</q>
<li><code>URL.revokeObjectURL()</code> を忘れずに。
<li>iOS の WebView では使えないので注意。つまり、iOS 版 Chrome 等でも使えません。
<li>Firefox 4-27 では <a href="https://caniuse.com/mdn-api_htmlaudioelement_mozwriteaudio" target="_blank" rel="nofollow">Audio Element 拡張</a>が使えました。
</ol>
<p><a target="_blank" rel="nofollow" title="MDN" href="https://developer.mozilla.org/ja/docs/Web/API/Web_Workers_API/Functions_and_classes_available_to_workers">Web Workers が使用できる関数とクラス</a>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-42229889467344473742018-03-24T23:36:00.007+09:002021-05-05T13:05:40.463+09:00pettanRのテキストレンジAPI<div class="note"><p>マークアップを更新し、誤った説明と表記のブレを修正しました。TODO を追記しています。(2021/05/05)
</div>
<h2>はじめに</h2>
<p>W3C Range と IE 独自の先行実装 TextRange をラップしています。リッチテキストエディタ的なものを実装しながら必要なAPIを追加しています。
<div class="links"><a rel="nofollow" target="_blank" href="https://github.com/pettanR/webframework/tree/master/js/08_domRange">pettanR/webframework/js/08_domRange/</a>
</div>
<!--
<p>DOM の差異が可愛くなるくらいの異世界にクラクラしつつ、綺麗にラップして便利に使う方法を考えてみます。
<p>うまく為遂げれば、オレオレなリッチテキストエディタを作れたり新しい世界が見えてくるでしょう。
<p>文字の座標を知りたい場合に W3C Range が使えます。
<p>ActionScript3.0 では LineMatrix オブジェクト等が提供されていて細かいテキストの計測が可能です。一方の HTML + DOM は貧相で、ブラウザ毎に異なる API を駆使することで疑似的に測定が可能になります。
<p>
例
* 現在の選択範囲からテキストレンジを作る
* 文字のindexを指定して作る from, to
* 座標から作る
* 行のindexを指定する
* 最後の行からのindexを指定する
* 通常のテキストフローに対しては判定できるが、そうでないものは無理!
* numLines のために、途中経過の保持 -->
<h3>用語</h3>
<dl>
<dt>テキスト編集要素<dd><code><textarea></code> と <code>type</code> が <code>text</code>, <code>search</code>, <code>url</code>, <code>telephone</code>, <code>password</code> の <code><input></code> 要素。
<dt>W3C レンジと Mozilla セレクション<dd>Firefox, Webkit がサポートする。IE は9以降でサポート。
<dt>IE 独自レンジ<dd>IE4~IE10までサポートした。テキスト編集要素のテキスト(<code>value</code>)に対しても矩形の測定などができて高性能。
<dt>ページ座標<dd>ドキュメントの上端左を <code>(0,0)</code> とする座標系。
</dl>
<blockquote cite="https://msdn.microsoft.com/ja-jp/library/cc391970.aspx" title="DHTMLリファレンス > ドキュメントオブジェクトモデルリファレンス > プロパティ> isTextEdit">
<p><code>BODY</code>、<code>BUTTON</code>、<code>TEXTAREA</code> の各エレメント、および <code>text</code> タイプを持った <code>INPUT</code> エレメントでのみ TextRange オブジェクトが作成できる。
</blockquote>
<h2>使用技術とブラウザのサポート</h2>
<table>
<thead>
<tr>
<th>ブラウザ<th><a rel="nofollow" target="_blank" href="https://caniuse.com/#feat=selection-api">Selection API</a><th><a rel="nofollow" target="_blank" href="https://developer.mozilla.org/ja/docs/Web/API/HTMLInputElement/setSelectionRange">HTMLInputElement.setSelectionRange()</a><th>IE 独自レンジ
<tbody>
<tr>
<th>IE<td>9+<td>9+<td>4~10
<tr>
<th>Opera<td><a rel="nofollow" target="_blank" href="https://books.google.co.jp/books?id=GEQlVcVf_zkC&pg=PA882&lpg=PA882&dq=getSelection+Opera&source=bl&ots=ivr_yKPSvJ&sig=XKbHsaJZnKvgzpPsgeyWJrzIMJM&hl=ja&sa=X&ved=0ahUKEwjBkZux_tTZAhWKXLwKHdvoDpE4ChDoAQhWMAc#v=onepage&q=getSelection%20Opera&f=false">9+ (*1)</a><td>8+<td>8 beta2(*2)~10.5
<tr>
<th>Firefox<td>2+<td>1.0<td>
<tr>
<th>Safari<td>2+<td>2.0.3+ または 1.3.2+<td>
</table>
<ol>
<li>
<blockquote cite="https://forum.vingrad.ru/forum/topic-107024/view-all.html" title="VPF::Сборная солянка-3 (текст под курсором, псевдотеги - Форум программистов"><p><pre class="prettyprint lang-js">/*для цитаты*/d.onmouseup=function(){if(self.opera)str=d.getSelection();}<br>
//--for selection capture in old Opera (>7,<8) only</code></pre></blockquote>
<li>
<blockquote cite="https://web.archive.org/web/20080517124146/http://www.opera.com/windows/changelogs/800b2/" title="Changelog for Opera Beta 2 for Windows">
<ul>
<li>Added support for <code>document.selection</code> and <code>document.getSelection</code> in form input fields.
<li>Added support for TextRange with methods <code>collapse</code>, <code>move</code>, <code>moveStart</code>, and <code>moveEnd</code>, required by Google Suggest.
</ul></blockquote>
</ol>
<h2>概要</h2>
<h3>注意事項、レンジオブジェクトのライフサイクル</h3>
<p>レンジオブジェクトが内部で持つ値は <code>createRange()</code> 時点でのスナップショットであり、DOM ツリーを変更すると不正な値になります。<strong>DOM ツリーを変更した後は <code>createRange()</code> を取り直します</strong>。最適化する場合はソースを確認してね。
<h3>レンジオブジェクトのタイプ毎の公開メソッド</h3>
<table>
<thead>
<tr>
<th rowspan="2">メソッド<th colspan="6">レンジのタイプ
<tr>
<td>選択範囲<td>index<td>n行目<td>最後からn行目<td>ページ座標<td>ページ座標の行
<tbody>
<tr>
<th><code>xnode.createRange</code><td colspan="2">IE 独自レンジが無い場合に制限があり *1<td colspan="4">IE 独自レンジが無い場合テキスト編集要素についてはレンジを作ることができない
<tr>
<th><code>range.getOffset</code><td colspan="6">〇
<tr>
<th><code>range.getRect</code><td colspan="6">IE 独自レンジが無い場合、テキスト編集要素についてはメソッドが居ない *1
<tr>
<th><code>range.move</code><td colspan="6">〇
<tr>
<th><code>range.select</code><td colspan="6">〇 *2
<tr>
<th><code>range.text</code><td colspan="6">テキスト編集要素でない場合、メソッドが居ない
</table>
<ol>
<li>IE 独自レンジが無い場合、テキスト編集要素のコンテンツに対して座標系の操作が行えません。このため、行の取得、座標の文字を取得もできません。
<li><a rel="nofollow" target="_blank" href="https://masawada.hatenablog.jp/entry/2015/08/28/111117">iOS11.2 でも選択範囲を js から変更できない</a>。<a rel="nofollow" target="_blank" href="https://stackoverflow.com/questions/9296990/how-to-change-users-selection-range-in-uiwebview"><code>contentEditable</code> を true にすれば良い</a> という書き込みがある。またおいおい。
</ol>
<h2>レンジの作成</h2>
<h3>選択範囲から作成</h3>
<p>現在の選択範囲からレンジを作ります。テキスト編集要素の場合、要素にフォーカスが無いとレンジは作られません。
<p>選択範囲から xnode がはみ出す場合、truncate オプションに true を与えると xnode の範囲に切り詰めたレンジにします。true 以外の場合、レンジは作られません。
<pre class="prettyprint lang-js"><code>var range = xnode.createRange("selection", true);
</code></pre>
<table>
<caption><code>xnode.createRange("selection" [, truncate=false])</code></caption>
<thead>
<tr>
<th>引数名<th>値または型<th>ノート
<tbody>
<tr>
<th>rangeType<td>"selection"<td>現在の選択範囲からレンジを作ります。
<tr>
<th>truncate<td>boolean<td>レンジが xnode からはみ出している場合の処理を決めます。true の場合 xnode の範囲にレンジを切り詰めます。falseではレンジは作成されません。
<tfoot>
<tr>
<th>戻り値<td>レンジ | null<td>xnodeの範囲にレンジが無い場合、テキストエリアでフォーカスが無い場合 null が返る。
</table>
<h3>開始位置と終了位置から作成</h3>
<p>from が要素の文字数を超えた場合、最後の文字の後ろに幅0のレンジが作られます。
<pre class="prettyprint lang-js"><code>var range = xnode.createRange("index", 0, 5);
</code></pre>
<table>
<caption><code>xnode.createRange("index", from [, to])</code></caption>
<thead>
<tr>
<th>引数名<th>値または型<th>ノート
<tbody>
<tr>
<th>rangeType<td>"index"<td>開始位置と終了位置からレンジを作ります。
<tr>
<th>from<td>Number<td>0以上。テキストの文字数を超えた場合は <code>text.length</code> が入る。
<tr>
<th>to<td>Number<td>テキストの文字数を超えた場合は <code>text.length</code> が入る。省略した場合、from と同じ値。
<tfoot>
<tr>
<th>戻り値<td>レンジ<td>
</table>
<h4>TODO</h4>
<p>テキストの文字数を超えた場合は null を返すのは?検討する。(2021/05/05)
<h3>マウスイベント等のページ座標から作成</h3>
<pre class="prettyprint lang-js"><code>var range = xnode.createRange("point", e.pageX, e.pageY);
</code></pre>
<table>
<caption><code>xnode.createRange("point", pageX, pageY)</code></caption>
<thead>
<tr>
<th>引数名<th>値または型<th>ノート
<tbody>
<tr>
<th>rangeType<td>"point"<td>ページ座標からレンジを作ります。
<tr>
<th>pageX<td>Number<td>ページ座標の x
<tr>
<th>pageY<td>Number<td>ページ座標の y
<tfoot>
<tr>
<th>戻り値<td>レンジ | null<td>座標の位置に文字が無い場合、null が返ります。
</table>
<h3>開始行と終了行から行レンジを作成</h3>
<pre class="prettyprint lang-js"><code>var range = xnode.createRange("line-index", 0);
</code></pre>
<table>
<caption><code>xnode.createRange("line-index", lineFrom [, lineTo])</code></caption>
<thead>
<tr>
<th>引数名<th>値または型<th>ノート
<tbody>
<tr>
<th>rangeType<td>"line-index"<td>開始行と終了行から行レンジを作ります。
<tr>
<th>lineFrom<td>Number<td>0以上。開始行。
<tr>
<th>lineTo<td>Number<td>省略した場合、lineFrom と同じ値。
<tfoot>
<tr>
<th>戻り値<td>レンジ | null<td>lineFrom が xnode の行数を超える場合、null が返ります。
</table>
<h3>最終行からのindexから行レンジを作成</h3>
<pre class="prettyprint lang-js"><code>var range = xnode.createRange("line-last", 0);
</code></pre>
<table>
<caption><code>xnode.createRange("line-last", lastLineFrom [, lastLineTo])</code></caption>
<thead>
<tr>
<th>引数名<th>値または型<th>ノート
<tbody>
<tr>
<th>rangeType<td>"line-last"<td>最終行からのindexから行レンジを作ります。
<tr>
<th>lastLineFrom<td>Number<td>0以上。
<tr>
<th>lastLineTo<td>Number<td>省略した場合、lastLineFrom と同じ値。
<tfoot>
<tr>
<th>戻り値<td>レンジ | null<td>lastLineFrom が xnode の行数を超える場合、null が返ります。
</table>
<h3>マウスイベント等のページ座標から行レンジを作成</h3>
<pre class="prettyprint lang-js"><code>var range = xnode.createRange("line-point", e.pageX, e.pageY);
</code></pre>
<table>
<caption><code>xnode.createRange("line-point", pageX, pageY)</code></caption>
<thead>
<tr>
<th>引数名<th>値または型<th>ノート
<tbody>
<tr>
<th>rangeType<td>"line-point"<td>
<tr>
<th>pageX<td>Number<td>
<tr>
<th>pageY<td>Number<td>
<tfoot>
<tr>
<th>戻り値<td>レンジ | null<td>座標の位置に文字が無い場合、null が返ります。
</table>
<h2>レンジのメソッド</h2>
<h3>レンジの開始位置、終了位置の取得</h3>
<p>xnode のコンテンツの中で、レンジの開始 index と終了 index を返します。
<table>
<caption><code>range.getOffset()</code></caption>
<thead>
<tr>
<th>引数名<th>値または型<th>ノート
<tbody>
<tr>
<th><td>無し<td>
<tfoot>
<tr>
<th>戻り値<td>{ from : Number, to : Number }<td>
</table>
<h3>レンジのページ座標と幅と高さを取得</h3>
<p>テキスト編集要素であり、ブラウザが IE TextRange をサポートしない場合、<code>getRect</code> は range に居ません。
<table>
<caption><code>range.getRect()</code></caption>
<thead>
<tr>
<th>引数名<th>値または型<th>ノート
<tbody>
<tr>
<th><td>無し<td>
<tfoot>
<tr>
<th>戻り値<td>{ x : Number, y : Number, width : Number, height : Number }<td>ページ座標です。
</table>
<h3>レンジの移動</h3>
<p>レンジを移動します。負の値を指定した場合、現在の各位置に加算します。
<table>
<caption><code>range.move( from [, to] )</code></caption>
<thead>
<tr>
<th>引数名<th>値または型<th>ノート
<tbody>
<tr>
<th>from<td>Number<td>負の値を指定した場合、現在の開始位置に加算した位置に移動します。開始位置は0以下にはなりません。
<tr>
<th>to<td>Number<td>負の値を指定した場合、現在の修了位置に加算した位置に移動します。修了位置は xnode からはみ出すことはありません。
<tfoot>
<tr>
<th>戻り値<td>レンジ<td>チェインメソッド用に自信を返します。
</table>
<h4>TODO</h4>
<p>相対位置用のメソッドを追加して、正数と負数どちらにもレンジを移動できるようにする。(2021/05/05)
<h3>レンジを選択する</h3>
<p>レンジを選択状態にします。以前の選択範囲は解除される点に注意します。<code>createRange("selection")</code> で作ったレンジにはこのメソッドが提供されません。
<table>
<caption><code>range.select()</code></caption>
<thead>
<tr>
<th>引数名<th>値または型<th>ノート
<tbody>
<tr>
<th><td>無し<td>
<tfoot>
<tr>
<th>戻り値<td>レンジ<td>チェインメソッド用に自信を返します。
</table>
<h3>レンジのテキストを取得、またはテキスト挿入ないし置換</h3>
<p>レンジのテキストを取得または選択範囲へテキストを挿入または置換します。テキスト編集要素の場合だけこのメソッドが提供されます。
<p>挿入した場合、レンジの開始位置・終了位置は挿入したテキストの最後に移動します。
<p>置換した場合、レンジの終了位置は置換したテキストの最後に移動します。
<table>
<caption><code>range.text([text])</code></caption>
<thead>
<tr>
<th>引数名<th>値または型<th>ノート
<tbody>
<tr>
<th>text<td>String<td>選択範囲がこのテキストで置換されます。
<tfoot>
<tr>
<th>戻り値<td>String | レンジ<td>
</table>
<!-- h2>どんなことができる、やりたい</h2>
<ol>
<li>選択されたテキスト(レンジ)を取得
<li>textarea, input, iframe[designMode] のカーソル位置を取得
<li>(ポインターの)座標の位置にあるテキスト(レンジ)の取得
<li>要素の複数行の文章から、n行目に所属する文字列をレンジとして取得
</ol>
<p>レンジを取得できたらしたいことは…
<ol>
<li>レンジを選択、選択の解除
<li>レンジの締める座標や幅×高さを測る
<li>レンジの頭の文字の node.textContent の index, レンジの最後の文字の index(複数ノードにはまたがる場合有)
<li>レンジのコンテンツの上書き、挿入、削除、html タグでラップ -> execCommand 的な
<li>レンジの変形、開始文字位置と終了文字位置を指定して。
</ol -->
<h2>参考情報</h2>
<div class="links"><a target="_blank" rel="nofollow" href="https://github.com/madapaja/jquery.selection/wiki/API">madapaja/jquery.selection</a>選択位置への 文字の挿入、置換、取得(テキスト, html) 選択位置の 始点・終点 移動 テキストを選択した矩形の座標とサイズ
<a target="_blank" rel="nofollow" href="https://msdn.microsoft.com/ja-jp/library/cc392338.aspx">ダイナミック HTML > ダイナミックコンテント > TextRangeオブジェクトの使用</a>
<a target="_blank" rel="nofollow" href="http://mamewaza.com/support/blog/howto-use-range-selection.html">rangeとselectionを使ってtextarea・WYSIWYG用iframe等のテキスト・HTMLを取得・置換する方法まとめ [無料ホームページ作成クラウドサービス まめわざ]</a>
</div>
<blockquote title="JavaScript Rangeの使い方 - とみぞーノート" cite="http://wiki.bit-hive.com/tomizoo/pg/JavaScript%20Range%A4%CE%BB%C8%A4%A4%CA%FD">
<p>Linux 版 FireFoxだと、<code>designMode = "On"</code> の時に図1のようにセルを選択できる。このような場合、選択した各々のセルが1つの Region となり、Selection に3つの Range が含まれることになる。</blockquote>
<blockquote cite="http://d.hatena.ne.jp/javascripter/20080629/1214716601" title="シンプルなマウスオーバー辞書のGreasemonkeyスクリプト - 素人がプログラミングを勉強していたブログ">
<p>DOM 標準には <code>document.caretRangeFromPoint</code> というメソッドがあり、座標から collapsed range を得ることができる。ただし WebKit しか実装してないらしい。
<p><a rel="nofollow" target="_blank" href="http://www.w3.org/TR/cssom-view/#dom-documentview-caretrangefrompoint">http://www.w3.org/TR/cssom-view/#dom-documentview-caretrangefrompoint</a>
<p>Firefox はマウスイベントの <code>rangeParent</code> と <code>rangeOffset</code> というガラパゴスプロパティがある。</blockquote>
<div class="links"><a target="_blank" rel="nofollow" href=" http://stackoverflow.com/questions/3189812/creating-a-collapsed-range-from-a-pixel-position-in-ff-webkit">javascript - Creating a collapsed range from a pixel position in FF/Webkit - Stack Overflow</a>
<a target="_blank" rel="nofollow" href="http://d.hatena.ne.jp/dayflower/20080423/1208941641">選択範囲の取得について調べた - daily dayflower 2008-04-23</a>
<a target="_blank" rel="nofollow" href="http://d.hatena.ne.jp/edvakf/20081014/1224007239">http://d.hatena.ne.jp/edvakf/20081014/1224007239</a>
<a target="_blank" rel="nofollow" href="http://help.dottoro.com/ljvmcrrn.php">http://help.dottoro.com/ljvmcrrn.php</a>
<a target="_blank" rel="nofollow" href="http://www.adventar.org/calendars/723">http://www.adventar.org/calendars/723</a>
<a target="_blank" rel="nofollow" href="https://hyper-text.org/archives/2015/12/css_old_tale.shtml">https://hyper-text.org/archives/2015/12/css_old_tale.shtml</a>
</div>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-85785584633683211892018-02-25T23:19:00.019+09:002024-01-27T15:13:35.288+09:00Webフォントがブラウザで有効か?きっちり調べる<div class="note"><p>「古典的な方法」に加筆修正しています。(2024/01/27)
<p>内容が重複する記事「<a href="/2023/10/webfont.html">アイコンの為に Web フォント、合字を深堀してフォールバックを検討する</a>」を公開しました。(2024/01/26)
<p>テーブルに WOFF2 を追記しました。(2023/07/01)
<p>フロー図を追加して、若干の追記と推敲を行いました。(2022/10/06)<p>#BLM を支持し「ブロックリスト」への書き換え。webfontTest.js へのリンクの修正。(2020/8/31)
</div>
<div class="box">
<span class="caption" style="width:160px">
<figure>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXVnek_jbnLWi5l56O3bxemNogR4XeoZnEyrgRW0CoCQIynJ2st-v7tKwdMdN3CdJqNfmhOEY7V0j5JL-gf8ndWOdq2o17y57-mwXtgcIZMQ4RXdt-QNY7-YJSOfaqhHCplpqkVoT63b-zv1m_NwvS5wLOChFMEtxpiRcpTjWtck1A-T29e2lkf_Vn/s800/test-webfont.drawio.png"><img alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXVnek_jbnLWi5l56O3bxemNogR4XeoZnEyrgRW0CoCQIynJ2st-v7tKwdMdN3CdJqNfmhOEY7V0j5JL-gf8ndWOdq2o17y57-mwXtgcIZMQ4RXdt-QNY7-YJSOfaqhHCplpqkVoT63b-zv1m_NwvS5wLOChFMEtxpiRcpTjWtck1A-T29e2lkf_Vn/s160/test-webfont.drawio.png"></a>
<figcaption>Web フォントのテストコードのフロー図 <a href="https://viewer.diagrams.net/?tags=%7B%7D&highlight=0000ff&edit=_blank&layers=1&nav=1&title=test-webfont#R7V1bd5s4F%2F0t8%2BA1nYewuF8eE9vpZDWdSZtepk%2FfwiDbdDDygJzY%2FfWfJC4GCWJMDCYJeUiMkIXQ3ufoaOtARsp4tX0f2uvlR%2BgCfySL7nakTEaybBkm%2Fk0KdnGBYYlxwSL03LhI2hfce79AUphW23guiAoVEYQ%2B8tbFQgcGAXBQocwOQ%2FhYrDaHfvGqa3sBuIJ7x%2Fb50u%2Bei5ZxqSmK%2B%2FI%2FgbdYIubEzHb%2BXYRwEySXG8mKbCq6lAzHyk6bSupHS9uFj7kiZTpSxiGEKP602o6BT0Y2HbX4e9cVZ7NuhyBAdb6wuv8v0NSHD9vpr8n3YG5%2B%2BrxDF3rcyoPtb0B6G7SzaJeOD71FQBoRR8rV49JD4H5tO%2BTsIyYELluilY%2BPJPwxQiH8F4yhD0P6beX6eqpZFj4zhwFKwJfU5Dhfb3p9OSUXmHu%2Bn5YHMMD1r%2Fg7TW7%2BAYQIbHNFyZ2%2FB3AFULjDVZKzagJCwtEMlMc94qqWlC1zaEtpRTth2SJrej%2FU%2BEMy2keMvMyNvCTg4%2FvNeg1DFI3IhfX%2FNoQdVy50Nit88wIZtGhfTiop1xxieExQbVj44bZ9bxHgQx%2FMSTNkkD1sLpdJ8cpzXXKlUioUyVKJcY4LCukebsQLFrf0ghNyUy1gLmk85rpYgrnaFuQKB7lMIB%2Fb9KtFkAUf2u478vEP4WiAEyD7iq1vz4B%2FByMPeZBc1cF3DcJcd26ZClm3uvEEstIlK1SOFR%2BBHW1CPGhkKlyCrHOyCOekB5QM5PzxzHgjpi%2BJDMomj7JidImyxqGsENv%2FDNbARsD1SedXFHdwCHUa5ITkEPeNVPZW4J0WAUf4Y%2BBDPT5k2B%2Ba%2F1vjg3E48AKBe0niW%2BIhfTuKPKeIZHGAOVwnk0tJmxaHWH4Sihz%2BuPxqrI9lDZeDrYf%2BIVcRDMlIjn8kfSCfJ9ukC%2FRglzu4AyHmJvXtkyeRBG4hRudxzOFUBlNaFgLfRt5DMbIvwy65wh30cE8ymmiSKMhi7kcrRhAWw4YIbkIHJI3kQ2%2B%2B3XL6pQ0hO1wAxDVEmZWNQnOymRzZ%2FoK9DSpSbyA%2FQdUTuARNFsvBzU8RJVRT2vIIFgcSXRB8%2Fevy2%2BXN7eXV7RQfTb6S31%2F%2Bxr%2Bubv8ef7i9uf8yOP1akV5JCNBt%2BJ86gY59Ph3hY31%2B3z21yRgvu0yv65nZdrRuHbMkcZQYPLNVge25HLPESzWD3Z7IbptGVEw7Mmv%2FbdstL%2BX8ANFguP2KqCReWhkMt6HhSjpjcexMWddyuYbMjk2XV2IEtATBu%2BPFk1dmvpUQ5xhWppm1Z7%2F87pRKlkQTGxE1bCTrPopXDwE%2BpOZLa6XbIze38803t7Bd4tvBolDnp50%2Fry%2BSv083vFx8mPoO%2F8Wvn28Ig5wlIMJc3Ai%2B87idYttcsbi0yabPDAByTQQihDmABzUgv70oHgYyXMN%2BT731nlqi8XW84ONFPo3yFyDg0K0N0jkq8X4HsxGRden2nghWM%2BC6FH%2BPVBrf3xMeUja69MujVCN2YBiCaA0DN1aG9w3RP%2BHKRsMuQT3C6NLZCcMLdb0NWPCwh7tYFhZVIy34kVyXHuyFYXq0yx%2FVlobjcKDGLNGTQEk3mUlUbhYn6eZTUrSqMB1rOWpK11c5ZobgJ3ZExEm97bDJOBw1ldGttagp9Rk5qJIMg%2FX%2FSFhBoiccqLxrkFfwRuYFdrdQU0sgVbucGGReb%2BjvxJBtF4pqetxsu7B6irnAJUY2C51knon9co155vCEZPRqQlKMirj42BlJZXbM1I5FN5mXcwbRjVVCtZIgtlPRTeb1ld66qsrh74np6uxEJDU0Xa4hdqZq23R5JWfY59KlvpnueZKSXqXpSgoDLitz19bLmYZ01ge0bbq8JuHYwSYCb918JbUC4bMt%2FPgMIp3IjTer9ImCWEdMJMecyPhYUB9jyTnWGcnx45JK0iQhPdYYqRrtwNXax3WGVWRNdfHs%2BUcp8Qb3%2Fnz3zqyp9Ka7oWw7HW%2BGpipijhKx3Q%2BynlmBcMF8O%2FTuCi%2Fr9dZ698JNYV9AOKTYVMJ2UHPR%2BuwdjKbZiZziUjM9EZPA3uWqrUmFqH5%2Fk8tUdUt%2BVnXFKlTHH%2BLuntaxvUDBNBVIc7ZSLZdWWJilW92qomnQ2RPLY8VOjfXHtSdmJnwzRFGQcMya%2FXQ7T7%2BgTLZn0ZkI%2B2qR0qZ2Wkr3hKk6uz6QLUFryFXFFNTcVrHENWzo3dL1BWnAp%2FS%2BB7ekXhopNa05KUuayrlPy%2ByWkTVedPE6GClIctGBdhsPJGw5HLD3K2Jnia%2BYjYmv6wYT73abqqO8IBX%2FmVTXTCtPdRI8yB1nBagvk%2B8as6sgW835zoTcilhvkXoyvr%2FIpMli4CDK5luIcdlJv2ksYRmCJeViiY6jW36fpbeE6ztD2GdOlKZSGddQx69YSBk6ZDjkt0jZqaEkkbLTDAf1JcmCVSL6Puh5TXMFa8Bq01wndrJQNV2w9Jw8otZyDMdq6Fz%2FNYOhawsyt8oLLY4d%2FE66NWRo7PfsWDH4XA80qrwKMWSwcjBl6fdnmyX4FfQwl7Mo6edGSeMjrrsQzuwZfZceeUB4n7E0tz1%2FEzbIVXrtIOo8iFanIPIJKOkT0usCUumj1r4XgIu0a5e4iiSodGzYZ7ELD8LSR6c9REbCgcHcC1c0722We%2BsiffVq7uns9f7R7J5zRm2XMxqn72iCaHK0kcpy2dh0ptPxRq7kjes9pNARB0CAzkDNnes9rN3mN2U5KufKb9L4pdkNee%2FpAs%2B8IlricVqQrFWS0ToepU%2B%2F%2F9y4C2K4oyQptWD0m8B%2BwH4fTwiD42dX4mpJKFz6AtT28OZTGqrQ%2B%2B1o9PDozUyN3BC3vp6bDnCcHI7c26efiaRJzyI7eXf1hVWSioznXVFRTgOtquhk47ngok2xzEXrqiykT%2BIUMDYFU2sL5rJUgMLrVfg5%2FsBknudFxctUjqeL7phgNufp4trAnHdOF%2FqG9KvsH0ywTqlIJqJpnIpMGtn3LOaPELW9bL63NEGzeDKpoqA%2FIf48j0z8Vs8XECHW8WcE6bvXV1r2%2Bgq7sOZ9flnU1p7P53dOaAjuIfhrtwnimR1ukOPDjSvMfLiI1hAJDlz1HcknFd6T2OVBKLM821ND6W2V7bfP772r3Wzy6e7PTw8f%2FzEvyuLv3gvpgpQdnyJfgFHOSyA%2Bm5jOrPNViWmi9rYa21B722qlNOMXBeS%2FHWAX0XuHcNi1c9Zfi0AV7yjJED7904f4cP9fqmJg9%2F8ITJn%2BHw%3D%3D" target="_blank" rel="nofollow">draw.io で編集する</a>(2022/10/06 追記)</figcaption>
</figure>
</span>
<p>趣味の Web 開発でも使う為いよいよガッツリ調べました。Web フォント無効を検出してフォールバックを実施したい場合、どのような判定法があるのでしょう?
<p>調べている間に知りましたが、ここで紹介する手法は <code>Canvas</code> 要素に Web フォントでテキストを書きたい場合にもマストです。Web 開発は罠が多いですね。
</div>
<div class="links"><a target="_blank" rel="nofollow" href="https://github.com/itozyun/web-doc-base/blob/master/src/js/6_CanUse/webfontTest.js">『web-doc-base > webfontTest.js』</a>今回の記事を実装したものです
<a target="_blank" rel="nofollow" href="https://docs.google.com/presentation/d/1n4NyG4uPRjAA8zn_pSQ_Ket0RhcWC6QlZ6LMjKeECo0/">『@font-face web font research』</a>プレゼンテーション形式の資料
<a target="_blank" rel="nofollow" href="https://www.monster-dive.com/blog/web_creative/20160314_001441.php">『Webフォントが無効な環境におけるアイコンフォントの問題からアイコンのマークアップの最適解を探す旅に出る』</a>広告ブロックアプリについて他
</div>
<h2>Webフォントのサポートブラウザ</h2>
<p>以下の表は 『<a target="_blank" rel="nofollow" href="http://www.lucasfonts.com/webfonts/">LucasFonts | Webfonts</a>』のもので、記事はさらに caniuse を元にしています。誤りがあったため、私の方で修正と追記を行っています。
<table>
<thead>
<tr>
<th><td>WOFF2<td>WOFF<td>EOT<td>SVG<td>TTF<td>OTF
<tbody>
<tr>
<th>Safari<td>10(*2)<td>5.1<td><td>3.2<td>3.1<td>3.1
<tr>
<th>iOS Safari<td>10<td>5.0<td><td>3.2<td>4.2<td>4.2
<tr>
<th>Firefox<td>39<td>3.6<td><td><td>3.5<td>3.5
<tr>
<th>Firefox for Android<td>39<td>15.0<td><td><td>15.0<td>15.0
<tr>
<th>Chrome<td>36<td>5.0<td><td>4.0<td>4.0<td>4.0
<tr>
<th>Chrome for Android<td>36<td>18.0<td><td>18.0<td>18.0<td>18.0
<tr>
<th>Internet Explorer<td><td>9.0<td><del>6.0</del> <ins>4.0</ins><td><td><td>
<tr>
<th>IE Mobile<td><td>10.0<td><td><td><td>
<tr>
<th>Opera<td><td>11.1<td><td><del>9.0</del> <ins>10.0</ins><td>10.0<td>10.0
<tr>
<th>Opera Mini<td><td><td><td><td><a target="_blank" rel="nofollow" href="https://www.6666666.jp/design/20160218/" title="CSSのWebフォント指定に関する考察 2016年版">〇</a><td>
<tr>
<th>Opera Mobile<td><td>11.0(*1)<td><td>10.0?<td>10.0?<td>10.0?
<tr>
<th>Android Browser<td><td>4.4<td><td>3.0<td>2.2<td>2.2
<tr>
<th>Blackberry Browser<td><td>7.0<td><td>7.0<td>7.0<td>7.0
</table>
<ol>
<li>『<a href="https://web.archive.org/web/20110325012353/http://my.opera.com/operamobile/blog/opera-mobile-11-for-android-and-symbian" target="_blank" rel="nofollow">Opera Mobile 11 for Android and Symbian</a>』<q>Support for Web Open Font Format (WOFF), Support for Arabic ligatures</q>
<li><q cite="https://caniuse.com/?search=woff2">Supported only on Safari for Mac OS Sierra, not El Capitan & older.</q>
</ol>
<h3>部分追記</h3>
<p>IE は正しくは4.0以降からサポートします。
<p>Opera は9.0から SVG フォントをサポートする、とありましたが手元の環境では確認できませんでした。『<a target="_blank" rel="nofollow" href="https://maqentaer.github.io/devopera-static-backup/http/dev.opera.com/articles/view/opera-presto-2-2-opera-10-ja/index.html#webfontssvg ">Opera Presto 2.2 と Opera 10 概観 - Dev.Opera</a>』では10から Web フォントと <a target="_blank" rel="nofollow" href="https://maqentaer.github.io/devopera-static-backup/http/devfiles.myopera.com/articles/593/SVGfonts_in_HTML.html">SVG Web Font</a> をサポートしているようです。
<blockquote title="安全でアクセシブルなアイコン・フォント" cite="https://hail2u.net/documents/bulletproof-icon-fonts.html"><p>私達は古い(そして新しい)モバイル・ブラウザー―例えば Opera Mini や Nokia XPress Browser, Blackberry 4-5, Android 2.1, Windows Phone 7-7.8―が <code>@font-face</code> をまったくサポートしていないことを発見しました。</blockquote>
<h2>Web フォントが有効か?判定する</h2>
<p>Web フォントが無効のケースには次の3パターンが考えられます。
<ol>
<li>そもそもブラウザが Web フォントに対応していない
<li>ユーザーの設定によって Web フォントが切られている
<li>通信量削減用のネットワーク監視アプリ等で Web フォントのダウンロードが制限されている
</ol>
<div class="note">
<p>残念ながら無効の場合、画像や SVG、<a href="/2018/02/PureCssIcon.html">Pure CSS アイコン</a>、記号文字(グリフ)によるフォールバックが考えられます。画像の表示を禁止するユーザー設定やアドオンもありますし、便利な記号文字は大抵機種依存です。ムキになると際限がありませんね…
<blockquote title="安全でアクセシブルなアイコン・フォント" cite="https://web.archive.org/web/20150905080442/http://hail2u.net/documents/bulletproof-icon-fonts.html"><p>フォールバックに使うグリフは細心の注意を払って決定しましょう。クロス・ブラウザー及びクロス・プラットフォームであるかはグリフによって違います。John Holt Ripleyの<a target="_blank" rel="nofollow" href="https://web.archive.org/web/20150905080442/http://unicode.johnholtripley.co.uk/">互換性の表</a>を参照してください。
</blockquote>
</div>
<h3>1. そもそもブラウザが Web フォントに対応していない</h3>
<p>この判定には Modernizr にある機能判定が有効な場合もありますが、これをすり抜けるブラウザもあるため Modernizr でも初めにブロックリストで弾いています。
<h4>ブロックリスト</h4>
<p>参考になるのは <a target="_blank" rel="nofollow" href="https://github.com/Modernizr/Modernizr/blob/1f8af5969233053e920e528e00a95be9786b7eae/feature-detects/css/fontface.js">Modernizr</a> です。最新のコードでは<a target="_blank" rel="nofollow" href="https://github.com/Modernizr/Modernizr/commit/d1c456600c64ff89bb64a6f9fa099d218cba6152#diff-03600c0740cd6ad1b6e032fc053e570d">古い Android の判定を削除</a>しているため、以前のコードにリンクしています。
<p>併せて更にマイナーなブラウザも調査している『<a target="_blank" rel="nofollow" href="http://blog.kaelig.fr/post/33373448491/testing-font-face-support-on-mobile-and-tablet">Testing @font-face Support on Mobile and Tablet</a>』を参考にするのが良いでしょう。
<p>そもそもマイナーなブラウザまでカバーする判定には拙著『<a href="/2017/10/uaDetector.html">「デスクトップ版を表示する」にチェックを付けると平然とUAを偽装するAndroid用標準ブラウザの判定をムキになってしてみます</a>』で紹介しているコードを一旦お勧めします。<code>navigator.uaserAgent</code> 文字列の偽装にもある程度の耐性があります。
<h4><code>@font-face</code> の機能判定</h4>
<p><code>@font-face</code> の判定コードは削除済です。これは動的判定を減らし、ブラウザエンジン・バージョン検出と機能カタログを組み合わせた静的判定を重視する web-doc-base の開発の大方針に沿っています。(2022/10/06 追記)
<p><del><a target="_blank" rel="nofollow" href="https://github.com/Modernizr/Modernizr/blob/1f8af5969233053e920e528e00a95be9786b7eae/feature-detects/css/fontface.js">Modernizr</a> を参考にします。</del>
<h3>2. ユーザー設定によって Web フォントが切られている</h3>
<p>Web フォントを無効にすると <code>@font-face</code> を <code>StyleSheet</code> に追加できなくなる事例を確認していない上に、<code>@font-face</code> 機能判定を削除済につき、この部分は意味をなさなくなりました。(2022/10/06 追記)
<p><del>ユーザー設定によって無効になっている場合、機能判定の時点で判断できると思われます。もしブラウザがそのような実装になっていない場合、後述の実測によって最終的な判断をします。</del>
<a name="2-3"></a>
<h3 id="2-3">3. 通信監視アプリ等で Web フォントのダウンロードが制限されている</h3>
<p>通信量の削減やセキュリティの為に通信監視アプリやアドオン等で Web フォントのダウンロードを禁止されているケースが考えられます。この場合、CSS に埋め込む等で監視をすり抜けることができます。
<h4>データ URI で CSS に埋め込んだ Web フォントは機能するか?</h4>
<p>データ URI な Web フォントが使用可能か? CSS にあらかじめチェック用の Web フォントを埋め込んだり、javascript から動的に書き出して確認します。
<p>但し、無用な通信をしたくない、というユーザーの意思をまずは尊重し、巨大な日本語フォントセットをダウンロードする様なことは控えましょう。小さなアイコンフォントに限るなど抑制的な利用に留めましょう。
<p>そもそもデータ URI が使えるか?の判定には <a target="_blank" rel="nofollow" href="https://github.com/Modernizr/Modernizr/blob/master/feature-detects/url/data-uri.js">Modernizr</a> が参考になります。また <a target="_blank" rel="nofollow" href="http://d.hatena.ne.jp/rikuo/20141015">IE8 以下では画像ファイルしか扱えない</a>、という制限があるためあらかじめ除外します。
<h3>Web フォントが有効になった?実測による判定</h3>
<p>Web フォントが有効になるタイミングを知るには、新しい API <code>document.fonts</code> を備えている場合はこれを利用できます。非対応の場合、隠し要素を測定して判定するという古典的な方法を用いて Web フォントが有効であることを確定させます。
<p>しかし <code>document.fonts.load().then()</code> で必ずしも検出できる訳では無いようで、古典的な方法を併用します。詳しくはソースコードを確認ください。(2022/10/06 追記)
<h4><code>document.fonts</code>を使う方法</h4>
<p><a target="_blank" rel="nofollow" href="https://github.com/bramstein/fontfaceobserver/blob/master/src/observer.js">bramstein > fontfaceobserver > observer.js</a> などを参考にします。
<p>observer.js の <code>document.hidden</code> の扱いが釈然としない為、僕のコードでは <code>document.hidden == true</code> で測定時間を延長する実装にしています。モバイル Firefox では、背面に回ったタブの Web フォントのロードやレンダリングを休止する動作をすると思うのですが… (2022/10/06 追記)
<h4>古典的な方法</h4>
<p>『<a target="_blank" rel="nofollow" href="http://www.lalit.org/lab/javascript-css-font-detect/">JavaScript/CSS Font Detector</a>』で紹介されているコードが参考になります<del>が、そのままのコードでは Webkit で判定に失敗するため <code>monospace</code> を外しました。同様の報告は『<a target="_blank" rel="nofollow" href="http://defghi1977-onblog.blogspot.jp/2013/02/canvasweb.html">canvas要素にwebフォントを確実に描画する方法</a>』のコードのコメントにもありました</del>。<code>monospace</code> を外す対処法はいまいちです。原因とより良い対処法は <a href="/2023/10/webfont.html#webkit-fallback-bug">WebKit フォールバックバグ</a>を参照します。(2024/01/27 追記)izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-13589327327688889772018-02-24T21:21:00.001+09:002023-07-01T16:41:25.412+09:00Webフォントより確実なピュアCSSアイコンのすゝめ<div class="note"><p>やっぱり<a href="/2023/07/svgfont-to-svgimage-by-svgo.html">ベクターアイコン</a>にします。(2023/07/01)
</div>
<h2>はじめに</h2>
<div class="box">
<a href="https://4.bp.blogspot.com/-mbLt41DJPB0/WpFVbGhREXI/AAAAAAAARhI/mAo7Q1fjmPgJsAT3h7fycZboxydoFHaYACLcBGAs/s1600/PureCssIcons.png">
<img src="https://4.bp.blogspot.com/-mbLt41DJPB0/WpFVbGhREXI/AAAAAAAARhI/mAo7Q1fjmPgJsAT3h7fycZboxydoFHaYACLcBGAs/s200/PureCssIcons.png"></a>
<p>Web ページのアイコンには、古くは画像を使うものに始まり、これを画像スプライト化したり、データ URI 化してスタイルシートに埋め込むなど最適化の工夫がされてきました。
<p>最近の主流は Web フォントによるアイコンです。2011年に登場するデザイントレンド「<a href="https://u-site.jp/alertbox/flat-design" target="_blank" rel="nofollow" title="フラットデザイン:
起源、問題、フラットデザイン2.0のほうが望ましい理由">フラットデザイン</a>」との相性も良く、拡大して良し、色も CSS で簡単に変更できるとあってそのメリットは絶大です。
<p>しかしモダンな環境でも確実に Web フォントが使えるわけでは無い点や、ダウンロードファイル数が増える点を気にして、趣味のブログ運営では導入に二の足を踏んでいました。また今回は関係ありませんでしたが、フォントアイコンをあくまで装飾ではなくコンテンツとして使う場合、<a href="/2018/02/IsWebfontEffective.html" title="Webフォントがブラウザで有効か?きっちり調べる">Web フォントの無効を検出してのフォールバック</a>についても準備が必要と厄介です。
</div>
<hr>
<p>そもそも、<strong>文字だけでもタイポグラフィの工夫で充分素敵なデザインが出来る</strong>という自負もありました。ところが、久しぶりに Blogger 用テンプレートの配布サイトを眺めていくと自信を喪失…いよいよアイコンの導入を決意しましたとさ。
<div class="links"><a href="https://github.com/itozyun/web-doc-base/blob/master/src/scss/03_Parts/icons.scss" target="_blank" rel="nofollow me" title="github">web-doc-base/src/scss/03_Parts/icons.scss</a>
</div>
<div class="note">
<h3>サンプル</h3>
<p>
<i class="ico-clock"></i>時計
<i class="ico-label"></i>ラベル
<i class="ico-author"></i>人物
<i class="ico-flag"></i>旗
<i class="ico-pen"></i>ペン
<i class="ico-chain"></i>リンク
<i class="ico-sylinder"></i>ドライブ
<i class="ico-comment"></i>コメント
</div>
<h2>:before, :after擬似要素によるピュアCSSアイコン</h2>
<p>今回は <code>:before</code>, <code>:after</code> 擬似要素にボーダーと角丸を組み合わせてみたところ、Web フォントアイコンに迫る表現力で、当面必要なものを揃えることが出来ました。その上、制限のある環境も少なそうだったため好奇心も手伝ってピュア CSS アイコンの導入へ踏み切ることができました。
<table>
<caption>アイコンのための技術の比較
<thead>
<tr>
<th>使用技術<th>利点<th>欠点
<tbody>
<tr>
<th>画像<td>広範な環境で使用可能。フルカラーが可能。<td>設定やアドオンで切っている場合あり。ブラウザの設定やアドオンで画像を無効化している場合が稀にある。拡大に弱い。スプライト画像の準備が結構苦痛。
<tr>
<th>Web フォント<td>データサイズが小さめ。拡大縮小に強い。色変えは極めて簡単。<td>一部の環境で非対応。設定やアドオンで無効になっている場合がある。
<tr>
<th>SVG<td>SVGスプライトで結構便利に使えそう。ここは不勉強。<td>
<tr>
<th>ピュア CSS アイコン<td>データサイズが小さい。拡大縮小に強め。色変えは簡単。<td>表現力が低い。ブラウザによって描画に微妙な差異がでる。角丸の使えない IE8, Opera Mini では更に低くなる。IE7 以下は非対応。
</table>
<h3>先行事例</h3>
<div class="links"><a href="https://saeedalipoor.github.io/icono/" target="_blank" rel="nofollow">icono | Pure CSS icons</a>
<a href="http://nicolasgallagher.com/pure-css-gui-icons/demo/" target="_blank" rel="nofollow">Pure CSS GUI icons</a>
<a href="https://www.designzzz.com/free-pure-css-icons/" target="_blank" rel="nofollow">500+ Free Pure CSS Icons</a>
</div>
<h3>先行事例からの変更点</h3>
<p>CSS3 の使用を <code>border-radius</code> に留め、これに対応しない IE8 と Opera Mini でもそれなりな表示になるようにデザインしました。表現の幅が大きく拡がる <code>transform</code>, <code>box-shadow</code> は使いませんでした。
<p>em 指定を使ってフォントサイズの変更で拡大表示できるようにしました。但し em 指定ではフォントサイズによっては三角形が綺麗に描画されない場合があります。
<h4>印刷対応</h4>
<p>印刷の設定から「背景色と背景画像も印刷」にチェックを付けていない場合にも対応するため、背景色は使わず全て枠線で描画します。この際に、矩形の場合は上下左右どちらか一本の枠線に幅を与えます。
<p>角丸指定がある場合は、当該の辺に幅が無いと角丸が正しく描画されません。相対する2辺に幅を持たせると、フォントサイズによってはボーダーの隙間ができるケースがあります。隙間は、縦にできる場合、横にできる場合、十字にできる場合、どれか一つ最も自然なものを選択する他ありません。
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-27222781034314901452017-10-06T20:48:00.003+09:002021-04-19T13:52:53.310+09:00「デスクトップ版を表示する」にチェックを付けると平然とUAを偽装するAndroid用標準ブラウザの判定をムキになってしてみます<div class="note"><p>モバイル版 Safari の「デスクトップ用サイトを表示」でも <a target="_blank" rel="me" href="https://github.com/itozyun/web-doc-base/commit/a19ef71f7b4849771ffbd82a93f5930e08a9e523">iOS のバージョンを取得できる</a>ようになりました。(2018/1/16 追記)
</div>
<p>リッチな Web アプリや手厚いフォールバックの実装にあたっては、やはり「<em>ブラウザ判定こそ基礎中の基礎、最近の表現だと一丁目一番地だ</em>」と何年振りかに根を詰めてやってみました。
<div class="links"><a target="_blank" rel="me" href="https://github.com/itozyun/what-browser-am-i"><del>web-doc-base/inline-js/01_useragent.js</del> -> github.com/itozyun/what-browser-am-i</a>
<a target="_blank" rel="me" href="https://itozyun.github.io/what-browser-am-i/">UA判定 デモページ</a>
<a target="_blank" rel="me" href="http://my-http-proxy-856.appspot.com/itozyun.github.io/what-browser-am-i/">http:版</a> https: が不可な環境用
</div>
<h3>はじめに</h3>
<div class="box">
<div class="caption" style="width:200px">
<figure>
<a href="https://4.bp.blogspot.com/-ixkHsjm0tRU/WddVtEsOS4I/AAAAAAAARbE/1c8rSKto1JcRvBYfiYQ3iQvEFOZxuQtxgCLcBGAs/s1600/AOSP_desktopSite.png">
<img src="https://4.bp.blogspot.com/-ixkHsjm0tRU/WddVtEsOS4I/AAAAAAAARbE/1c8rSKto1JcRvBYfiYQ3iQvEFOZxuQtxgCLcBGAs/s200/AOSP_desktopSite.png"></a>
<figcaption>Request desktop site</figcaption>
</figure>
</div>
<p>Android 標準ブラウザ(AOSP, Chrome WebView)の判定には、<code>navigator.userAgent</code> 文字列から "Android"と"Version"の有無を利用するものが知られています。しかしこれらの文字列の有無は必ずしも信頼できるものではありません。
<p>例えば Android 用ブラウザの多くには「デスクトップ版を表示する」といった設定があります。このチェックが付くとユーザーエージェント文字列は大きく変化して OS とブラウザの判定が難しくなります。しかしユーザーエージェント文字列が変わったからと言って、各モバイルブラウザに固有の挙動、バグを含む挙動がデスクトップ用ブラウザのソレへと変化することはありません。よってユーザーエージェント文字列に惑わされず正しく環境を判定する必要があります。
</div>
<div class="box">
<div class="caption" style="width:200px">
<figure>
<a href="https://2.bp.blogspot.com/-pKtkcbdcLqg/WddVtF9mUXI/AAAAAAAARbI/-lbrxeF3czktKKmzZfocFfT_ccggJ3cSgCPcBGAYYCw/s1600/AOSP_noDesktopSite.PNG">
<img src="https://2.bp.blogspot.com/-pKtkcbdcLqg/WddVtF9mUXI/AAAAAAAARbI/-lbrxeF3czktKKmzZfocFfT_ccggJ3cSgCPcBGAYYCw/s200/AOSP_noDesktopSite.PNG"></a>
<figcaption>Request mobile site</figcaption>
</figure>
</div>
<p>さらにユーザーエージェント文字列の変化を利用して<em>ユーザーの「デスクトップ版的なものを表示して欲しい」という意図を検出する</em>ことも可能です。この情報を元にページの表現を切り替えればよりユーザーにフレンドリィ、エクスペリエンスあげあげな HTML コンテンツを提供できるのではないでしょうか。
<p>いわゆる「おもてなし」、最近では「忖度」。それでは張り切っていきましょう。
</div>
<h3>各環境とブラウザの判定方法</h3>
<table>
<thead>
<tr>
<th>OS+ブラウザ<th>PC版を表示<th>OS判定<th>OSバージョン<th>エンジン判定<th>ブラウザバージョン
<tbody>
<tr>
<th rowspan="2">Android4.3- AOSP<td><td>Android<td>v<td>Version/<td rowspan="2">OSバージョンと同じ
<tr>
<td>v<td>矛盾文字列(*1)<td>△不正確(*2)<td>
<tr>
<th rowspan="2">Android4.4+ Chrome WebView<td><td>Android<td>v<td rowspan="2">(*3)<td rowspan="2">OSバージョンと同じ
<tr>
<td>v<td>矛盾文字列(*1)<td>△不正確(*2)
<tr>
<th rowspan="2">Android Firefox<td><td>Android<td>v<td rowspan="2">'MozAppearance'<td rowspan="2">'rv:'
<tr>
<td>v<td>矛盾文字列(*1)<td>不明
<tr>
<th rowspan="2">Android Chrome<td><td>Android<td>v<td rowspan="2">window.chrome<td rowspan="2">'Chrome/'
<tr>
<td>v<td>矛盾文字列(*1)<td>不明
<tr>
<th rowspan="2">Android Prsto Opera<td><td>platform=Android<td>v(ua)<td rowspan="2">window.opera<td rowspan="2">getVersion()
<tr>
<td>v<td>platform=Android<td>不明
<tr>
<th rowspan="2">Android Blink Opera<td><td>platform=Android<td>v(ua)<td rowspan="2">window.opr<td rowspan="2">'OPR/'
<tr>
<td>v<td>矛盾文字列(*1)<td>不明
</table>
<ol>
<li>次の「矛盾するプラットフォーム文字列を使ったAndroidシステムの判定」を参照
<li>「Android 標準ブラウザの Android バージョン判定」を参照
<li>UA を AOSP に偽装して出荷している端末があるため <code>document.registerElement</code> を確認する
</ol>
<h4>矛盾するプラットフォーム文字列を使ったAndroidシステムの判定</h4>
<p>次の Android 用ブラウザでは「デスクトップ版を表示する」場合にユーザーエージェント文字列等から Android 文字列が消えます。
<ol>
<li>Android 標準ブラウザ AOSP, Chrome WebView
<li>Android 用 Chrome
<li>Android 用 Blink Opera
</ol>
<p>この際には、プラットフォーム文字列に "Linux armv7l" または "Linux i686" が入っている一方で、ユーザーエージェント文字列に "Linux x86_64" という<em>矛盾した値が入っている</em>点を利用して Android を判定します。
<pre class="prettyprint lang-js"><code>maybeAndroid = ( navigator.platform === 'Linux armv7l' || navigator.platform === 'Linux i686' ) && navigator.userAgent.indexOf( 'Linux x86_64' ) !== -1;
</code></pre>
<p>また Android バージョンの取得ができなくなります。Android にバンドルされている標準ブラウザに限っては、実装状況をヒントに Android バージョンを推測することはできます。
<div class="note"><p>Ubuntu Mobile や Firefox OS などが似たようなことをしていないか?などは未検証です。</div>
<h4>Android 標準ブラウザの Android バージョン判定</h4>
<p>さて、ユーザーエージェント文字列等に "Android" がなくとも、Android と標準ブラウザの組み合わせであることが分かりました。続いて Android バージョンを判定していきます。
<p>Android 4.0 以降ではユーザーエージェント文字列の WebKit バージョンが当てにならなくなるので、プロパティの有無で判定していきます。
<table>
<thead>
<tr>
<th>バージョン<th>判定法<th>メモ
<tbody>
<tr>
<th>5.x<td>document.registerElement && !document.execCommand<td>execCommand が居なくなる…
<tr>
<th>4.4.3+<td>document.registerElement && document.execCommand<td>これ以降 Chrome Web View
<tr>
<th>4.4<td>window.Int8Array && !navigator.connection<td>ここまで AOSP
<tr>
<th>4.2<td>window.Int8Array && !window.searchBoxJavaBridge_<td>4.2 と 4.3 の判定は出来ていない
<tr>
<th>4.1<td>window.Int8Array && Number.isNaN<td>
<tr>
<th>4.0<td>window.Int8Array<td>
<tr>
<th>3.x<td>534 <= verWebKit<td>
<tr>
<th>2.3<td>531 <= verWebKit && window.HTMLAudioElement<td>
<tr>
<th>2.2<td>531 <= verWebKit && !window.HTMLAudioElement<td>
<tr>
<th>2.0<td>529 <= verWebKit<td>2.0 と 2.1 の判定は出来ていない
<tr>
<th>1.x<td>verWebKit < 529<td>
</table>
<p>ところで、Web 開発では「ユーザーエージェント判定よりも機能判定」とはよく言われます。しかし、触るとクラッシュする等で機能判定の使えないケースについてはコード内に有効な機能のカタログを持つしかありません。また Android のバージョンが分かれば端末の大まかなスペックも推定できるのが素晴らしいですね。
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-6642248856807575782017-02-02T01:01:00.001+09:002021-05-11T22:11:51.178+09:00VSCode拡張の静的サイトジェネレータをマーケットプレイスに公開しました<p>ホームページビルダーの素晴らしさにあやかりたい、という想いのにじむ素晴らしいトップ絵も用意できたのでリリースのお知らせをいたしますよ。
<div class="box">
<a href="https://4.bp.blogspot.com/-_jS4oD7mDQ8/WJFq8Z7sZ-I/AAAAAAAARP0/SJJHoRWJ37cwdBuO2pvuHQ_rY3GI1nIHQCLcB/s1600/NicePageBuilder_package.jpg">
<img src="https://4.bp.blogspot.com/-_jS4oD7mDQ8/WJFq8Z7sZ-I/AAAAAAAARP0/SJJHoRWJ37cwdBuO2pvuHQ_rY3GI1nIHQCLcB/s405/NicePageBuilder_package.jpg"></a>
<p><a href="/2016/12/create-static-site-gen.html">年末の記事</a>でご紹介した VS Code 拡張の静的サイトジェネレータは <a href="https://marketplace.visualstudio.com/items?itemName=itozyun.nice-page-builder" target="_blank" rel="nofollow">Visual Studio Marketplace</a> で公開しています。
<p>また <a href="https://github.com/itozyun/nice-page-builder" target="_blank" rel="nofollow">GitHub</a> にてソースコードをご確認いただけます。同様にしてフォルダツリーを探索するジェネレータ系の拡張を作ろうという方には参考になるのではないでしょうか。
</div>
<div class="note"><p>ちなみに僕は初めての VS Code 拡張の開発に着手する際には <a href="https://marketplace.visualstudio.com/items?itemName=mathiasfrohlich.latexcompile" target="_blank" rel="nofollow">LaTeX を生成する VS Code 拡張</a>のソースを参考にしました。
</div>
<h2>インストール・デバッグ・仕様</h2>
<div class="box">
<a href="https://4.bp.blogspot.com/--dlhUkPlQlk/WJHSr_neHUI/AAAAAAAARQI/WZdfVm942So-0N-6Xb8bNzGc7LmdF-dBQCPcB/s1600/install_nice_page_builder.png">
<img src="https://4.bp.blogspot.com/--dlhUkPlQlk/WJHSr_neHUI/AAAAAAAARQI/WZdfVm942So-0N-6Xb8bNzGc7LmdF-dBQCPcB/s160/install_nice_page_builder.png"></a>
<p>詳しい使い方やサンプルは次の記事を確認してください。マニュアルはこの機に大幅に加筆修正しています。
</div>
<div class="links"><a href="/2016/12/npb-manual.html">Nice Page Builderのマニュアル</a>
<a href="/2016/12/npb-test.html">Nice Page Builderをブログ書きながらテストしていったよ</a>
</div>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-57995015383193993952017-01-22T23:16:00.001+09:002021-07-13T15:05:18.728+09:00技術ブログに追加したいほっこりCSS5本<div class="note"><p><a href="/2016/01/blog-management.html">2016.1.18</a>に書いた記事から分けました。</div>
<p>本ブログのような技術情報を書いていくうえで追加して良かった css をご紹介します。
<h3>コードハイライター</h3>
<p>いわずもながですね…
<p><a href="https://github.com/google/code-prettify" target="_blank">Google Code Pritify</a> を使っています。テーマは <a href="https://code.google.com/p/google-code-prettify/source/browse/trunk/styles/sunburst.css" target="_blank">Vim sunburst theme</a> です。
<blockquote title="google/code-prettify - JavaScript - GitHub" cite="https://github.com/google/code-prettify"><p>Which browsers does it work with?
<p>It's been tested with IE 6, Firefox 1.5 & 2, and Safari 2.0.4. Look at the tests to see if it works in your browser.</blockquote>
<h3>フルHD用のレスポンシブレイアウト</h3>
<div class="box">
<a href="http://1.bp.blogspot.com/-LO7AVfTOFmA/VllOYEs2O9I/AAAAAAAAQgY/H6u4gYgo4kg/s1600/fhd_new.png">
<img src="http://1.bp.blogspot.com/-LO7AVfTOFmA/VllOYEs2O9I/AAAAAAAAQgY/H6u4gYgo4kg/s160/fhd_new.png" /></a>
<p>フルHD用のレイアウトによって大画面での閲覧時にメインコンテンツを2段組表示しています。
<p>開発の際にはパソコンモニタでの閲覧性が抜群で、まじお勧めです!
</div>
<div class="links"><a href="/2015/11/DowdyToCool.html">非デザイナーがチャチャッと野暮ったいブログを修正してみた > フルHD向けスタイルについて</a>
</div>
<h3>引用ブロック</h3>
<p>技術ブログを書いていると参照元を表示することが多くなります。
<p>うまく引用ブロックをデザインすれば、引用部分のマークアップを書く手間も苦にならなくなるかも。
<p>本ブログでは、<blockquote> タグの title 属性と cite 属性の内容を表示するようにしています。
<div class="note">
<h4>ずっと気になっているあのマークアップ・・・</h4>
<blockquote title="Naverまとめ、知ってる?HTMLソースがひどすぎて笑える" cite="http://anond.hatelabo.jp/20130627062344"><p>やっぱり、他のサイトからの「引用」文やツイッターからの「引用」文は、全部<div>で囲ってあるだけで、引用文であることを示す<blockquote>じゃない。</blockquote>
<p>2013-06-27 の記事ですが NAVER のソースを拝見すると現在も <div> タグで引用部分を囲っていて <blockquote> は使っていませんね…
</div>
<h3>CUI 風スタイル</h3>
<p>図示したいときに使っています。画像を用意する手間を省けます(^-^;
<pre class="aa">
-+- test_source
|
+- test_output
</pre>
<h3>ノート</h3>
<p>メインの内容から脇道にそれる場合や補足を書く際に使用します。内容の理解を損ねないかと躊躇する話題もどしどし盛り込んでいくことが出来ます。
<p>次のように左側に大きめに余白を開けて表示します。それだけ…<span role="hidden"> (^-^;;</span>
<div class="note">
<h4>“あの時代”は遠くになりにけり</h4>
<p>僕は2003年から“1980年代の文化と技術”に関するホームページを運営していています。ホームページ開始当時ですら懐かしい話題であり、現在は益々“あの時代”は遠くになりました。
<p>そして Web サイト開始当初には当たり前のように使っていた用語に注釈の必要を感じています。
<p>ゆくゆくは登場する固有名詞のほぼ全てにページ作者による注釈が必要になるかもしれません。
</div>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-79830112322956238662017-01-04T22:11:00.003+09:002021-06-08T01:37:50.306+09:00CSSのcontentプロパティと属性セレクタの調査<p>とある CSS ライブラリの開発にあたって content プロパティと属性セレクタの対応状況を調べてみました。
<table>
<thead>
<tr>
<th>ブラウザ<td>content プロパティ<td>属性セレクタ
<tbody>
<tr>
<th>IE<td>8+<td>7+
<tr>
<th>Opera<td>4+<td><a href="http://www.htmq.com/selector/attr.shtml">6+</a>
<tr>
<th>Gecko<td>Firefox0.6+, NN6+<td>Firefox1+
<tr>
<th>Webkit<td>Safari1+, Chrome1+<td>Safari1+
<tr>
<th>iOS<td colspan="2">1+
<tr>
<th>AOSP<td colspan="2">1+
<tr>
<th>Opera Mobile<td>9.5+<td>
<tr>
<th>WP<td>7.5+(IE9ベース)<td>7.0+(IE7ベース)
</table>
<p>表は次の文書を元にしています。実機での調査を元に追記していきます。Opera Mobile の 9.5 というのは正直怪しいと思っています。
<div class="links"><a href="https://developer.mozilla.org/ja/docs/Web/CSS/content">https://developer.mozilla.org/ja/docs/Web/CSS/content</a>
<a href="https://dev.l-c-n.com/CSS3-selectors/browser-support.php">https://dev.l-c-n.com/CSS3-selectors/browser-support.php</a>
<a href="https://hail2u.net/documents/bulletproof-icon-fonts.html">安全でアクセシブルなアイコン・フォント</a>
</div>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-56103012040567883752017-01-04T18:07:00.000+09:002021-07-13T15:04:03.310+09:00デザイナーズDTDとでもいうものを定義して古いコンテンツのまずいhtmlをアップデートする<p>ブログの外枠のデザイン変更は苦になりませんが、記事本文のマークアップのルール変更は大変です。新しいルールを元に記事本文の全てを手動で書き換えるのは現実的ではありません。
<p>この書き換えを自動化するには次の2つのアプローチが考えられます。
<ol>
<li>記事本文をマークダウン等の中間表現で持っていてHTML化のコンバータをアップデートする
<li>デザイナーが記事本文用のDTDを定義する
<ul>
<li>記事投稿の際に本文用DTDでチェックする
<li>アップデートの際には旧DTDから新DTDへの変換ツール用意する
</ul>
</ol>
<p>僕は後者の方針でいきます。
<p>便宜上DTDと書きましたが、要はタグ構造を定義し(制限し)これを検証ツールに突っ込むわけです。検証ツールは js で書くので定義部分も json になると思います。恐らく CSS のセレクターを流用してだいたい事足りるんじゃないでせうか。
<p>本年はそのためのツールの開発に取り組みたいと思っています。以上で方針を書きましたので一旦ここまで、これ以降は蛇足です。
<div class="note"><p>『<a href="/p/ddtd.html">ブログテンプレートのマークアップ規則</a>』に当ブログの DDTD を書きました。全ての組み合わせを列挙してみるとスタイルの指定漏れが見れてきます… (2017.1.20)</div>
<h3>昔書いた記事のhtmlがイケてない問題、そして今書いているhtmlも将来ダメになる問題</h3><p>ブログサービスを利用し始めて12年が過ぎました。この間 goo と livedoor で書いていた記事は Blogger にインポートし、ゆびとまで書いていた DIY 日記はごっそり消滅… 総じて9割超の日記は残すことが出来ています。
<hr>
<p>現在懸案なのが、以前に書いた日記のタグ構造です。些細なことから致命的なことまで以前に書いた記事(html)には様々な問題があります。
<ol>
<li>最新の記事と見栄えが異なり総じてダサい
<li><P> や <blockquot> が使えていない
<li>サムネイルの拡大スクリプト PicaThumbnail で拡大できない
</ol>
<p>しかし、1000件を超える記事たちを手書きで書き換えるわけにはいきません。書き換えが終わったころには HTML6 や新しいブラウザやデバイスが登場しデザイントレンドも変わって再び書き換えなんてことに…
<h3>企業メディアでも同じ問題は起こってる</h3>
<p>この問題は個人のブログに限らずより大きなリソースを注げる企業メディアでも起こっています。みなさんも過去に書かれた記事と最近書かれた記事で、本文の様子が違うなぁと感じたことあると思います。
<p>丁度、随分昔に書かれた記事ながら僕が度々読み返すお気に入り記事があります。この記事のスクリーンショットと同じ Web メディアの最近の記事のスクリーンショットを比較して見てみます。
<h4>2006年の記事『スマートフォンでAjax』</h4>
<div class="box">
<div class="caption" style="width:200px">
<figure>
<a href="https://3.bp.blogspot.com/-l8RehUruv0Q/WGyTZY1i6OI/AAAAAAAARKU/pQaJOZ2nM0wjP6m-OmDQ05UqdLA0o5jZQCLcB/s1600/allabout_ie4ajax.jpg">
<img src="https://3.bp.blogspot.com/-l8RehUruv0Q/WGyTZY1i6OI/AAAAAAAARKU/pQaJOZ2nM0wjP6m-OmDQ05UqdLA0o5jZQCLcB/s200/allabout_ie4ajax.jpg" width="200" height="160" /></a>
<figcaption><a href="https://allabout.co.jp/gm/gc/24133/" target="_blank" rel="nofollow">2006年11月21日に更新された『スマートフォンでAjax [Javascript] All About』のスクリーンショット</a></figcaption>
</figure>
</div>
<p>高橋 登史朗氏による記事は Windows Mobile を搭載した携帯電話、W-ZERO3 や X01HT の登場を背景に書かれたものです。フルブラウザを搭載する携帯電話が珍しかったこの時代に、DHTML・Ajax に不十分ながら対応した Internet Explorer Mobile 用の Web アプリ開発のための情報が紹介されています。
<p>Windows Mobile 5.0 時代の IE Mobile は css-p 対応が削除された一方で XHR を搭載しました。しかし DOM 自体は基本的に IE4.01 のソレで innerHTML を駆使してページを変更するという胸熱のサンプルプログラムが紹介されています。
<hr>
<p>すいません、つい熱くなってテーマに関係ないことを長く書きました…サムネイルをクリックして拡大して頂き、次の同メディアの最近の記事のスクリーンショットと比較してみましょう。
</div>
<h4>2015年の記事『表の空っぽのセルにだけ、CSSで斜線を引く方法』</h4>
<div class="box">
<div class="caption" style="width:200px">
<figure>
<a href="https://3.bp.blogspot.com/--ZOBUUCRGgo/WGyTenlWaqI/AAAAAAAARKY/w7X6pX-2YVwYJAZtz9JJWbVHyPZuFSLzQCLcB/s1600/allabout_css3.jpg">
<img src="https://3.bp.blogspot.com/--ZOBUUCRGgo/WGyTenlWaqI/AAAAAAAARKY/w7X6pX-2YVwYJAZtz9JJWbVHyPZuFSLzQCLcB/s200/allabout_css3.jpg" width="200" height="160" /></a>
<figcaption><a href="https://allabout.co.jp/gm/gc/457196/" target="_blank" rel="nofollow">2015年08月09日に公開の『表の空っぽのセルにだけ、CSSで斜線を引く方法 [ホームページ作成] All About』のスクリーンショット</a></figcaption>
</figure>
</div>
<p>最近書かれた記事で比較しようと物色していたところ、どうやって斜線を入れるのだろう?と目に留まった記事です。CSS3 の linear-gradient を使うとのこと、なるほど!
<hr>
<p>さて、2006年の記事と比較すると200pxのサムネイル画像にテキストが回り込んでいる点がまず目につきます。サムネイルに本文が回り込んだ方が余白が出来ず(読者のスクロール量が減る)画面上のアクセントとなるため読みやすさも上がると考えます。僕のブログでもサムネイルに本文を回り込ませています。
</div>
<h4>ソースのチェック</h4>
<p>回り込み(float)のクリアとか気になったのでここでソースのチェックをしてみます。ソースのコンテンツ部分は適宜に省略しています。
<h5>2006年更新の『スマートフォンでAjax』のソース</h5>
<div class="hscroll">
<pre class="prettyprint lang-html"><code><main role="main">
<article class="aa_article">
<div id="popin_read" class="aa_article-content clearfix" data-tracking-zone="m8">
<style type="text/css">
<div style="font: bold 24px Times;">
<br>
<font size="+2">スマートフォンでAjax</font>
<hr>
<br>
<ul>
<br>
<table id="setright" width="200" cellspacing="5" cellpadding="0" border="0">
<tbody>
<tr>
<td>
<img alt="X01HTでAllAboutを表示" src="htc3.jpg" width="200" border="0">
</td>
</tr>
<tr>
</tbody>
</table>
<br clear="all">
最近、携帯電話にキーボードの付いたものを見かけるようになってきました。...
<br>
</code></pre>
</div>
<h5>2015年公開の『表の空っぽのセルにだけ、CSSで斜線を引く方法』のソース</h5>
<div class="hscroll">
<pre class="prettyprint lang-html"><code><main role="main">
<article class="aa_article">
<div id="popin_read" class="aa_article-content clearfix" data-tracking-zone="m8">
<h3>表の空っぽのセルに対してだけ、CSSで斜線などの装飾を加える方法</h3>
ウェブ上に表(テーブル)を掲載する際、何も書かれていない空っぽのセルに...
<br>
<br>
■<b>縦横の見出しが交差する部分(=左上の1マス)に斜線を引く</b>
<br>
<div class="right200 article_image_box">
<a class="article_gallery" href="/gm/gc/457196/photo/1343758/" rel="" title="空欄に斜線を引いた表の例">
<img class="article_image" src="sampletable1.png" alt="空欄に斜線を引いた表の例" width="200" height="150">
</a>
<p class="cap">空欄に斜線を引いた表の例</p>
</div>
右図では、行と列の見出しが交差する「左上端の1マス(緑色矢印の部分)」に...
<br>
<br>
また、「空欄である」と明示する目的でセル内に斜線を引きたい場合もあるでしょう。...
<br>
<br>
<div class="BRClearAllClass">
<br class="articleFloatClear">
</div>
■<b>「総当たり戦」のような表で、行列が重複(交差)する部分にだけ斜線を引く</b>
<br>
</code></pre>
</div>
<p>えぇと、いろいろアレですがいちいちは書きません…
<p>翻って僕のブログも2009年頃まで遡るとカオスですし、2014年以前の記事ですらサムネイルが拡大できません…
<p>例え閲覧に支障がなくともまずいマークアップは意図を正しく検索エンジンに伝えることができなかったり、スクリーンリーダの動作に支障が出るかもしれません。
<p>僕は技術の維持向上のためというのもブログ運営の理由の一つのです。本年はいよいよこの問題にガツンと取り組みたいと思います。その上で書き換えのうまくいっていないIT系メディアに出会ったら、心の中でファビュラスな微笑をたたえたい。
<p>ではでは本年もよろぴくぴく。
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-3854876592900387332016-12-21T05:00:00.001+09:002021-05-11T22:19:23.631+09:00静的サイトジェネレータをVS Code拡張で作ってみた<div class="note">
<p><a href="https://marketplace.visualstudio.com/items?itemName=itozyun.nice-page-builder">Visual Studio Marketplace</a> で公開してます。(2017.1.22)
<p>900KB のソースから html を生成したところ 1.2MB になりました。(2017.1.4)
</div>
<p><a href="http://qiita.com/advent-calendar/2016/static-site-generator">静的サイトジェネレーター Advent Calendar 2016</a> の21日目です。前の記事はTakeshiNickOsanai氏の『<a href="http://qiita.com/TakeshiNickOsanai/items/060adba3214dc3bb509c">静的サイトジェネレーター「Movable Type」について、誤解されている4つの事柄</a>』です。
<blockquote title="静的サイトジェネレーター Advent Calendar 2016" cite="http://qiita.com/advent-calendar/2016/static-site-generator"><p>選択肢が多いのは嬉しいですが、一方では「いっぱいありすぎてどれを選べばいいか…」的な悩みがありますよね。
</blockquote>
<p>という静的サイトジェネレーターについて、いっぱいありすぎたので“さらに作って増やしてみた”という記事です。
<p>記事の結論としては、簡単でちっちゃなものでもいい仕事をしてくれるので自作しましょう、VS Code 拡張などにして js で開発しましょう、です。
<div class="note">
<p>テストしつつ書き進めた使い方の記事があります。動作や設計などはそちらなどを参考にしてください。
<div class="links"><a href="/2016/12/npb-test.html">Nice Page Builderをブログ書きながらテストしていったよ</a>
<a href="/2016/12/npb-manual.html">Nice Page Builderのマニュアル</a>
</div>
</div>
<h2>制作の背景</h2>
<p>僕は2003年からホビーに関するホームページを Yahoo! Geocities で運営しています。運営開始当初は個人ホームページによくあるシンプルなページでした。
<p>長らくこの状態のまま運営されたホームページは2009年に当時風な2カラムのデザインにリニューアル、続いてレスポンシブデザインに。この際に数十ページを書き換えることができたのは Adobe の <em>Dreamweaver(以下<abbr title="Dreamweaver">Dw</abbr>) という静的サイトジェネレータのおかげ</em>でした。
<h3>Dw でお世話になった機能</h3>
<dl>
<dt>テンプレート
<dd>テンプレートとなる HTML を継承してページを作る機能、なんと継承したページをさらに継承することも出来ました。
<dt>ライブラリ
<dd>共通部品を切り出して複数のページから読み込む機能
<dt>CSS 等のコード保管
<dd>そういえば Dw が初めて触ったコードハイライトの効くエディタでした、その後は最近まで Aptana Studio のお世話になりました。
<dt>WYSIWYG 編集機能、特にテーブル
<dd>慣れてくるとコード直打ちの方が速くて確実なのですが。テーブルタグの <code>rowspan</code>, <code>colspan</code> をマウス操作で指定できる機能は最後まで便利だなと思ってました。
<dt>ftp アップロード
<dd>使いだしたときは便利で感動しました。
</dl>
<hr>
<p>最後のリニューアルから5年近くが経過して、デザインが野暮ったくてコンテンツを追加する気が起きない… 再び大型リニューアルを!という状態になりました。しかしこの時にはもう Dw とそりが合わなくなっていたため足踏み状態が長く続いてしまいました。
<h3>Dw が合わない点</h3>
<ol>
<li>invalid な HTML を書くことができない
<li>プラグインでやりたいことができなかった
<li>テンプレートとライブラリしか使っていないから機能過多
</ol>
<p>そんな矢先に Visual Studio Code を使い始め、このたび拡張機能で静的サイトジェネレータをつくることにしました。
<h2>VS Code拡張で静的サイトジェネレートする</h2>
<p>今回実装した機能は次になります。これだけで僕のニーズは全て満たすことが出来ています。
<ol>
<li>テンプレート用 HTML とコンテンツ HTML の合成
<li>複数のページで共用するデータを別ファイルに分離するミックスイン機能(Dw のライブラリ機能に近い)
<li>サイト開発者が HTML 文字列を返す関数を自由に追加・呼び出す機能
<li>Google Spreadsheets に自動で蓄えた(Google Apps Script 使用)ページに関するツイートを json で取得してページに静的に埋め込む機能(コードだけ用意して<del>未確認</del> → http[s]:経由で json を取得することが出来なかった…)
<li>停止した掲示板の json 形式のログからページを作る機能(コードだけ用意して<del>未確認</del> → 動作した)
</ol>
<p>ほんのわずかなコードで実装できるのでお勧め、みんなもドンドン自分で作って「これからは一人いち静的サイトジェネレータだ」という結論のつもりでしたが… いざ数えてみたら500行を超えていました… なのであえてお勧めしません…
<h3>JavaScript でつくるメリット</h3>
<p>静的サイトジェネレータを VS Code 拡張で制作しておくと全てを js で記述することができます。js で書けるということは次の利点が思いつきます。
<ol>
<li>Web 開発者がもっとも馴染んだ言語で開発できる
<li>ソースから HTML を生成するロジックをそのままブラウザで動かすことができる
</ol>
<p>2 については、例えばオフラインでサイトの全文を閲覧したいケース。ソースと生成ロジックをダウンロードすれば全てのページが再現できます。ということで僕はホームページのオフライン化を次の目標に致します。
<p>ではでは。
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-65804234528354591192016-12-21T04:59:00.007+09:002021-05-13T16:56:36.371+09:00Nice Page Builderをブログ書きながらテストしていったよ<div class="note">
<p>目次を追加してマークアップを修正、併せて追記と修正を行っています。(2021.5.11)
<p><a href="/2017/02/npb-released.html">諸々公開</a>しています。(2017.2.2)
</div>
<ol>
<li><a href="#nice_page_builder_tutorial_1">最小のパターン</a>
<li><a href="#nice_page_builder_tutorial_2">任意のプロパティを追加してみる</a>
<li><a href="#nice_page_builder_tutorial_3">各ページで共通する値を別ファイルに分離したい <code>MIXINS</code></a>
<li><a href="#nice_page_builder_tutorial_4">ルート相対リンクから相対リンクへ変換</a>
<li><a href="#nice_page_builder_tutorial_5"><code>beforeBuild</code> スクリプトと <code>Page</code> クラスの拡張</a>
</ol>
<p>現在 Nice Page Builder は自分のホームページ開発に使っています。生憎とコードが散らかっているので公開はもうちょい先になります。
<a name="nice_page_builder_tutorial_1"></a>
<h2 id="nice_page_builder_tutorial_1">1. 最小のパターン</h2>
<pre class="aa">npmTestProject
- source
templete.html
index.html
- output
index.html
</pre>
<p>まずは最低限の機能、テンプレートだけな HTML とコンテンツだけの HTML から完成版の HTML を生成します。
<h3>source/templete.html</h3>
<pre class="prettyprint lang-html"><code><!DOCTYPE html>
<html>
<head></head>
<body>
<header></header>
<main>{$$ this.CONTENT $$}</main>
<footer></footer>
</body>
</html>
</code></pre>
<p>テンプレート側からコンテンツは <code>this.CONTENT</code> または <code>page.CONTENT</code> で取得します。
<h3>source/index.html</h3>
<pre class="prettyprint lang-html"><code><script type="nice-page-builder/object" for="page-option">
{
TEMPLETE : '/templete.html'
}
</script>
<p>Hello, World!
</code></pre>
<p>テンプレートへの参照は上の通り <code><script></code> 要素内のオブジェクトリテラルで行います。独自の <code>type</code> と <code>for</code> 属性が付いています。
<p>この独自 <code><script></code> 要素の内容は生成過程で評価・破棄されて生成物に含まれることはありません。
<h3>output/index.html</h3>
<p>18日(日)夕までに先の2つのファイルから次の index.html を得ることが出来ました。
<pre class="prettyprint lang-html"><code><!DOCTYPE html>
<html>
<head></head>
<body>
<header></header>
<main>
<p>Hello, World!</main>
<footer></footer>
</body>
</html>
</code></pre>
<a name="nice_page_builder_tutorial_2"></a>
<h2 id="nice_page_builder_tutorial_2">2. 任意のプロパティを追加してみる</h2>
<p>次に任意のプロパティの使い方を見ていきます。これはサイト開発者がプロジェクト毎に独自に定義していきます。
<h3>source/index.html</h3>
<pre class="prettyprint lang-html"><code><script type="nice-page-builder/object" for="page-option">
{
TEMPLETE : '/templete.html',
title : 'Hello'
}
</script>
<p>Hello, World!
</code></pre>
<p>ページ毎にタイトルを変えたいので(当たり前ですね)、<code>title</code> というプロパティを追加します。
<h3>source/templete.html</h3>
<pre class="prettyprint lang-html"><code><!DOCTYPE html>
<script type="nice-page-builder/object" for="page-option">
{
title : 'No Title!'
}
</script>
<html>
<head><title>{$$ this.title $$}</title></head>
<body>
<header><h1>{$$ this.title $$}</h1></header>
<main>{$$ this.CONTENT $$}</main>
<footer></footer>
</body>
</html>
</code></pre>
<p>テンプレートで <code>title</code> 文字列を挿入したい位置に追記していきます。またデフォルトのタイトルがある場合、テンプレートに書いておきます。
<h3>output/index.html</h3>
<p><samp>Hello</samp> が挿入されていること、source/index.html で <code>title</code> を指定しなかった場合、<samp>No Title!</samp> が代わりに挿入されていることを確認できました。
<pre class="prettyprint lang-html"><code><!DOCTYPE html>
<html>
<head><title>Hello</title></head>
<body>
<header><h1>Hello</h1></header>
<main>
<p>Hello, World!</main>
<footer></footer>
</body>
</html>
</code></pre>
<a name="nice_page_builder_tutorial_3"></a>
<h2 id="nice_page_builder_tutorial_3">3. 各ページで共通する値を別ファイルに分離したい <code>MIXINS</code></h2>
<p>DreamWeaver でいうところのライブラリ機能のように各ページで共通して使う値を分離することができます。
<p>トップページ(index.html)の他に商品の紹介ページ(今回はペン、パイナップル、アップルの計3ページ)を持つ企業サイトを例にします。
<pre class="aa">npmTestProject
- source
templete.html
index.html
products
apple.html
pen.html
pineapple.html
mixins
products.json
- output
index.html
products
apple.html
pen.html
pineapple.html
</pre>
<h3>source/templete.html</h3>
<pre class="prettyprint lang-html"><code><!DOCTYPE html>
<script type="nice-page-builder/object" for="page-option">
{
title : 'No title!'
}
</script>
<html>
<head><title>{$$ (this.category ? this.category + ' &gt; ' : '' ) + this.title $$}</title></head>
<body>
<main>{$$ this.CONTENT $$}</main>
</body>
</html>
</code></pre>
<p>新しいプロパティ <code>category</code> を追加します。三項式を使って <code><title></code> に出力されるようにしました。
<h3>source/products/apple.html</h3>
<pre class="prettyprint lang-html"><code><script type="nice-page-builder/object" for="page-option">
{
MIXINS : ['/mixins/products.json'],
title : 'Apple'
}
</script>
<p>This is a Apple.
</code></pre>
<p><code>MIXINS</code> というビルトインプロパティで商品紹介ページに共通する値を持つ <code>"/mixins/products.json"</code> のパスを書きます。
<h3>source/mixins/products.json</h3>
<pre class="prettyprint lang-js"><code>{
"TEMPLETE" : "/templete.html",
"category" : "商品紹介",
"title" : "商品の title がありません"
}
</code></pre>
<p>ミックスインの内容はページのプロパティにコピーされます。ページ側ですでにプロパティが定義されている場合、上書きされることはありません。優先順位は ページ > ミックスイン[0] > ミックスイン[z] > テンプレートです。
<p>json の書き方がめんどくさい場合、js のオブジェクトリテラルで書いてしまっても構いません。その際はエディタの構文チェックが警告してくるのでファイル名を products.js にします。
<h3>output/products/apple.html</h3>
<pre class="prettyprint lang-html"><code><!DOCTYPE html>
<html>
<head><title>商品紹介 &gt; pineapple</title></head>
<body>
<main>
<p>This is a pineapple.</main>
</body>
</html>
</code></pre>
<p>できた!
<a name="nice_page_builder_tutorial_4"></a>
<h2 id="nice_page_builder_tutorial_4">4. ルート相対リンクから相対リンクへ変換</h2>
<p>ここまでのテストでフォルダ階層ができたのでリンクの変換を CSS の追加をダシに確認します。
<pre class="aa">npmTestProject
- source
templete.html
index.html
products
apple.html
pen.html
pineapple.html
mixins
products.json
- output
index.html
products
apple.html
pen.html
pineapple.html
css
all.css
</pre>
<h3>output/css/all.css</h3>
<p>output/css 下に次のファイルを追加しました。
<pre class="prettyprint lang-css"><code>body { background: yellow; color : darkgoldenrod; }
</code></pre>
<h3>source/templete.html</h3>
<p>続いて <code><link></code> をテンプレートに追加します。この際にリンクをソースのルートフォルダからのルート相対リンクで指定して <code>($$ ~ $$)</code> で挟みます。
<pre class="prettyprint lang-html"><code><link rel="stylesheet" type="text/css" href="($$ /css/all.css $$)">
</code></pre>
<div class="box">
<a href="https://3.bp.blogspot.com/-344FZ67IQBo/WFeVG6M6dyI/AAAAAAAARHM/Hwq2m2TXLEYNYrVXPj-Ai2jsAgprj5PkwCLcB/s1600/npb_test_pen.png"><img src="https://3.bp.blogspot.com/-344FZ67IQBo/WFeVG6M6dyI/AAAAAAAARHM/Hwq2m2TXLEYNYrVXPj-Ai2jsAgprj5PkwCLcB/s200/npb_test_pen.png"></a>
<p>テンプレートは様々な階層から参照されます。その際にパスがズレない為のルート相対リンクです。
<p>/index.html では <code><link rel="stylesheet" type="text/css" href="css/all.css"></code> が products/*.html では <code><link rel="stylesheet" type="text/css" href="../css/all.css"></code> が追加されました。
</div>
<a name="nice_page_builder_tutorial_5"></a>
<h2 id="nice_page_builder_tutorial_5">5. <code>beforeBuild</code> コールバックと <code>Page</code> クラスの拡張</h2>
<p>インラインスクリプト(<code>{$$ /* inline script */ $$}</code>)では長々とスクリプトを書くには適しません。また同じ内容のインラインスクリプトが複数ある場合メソッドにまとめたいところです。
<p>次のように <code><script type="nice-page-builder/js" for="beforeBuild"></code> 内にスクリプトを書きます。ここに書かれたスクリプトは <code>pages</code> と <code>Page</code> のグローバル変数にアクセスできます。
<p><code>pages</code> を <code>for in</code> ループで回して集計をしたり、<code>Page.prototype</code> に値やメソッドを追加できます。
<pre class="prettyprint lang-html"><code><!DOCTYPE html>
<script type="nice-page-builder/object" for="page-option">
{
title : 'No title!'
}
</script>
<script type="nice-page-builder/js" for="beforeBuild">
// 全ページのリンクを取得
var links = [], path, label;
for( path in pages ){
links.push({title:pages[path].title,path:pages[path].FILE_PATH});
};
// リンクリストを書きだすメソッドの追加
Page.prototype.ALL_LINK = links;
Page.prototype.createLinkList = function(){
var html = [], i = -1, link;
for( ; link = this.ALL_LINK[++i]; ){
if( link.path !== this.FILE_PATH )
html.push('<a href="'+ this.toRelativePath(link.path) + '">' + link.title + '</a>');
};
return html.join(',');
};
</script>
<html>
<head>
<title>{$$ (this.category ? this.category + ' > ' : '' ) + this.title $$}</title>
<link rel="stylesheet" type="text/css" href="($$ /css/all.css $$)">
</head>
<body>
<main>{$$ this.CONTENT $$}</main>
<footer>{$$ this.createLinkList() $$}</footer>
</body>
</html>
</code></pre>
<div class="box">
<a href="https://4.bp.blogspot.com/-n6olk5Lwfz8/WFe0Sge3uEI/AAAAAAAARHc/nAvXvi2zse82jfuANf_eQBEvpdvq8omEACLcB/s1600/npb_test_apple.png"><img src="https://4.bp.blogspot.com/-n6olk5Lwfz8/WFe0Sge3uEI/AAAAAAAARHc/nAvXvi2zse82jfuANf_eQBEvpdvq8omEACLcB/s160/npb_test_apple.png"></a>
<p><code><footer></code> に他のページへのリンクを貼ることが出来ました!
</div>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-76853777079337406882016-12-19T08:44:00.009+09:002021-05-12T12:02:07.784+09:00Nice Page Builderのマニュアル<div class="note"><p><code>onBeforeWrite</code> から <code>beforeBuild</code> へ修正。構成を改めてマークアップと文言の修正をしました。目次を追加しました。(2021.5.11)
<p><code>page.URL</code> について追記。(version 0.0.12~, 2019.5.2)
<p>加筆と修正を行いました。(2017.2.2)
</div>
<h2>目次</h2>
<ol>
<li><a href="#nice_page_builder_1">はじめに</a>
<li><a href="#nice_page_builder_2">インストール</a>
<ol>
<li><a href="#nice_page_builder_2_1">settings.json</a>
</ol>
<li><a href="#nice_page_builder_3">デバッグ</a>
<li><a href="#nice_page_builder_4">実行フロー</a>
<li>HTML の拡張タグ
<ol>
<li><a href="#nice_page_builder_5_1">ページのプロパティを記述</a>
<ol>
<li><a href="#nice_page_builder_5_1_1">ページのプロパティの優先順位</a>
</ol>
<li><a href="#nice_page_builder_5_2"><del>onBeforeWrite</del><code>beforeBuild</code> スクリプト</a>
</ol>
<li>HTML の拡張表記
<ol>
<li><a href="#nice_page_builder_6_1"><code>{$$ インラインスクリプト $$}</code></a>
<li><a href="#nice_page_builder_6_2"><code>($$ ルート相対パスの相対パスへの変換 $$)</code></a>
</ol>
<li><code>Page</code> クラス
<ol>
<li><a href="#nice_page_builder_7_1"><code>Page</code> インスタンスの読み取り専用プロパティ</a>
<li><a href="#nice_page_builder_7_2"><code>Page</code> インスタンスのビルトインメソッド</a>
<li><a href="#nice_page_builder_7_3"><code>Page</code> インスタンスのビルトインプロパティ</a>
</ol>
</ol>
<a name="nice_page_builder_1"></a>
<h2 id="nice_page_builder_1">1. はじめに</h2>
<p>テンプレートとなる HTML ファイル、コンテンツだけを記述した HTML ファイル、複数のページで共通したプロパティが記述してある json (.js 形式でも可)ファイル。データが記述された json ファイル。これらから Web サイトを生成する静的サイトジェネレータです。
<p>HTML を生成する複雑なロジックを javascript で記述できます。この文書より先に<a href="/2016/12/npb-test.html">チュートリアル</a>を読んだ方が良いでしょう。僕が書いたにしては分かりやすく書けていると思います。
<a name="nice_page_builder_2"></a>
<h2 id="nice_page_builder_2">2. インストール</h2>
<div class="box">
<a href="https://4.bp.blogspot.com/--dlhUkPlQlk/WJHSr_neHUI/AAAAAAAARQI/WZdfVm942So-0N-6Xb8bNzGc7LmdF-dBQCPcB/s1600/install_nice_page_builder.png">
<img src="https://4.bp.blogspot.com/--dlhUkPlQlk/WJHSr_neHUI/AAAAAAAARQI/WZdfVm942So-0N-6Xb8bNzGc7LmdF-dBQCPcB/s200/install_nice_page_builder.png"></a>
<p>拡張機能のインストールは VS Code の GUI から簡単に行えます。拡張機能タブを開いて『Nice Page Builder』を検索してください。
</div>
<a name="nice_page_builder_2_1"></a>
<h3 id="nice_page_builder_2_1">2.1. settings.json</h3>
<div class="box">
<a href="https://1.bp.blogspot.com/-mUoqZK7l-_U/WJH8eT76yeI/AAAAAAAARQU/xX1hdTYefqUt7SzyF8qAjchHf3laCz7fACLcB/s1600/settings.json_nice_page_builder.png">
<img src="https://1.bp.blogspot.com/-mUoqZK7l-_U/WJH8eT76yeI/AAAAAAAARQU/xX1hdTYefqUt7SzyF8qAjchHf3laCz7fACLcB/s160/settings.json_nice_page_builder.png"></a>
<p>ワークスペースの設定にソースフォルダのルートや json の読み込み、アウトプットフォルダを指示します。アウトプットフォルダには RAM ディスクなどの異なるドライブを指定することもできます。
</div>
<pre class="prettyprint lang-js"><code>{
"nicePageBuilder.tasks" : [{
"htmlRoot" : { "rootPath" : "source", "include" : "", "exclude" : "" },
"jsonList" : [
{ "path" : "jsons/comment.json", "name" : "comment" },
{ "path" : "jsons/tweet.json", "name" : "tweet" }
],
"output" : "R:/output"
}]
}
</code></pre>
<a name="nice_page_builder_3"></a>
<h2 id="nice_page_builder_3">3. デバッグ</h2>
<div class="box">
<a href="https://1.bp.blogspot.com/-Rw_uwy-vEhA/WJH8fXrlVRI/AAAAAAAARQY/1ybtGcH26-YcD2yPmVn8YmxpQce2qRZQgCLcB/s1600/debug_nice_page_builder.png">
<img src="https://1.bp.blogspot.com/-Rw_uwy-vEhA/WJH8fXrlVRI/AAAAAAAARQY/1ybtGcH26-YcD2yPmVn8YmxpQce2qRZQgCLcB/s160/debug_nice_page_builder.png"></a>
<p>エラー時には簡単なエラーメッセージが表示されます。
<p>詳細なデバッグには開発者ツールを使用します。JavaScript デバッガが使えないようで <code>console.log</code> で頑張ります…
</div>
<a name="nice_page_builder_4"></a>
<h2 id="nice_page_builder_4">4. 実行フロー</h2>
<ol>
<li>コンテンツだけの HTML、この<a href="#nice_page_builder_5_1">ページのプロパティ</a>で関連付けられたテンプレートファイルとミックスインファイルの読み込み
<li>settings.json の <code>"jsonList"</code> に記述された json ファイルの読み込み
<li>HTML に<a href="#nice_page_builder_5_2">拡張タグ</a>内に記述された <del>onBeforeWrite</del><code>beforeBuild</code> スクリプトの実行
<li>書き出し
</ol>
<h2>5. HTML の拡張タグ</h2>
<a name="nice_page_builder_5_1"></a>
<h3 id="nice_page_builder_5_1">5.1. ページのプロパティを記述</h3>
<div class="hscroll">
<pre class="prettyprint lang-html"><code><script type="nice-page-builder/object" for="page-option">
{
TEMPLETE : '/Templetes/templete.html',
MIXINS : ['/Mixin/top.json'],
title : '俺のサイトにようこそ!'
}
</script>
</code></pre></div>
<p><code>TEMPLETE</code> についてはミックスインファイル側に書いておくこともできます。テンプレートファイルのプロパティに <code>TEMPLETE</code> を持つことはできません。
<a name="nice_page_builder_5_1_1"></a>
<h4 id="nice_page_builder_5_1_1">5.1.1. ページのプロパティの優先順位</h4>
<ol>
<li>ページの <code><script type="nice-page-builder/object" for="page-option"></code> 下にあるプロパティ
<li><code>MIXINS[0]</code> のプロパティ
<li><code>MIXINS[n]</code> のプロパティ
<li><code>TEMPLETE</code> のプロパティ
</ol>
<a name="nice_page_builder_5_2"></a>
<h3 id="nice_page_builder_5_2">5.2. <del>onBeforeWrite</del><code>beforeBuild</code> スクリプト</h3>
<p>ソースの HTML、 ミックスインファイル、テンプレート、JSON の読み取りが終わって、ファイルの書き出しがはじまる前に実行したい javascript を記述します。
<div class="hscroll">
<table>
<thead>
<tr>
<th>値<td>名前<td>説明
<tbody>
<tr>
<th><code>Page</code><td>クラス<td><code>Page.prototype.createSocialButton=function(){}</code>などとページ用のメソッドを追加できます
<tr>
<th><code>pages</code><td>全ての <code>page</code> を収めたハッシュ<td>key:ルート相対パス, value:<code>page</code> で全てのページを保持しています
<tr>
<th><code>page</code> または <code>this</code><td>インスタンス<td><del>onBeforeWrite</del><code>beforeBuild</code> スクリプトの書いてあった <code>page</code> が入っています
</table>
</div>
<div class="hscroll">
<pre class="prettyprint lang-html"><code><script type="nice-page-builder/js" for="beforeBuild">
// 全ページから label を回収
var labels = {}, path, label;
for( path in pages ){
if( pages[path].label ) labels[ label ] = true;
};
// ラベルリストを書きだすメソッドの追加
Page.prototype.ALL_LABELS = labels;
Page.prototype.createLabelList = function(){
var html = [], label;
for( label in this.ALL_LABELS ){
html.push('<b>' + label + '</b>');
};
return html.join(',');
};
</script>
</code></pre>
</div>
<p>このタイミングで新しいページを追加することもできます。<code>pages</code> の集計結果や json を使って動的にページを追加します。
<div class="hscroll">
<pre class="prettyprint lang-html"><code><script type="nice-page-builder/js" for="beforeBuild">
var comments = this.getJSON( 'bbs' ), comment, bbsPage, key, lastPage;
while( comment = comments.shift() ){
bbsPage = new Page( '/bbs/' + comment.file_name );
bbsPage.MIXINS = ['/Templetes/bbs.js'];
bbsPage.CONTENT = '<div>' +
'<span itemprop="author">' + comment.author + '</span> ' +
'<time datetime="' + (new Date(comment.created_at)).toISOString() + '" itemprop="commentTime">' + comment.created_at + '</time> ' +
'</div>' +
'<p itemprop="commentText">' + comment.comment + '</p>';
for( key in comment ) bbsPage[ key ] = comment[ key ];
};
</script>
</code></pre>
</div>
<h2>6. HTML の拡張表記</h2>
<a name="nice_page_builder_6_1"></a>
<h3 id="nice_page_builder_6_1">6.1. <code>{$$ インラインスクリプト $$}</code></h3>
<p><code>eval()</code> の戻り値が文字列として埋め込まれます。<code>this</code> は <code>page</code> インスタンスです。
<div class="hscroll">
<pre class="prettyprint lang-html"><code><main>{$$ this.CONTENT $$}</main>
</code></pre>
</div>
<a name="nice_page_builder_6_2"></a>
<h3 id="nice_page_builder_6_2">6.2. <code>($$ ルート相対パスの相対パスへの変換 $$)</code></h3>
<p>内容をパスとして評価しルート相対パスの場合、相対リンクに変換する。<code>page.FOLDER_PATH</code> を元に置き換えます。
<p>またルート相対パスは、ソースフォルダをルートとするルート相対パスを記述する点に注意が必要です。
<div class="hscroll">
<pre class="prettyprint lang-html"><code><link href="($$ /campany/about.html $$)">
↓
<link href="about.html">
</code></pre>
</div>
<p>Nice Page Builder では出力結果にルート相対パスを含むことはありません。これはジオシティーズのようにサブディレクトリをルートにしてホームページスペースが提供されている場合に都合が悪いためです。
<p>例 <samp>geocities.jp/outcloud/</samp>
<h2>7. <code>Page</code> クラス</h2>
<p>次に示す以外のプロパティはサイト制作者がプロジェクト毎に定義します。<code>page</code> のメソッドもサイト制作者によって <code><script type="nice-page-builder/js" for="beforeBuild"></code> スクリプト時に追加できます。
<a name="nice_page_builder_7_1"></a>
<h3 id="nice_page_builder_7_1">7.1. <code>Page</code> インスタンスの読み取り専用プロパティ</h3>
<p>NicePageBuilder によって設定されるプロパティ。書き換えないでね。
<div class="hscroll">
<table>
<thead>
<tr>
<th>キーワード<td>例<td>型<td>説明
<tbody>
<tr>
<th><code>FILE_PATH</code><td><code>"/game/rpg/about.html"</code><td>string<td>ソースのルートフォルダからのルート相対パス
<tr>
<th><code>FILE_NAME</code><td><code>"about.html"</code><td>string<td>
<tr>
<th><code>FOLDER_PATH</code><td><code>"/game/rpg"</code><td>string<td>ソースのルートフォルダからのルート相対パス、ルート直下の場合 <code>""</code>(空文字列)
<tr>
<th><code>URL</code><td><code>"/game/puzzle/"</code>, <code>"/game/rpg/about.html"</code><td>string<td><code>FILE_PATH</code> から <code>"index.html"</code> を除いた文字列
<tr>
<th><code>CREATED_AT</code><td><code>1234567890</code><td>number<td>ファイルが作られた日付
<tr>
<th><code>MODIFIED_AT</code><td><code>1234567890</code><td>number<td>ファイル自身が修正された日付
<tr>
<th><code>UPDATED_AT</code><td><code>1234567890</code><td>number<td>ファイル自身と <code>TEMPLETE</code> と <code>MIXINS</code> の更新日のうち最新のもの
<tr>
<th><code>CONTENT</code><td><code>"<p>俺のホームページにようこそ!俺です…"</code><td>string<td><p>.html ファイルの内容。
<p>但しページのプロパティ(<code><script type="nice-page-builder/object" for="page-option"></code>)と <code><script type="nice-page-builder/js" for="beforeBuild"></code> は除去してある。
</table>
</div>
<p>同一ドメインの他ファイルへのパスを書くときは<strong>ソースのルートフォルダからのルート相対パス</strong>とします。つまり <samp>/</samp> で始まります。
<a name="nice_page_builder_7_2"></a>
<h3 id="nice_page_builder_7_2">7.2. <code>Page</code> インスタンスのビルトインメソッド</h3>
<div class="hscroll">
<table>
<thead>
<tr>
<th>メソッド<td>引数<td>戻り値<td>説明
<tbody>
<tr>
<th><code>toRelativePath</code><td>string ルート相対パス<td>string 相対パス<td><code>this.FILE_PATH</code> を元に相対パスに変換します
<tr>
<th><code>getPage</code><td>string ルート相対パス<td><code>page</code><td>
<tr>
<th><code>getJSON</code><td>string 名前<td>object<td>settings.json に書いた名前を使って json を取得します
</table>
</div>
<a name="nice_page_builder_7_3"></a>
<h3 id="nice_page_builder_7_3">7.3. <code>Page</code> インスタンスのビルトインプロパティ</h3>
<p>ビルトイン機能のためのプロパティです。ページのプロパティ(<code><script type="nice-page-builder/object" for="page-option"></code> かテンプレートファイルかミックスインファイル)に記述しておくと javascript からは次のプロパティからアクセスできます。
<div class="hscroll">
<table>
<thead>
<tr>
<th>キーワード<td>例<td>型<td>説明
<tbody>
<tr>
<th><code>TEMPLETE</code><td><code>"/Templete/templete.html"</code><td>string<td>テンプレートファイルへの参照。
<tr>
<th><code>MIXINS</code><td><code>["/Mixin/category-game.json", "/Mixin/pageType-item.json"]</code><td><code>array.<string></code><td>ミックスイン用 json ファイルへの参照。
</table>
</div>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-63100145360280238312016-12-19T00:00:00.000+09:002016-12-19T06:26:30.100+09:00Google Apps Script上に制作してた静的サイトジェネレータの始末記<div class="box">
<div class="caption" style="width:200px">
<figure>
<a href="https://2.bp.blogspot.com/-9vL2GXgiJNY/WFZ_1XIHoDI/AAAAAAAARG8/YGbAmJzvSJYwE6bn57o_5YLnzD-JOACKwCLcB/s1600/ssg_on_gas.png"><img src="https://2.bp.blogspot.com/-9vL2GXgiJNY/WFZ_1XIHoDI/AAAAAAAARG8/YGbAmJzvSJYwE6bn57o_5YLnzD-JOACKwCLcB/s200/ssg_on_gas.png"></a>
<figurecaption>ありし日の静的サイトジェネレータ on GAS</figurecaption>
</figure>
</div>
<p><a href="http://qiita.com/advent-calendar/2016/static-site-generator">静的サイトジェネレーター Advent Calendar 2016</a> の19日目になります。
<p>直前の記事は sky_y 氏による『
<a href="http://qiita.com/sky_y/items/7c29909c5cffa28b23d8">HexoのレンダリングエンジンとしてPandocを使う - Qiita</a>』です。次の記事は TakeshiNickOsanai 氏が準備されています。
</div>
<div class="note">
<p>Google Apps Script はユーザーの登録した js をサーバ側で実行する環境です。この js から Google の様々なサービスを利用することができます。今回は主に Google Drive を操作して html ファイルを生成します。
</div>
<h3>静的サイトジェネレータ on Google Apps Script の始末</h3>
<p>ホームページの更新のために制作していた静的サイトジェネレータ on Google Apps Script(以下<abbr title="Google Apps Script">GAS</abbr>) は次の理由により破棄しました。
<ol>
<li>ソースの更新・HTML の生成の毎に Google Drive 内のファイル同期で通信が発生する
<ul>
<li>HTML の確認に時間がかかる
<li>従量制の回線のライフが削られる
</ul>
<li>100程度のファイル更新を数回行うと GAS のマシンタイムを使い切ってしまいその日は作業できなくなる
</ol>
<p>こう書いてしまうとやる前から分かりきったことを…
<p>結局デザインを流用しつつ Visual Studio Code の拡張機能として再実装しましたとさ、チャンチャン♪
<p>次の駄文は GAS 版の紹介用に用意していました。こっそり公開フラグを立てておきますよ。
<hr>
<p>試験運用を開始してから知ったのですが、静的サイトジェネレータというジャンルのツールで出てきているそうです。
<p>ナイスページビルダーはその GAS 版です。
<ol>
<li>本文だけの .html とテンプレートファイルを用意します
<li>これらを元に完全版の .html を出力用フォルダに書き出します
<li>以上の操作をプロジェクトフォルダ以下のすべての .html(.htm) に対して行います
<li>操作を行うのは Google Apps Script です
<li>テンプレートも .html も書き出しフォルダも Google Drive 上に配置します
<li>ナビゲーションリンクなどの生成は js で書いて自動化できます
</ol>
<h3>個人ホームページあるある?</h3>
<p>本題の前に開発の背景を個人ホームページあるあるで明らかにします。
<h4>1. 無料ホームページサービスに登録して10年選手だ</h4>
<p>Yes, 2003年から無料ホームページサービスの geocities.jp のお世話になっています。
<p>なんと最初期のコンテンツはシグマリオン2の Pocket Word で書いていました。
<p>現在も細々と更新を続けていて反響もたまあに頂きます。
<h4>2. ホームページと連動する(はずの)ブログをうっかり始めたが連動していない</h4>
<p>Yes, html の更新が大変なことに業を煮やし2009年からブログを併設しました。それもうかりと3つも、、、
<p>Google の無料ブログサービス Blogger でしたのでとてもカスタマイズ性がよく、頑張ってデザインをシームレスにすることはできました。
<h4>3. ホームページビルダーでなく Dreamweaver を導入したのは不幸中の幸いだった</h4>
<p>Yes, 先のシームレス化に多大な貢献をしてくれたのが途中から導入した Adobe Dreamwerver でした。
<p>個人ホームページ時代の産物をこれまで継続して更新できたのは、Dreamwerver のテンプレート機能とライブラリ機能のおかげです。
<h4>4. 個人ホームページだけどおかげさまでレスポンシブレイアウト化した</h4>
<p>Yes, 2011年に頑張ってレスポンシブレイアウトを導入しました。個人ホームページなのによくやる、と友人にうけていました。
<h4>5. とってもお世話になった Dreamweaver だがそろそろ縁を切りたい</h4>
<p>Yes, そんな Dreamweaver ですが、使っている機能といえばテンプレート機能とライブラリ機能だけでした。
<p>一方でデメリットが目に付くようになってきました。
<ol>
<li>プラグイン機能でやりたいことが出来なかった
<li>Dreamweaver 用のコメントがHTMLに大量に書き出されてしまう
<li>invalid な HTML を書くことが出来ない
</ol>
<hr>
<p>そんなあるあるを経て、現在更新が滞りデザインのイケテなさに萎えています…
<h3>さぁてこ入れだ、それも頑張らないで</h3>
<p>読者諸賢は“個人ホームページあるある”いくつ当てはまりましたか?
<p>さて、そんなこんなでてこ入れをしようと考えていたところ、ようやく頑張らなくてもよさそうな手が見つかりました。
<p>別件で久しぶりに GAS を使ってみて(随分前にサービス提供終了した Yahoo!Pipes の置き換えです…) Google Drive に様々な操作を行えることがわかりました。
<p>これでしたら Dreamweaver のテンプレート機能やライブラリ機能、プラグイン機能を javascript(Google Apps Script)で置き換えることが出来ます。
<hr>
<p>記事は紹介編として準備していて、これに続く使い方編も書きかけていました。使い方編を書き付けていたお蔭で VSCode 拡張として仕切りなおすときには資料にできましたよ、テヘヘ…
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-13425088238676076072016-12-13T20:30:00.000+09:002016-12-13T20:32:58.634+09:00シャープのバブルラジカセQT-34CDの分解洗浄<div class="box">
<div class="caption" style="width:200px">
<figure><a href="https://3.bp.blogspot.com/-2lWt0yG3ca8/WEbqbSN1aEI/AAAAAAAARF0/R7JCDtqr2BAzUihvnVUvIU896hhOM9BrwCLcB/s1600/clean_radio_cassette_7.jpg">
<img src="https://3.bp.blogspot.com/-2lWt0yG3ca8/WEbqbSN1aEI/AAAAAAAARF0/R7JCDtqr2BAzUihvnVUvIU896hhOM9BrwCLcB/s200/clean_radio_cassette_7.jpg"></a>
<figurecaption>分解洗浄が済んだQT-34CD</figurecaption>
</figure>
</div>
<p><a href="/2016/12/antique-chair.html">件のリサイクルショップ</a>で頂戴したラジカセの分解清掃を行いました。
<p>シャープの簡易モデル QT-34CD (<a href="http://thunder17.blog103.fc2.com/blog-entry-398.html" title="SALTAWAY シャープ CDラジカセの定価とリモコンのメモ"><q>1989年発売 QT-34CD 43,900円 リモコンなし</q></a>)です。
<p>ネジがかなり深いところにあったので100円ショップで一番長いドライバーを購入し、さらに柄を削って長さを稼ぎました。
</div>
<h3>簡易動作確認(分解洗浄前)</h3>
<p>分解洗浄前の簡易動作確認は次の通り。結構ちゃんと動いてくれて感動です。
<table>
<thead>
<tr>
<th>機能<td>動作<td>メモ
<tbody>
<tr>
<th>ラジオ<td>〇<td>
<tr>
<th>カセットデッキ<td>多分 〇<td>再生のみ確認(ABデッキ)
<tr>
<th>CD デッキ<td>△<td>TOC 情報取得に成功、再生に失敗
</table>
<h3>分解の様子</h3>
<p>写真はあとで組み立てに困らないように撮影しました。
<div class="box">
<a href="https://2.bp.blogspot.com/-xhwPOBMh-3g/WEbqZyE0SdI/AAAAAAAARFg/ouYTSOaMViQvl4iBK4394s2prgXS609qACLcB/s1600/clean_radio_cassette_1.jpg">
<img src="https://2.bp.blogspot.com/-xhwPOBMh-3g/WEbqZyE0SdI/AAAAAAAARFg/ouYTSOaMViQvl4iBK4394s2prgXS609qACLcB/s100/clean_radio_cassette_1.jpg"></a>
<a href="https://3.bp.blogspot.com/-HzoiGa4pcNY/WEbqaBx7d7I/AAAAAAAARFk/FH2DF64x7sgK6GYPbyeHZ6KNMuUAISP9gCLcB/s1600/clean_radio_cassette_2.jpg">
<img src="https://3.bp.blogspot.com/-HzoiGa4pcNY/WEbqaBx7d7I/AAAAAAAARFk/FH2DF64x7sgK6GYPbyeHZ6KNMuUAISP9gCLcB/s100/clean_radio_cassette_2.jpg"></a>
<a href="https://1.bp.blogspot.com/-AGjvljJt_g4/WEbqZq6dQcI/AAAAAAAARFc/RsdK70t_d8g5qGgzhiozPCByN2AsZ8CAgCLcB/s1600/clean_radio_cassette_3.jpg">
<img src="https://1.bp.blogspot.com/-AGjvljJt_g4/WEbqZq6dQcI/AAAAAAAARFc/RsdK70t_d8g5qGgzhiozPCByN2AsZ8CAgCLcB/s100/clean_radio_cassette_3.jpg"></a>
</div>
<p>埃が酷いです。
<p>分解の最中にバネとプラスチック片が一つづつ落ちて来ました。もともと何処にあったものかサッパリわかりません… 動作確認が上々だったので一旦忘れることにします。
<h3>洗浄</h3>
<div class="box">
<a href="https://3.bp.blogspot.com/-e2CXd0f96OA/WEbqasVUCOI/AAAAAAAARFo/NZXMj7eW184jq3RCf2GyaTHYmmrHkf1kACLcB/s1600/clean_radio_cassette_4.jpg">
<img src="https://3.bp.blogspot.com/-e2CXd0f96OA/WEbqasVUCOI/AAAAAAAARFo/NZXMj7eW184jq3RCf2GyaTHYmmrHkf1kACLcB/s100/clean_radio_cassette_4.jpg"></a>
<p>洗浄は一番心踊る時間です。風呂場に持ち込んでシャワーで一気に流します。
<p>メカ部分はシャワーを当てる方向に気を使ってホコリを奥に押し込まないように気をつけます。
</div>
<h3>組み付け</h3>
<div class="box">
<a href="https://3.bp.blogspot.com/-30wOgrRlZuA/WEbqa6RBVtI/AAAAAAAARFs/iOIPfpP7rsE591JpQw3aclTtVlP9ibliACLcB/s1600/clean_radio_cassette_5.jpg">
<img src="https://3.bp.blogspot.com/-30wOgrRlZuA/WEbqa6RBVtI/AAAAAAAARFs/iOIPfpP7rsE591JpQw3aclTtVlP9ibliACLcB/s100/clean_radio_cassette_5.jpg"></a>
<a href="https://4.bp.blogspot.com/-jKa7tXD79tk/WEbqbDjOhxI/AAAAAAAARFw/0YVWBD3cc2gHp-4JuMywPdMTKXnVB1vCACLcB/s1600/clean_radio_cassette_6.jpg">
<img src="https://4.bp.blogspot.com/-jKa7tXD79tk/WEbqbDjOhxI/AAAAAAAARFw/0YVWBD3cc2gHp-4JuMywPdMTKXnVB1vCACLcB/s100/clean_radio_cassette_6.jpg"></a>
<p>翌朝、なんとか元どおりに出来たようで無事蓋を閉めることができました。
<p>季節は晩秋でたった一晩と乾燥が十分ではないため通電・動作確認は次回の帰省の際に行います。
</div>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-71413475132452395862016-12-13T19:52:00.002+09:002016-12-13T20:00:41.268+09:0060~70年代風なオフィスチェアを買ったよ<div class="box">
<div class="caption" style="width:200px">
<figure><a href="https://1.bp.blogspot.com/-AGDdw8uX860/WEbj2zsfGNI/AAAAAAAARFE/_97YqwUKQr4REwt4bZQflu_kzpG-MIjLACLcB/s1600/office_chair_1.jpg">
<img src="https://1.bp.blogspot.com/-AGDdw8uX860/WEbj2zsfGNI/AAAAAAAARFE/_97YqwUKQr4REwt4bZQflu_kzpG-MIjLACLcB/s200/office_chair_1.jpg"></a>
<figurecaption>アンティークチェアの上に陣取る愛猫</figurecaption>
</figure>
</div>
<p>60~70年代風な意匠の事務椅子をリサイクルショップで発見したので、実家のワークチェアとして購入しました。2500円のところをまけてもらって2000円だったと思います。
<p>メッキの上に細かい茶色の錆が浮いていたので、防錆剤をかけて磨いてから部屋に運び込みました。
<p>母はまた変なものを買ってきたと顔をしかめています。
</div>
<hr>
<div class="box">
<div class="caption" style="width:160px">
<figure><a href="https://2.bp.blogspot.com/-jWQEEAdPVNY/WEbj3LfuoII/AAAAAAAARFI/L1OQACJthyQ0fceKxb2uSQymGsvlxuTkwCLcB/s1600/office_chair_2.jpg">
<img src="https://2.bp.blogspot.com/-jWQEEAdPVNY/WEbj3LfuoII/AAAAAAAARFI/L1OQACJthyQ0fceKxb2uSQymGsvlxuTkwCLcB/s160/office_chair_2.jpg"></a>
<figurecaption>アンティークチェアからジャンプする愛猫</figurecaption>
</figure>
</div>
<div class="caption" style="width:214px">
<figure><a href="https://2.bp.blogspot.com/-6hKPKrKvxQo/WEbj3QznfbI/AAAAAAAARFM/40mtbgPMkIsMCq24XmFKLz9SCUm0S6NDgCLcB/s1600/wise.jpg">
<img src="https://2.bp.blogspot.com/-6hKPKrKvxQo/WEbj3QznfbI/AAAAAAAARFM/40mtbgPMkIsMCq24XmFKLz9SCUm0S6NDgCLcB/h160/wise.jpg"></a>
<figurecaption>椅子を購入したリサイクルショップの外観</figurecaption>
</figure>
</div>
<div class="caption" style="width:214px">
<figure><a href="https://3.bp.blogspot.com/-YrlOvemWHPY/WEbj5B7NmLI/AAAAAAAARFQ/omK_YAFzmB0XF6MgxdhOt7Zb7ZbXedx2ACLcB/s1600/closing.jpg">
<img src="https://3.bp.blogspot.com/-YrlOvemWHPY/WEbj5B7NmLI/AAAAAAAARFQ/omK_YAFzmB0XF6MgxdhOt7Zb7ZbXedx2ACLcB/h160/closing.jpg"></a>
<figurecaption>椅子を購入したリサイクルショップ近くの閉店セール中のホームセンター</figurecaption>
</figure>
</div>
</div>
<hr>
<div class="box">
<div class="caption" style="width:71px">
<figure><a href="https://4.bp.blogspot.com/-iPKjytc0Oh8/WE_Q6Lnu6LI/AAAAAAAARGg/9ruXRzIAM88y7tkG6sE0elT4IS-wr0kgQCLcB/s1600/colossus.jpg">
<img src="https://4.bp.blogspot.com/-iPKjytc0Oh8/WE_Q6Lnu6LI/AAAAAAAARGg/9ruXRzIAM88y7tkG6sE0elT4IS-wr0kgQCLcB/s100/colossus.jpg"></a>
<figurecaption><a href="http://amzn.to/2gGvevN">地球爆破作戦 [DVD]</a></figurecaption>
</figure>
</div>
<p>『Colossus: The Forbin Project』 (1970年・邦題『地球爆破作戦』)という冷戦時代を背景に人工知能の暴走を描く映画があります。
<p>この小道具に出てきても良さそうなオフィスチェアです。お気に入りです。
<p>これまでは家が建った時からダイニングテーブルの椅子だったものを使っていました。圧倒的にグレードアップできましたよ。
</div>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-84379847386830010532016-12-10T17:30:00.003+09:002022-04-24T11:43:40.466+09:00textareaをjsから徹底調教してオレオレエディタをつくるための情報まとめ<p>textarea を js で制御してオレオレ・テキストエディタを作ってみます、という点から制御方法を調べていきます。
<p>同じ手口で input[type=text] もイケます、多分。IE には改行文字の問題があるため textarea の方が格段に難しくなります。
<p>次の目標は designMode=on です。
<h3>したいこと</h3>
<ol>
<li>カーソル位置・選択範囲の取得
<li>カーソル位置・選択範囲の変更
<li>カーソル位置にテキストの挿入
<li>選択範囲のテキストの置換
</ol>
<p>textarea のカーソル位置等の取得・変更には selectionStart 等のプロパティがあります。これが使えればとても素直に実装できそうです。さてブラウザの対応状況はいかがでしょうか?
<div class="note">
<h4>もしかしたらしたいこと、座標と矩形から…</h4>
<ol>
<li>座標から文字の index を取得
<li>カーソル位置の座標の取得
<li>選択範囲の座標と矩形の取得
<li>座標と矩形から選択範囲に相当する値を取得
</ol>
<p>ちなみに座標が絡む場合 TextRange が使えないと難しくなる。TextRange は IE が独自に実装し Opera だけが取り入れている。
<p>これ以外のブラウザでは<a href="http://d.hatena.ne.jp/project_the_tower2/20071228/1198785069" target="_blank" rel="nofollow">隠し要素を作って textarea と同じテキストフローになるようにした上でこれを測定している記事</a>が出てくる。
<p>Github では <a href="https://github.com/akiroom/caretposition.js/blob/master/caretposition.js" target="_blank" rel="nofollow">caretposition.js</a> のコードが読みやすいかも。
</div>
<h3>カーソル位置・選択範囲の取得と更新</h3>
<h4>textareaのselectionStart, selectionEnd, setSelectionRangeとTextRangeの対応状況</h4>
<table>
<thead><tr><th>ブラウザ<td>対応バージョン
<tbody>
<tr>
<th>IE<td>9+
<tr>
<th>IE <a href="https://msdn.microsoft.com/ja-jp/library/cc392338.aspx">TextRange</a><td>4~10
<tr>
<th>Opera<td>8+
<tr>
<th>Opera TextRange<td><a href="https://books.google.co.jp/books?id=GEQlVcVf_zkC&pg=PA736&lpg=PA736&dq=TextRange+Opera&source=bl&ots=iux0zKKWrN&sig=MJupPxgyg54VTAxu4g89QPGN1IE&hl=ja&sa=X&ved=0ahUKEwi7_qzO6IXRAhXBjLwKHdztDWAQ6AEISTAG#v=onepage&q=TextRange%20Opera&f=false" target="_blank" rel="nofollow">7 or 8</a>~<a href="http://help.dottoro.com/ljouisvm.php" target="_blank" rel="nofollow">10.5</a>
<tr>
<th>Firefox<td>1+
<tr>
<th>Safari<td><a href="http://travel-lab.info/tech/pblog/article.php?id=13" target="_blank" rel="nofollow">2.0.3+ または 1.3.2+</a>
<tr>
<th>Chrome<td>1+
</table>
<div class="links"><a href=" https://developer.mozilla.org/ja/docs/Web/API/HTMLInputElement/setSelectionRange" target="_blank" rel="nofollow">HTMLInputElement.setSelectionRange() - Web API インターフェイス | MDN</a>
<a href="http://travel-lab.info/tech/pblog/article.php?id=13" target="_blank" rel="nofollow">Travellers Tales : Safari でも selectionStart, selectionEnd がサポートされている</a>
</div>
<h4>IEでの実装方針</h4>
<p>selectionStart, selectionEnd と互換性のある数値を返すようにします。カーソル位置・選択の変更の際も同様です。
<p>IE8 以下については TextRange を使用します。
<h5>readonly 属性は不可</h5>
<p>js から制御する場合 readonly 属性を設定しても良さそうです。しかしいざ設定すると改行の動きがおかしくなってしまい実用になりません。他のブラウザでは正しく改行するのでこれは IE だけの問題です。IE11 や WP10 でも確認しました。
<p>この他にペーストや選択範囲をドラッグも出来なくなります。
<h5>IE9~11</h5>
<h6>ちょっとしたパッチ</h6>
<p>selectionStart 等をサポートするがカーソルが末尾にいる際に textarea.value.length より大きい textarea.selectionStart を返すときがあります。これは他のブラウザと異なるため補正します。Edge(IE12) では修正されているため不要でした。
<pre class="prettyprint lang-js"><code>if( IE < 12 ){
var len = textarea.value.length;
return {
from : textarea.selectionStart < len ? textarea.selectionStart : len,
to : textarea.selectionEnd < len ? textarea.selectionEnd : len
}
}
</code></pre>
<p>また IE9~10 では以下の TextRange を使ったコードも動作しましたがパフォーマンスの良さそうな selectionStart を使うことにしました。
<h5>IE8以下</h5>
<p>カーソル位置・選択範囲の取得に苦しめられましたが、これ以降はトントンと実装できました。
<h6>改行文字が異なるため変換する</h6>
<p>ライブラリ内で textarea.value を読み出す際に \r\n を \n に変換して返り値を他のブラウザと合わせています。
<pre class="prettyprint lang-js"><code>val = textarea.value.split('\r').join('');
</code></pre>
<p>ちなみに、range.moveEnd, range.moveStart に与える引数は以上の変換を考慮し改行分の補正を加える必要はありません。他のブラウザと同じ値を与えれば意図した動作をします。
<h6>カーソル位置・選択範囲を求めるコード</h6>
<p>selectionStart, selectionEnd と互換性があり、正しくキャレット位置を求めるコードは <a target="_blank" rel="nofollow" href="https://web.archive.org/web/20090904134938/http://www.dedestruct.com/2008/03/22/howto-cross-browser-cursor-position-in-textareas/" target="_blank" rel="nofollow">HowTo: Cross-Browser Cursor Position in Textareas</a> に紹介されているものを元にしました。そのままでは \r を含む start 位置が変えるため \r の数だけ数字が小さくなるように手を入れました。
<p>その後気づきましたがこの手のノウハウは Closure Library にばちっと収録されていますので、ソースを検索してみるのがいいですね。本件についてもブラッシュアップされたコードが収録されていました。 <a href="https://github.com/google/closure-library/blob/5f644a73ca021f843c0a3f684ba9a1611740ff3b/closure/goog/dom/selection.js" target="_blank" rel="nofollow">closure-library/closure/goog/dom/selection.js</a>
の goog.dom.selection.getEndPointsTextareaIe_ です。
<hr>
<p>ちなみに次のコードでは selectionStart, selectionEnd と互換性のある値を取ることができませんでした。
<ol>
<li><a href="http://stackoverflow.com/questions/3622818/ies-document-selection-createrange-doesnt-include-leading-or-trailing-blank-li" target="_blank" rel="nofollow">javascript - IE's document.selection.createRange doesn't include leading or trailing blank lines - Stack Overflow</a> の回答のうち Tim Down 氏によるコード
<li><a target="_blank" rel="nofollow" href="http://note.chiebukuro.yahoo.co.jp/detail/n32448" target="_blank" rel="nofollow">HTML のテキストエリアでカーソル位置を得る - Yahoo!知恵袋</a>
</ol>
<p>次の記事で図解されている<a href="http://www.studio-freesky.net/programming/javascript/3/" target="_blank" rel="nofollow">改行を TextRange が取りこぼす問題</a>が関係しています。
<blockquote title="Studio FREE-SKY - テキストエリアの選択範囲の位置を特定する" cite="http://www.studio-freesky.net/programming/javascript/3/"><p>その前に、IEとNNでは選択範囲の実装の違いから共通化できない部分があります。
<p>それは、IEのTextRangeオブジェクトで取得した範囲にもしラストに改行コード¥r¥nがあった場合それが含まれないのです。(視覚的な選択範囲には含まれています)</blockquote>
<h6>現象を確認していませんが懸念事項としてメモ</h6>
<blockquote title="[JavaScript] IE8でのTextRange.moveToPoint() - @・ェ・)やるっきゃない" cite="http://d.hatena.ne.jp/kanehama/20100330/1269946922">
<p>まぁこれをIE8で動かすと range.moveToPoint()でエラーが起きます。 IE8「未定義だよ!未定義だよ!」 ちなみにこの未定義のエラーが起きるパターンは私が調べた限りでは 行頭か行末にカーソルがある場合。(つまりテキストがない場合もエラーが起きます。)</blockquote>
<hr>
<p>以下はいずれ追記します。
<h3>スクロールについて</h3>
<ul>
<li><a href="http://qiita.com/tatesuke/items/b3df2e263e5ca4dee138" target="_blank" rel="nofollow">【黒魔術】テキストエリアのキャレット位置をjsで指定した時にスクロールバーを追従させる - Qiita</a>
<li><a href="https://www.opera.com/docs/changelogs/windows/950b1/" target="_blank" rel="nofollow">Fixed problem where setting the scrollTop attribute for textarea elements didn't scroll the textarea contents</a>
</ul>
<h3>モバイル対応</h3>
<h4>iOSで物理キーボードのキーイベントを拾う</h4>
<h4>HTMLで独自のソフトウェアキーボードを用意するケース</h4>
<h3>その他のバグ情報</h3>
<ul>
<li><a href="http://blog.livedoor.jp/tzifa/archives/50799216.html" target="_blank" rel="nofollow">Firefox ・バグの再現・ textarea 内でカーソルの点滅が消える問題</a>
</ul>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-57562107336251476492016-10-12T17:17:00.003+09:002022-12-26T17:29:55.799+09:00リンクテキストのインタラクションを整理する<p>リンクテキストのインタラクションをなんとなく指定していったところ、一貫性に欠けコードもゴチャゴチャしていました。先月にかけて腰を据えて整理したところ、インタラクションもコードも納得の出来にすることができました。この記事では当ブログのテキストリンクのインタラクションのルールと実装の注意点をご紹介します。</p>
<a name='more'></a>
<p>パソコンのブラウザから閲覧している方は、マウスホバーやタブフォーカスを実際に行ってみてブログのインタラクションを確認しつつ読み進めてみてください。
<h2>リンクテキストの色と下線のインタラクション設計</h2>
<p>リンクテキストに指定するスタイルは次の通りブラウザのデフォルト CSS に準じています。
<ol>
<li>リンクには青系色、訪問済みリンクには紫系色を使う
<li>モノクロ環境等を考慮して下線を引く
</ol>
<p>以上を実施すると、サイトで使う色が増え下線も現れて、うるさい印象になってしまいます。
<p>そこで、記事のボディー部分とそれ以外の部分に2種類のルールを用意することにしました。
<hr>
<div class="note">
<p>ところで“リンク 下線”で検索すると下線の消し方を解説するページがいくつも並びます。確かにリンクテキストへの下線はデザインを損なっているかもしれません。しかしアクセシビリティの観点から引くべき、という考えに賛同します。
<div class="links"><a rel="nofollow" target="_blank" href="http://mzmjp.net/blog/2015/03/08/0051/">リンクを色だけで表現しないようにする – mzmjp.net::blog</a>
</div>
</div>
<h3>記事本文とそれ以外の部分で異なる2つのルールを設定</h3>
<p>記事本文以外の部分は各ページでだいたい共通する内容であり、またその配置からリンクであることが判ります。そこで賑やかめのインタラクションは記事本文に対してだけ設定します。
<p>そして記事本文以外の部分はリンクの下線を非表示とし <code>:hover</code> で表示します。また <code>:visited</code> のテキスト色を通常のテキスト色と同じにします。
<table>
<thead>
<tr>
<th><th>記事本文<th>それ以外の部分
<tbody>
<tr>
<th><code>:link</code> (未訪問リンク)の色<td colspan="2"><span style="color:#69f">青系</span>
<tr>
<th><code>:visited</code> (訪問済リンク)の色<td><span style="color:#c3f">紫系</span><td>黒系等通常のテキストカラーと同じ
<tr>
<th><code>:link:hover</code> の色<td colspan="2"><span style="color:#69f">青系</span>
<tr>
<th><code>:visited:hover</code> の色<td colspan="2"><span style="color:#c3f">紫系</span>
<tr>
<th><code>:link</code> の下線<td>有<td>無
<tr>
<th><code>:visited</code> の下線<td>有<td>無
<tr>
<th><code>:hover</code> の下線<td>無<td>有
</table>
<p>タブフォーカスのインタラクション、フォーカス中にマウスホバーが起こった際のインタラクションは両者で共通です。
<h3>モジュールレベルでの色の上書きを減らす・無くす</h3>
<div class="box">
<a href="https://3.bp.blogspot.com/-RoVcSucMvRM/V_2bFv9mWoI/AAAAAAAARBY/9aTiCMEB1_EcsuQ-emf11sdiuwAFeCn1ACLcB/s1600/links.png">
<img alt="未訪問のリンクが多いときのクラウド番外地のスクリーンショット" src="https://3.bp.blogspot.com/-RoVcSucMvRM/V_2bFv9mWoI/AAAAAAAARBY/9aTiCMEB1_EcsuQ-emf11sdiuwAFeCn1ACLcB/s200/links.png"></a>
<a href="https://1.bp.blogspot.com/-Ejl3adiMjWY/V_2ZtU7CpzI/AAAAAAAARBI/TrORUj3cs085evgqJQSSJHpOmkFQEocKwCLcB/s1600/links_visited.png">
<img alt="未訪問のリンクが少ないときのクラウド番外地のスクリーンショット" src="https://1.bp.blogspot.com/-Ejl3adiMjWY/V_2ZtU7CpzI/AAAAAAAARBI/TrORUj3cs085evgqJQSSJHpOmkFQEocKwCLcB/s200/links_visited.png"></a>
<p>以上のルールはナビゲーションにも例外なく適用されます。
<p>ナビゲーションは当初デザイン性を重視してリンクテキスト色を上書きしていましたが、これを辞めました。
<p>未訪問のリンクという情報がユーザーに伝わるようになり、どんどん読み進めていくと青字が黒字に置き換わっていって画面が締まってくるのも気に入っています。
</div>
<h2>実装の際の注意</h2>
<p>リンクテキストには、<code>:hover</code>, <code>:focus</code>, <code>:active</code> に加えて固有の疑似クラスである <code>:link</code>, <code>:visited</code> があります。これらが組み合わさって <code>:visited:active</code>, <code>:link:focus:hover</code> などのセレクタに対してスタイルを指定していきます。
<p>指定に漏れがあるとユーザーの操作に対してインタラクションが発生しない(画面が変化しない)ことがあるので注意しなくてはいけません。
<p>また、これだけでもなかなかにコードが長大になってしまうので、リンク色には上書き指定の不要なデザインを心がけることもポイントに思います。
<!--h3>古いIEでの注意</h3>
<p>現行のブラウザは :link のスタイルが :visited にも継承されます。一方古い IE では継承されないようです。このため css を書く際には若干の注意と古い環境での確認が必要です。
<p>古いIEというモヤッとした表現ですいません。今後バージョンを特定して追記いたします。
<blockquote title="ハンディがあっても利用できるページづくり:Webアクセシビリティについて > 元祖ガイドライン:WCAG 1.0" cite="http://www.kanzaki.com/docs/html/accessible.html">
<h5>14の指針</h5>
<p>(中略)<br>10.補助技術や古いブラウザが正しく動作するような解決策を用意する</blockquote>
<p>補助技術の提供状況やソフトウェア(ブラウザ)の移行コストを鑑み、可能な限り古いブラウザの対応も行っていきましょう。-->
<hr>
<p>当ブログの当該部分の CSS のソースコードは Github でご確認いただけます。
<div class="links"><a rel="nofollow" target="_blank" href="https://github.com/itozyun/web-doc-base/blob/895300ffa20dfe228eb690e01e5a697e49996013/src/scss/04_Typography/03_LinkInteraction.scss">web-doc-base/src/scss/01_Base/06_A.scss</a></div>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-44558551834396119352016-10-03T21:04:00.001+09:002019-12-27T14:13:06.376+09:00【VS Code 拡張】js,css,scssをブラウザ別にビルドするためのプリプロセッサを公開しました<div class="note"><p>VSCode 拡張での開発を中止し、<a href="/2019/12/gulp-iz-preprocessor.html">gulp プラグインに移行しました</a>。(2019/12/27)</div>
<div class="box">
<a href="https://3.bp.blogspot.com/-4jmNhFebyQo/V_ItG1HLY-I/AAAAAAAARAI/B5DWzBbA5FkkWQDxmM7lRClmCStfFdbHQCLcB/s1600/vscode-install-izp.png">
<img src="https://3.bp.blogspot.com/-4jmNhFebyQo/V_ItG1HLY-I/AAAAAAAARAI/B5DWzBbA5FkkWQDxmM7lRClmCStfFdbHQCLcB/s200-c/vscode-install-izp.png"/></a>
<a href="https://2.bp.blogspot.com/-jvRFQcj0iIY/V_ItG_Zej6I/AAAAAAAARAM/-N9VSnVRHeYPLay17bEHCYctXP7kYQB0wCLcB/s1600/vscode-run-izp.png">
<img src="https://2.bp.blogspot.com/-jvRFQcj0iIY/V_ItG_Zej6I/AAAAAAAARAM/-N9VSnVRHeYPLay17bEHCYctXP7kYQB0wCLcB/s200-c/vscode-run-izp.png"></a>
<p>クロスブラウザな Web 開発においてカリカリのパフォーマンスを発揮するべく環境(ブラウザ)毎にビルドした js を用意する誘惑にかられたことはないでしょうか?
<p>フォールバックやパッチからなる他環境向けのコードが一切読み込まれないということは、通信にも端末のメモリや CPU にも優しいです。
<hr>
<p>ということで、環境別ビルドを行うための拡張コメントを定義し、<a target="_blank" rel="nofollow" href="https://marketplace.visualstudio.com/items?itemName=itozyun.iz-preprocessor">Visual Studio Code 拡張として実装・公開</a>しました。</p>
<p>ソースコードは <a target="_blank" rel="nofollow" href="https://github.com/itozyun/iz-preprocessor">Github itozyun/iz-preprocessor</a> でご確認ください。
</div>
<a name='more'></a>
<h3>ターゲット別ビルドの実際</h3>
<p>しかしこの環境別ビルドは、寡聞にして僅かな実施例しか見ません。
<ol>
<li>jQuery での 1.x 系(ie8- をサポート)と 2.x 系(ie8- サポートを削除)
<li>uupaa.js の<a target="_blank" href="http://d.hatena.ne.jp/uupaa/20100604/1275609745"> mobile safari 向けビルド</a>
</ol>
<p>機能別ビルドについては Modernizr など素晴らしい Web I/F を提供しているものまであるのに、環境別ビルドについてはお寒い限り…
<h3>謝辞</h3>
<p>VS Code 拡張の作成・公開には次の記事を参考にいたしました。
<div class="links"><a rel="nofollow" target="_blank" href="http://toach.click/vsc-ext/">Visual Studio Codeの拡張機能をTypeScriptで作る方法</a>
<a rel="nofollow" target="_blank" href="http://qiita.com/YuichiNukiyama/items/ffcb32188f473b92133d">VS CodeのエクステンションをMarketPlaceに公開する</a>
<a rel="nofollow" target="_blank" href="http://toach.click/vscode-blade-runner/">Visual Studio Codeの拡張機能を公開する方法</a></div>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-34274456974337275772016-09-28T02:54:00.002+09:002021-07-13T15:02:31.787+09:00[blogger template customize]How to fill empty <data:post.dateHeader/><div lang="en">
<p>This article is for blogger widget version 1 only.
<div class='box'><a href="https://4.bp.blogspot.com/-Wy3mwKu6CEk/V-qs_pRujHI/AAAAAAAAQ_k/ha7_PfR3_Q0HvYZ_fLKomIZoMRx8keW1QCLcB/s1600/IMG_1872%255B1%255D.JPG">
<img src="//4.bp.blogspot.com/-Wy3mwKu6CEk/V-qs_pRujHI/AAAAAAAAQ_k/ha7_PfR3_Q0HvYZ_fLKomIZoMRx8keW1QCLcB/s160/IMG_1872%255B1%255D.JPG"></a>
<p>When you post a lot in a day to "blogger", The second and subsequent <code><data:post.dateHeader></code> will be empty. It is often disturbs the design.
<p>Article will show you how to fill the empty <code><data:post.dateHeader></code>. </p><a name='more'></a>
<p><del>But, not a completely pretty. So, Unnecessary contents is written. And it's dropped between the comment tag (^-^;)</del> It was fixed by using a recursive call, So completely pretty.(16/09/28 22:55)
</div>
<div class='box'><a href="https://2.bp.blogspot.com/-lUdcpfg6iTI/Wm2n89UTkyI/AAAAAAAARgU/iiF7ngMfiP4wyozXIheK1y6CnbxJSKFXQCLcBGAs/s1600/check_dateHeader.png">
<img src="https://2.bp.blogspot.com/-lUdcpfg6iTI/Wm2n89UTkyI/AAAAAAAARgU/iiF7ngMfiP4wyozXIheK1y6CnbxJSKFXQCLcBGAs/s160/check_dateHeader.png"></a>
<p>Fixed an issue where an error occurred when the blue circle check box was not checked. If not checked, <code><data:post.dateHeader></code> will be empty.(2018/1/28 19:42)
</div>
<h3>Get dateHeader function</h3>
<p>Call the funciton as <code><b:include name='get_dateheader' data='post'/></code>, Enjoy!
</div>
<div class="hscroll">
<pre class="prettyprint lang-xml"><code><b:includable id='get_dateheader' var='post'>
<b:if cond='data:post.isDateStart'>
<data:post.dateHeader/>
<b:else/>
<b:loop values='data:posts' var='_post' index='i'>
<b:if cond='data:post.id == data:_post.id'>
<b:with var='next' value='data:posts[data:i - 1]'>
<b:if cond='data:next.isDateStart'>
<data:next.dateHeader/>
<b:else/>
<b:include name='get_dateheader' data='next'/>
</b:if>
</b:with>
</b:if>
</b:loop>
</b:if>
</b:includable>
</code></pre>
</div>
<div class="hscroll">
<pre class="prettyprint lang-xml"><del><code><b:includable id='get_dateheader' var='post'>
<b:if cond='data:post.dateHeader'>
<data:post.dateHeader/>
<b:else/>
<b:loop values='data:posts' var='_post' index='i'>
<b:if cond='data:post.id == data:_post.id'>
<b:with var='next' value='data:posts[data:i - 1]'>
<b:if cond='data:next.isDateStart'>
<data:next.dateHeader/>
<b:else/>
<b:include name='get_dateheader' data='next'/>
</b:if>
</b:with>
</b:if>
</b:loop>
</b:if>
</b:includable>
</code></del></pre>
</div>
<div class="hscroll">
<pre class="prettyprint lang-xml"><del><code><b:includable id='get_dateheader' var='post'>
<b:if cond='data:post.dateHeader'>
<data:post.dateHeader/>
<b:else/>
<b:loop values='data:posts' var='_post' index='i'>
<b:if cond='data:post.id == data:_post.id'>
<b:loop values='data:i to 0' var='_i'>
<b:with var='newer' value='data:posts[ data:_i ]'>
<b:if cond='data:newer.isDateStart'>
<data:newer.dateHeader/>&lt;!--
</b:if>
</b:with>
</b:loop>
</b:if>
</b:loop>
--&gt;
</b:if>
</b:includable>
</code></del></pre>
</div>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-39118026635447113662016-09-25T01:18:00.001+09:002022-03-30T09:54:09.861+09:00[blogger template customize]Elegant navigation for the archive page<div lang="en">
<div class="box"><a href="https://4.bp.blogspot.com/-5GZDhMSUUyA/V-aigFdZE1I/AAAAAAAAQ_I/7HJGeYuolv8bYpxrLC97biXe6t_EQp0pgCPcB/s1600/IMG_1828.JPG"><img src="//4.bp.blogspot.com/-5GZDhMSUUyA/V-aigFdZE1I/AAAAAAAAQ_I/7HJGeYuolv8bYpxrLC97biXe6t_EQp0pgCPcB/s160/IMG_1828.JPG"></a>
<p>This article is for blogger widget version 1 only.
<p>You can test elegant archive navigation. <a href="/2016_08_28_archive.html">/2016_08_28_archive.html</a>
<p>By year, monthly, daily, complete navigation has been realized.(2017/1/28 20:00)
</div>
<ol>
<li>JS free!
<li>Use a BlogArchive widget for navigation.(BlogArchive widget limite is just 2.)
<li>Use <a href="//blogger.googleblog.com/2016/05/more-custom-template-flexibility.html" target="_blank">lambda expression</a> to get last index of loop.
<pre class="prettyprint lang-xml"><code><b:with var='ylast' value='data:data.data count ( y => y.name != &quot;&quot; )'/></code></pre>
<li>Only <code><b:eval></code> and <code><b:with></code> can touch list item directly.
<li>Need a space around the operator.
<pre class="prettyprint lang-xml"><code><b:with var='_m' value='data:y.data[data:mi + 1]'/></code></pre>
</ol>
<h3>Elegant Archive Pager</h3>
<div class="hscroll">
<pre class="prettyprint lang-xml linenums"><code><b:widget id='BlogArchive1' locked='true' type='BlogArchive' mobile='yes'>
<b:includable id='main'>
<b:if cond='data:blog.pageType == &quot;archive&quot;'>
<div class="Pager"><section role="navigation"><b:include name='navi'/></section></div>
</b:if>
</b:includable>
<b:includable id='navi'>
<b:with var='is_year' value='data:data count ( _y => _y.url == data:blog.url )'>
<b:if cond='data:is_year != 0'>
<b:include name='navi_year'/>
<b:else />
<b:loop values='data:data' var='y'>
<b:loop values='data:y.data' var='m'>
<b:if cond='data:m.url == data:blog.url'>
<b:include name='navi_month'/>
<b:else />
<b:with var='is_day' value='data:m.data count ( _d => _d.url == data:blog.url )'>
<b:if cond='data:is_day != 0'>
<b:include name='navi_day'/>
</b:if>
</b:with>
</b:if>
</b:loop>
</b:loop>
</b:if>
</b:with>
</b:includable>
<b:includable id='navi_year'>
<b:loop values='data:data' var='y' index='yi'>
<b:if cond='data:y.url == data:blog.url'>
<b:with var='ylast' value='data:data count ( _y => _y.url != &quot;&quot; )'>
<b:if cond='data:ylast - 1 != data:yi'>
<b:with var='_y' value='data:data[data:yi + 1]'>
<link rel="next" expr:href='data:_y.url'/>
<a class="Pager-next" expr:href='data:_y.url' rel="tag" hidefocus="true">
<data:_y.name/>(<data:_y.post-count/>)
</a>,
</b:with>
</b:if>
</b:with>
<a class="Pager-top" href='#lB' hidefocus="true" alia-hidden="true">▲ トップ</a>
<b:if cond='data:yi != 0'>
<b:with var='_y' value='data:data[data:yi - 1]'>
,
<link rel="prev" expr:href='data:_y.url'/>
<a class="Pager-prev" expr:href='data:_y.url' rel="tag" hidefocus="true">
<data:_y.name/>(<data:_y.post-count/>)
</a>
</b:with>
</b:if>
</b:if>
</b:loop>
</b:includable>
<b:includable id='navi_month'>
<b:loop values='data:data' var='y' index='yi'>
<b:loop values='data:y.data' var='m' index='mi'>
<b:if cond='data:m.url == data:blog.url'>
<b:with var='mlast' value='data:y.data count ( _m => _m.url != &quot;&quot; )'>
<b:if cond='data:mlast - 1 != data:mi'>
<b:with var='_m' value='data:y.data[data:mi + 1]'>
<link rel="next" expr:href='data:_m.url'/>
<b:if cond='data:_m.post-count != 1'>
<a class="Pager-next" expr:href='data:_m.url + &quot;#&quot; + data:_m.post-count' rel="tag" hidefocus="true">
<data:y.name/>-<data:_m.name/>(<data:_m.post-count/>)
</a>,
<b:else/>
<a class="Pager-next" expr:href='data:_m.url' rel="tag" hidefocus="true"><data:y.name/>-<data:_m.name/>(1)</a>,
</b:if>
</b:with>
<b:else/>
<b:with var='ylast' value='data:data count ( _y => _y.name != &quot;&quot; )'>
<b:if cond='data:ylast - 1 != data:yi'>
<b:loop values='data:data' var='_y' index='_yi'>
<b:if cond='data:yi + 1 == data:_yi'>
<b:with var='_m' value='data:_y.data[0]'>
<link rel="next" expr:href='data:_m.url'/>
<b:if cond='data:_m.post-count != 1'>
<a class="Pager-next" expr:href='data:_m.url + &quot;#&quot; + data:_m.post-count' rel="tag" hidefocus="true">
<data:_y.name/>-<data:_m.name/>(<data:_m.post-count/>)
</a>,
<b:else/>
<a class="Pager-next" expr:href='data:_m.url' rel="tag" hidefocus="true"><data:_y.name/>-<data:_m.name/>(1)</a>,
</b:if>
</b:with>
</b:if>
</b:loop>
</b:if>
</b:with>
</b:if>
</b:with>
<a class="Pager-top" href='#lB' hidefocus="true" alia-hidden="true">▲ トップ</a>
<b:if cond='data:mi == 0'>
<b:if cond='data:yi != 0'>
<b:loop values='data:data' var='_y' index='_yi'>
<b:if cond='(data:yi - 1) == data:_yi'>
<b:with var='mlast' value='data:_y.data count ( _m => _m.url != &quot;&quot; )'>
<b:with var='_m' value='data:_y.data[data:mlast - 1]'>
,
<link rel="prev" expr:href='data:_m.url'/>
<b:if cond='data:_m.post-count != 1'>
<a class="Pager-prev" expr:href='data:_m.url + &quot;#&quot; + data:_m.post-count' rel="tag" hidefocus="true">
<data:_y.name/>-<data:_m.name/>(<data:_m.post-count/>)
</a>
<b:else/>
<a class="Pager-prev" expr:href='data:_m.url' rel="tag" hidefocus="true"><data:_y.name/>-<data:_m.name/>(1)</a>
</b:if>
</b:with>
</b:with>
</b:if>
</b:loop>
</b:if>
<b:else/>
<b:with var='_m' value='data:y.data[data:mi - 1]'>
,
<link rel="prev" expr:href='data:_m.url'/>
<b:if cond='data:_m.post-count != 1'>
<a class="Pager-prev" expr:href='data:_m.url + &quot;#&quot; + data:_m.post-count' rel="tag" hidefocus="true">
<data:y.name/>-<data:_m.name/>(<data:_m.post-count/>)
</a>
<b:else/>
<a class="Pager-prev" expr:href='data:_m.url' rel="tag" hidefocus="true"><data:y.name/>-<data:_m.name/>(1)</a>
</b:if>
</b:with>
</b:if>
</b:if>
</b:loop>
</b:loop>
</b:includable>
<b:includable id='navi_day'>
<b:loop values='data:data' var='y' index='yi'>
<b:loop values='data:y.data' var='m' index='mi'>
<b:loop values='data:m.data' var='d' index='di'>
<b:if cond='data:d.url == data:blog.url'>
<b:with var='dlast' value='data:m.data count ( _d => _d.url != &quot;&quot; )'>
<b:if cond='data:dlast - 1 != data:di'>
<b:with var='_d' value='data:m.data[data:di + 1]'>
<link rel="next" expr:href='data:_d.url'/>
<b:if cond='data:_d.post-count != 1'>
<a class="Pager-next" expr:href='data:_d.url + &quot;#&quot; + data:_d.post-count' rel="tag" hidefocus="true">
<data:y.name/>&#32;<data:_d.name/>(<data:_d.post-count/>)
</a>,
<b:else/>
<a class="Pager-next" expr:href='data:_d.url' rel="tag" hidefocus="true"><data:y.name/>&#32;<data:_d.name/>(1)</a>,
</b:if>
</b:with>
<b:else/>
<b:with var='mlast' value='data:y.data count ( _m => _m.name != &quot;&quot; )'>
<b:if cond='data:mlast - 1 != data:mi'>
<b:with var='_m' value='data:y.data[data:mi + 1]'>
<b:with var='_d' value='data:_m.data[0]'>
<link rel="next" expr:href='data:_d.url'/>
<b:if cond='data:_d.post-count != 1'>
<a class="Pager-next" expr:href='data:_d.url + &quot;#&quot; + data:_d.post-count' rel="tag" hidefocus="true">
<data:y.name/>&#32;<data:_d.name/>(<data:_d.post-count/>)
</a>,
<b:else/>
<a class="Pager-next" expr:href='data:_d.url' rel="tag" hidefocus="true"><data:y.name/>&#32;<data:_d.name/>(1)</a>,
</b:if>
</b:with>
</b:with>
<b:else/>
<b:with var='ylast' value='data:data count ( _y => _y.name != &quot;&quot; )'>
<b:if cond='data:ylast - 1 != data:yi'>
<b:with var='_y' value='data:data[data:yi + 1]'>
<b:with var='_m' value='data:_y.data[0]'>
<b:with var='_d' value='data:_m.data[0]'>
<link rel="next" expr:href='data:_d.url'/>
<b:if cond='data:_d.post-count != 1'>
<a class="Pager-next" expr:href='data:_d.url + &quot;#&quot; + data:_d.post-count' rel="tag" hidefocus="true">
<data:_y.name/>&#32;<data:_d.name/>(<data:_d.post-count/>)
</a>,
<b:else/>
<a class="Pager-next" expr:href='data:_d.url' rel="tag" hidefocus="true"><data:_y.name/>&#32;<data:_d.name/>(1)</a>,
</b:if>
</b:with>
</b:with>
</b:with>
</b:if>
</b:with>
</b:if>
</b:with>
</b:if>
</b:with>
<b:if cond='data:di != 0'>
<b:with var='_d' value='data:m.data[data:di - 1]'>
,
<link rel="prev" expr:href='data:_d.url'/>
<b:if cond='data:_d.post-count != 1'>
<a class="Pager-prev" expr:href='data:_d.url + &quot;#&quot; + data:_d.post-count' rel="tag" hidefocus="true">
<data:y.name/>&#32;<data:_d.name/>(<data:_d.post-count/>)
</a>
<b:else/>
<a class="Pager-prev" expr:href='data:_d.url' rel="tag" hidefocus="true"><data:y.name/>&#32;<data:_d.name/>(1)</a>
</b:if>
</b:with>
<b:else/>
<b:if cond='data:mi != 0'>
<b:with var='_m' value='data:y.data[data:mi - 1]'>
<b:with var='dlast' value='data:_m.data count ( _d => _d.url != &quot;&quot; )'>
<b:with var='_d' value='data:_m.data[data:dlast - 1]'>
,
<link rel="prev" expr:href='data:_d.url'/>
<b:if cond='data:_d.post-count != 1'>
<a class="Pager-prev" expr:href='data:_d.url + &quot;#&quot; + data:_d.post-count' rel="tag" hidefocus="true">
<data:y.name/>&#32;<data:_d.name/>(<data:_d.post-count/>)
</a>
<b:else/>
<a class="Pager-prev" expr:href='data:_d.url' rel="tag" hidefocus="true"><data:y.name/>&#32;<data:_d.name/>(1)</a>
</b:if>
</b:with>
</b:with>
</b:with>
<b:else/>
<b:if cond='data:yi != 0'>
<b:with var='_y' value='data:data[data:yi - 1]'>
<b:with var='mlast' value='data:_y.data count ( _m => _m.name != &quot;&quot; )'>
<b:with var='_m' value='data:_y.data[data:mlast - 1]'>
<b:with var='dlast' value='data:_m.data count ( _d => _d.url != &quot;&quot; )'>
<b:with var='_d' value='data:_m.data[data:dlast - 1]'>
,
<link rel="prev" expr:href='data:_d.url'/>
<b:if cond='data:_d.post-count != 1'>
<a class="Pager-prev" expr:href='data:_d.url + &quot;#&quot; + data:_d.post-count' rel="tag" hidefocus="true">
<data:_y.name/>&#32;<data:_d.name/>(<data:_d.post-count/>)
</a>
<b:else/>
<a class="Pager-prev" expr:href='data:_d.url' rel="tag" hidefocus="true"><data:_y.name/>&#32;<data:_d.name/>(1)</a>
</b:if>
</b:with>
</b:with>
</b:with>
</b:with>
</b:with>
</b:if>
</b:if>
</b:if>
</b:if>
</b:loop>
</b:loop>
</b:loop>
</b:includable>
</b:widget>
</code></pre>
</div>
<div class="hscroll">
<pre class="prettyprint lang-xml"><del><code><b:widget id='BlogArchive1' locked='true' type='BlogArchive' mobile='yes'>
<b:includable id='main'>
<b:if cond='data:blog.pageType == "archive"'>
<b:loop values='data:data' var='y' index='yi'>
<b:loop values='data:y.data' var='m' index='mi'>
<b:if cond='data:m.url == data:blog.url'>
<b:with var='mlast' value='data:y.data count ( _m => _m.url != &quot;&quot; )'>
<b:if cond='data:mlast - 1 != data:mi'>
<b:with var='_m' value='data:y.data[data:mi + 1]'>
<a expr:href='data:_m.url' hidefocus="true"><data:y.name/>-<data:_m.name/>(<data:_m.post-count/>)</a>
</b:with>
<b:else/>
<b:with var='ylast' value='data:data count ( _y => _y.name != &quot;&quot; )'>
<b:if cond='data:ylast - 1 != data:yi'>
<b:loop values='data:data' var='_y' index='_yi'>
<b:if cond='data:yi + 1 == data:_yi'>
<b:with var='_m' value='data:_y.data[0]'>
<a expr:href='data:_m.url' hidefocus="true"><data:_y.name/>-<data:_m.name/>(<data:_m.post-count/>)</a>
</b:with>
</b:if>
</b:loop>
</b:if>
</b:with>
</b:if>
</b:with>
<b:if cond='data:mi == 0'>
<b:if cond='data:yi != 0'>
<b:loop values='data:data' var='_y' index='_yi'>
<b:if cond='(data:yi - 1) == data:_yi'>
<b:with var='mlast' value='data:_y.data count ( _m => _m.url != &quot;&quot; )'>
<b:with var='_m' value='data:_y.data[data:mlast - 1]'>
<a expr:href='data:_m.url' hidefocus="true"><data:_y.name/>-<data:_m.name/>(<data:_m.post-count/>)</a>
</b:with>
</b:with>
</b:if>
</b:loop>
</b:if>
<b:else/>
<b:with var='_m' value='data:y.data[data:mi - 1]'>
<a expr:href='data:_m.url' hidefocus="true"><data:y.name/>-<data:_m.name/>(<data:_m.post-count/>)</a>
</b:with>
</b:if>
</b:if>
</b:loop>
</b:loop>
</b:if>
</b:includable>
</b:widget>
</code></del></pre>
</div>
<p>Loop monster (T-T)...
</div>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-39485491412652325632016-09-15T22:20:00.003+09:002022-09-16T01:46:09.722+09:00【Blogger改造】記事でもない静的ページでもない特別なページを作る完璧すぎる方法<div class="note"><p>特別なページへのリンクを修正しました。以前はサーチラベルに : を含んでいましたがこれを - に改めました。(2020/09/18)
</div>
<p>Blogger 改造ガチ勢のみなさん、こんにちわ。
<p>テンプレートのカスタマイズに力が入ってくると“<strong>記事でもなく、静的ページでもない、特別なページを作りたい</strong>”ケースがあると思います。そんなときにどうやってテンプレートをホゲホゲしたら良いのか?今宵あなたは完全なる正解を手にします。
<p>なんとそれは検索結果ページとサーチクエリを使った方法でした。</p>
<a name='more'></a>
<h2>モバイルで消したウィジェットを特別ページで復活</h2>
<p>僕の場合ではモバイル用にテンプレートを最適化している際に遭遇しました。
<p>モバイル版ではサイドバーやフッターに配置した<a href="/search?m=1&q=extra-page-label">ラベルリスト</a>、<a href="/search?m=1&q=extra-page-blog-archive">記事アーカイブ</a>、<a href="/search?m=1&q=extra-page-popular-posts">人気の投稿</a>、ページリストの各ウィジェットを非表示にしました。
<p>しかしこれらの情報がどこかにないと不自由なため4つのウィジェットそれぞれにページが欲しくなりました。
<div class="links"><a href="?m=1">クラウド番外地のモバイル用ページを確認する</a></div>
<hr>
<div class="box">
<a href="https://1.bp.blogspot.com/-qL097JiYozo/V9qL-idziZI/AAAAAAAAQ6o/TeukYqsvZbgupmhiC_vruPgCCRCWd8yggCLcB/s1600/pages.png"><img src="https://1.bp.blogspot.com/-qL097JiYozo/V9qL-idziZI/AAAAAAAAQ6o/TeukYqsvZbgupmhiC_vruPgCCRCWd8yggCLcB/s160/pages.png"></a>
<p>まずは画像のように“空のページを4つ作った上でそれを次のようなコードでフックする”という方法が考えられます。僕も長い間この方法しか考えられませんでした。
</div>
<pre class="prettyprint lang-xml"><code><b:if cond='data:blog.pageName == &quot;mobile-labell&quot;'>
<!-- ラベル一覧 -->
<b:elseif cond='data:blog.pageName == &quot;mobile-blog-archive&quot;' />
<!-- 記事アーカイブ -->
<b:elseif cond='data:blog.pageName == &quot;mobile-popular-posts&quot;' />
<!-- 人気の記事 -->
<b:else/>
<b:elseif cond='data:blog.pageName == &quot;mobile-pages&quot;' />
<!-- ページ一覧 -->
<b:else/>
<b:section id='sec2' showaddelement='no'>
<b:widget id='Blog1' locked='true' type='Blog'>
<!-- 通常のページ -->
</b:widget>
</b:section>
</b:if>
</code></pre>
<p>しかしこの方法は次の点がスマートではありません。
<ul>
<li>管理画面が空のページで煩くなる
<li>空のエントリが<a href="/feeds/pages/default" target="_blank">ページのフィード(/feeds/pages/default)</a>に出てきてしまう
</ul>
<h2>検索結果ページを使う完璧な方法</h2>
<p>今回ご紹介する完璧な方法とは、検索結果ページとサーチクエリを使った横綱技です。
<p>検索結果ページを乗っ取る形で特別ページを表示します。4つの特別ページのどれを表示するかは検索文字列(<code>data:blog.searchQuery</code>)で分岐させます。
<p>検索文字列は任意に決めることができますが、読者が検索する文字と被ることが無いように冗長なものにします。
<pre class="prettyprint lang-xml"><code><b:if cond='data:blog.searchQuery == &quot;extra-page-label&quot;'>
<!-- ラベル一覧 -->
<b:section id='sec-ex1' showaddelement='no'>
<b:widget id='Label2' locked='true' type='Label' mobile='yes'/>
</b:section>
<b:elseif cond='data:blog.searchQuery == &quot;extra-page-blog-archive&quot;'/>
<!-- 記事アーカイブ -->
<b:section id='sec-ex2' showaddelement='no'>
<b:widget id='BlogArchive2' locked='true' type='BlogArchive' mobile='yes'/>
</b:section>
<b:elseif cond='data:blog.searchQuery == &quot;extra-page-popular-posts&quot;'/>
<!-- 人気の記事 -->
<b:section id='sec-ex3'showaddelement='no'>
<b:widget id='PopularPosts2' locked='true' type='PopularPosts' mobile='yes'/>
</b:section>
<b:elseif cond='data:blog.searchQuery == &quot;extra-page-page-list&quot;'/>
<!-- ページ一覧 -->
<b:section id='sec-ex4' showaddelement='no'>
<b:widget id='PageList2' locked='true' type='PageList' mobile='yes'/>
</b:section>
<b:else/>
<b:section id='sec2' showaddelement='no'>
<b:widget id='Blog1' locked='true' type='Blog'>
<!-- 通常のページ -->
</b:widget>
</b:section>
</b:if>
</code></pre>
<p>4つの特別ページのリンクリストをモバイルにだけ表示するコードが次になります。
<pre class="prettyprint lang-xml"><code><b:if cond='data:blog.isMobile'>
<h3>索引</h3>
<ul>
<li><a href='/search?m=1&amp;q=extra-page-label'>ラベル一覧</a></li>
<li><a href='/search?m=1&amp;q=extra-page-blog-archive'>記事アーカイブ</a></li>
<li><a href='/search?m=1&amp;q=extra-page-popular-posts'>人気の投稿</a></li>
<li><a href='/search?m=1&amp;q=extra-page-page-list'>特設ページ</a></li>
</ul>
</b:if>
</code></pre>
<hr>
<p>僕は使っていませんが連絡フォームなどはモバイルにかかわらず、このテクニックで専用ページに仕立ててしまうのがエレガントに思います。
<blockquote title="Bloggerの連絡フォーム機能を使ってお問い合わせページを作る方法" cite="http://toumaswitch.com/blogger-contact-form/"><p>しかし、Bloggerの連絡フォームはサイドバーには設置しやすくなっているものの、サイドバーに付けると「ここじゃない感」がハンパではないのは、決して揺らぐことはない事実です。</blockquote>
<p>そうそう、検索が話題に出ましたので併せて大関技の<a href="/2016/09/search-box.html">完璧な検索窓の設置の仕方</a>もぜひ目を通しておきましょう。
<h2>もうちょっと続くよ、今度はコンソールページだ</h2>
<div class="note"><p>以下の情報はレイアウトの編集ページに、特別なページに追加したウィジェットも表示されるようになったため不要になりました。(2020/09/18)
</div>
<div class="box">
<a href="https://4.bp.blogspot.com/-Mx4uBa_qHiU/V9qZHLAqfPI/AAAAAAAAQ64/kinpU_pO_DIOuSWpB_VhGWMWCEdAv8CQgCLcB/s1600/layout.png"><img src="https://4.bp.blogspot.com/-Mx4uBa_qHiU/V9qZHLAqfPI/AAAAAAAAQ64/kinpU_pO_DIOuSWpB_VhGWMWCEdAv8CQgCLcB/s200/layout.png" width="151" height="200" /></a><p>ここまでで特定のウィジェットをメインコンテンツとする特別ページを仕込む方法が分かりました。
<p>しかし、最後に一点だけ問題が残っています。なんとレイアウトの編集ページに以上で追加されたセクションとウィジェットは表示されないのです。
<p>このためウィジェットの編集メニューに入ることができません。
<p>幸いに、<code>blogId</code> とセクションID、ウィジェットID が判れば、URL 直打ちで編集メニューに入ることができます。
<p>もうお分かりですね、もう1つ特別ページを追加します。このページは各ウィジェットの編集メニューへのリンクが張られています。
</div>
<pre class="prettyprint lang-xml"><code><b:elseif cond='data:blog.searchQuery == &quot;extra-page-config&quot;' />
<!-- 各ウィジェットの編集ページ -->
<h3>Edit-links of extra-page widget</h3>
<ul>
<li><a expr:href='&quot;https://www.blogger.com/rearrange?blogID=&quot; + data:blog.blogId + &quot;&amp;action=editWidget&amp;sectionId=sec-ex1&amp;widgetType=null&amp;widgetId=PopularPosts2&quot;' target='_blank'>Edit PopularPosts widhet</a></li>
<li><a expr:href='&quot;https://www.blogger.com/rearrange?blogID=&quot; + data:blog.blogId + &quot;&amp;action=editWidget&amp;sectionId=sec-ex2&amp;widgetType=null&amp;widgetId=Label2&quot;' target='_blank'>Edit Label widget</a></li>
<li><a expr:href='&quot;https://www.blogger.com/rearrange?blogID=&quot; + data:blog.blogId + &quot;&amp;action=editWidget&amp;sectionId=sec-ex3&amp;widgetType=null&amp;widgetId=BlogArchive2&quot;' target='_blank'>Edit BlogArchive widget</a></li>
<li><a expr:href='&quot;https://www.blogger.com/rearrange?blogID=&quot; + data:blog.blogId + &quot;&amp;action=editWidget&amp;sectionId=sec-ex4&amp;widgetType=null&amp;widgetId=PageList2&quot;' target='_blank'>Edit PageList widget</a></li>
</ul>
<b:if cond='data:blog.searchQuery == &quot;extra-page-label&quot;'>
<!-- ラベル一覧 -->
</code></pre>
<p>このページは読者に公開する必要がないので完全な隠しページとなります。テンプレートのソースコードを読まないと存在が判りません。
<p>管理者だけが次のリンクをブラウザにブックマークしておきます。
<div class="links"><a href="/search?q=extra-page-config" rel="nofollow">/search?m=1&q=extra-page-config</a></div>
<h3>完璧な独自ページの追加技によって益々存在感を増すBlogger</h3>
<p>この横綱技によって WordPress のライバルとして Blogger は益々その存在感を増すでしょう。
<p>つねづね「<q cite="/2016/01/blog-management.html">Wordpress の1割程度の自由度はあると思います</q>」と言ってきましたが、ここに至って訂正しなくてはいけません。
<p>1割5分程度のカスタマイズ性があるよ!izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-9320725827955776022016-09-13T05:21:00.004+09:002021-07-13T15:02:31.784+09:00【Blogger改造】完璧な検索窓設置のためのポイント2つ<div class="note">
<p>モバイルからPC版を表示しているフラグ <code>?m=0</code> の考慮がされた、更に完璧な検索窓を2018年10月の記事『<a href="/2018/10/blogger-templete-custmize-How-to-detect-isDesktop.html">貴方のBloggerの閲覧性を爆上げする!テンプレート式でデスクトップ版(m=0)を判定するには?</a>』で紹介しています。(2019/3/30)
<hr>
<p><del>モバイルからPC版を表示しているフラグ <code>?m=0</code> の考慮がなく完璧ではありませんでした。</del>
<p><del><code>?m=0</code> の付与は<code><data:mobileLinkUrl/></code> の有無で判定します。しかしこの値は Blog ウィジェット内にしか存在しません。(2016/10/04)</del></p>
<pre class="prettyprint lang-xml"><code><b:if cond='data:blog.isMobile'>
<input name='m' type='hidden' value='1'/>
<b:elseif cond='data:mobileLinkUrl'/>
<input name='m' type='hidden' value='0'/>
</b:if>
</code></pre>
</div>
<p>Blogger のテンプレートのカスタマイズに関する話題です。
<p>検索窓の設置に関する記事で言及を見ないがそつなく設定しておくとエレガントな2つのポイントをご紹介しますよ。
<hr>
<p>以下が当ブログでも使用している完璧な検索窓のコードになります。次の2つの配慮がされている点がグレート過ぎます。
<ol>
<li>検索結果ページに入った際に検索ワードが検索窓に入っている
<li>PCブラウザ+モバイルテンプレートで検索結果ページに飛んだ際にモバイルテンプレートを維持する
</ol>
<pre class="prettyprint lang-xml"><code><form action='/search' method='get'>
<b:if cond='data:blog.isMobile'>
<input name='m' type='hidden' value='1'/>
</b:if>
<input name='max-results' type='hidden' value='10'/>
<input type='text' name='q' placeholder='ブログ内を検索' autocapitalize="off" expr:value='data:blog.searchQuery'/>
<input type='submit' value='検索'/>
</form>
</code></pre>
<p>それぞれのポイントについて解説していきます。
<h3>その1、検索ワードが検索窓に入ってる</h3>
<div class="box">
<a href="https://4.bp.blogspot.com/-LystyvvKZhQ/V9cFmoB1EhI/AAAAAAAAQ6Q/z-jzLLIZzHIgNhn4lHygAU7GdrU0bJvXgCLcB/s1600/search_query.png"><img src="https://4.bp.blogspot.com/-LystyvvKZhQ/V9cFmoB1EhI/AAAAAAAAQ6Q/z-jzLLIZzHIgNhn4lHygAU7GdrU0bJvXgCLcB/s160/search_query.png"></a>
<p>検索結果ページの検索窓に検索文字が入っていれば、ユーザは検索文字を再編集できるのでフレンドリですね。
<p>このカスタマイズの当該コードは<code>expr:value='data:blog.searchQuery'</code>です。
</div>
<h3>その2、PCブラウザで検索結果ページに飛んだ際にモバイルテンプレートを維持</h3>
<p>スマホからのアクセスで検索結果ページに飛んだ際は Google 側で判定してモバイルテンプレートが使用されます。
<p>一方でPCブラウザを使っての検証や、転送量の節約のためにモバイルページを読み込んでいる際には通常、モバイルテンプレートが解除されてしまいます。
<p>この意図しない解除を防ぐために GET のパラメータに <code>&m=1</code> を追加します。
<p>そのためのコードが <code><b:if cond='data:blog.isMobile'><input name='m' type='hidden' value='1'/></b:if></code> です。
<hr>
<p>ちなみに当ブログのモバイルテンプレートはPC用テンプレートに比べて転送量が16KB(47KB→31KB)少ないです。これは、モバイルテンプレートで"人気の記事"が非表示になりこのためのサムネイル画像が読み込まれなくなるためです。
<p>モバイル通信では前時代的な従量制が一般なことですし、ご自身のブログのブックマークにはモバイル版を設定しておくのはアリに思います。
<div class="links"><a href="?m=1">クラウド番外地のモバイル版を表示</a></div>
<p>ではでは~
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-83077698381699792062016-09-10T21:58:00.000+09:002020-07-04T19:01:22.640+09:00VAIO P(VPCP11ALJ)のリカバリDVD作成とWindows10へのアップグレード<p>大慌てで VAIO P (VPCP11ALJ)をプリインストールの Windows 7 Professional から Windows 10 Pro にアップグレードしました。作業メモです。
<h2>最初に端末の冷却を準備する</h2>
<div class="box"><a href="https://1.bp.blogspot.com/-3Ln9BHebowQ/V6OFibBBHII/AAAAAAAAQ2c/J4JlH4fLp7QH5Mg3unI-dD5tyWTpf_7HwCPcB/s1600/IMG_1563.JPG"><img src="https://1.bp.blogspot.com/-3Ln9BHebowQ/V6OFibBBHII/AAAAAAAAQ2c/J4JlH4fLp7QH5Mg3unI-dD5tyWTpf_7HwCPcB/s160/IMG_1563.JPG"></a>
<p>VAIO P は非力な端末なため、一連の処理にとても時間がかかってしまいます。
<p>その上、<a href="http://bbs.kakaku.com/bbs/K0000062587/SortID=10591757/" target="_blank">端末が高温(67℃以上)になると CPU は 800MHz の低速動作</a>になってしまい、モッサリやフリーズ等の不具合の原因となるようです。
</div>
<blockquote title="VAIO Type PをWindows 10にアップデートしてみた。けど使いません。 | しま★りん.blog" cite="http://blog.ayurina.net/2015/08/02/vaio-type-p%E3%82%92windows-10%E3%81%AB%E3%82%A2%E3%83%83%E3%83%97%E3%83%87%E3%83%BC%E3%83%88%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F%E3%80%82%E3%81%91%E3%81%A9%E4%BD%BF%E3%81%84%E3%81%BE%E3%81%9B/"><p>熱暴走と思われる症状でフリーズしてしまったため、2回目から以降Windows 10アップデート完了まで、タオルでくるんだアイスノンの上でPCを動かしてました(苦笑)。これ、すこぶる安定します。</blockquote>
<p>まず普段は着けている端末カバーを忘れずに外します。
<p><a href="http://blog.ayurina.net/2015/08/02/vaio-type-p%E3%82%92windows-10%E3%81%AB%E3%82%A2%E3%83%83%E3%83%97%E3%83%87%E3%83%BC%E3%83%88%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F%E3%80%82%E3%81%91%E3%81%A9%E4%BD%BF%E3%81%84%E3%81%BE%E3%81%9B/" target="_blank">上の記事</a>で紹介されているアイスノン冷却を実行しましたが早々に溶けてしまったため、端末を傾けて底に向けて扇風機を当てる方法に切り替えました。
<h2>リカバリDVD作成</h2>
<h3>Widows Update</h3>
<p>しばらく起動していなかった機体なので、まずはじめに Windows のアップデートをしました。これには2時間程度を要しました。
<p>しかも長い間アップデートしていなかったせいなのか、ダウンロードの進捗(%)が正しく表示されません。タスクバーの Windows Update アイコンからマウスホバーに進捗が表示されますが、こちらも更新され無いため基本的に数十分待つ→再起動して見る、を繰り返します。いくつかアップデートが当たると進捗が確認できるようになりました。
<h3>VAIO Care のアップデート</h3>
<p>VAIO が提供しているリカバリメディア作成機能を実行する前に、<a href="http://www.sony.jp/support/vaio/products/vpc/vpcp11alj.html" target="_blank">VAIO 専用アプリ</a>のアップデートを行います。
<p>VAIO Care のアップデートしていないと、リカバリメディアの作成が 29% 時点で失敗してしまいます。
<p>次のアップデートを順にインストールしました。</p>
<div class="links"><a href="http://www.sony.jp/support/vaio/download/EP0000261503.html" target="_blank">「VAIO Care Ver.6.4.2.11150」アップデートプログラム</a>
<a href="http://www.sony.jp/support/vaio/download/EP0000321151.html" target="_blank">「VAIO Care Recovery Ver.1.1.1.13230(Windows 7 32ビット用)」アップデートプログラム</a>
<a href="http://www.sony.jp/support/vaio/download/EP0000324609.html" target="_blank">「VAIO Care Ver.8.4.5.06020(Windows 7 32ビット用)」アップデートプログラム</a></div>
<h3>リカバリメディアの作成</h3>
<p>ここまででようやくリカバリメディアの作成ができるようになりました。このメディアの作成にも2時間弱を要しました。
<div class="links"><a href="http://www.sony.jp/support/vaio/products/manual/vpcp11/contents/03_rec/03/02/02.html" target="_blank">リカバリメディアの作成</a></div>
<h2>Windows 10 へのアップグレードインストール</h2>
<p>あらかじめ作成しておいた DVD メディアから Windows 10 をアップグレードインストールしました。
<p>クリーンインストールを好みますが、VAIO 専用アプリの一部が引き続き使えるそうなのでアップグレードを選択しました。
<p>このインストールには2時間程度かかってしまいました。
<h3>Windows 10の高速化設定</h3>
<p>さてインストールが済みましたが、動作のモッサリがどうにも我慢ならないレベルです。
<p>"Windows10 高速化" の検索結果上位を読んでいって不要なサービスの停止やパフォーマンス設定の変更などを行いました。
<p>この段階で若干変化があったかな、という印象でした。
<div class="links"><a href=" http://www.webessentials.biz/windows10/windows10firstconfig/" target="_blank">Windows10を爆速仕様にする高速化設定方法 | WebEssentials</a>
<a href="http://productionig.sakura.ne.jp/blog/2015/08/23/windows10%E3%81%A7%E9%81%85%E3%81%84%E5%A0%B4%E5%90%88%E3%81%AE%E5%AF%BE%E5%87%A6%E6%B3%95/" target="_blank">windows10で遅い場合の対処法 - レベルの低いSE日記</a>
<a href="http://d-vecter.blogspot.jp/2015/08/windows10antimalware-service-executable.html" target="_blank">Windows10でAntimalware Service Executableが暴走する問題|vecterの日記</a>
<a href="http://qiita.com/kmry2045/items/b23a7e093f2fbd3a3ebc" target="_blank">[備忘録] 低速CPUでwindows10環境構築 - Qiita</a>
<a href="http://serverxyg.xsrv.jp/winosoi-2" target="_blank">Windows10 軽量化&高速化するためにすべきこと
</a></div>
<h3>グラフィックドライバのインストール</h3>
<div class="box">
<a href="https://2.bp.blogspot.com/-gXxH5Vl-DUw/V6Nx645r07I/AAAAAAAAQ14/Nk9koQ-WkqkGDLfyLVIoL7WVeNEZP_VTwCLcB/s1600/GM500.png"><img src="https://2.bp.blogspot.com/-gXxH5Vl-DUw/V6Nx645r07I/AAAAAAAAQ14/Nk9koQ-WkqkGDLfyLVIoL7WVeNEZP_VTwCLcB/s160-c/GM500.png" width="160" height="160" /></a>
<p><a href="https://downloadcenter.intel.com/ja/product/81506/-500-GMA-500-" target="_blank">インテルから GMA500 Windows 7 32bit 用のドライバをダウンロード</a>します。
<p>ドライバを当てるまでは描画が止まることが多かったですが大分改善されました。
</div>
<h3>最後に</h3>
<p>最後に 設定 > システム > テキスト、アプリ、その他の項目のサイズを変更する を 100% → 125% にしました。
<p>VAIO P は画素が細かく画面が見辛いですがこの設定でそこそこ改善します。
<p>Windows 7 の時はこの設定をいじると Windows の設定の際に画面が見切れて操作ができない事態に度々遭遇しました。幸いに Windows 10 にしてからはそのようなことはありません。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-55039598813264280652016-08-30T23:56:00.002+09:002021-07-13T15:02:31.790+09:00Blogspotのテンプレートカスタマイズで空のタグを作らないための工夫を2つ<p>みんな大好き Qiita のように技術記事をみんなで更新していく仕組みは魅力的で、変化著しい Web 技術との相性も抜群です。
<p>しかし、既成の記事プラットフォームに投稿するということは、自身でブログをメンテしコンテンツを制作していく、という Web 屋にとって重要な機会を手放すことでもあり悩ましいところ…
<p>などと思いつつ今回は Blogger のカスタマイズの話題です。
<hr>
<p>Blogger のテンプレートをカスタマイズしていると、たまに意図せず空のタグが出来てしまいモヤッとする時がありました。
<p>あまり綺麗ではありませんが一応の解決をみましたので共有いたします。
<h3>その1 データが空の場合に備える</h3>
<p>まず手始めによくあるパターン。でもこれって Blogger 公式のテンプレートでも実施されていない場合があります。
<p>下のように必ずデータの存在確認をしてから html タグを書きだすようにします。
<pre class="prettyprint lang-html"><code><p>
<b:if cond='data:navMessage'>
<data:navMessage/>
</b:if>
</p>
<!-- ↓v(^-^) -->
<b:if cond='data:navMessage'>
<p><data:navMessage/></p>
</b:if>
</code></pre>
<p>または、データの有無を確認して代替のコンテンツを埋め込んで置くケースもありますね。
<pre class="prettyprint lang-html"><code><b:switch var='data:blog.pageType'>
<b:case value="archive" />
<b:if cond='data:blog.pageName'>
<h2 class="aH"><data:blog.pageName/> のアーカイブ</h2>
<b:else/>
<h2 class="aH">アーカイブ</h2>
</b:if>
<b:case value="index" />
<b:if cond='data:blog.pageName'>
<h2 class="aH"><data:blog.pageName/> の記事一覧</h2>
<b:else/>
<h2 class="aH">記事一覧</h2>
</b:if>
<b:case value="error_page" />
<b:if cond='data:blog.pageName'>
<h2 class="aH wH"><data:blog.pageName/></h2>
<b:else/>
<h2 class="aH wH">Page not Found</h2>
</b:if>
</b:switch>
</code></pre>
<div class="note">
<p>switch ~ case 文は<a href="https://blogger.googleblog.com/2015/06/even-more-expansions-to-blogger.html" target="_blank">いつの間にか追加</a>されていました。地味に進化を重ねていてありがたい限りです。
</div>
<h3>その2 記事一覧等のループを包むかたちでの空タグ</h3>
<p>ラベル一覧やエラーページで次のように空のタグが出来てしまうケースがあります。
<pre class="prettyprint lang-html"><code><div id="Blog1" class="widget Blog" data-version="1">
<nav> </nav>
</div>
</code></pre>
<p>この時にテンプレートは以下のようなコードになっていました。
<pre class="prettyprint lang-html"><code><nav>
<b:loop values='data:posts' var='post'>
<!-- loop of contents -->
</b:loop>
</nav>
</code></pre>
<p><code><b:loop></code> 内に確実にコンテンツが存在するか?確認してから開始タグ(<code><nav></code>)と終了タグ(<code></nav></code>)を書きだすために、if 文を前後に追加しました。
<p>if 文の条件式には<a href="https://blogger.googleblog.com/2016/05/more-custom-template-flexibility.html" target="_blank">少し前に追加された構文を使っています。</a>
<pre class="prettyprint lang-html"><code><b:if cond='data:posts any (post => post.isFirstPost)'>&lt;nav&gt;</b:if>
<b:loop values='data:posts' var='post'>
<!-- loop of contents -->
</b:loop>
<b:if cond='data:posts any (post => post.isFirstPost)'>&lt;/nav&gt;</b:if>
</code></pre>
<hr>
<p>ちなみに <code>data:post.isFirstPost</code> という値を使って次のように前に追加した if 文を消すことはできます。
<p>残念ながら、ループの終わりを検出できないため(isLastPost 的な値がない) <code>&lt;/nav&gt;</code> をループ内に持ってくる方法はなさそうです。
<p>Enjoy!
<pre class="prettyprint lang-html"><code><b:loop values='data:posts' var='post'>
<b:if cond='data:post.isFirstPost'>&lt;nav&gt;</b:if>
<!-- loop of contents -->
</b:loop>
<b:if cond='data:posts any (post => post.isFirstPost)'>&lt;/nav&gt;</b:if>
</code></pre>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-42230923409553533132016-08-28T13:51:00.002+09:002021-07-13T15:02:31.788+09:00Bloggerのファイル置き場をGoogle DriveからDropboxへ、CSSのブラウザ別ビルド、SMACSS導入など<div class="note">
<p><a href="/2016/10/iz-preprocessor.html">ブラウザ別ビルドのためのプリプロセッサを公開</a>しました。(2016/10/03)
<p>css の minify を YUI Compressor から clean-css に変更しました。YUI Compressor では同じメディアクエリブロックを纏める機能がなく20%程度ファイルサイズが大きくなっていました。(24KB → 19KB, 2016/09/02)
</div>
<p>Google Drive の<a href="http://jp.techcrunch.com/2015/09/01/20150831google-starts-deprecating-web-hosting-support-in-google-drive/" target="_blank">Web ホスト機能がこの8月末で終了</a>します。
<p>本ブログでも Google Drive を js css の置き場所にしていたので、今週に入って Dropbox に移動しました。
<p>これにあわせて前々から関心のあったブラウザ別ビルドを css のビルドプロセスに導入したり、SMACSS を参考にタグ構造と命名を見直しました。
<hr>
<div class="box">
<a href="https://2.bp.blogspot.com/-lCT_qJs6ljU/V8Js5_VNGdI/AAAAAAAAQ5M/HWH1dkLqUiQFy6gFpAafysOMSm81RdNawCLcB/s1600/VSCode_CCPC.jpg"><img src="//2.bp.blogspot.com/-lCT_qJs6ljU/V8Js5_VNGdI/AAAAAAAAQ5M/HWH1dkLqUiQFy6gFpAafysOMSm81RdNawCLcB/s160/VSCode_CCPC.jpg"></a>
<p>以上を先週からリハビリとしてやってみました。
<p>実はこの春からずっと体調を崩していて、仕舞には十分な睡眠の後にもかかわらず瞼が重くてパソコンモニタを見続けることができない。寝て過ごすだけの日が何日か続いたりもしました。
<p>健康って大切ですねぇ~
</div>
<h3>CSS や Javascript のブラウザ別ビルド</h3>
<p>CSS や js には特定の環境ではスキップされるコードや、CSS ハック等で上書きされるコードが存在します。これらは僅かとはいえ、通信量を肥らせ、端末のメモリや CPU リソースを浪費します。
<p>ブラウザ別ビルドをすることで、これらのロスをゼロに近づけることができるってわけですね。
<div class="note">
<p>しかし寡聞にして実施例は僅かにしか知りません。(JQuery と <a href="http://d.hatena.ne.jp/uupaa/20100604/1275609745" target="_blank">uupaa.js</a>)
<p>労力に比して恩恵が少なそうですしねぇ…
<p>とはいえコレは自身のブログの改装というとっても小さなプロジェクト、深く考えずにジャンジャンいきましょう♪
</div>
<h4>本件でのCSSのターゲット環境は計8つ</h4>
<p>今回は自前のサーバを用意しないため Web サーバ側でユーザーエージェント文字列を元に配信する css を切り替えることはありません。
<p>また Web アプリではなく Web 文書であるため js が無効な環境を考慮します。js で環境を判定して css を動的に読み込むこともしません。
<p>IE9 以下で使えるコンディショナルコメントとブラウザ毎の解釈のブレを利用して(CSS ハックな import 文)大雑把に、モダンブラウザか?旧IE系か?だけを切り替えることとしました。
<p>これによってターゲット環境は計8つとなりました。
<table>
<thead>
<tr><th>ファイル名<th>説明<th>ファイルサイズ
<tbody>
<tr><th>modern.css<td>全アクセスの9割9分はこのcssを読み込むはず。計6段階のレスポンシブデザインを組み込んでいるので他の倍のサイズ<td>19KB
<tr><th>ie9.css<td><td>17KB
<tr><th>ie8.css<td>contentによる修飾がある分 ie7 以下用より大きい。<td>12KB
<tr><th>ie7.css<td>以下はPC用2カラムレイアウトのみ<td>11KB
<tr><th>ie6.css<td>少し前までサポート対象でしたしね<td>11KB
<tr><th>ie55.css<td>ie6対応ができると5.5対応まであと少し!<td>10KB
<tr><th>ie5win.css<td>5.5に比べると一段劣るけどまぁまぁちゃんとしてる<td>9KB
<tr><th>ie5mac.css<td>ファンキーな挙動で苦しませてくれるじゃじゃ馬、気が向いたらやってみます<td>未
</table>
<p>僕のケースではモダンブラウザ用と ie8 用では倍近いファイルサイズの差となりました。つまり低速なネット環境の方は ie8 でアクセスすればよいですね…
<p>ブラウザ別ビルドのためには、ソースコードに特定のターゲット環境専用のコードであることをコメントに記載します。
<p>手間はありますが、特定環境用であることをコード上に明示し、そのうえ例え副作用がなくとも他の環境では決して読み込まれない、という状態は精神衛生に良さそうです。
<h3>ブラウザ別ビルドのためのプリプロセッサ</h3>
<p>今回ブラウザ別ビルドのために、拡張コメントを定義し、VSCode 拡張として動作するプリプロセッサを制作しました。
<p>このプリプロセッサを通すことで、ターゲット環境専用のコードがターゲット環境数分だけ生成されます。
<p>続いてこの専用コードをコンパイラに通してカリカリに最適化されたリリース用 js css をゲットだぜ!という寸法です。
<p>遠からず、マーケットプレイスで公開しますのでお楽しみに。ちなみに名前はまだ決めていません。
<h3>BloggerとSMACSS、テンプレートの配布</h3>
<p>高いカスタマイズ性を持つ Blogger ですが、完全にページ制作者の意図した HTML 構造にすることはできません。
<p>Blogger ではブログテンプレートの制御用の情報が <code>div.section</code> 等のタグとして書き出されてしまうためです。
<p>このようななか、なるべく冗長な <div> の入れ子を作らないようにした結果、お恥ずかしながら今までの CSS はスパゲッティになっていました。
<p>SMACSS の導入に際して冗長な <div> の入れ子を許容したことと引き換えに CSS のメンテナンス性を上げることはできました。
<p>とはいえ CSS 自体のコード量が小さいので“メンテナンス性を犠牲にして冗長な <div> の入れ子を作らない”という選択肢も十分にありえました。
<p>実は、本ブログのテンプレートを配布しようと考えています。このためにコードを可読性の高いものにし、配色の変更程度ならなんら迷わない程度にしておきたいところです。
<h4>Blogger用テンプレートの配布</h4>
<p>Blogger 用のテンプレートは有料から無料まで、すでに優れて美しいものが配布されています。
<p>そんななかではありますが、モバイル通信制限下でも閲覧できるよう開発を重ねた本テンプレートは一応の価値があるのでは、と。
<p>ではでは~☆ミ
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-65929523288943974802016-08-05T02:41:00.003+09:002016-08-05T02:51:11.029+09:00EPSON Endeavor ST100へWindows10のインストールの記録<h2>不具合に見舞われ戻ってきた本機</h2>
<div class="box">
<a href="https://2.bp.blogspot.com/-xAARKWJk9Q0/V5ju7G_rx5I/AAAAAAAAQ1E/6By3cDXVziEyDX7-_t4AvdO1rxcREXmAgCPcB/s1600/IMG_1561.JPG"><img src="https://2.bp.blogspot.com/-xAARKWJk9Q0/V5ju7G_rx5I/AAAAAAAAQ1E/6By3cDXVziEyDX7-_t4AvdO1rxcREXmAgCPcB/s160/IMG_1561.JPG" width="160" height="160"></a>
<p>長らく母が使っていましたが、OS の起動不能となり大阪に引き上げてきた EPSON Endeavor ST100 の Windows 10 へのアップグレードインストールを行いました。
<p>これ以前にも一度挑戦して原因不明の失敗をし、無償アップグレード期間終了の迫る中の再挑戦で成功しました。
<p>今回は筐体を開けて扇風機を当てながらでしたので、どうも熱で誤動作を起こしていたようです。メモリを外したり DVD ドライブを疑ったりといろいろ悩んでしまいました…
<p>この機体はしばしばビープ音が鳴って起動しない、という不具合もあるのですが、これはバックアップ用電池を抜き差しすることで解決する、ということも発見しました。
</div>
<h2>グラフィックドライバのインストール</h2>
<p>さて、インストール自体は熱対策以降はスムースだったのですが、グラフィックドライバのインストールが難関です。
<p>それも次の記事に沿って作業することで適切なドライバを充てることができました。大変有用な情報をどうもありがとうございます m(_ _)m
<div class="links"><a href=" http://blogs.yahoo.co.jp/asari_no_miso_soup/42344397.html" target="_blank">EndeavorにWin10をインストールしてグラフィックドライバを適用する ( その他趣味 ) - あさりのみそしるダイアリー</a></div>
<h2>さいごに</h2>
<p>廃熱がうまくいかないのは CPU グリスの劣化を疑っています。
<p>廃熱を解決して<a href="http://bbs.kakaku.com/bbs/0010X518885/SortID=18212445/#tab" target="_blank">メモリも上限の 4GB</a> にしてしまったらバックアップ機として実家に送り返そうかな、と思います。ではでは~
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-41171221231132722332016-05-12T22:07:00.000+09:002018-08-26T00:25:55.683+09:00Think Centre M92p Tinyに無線LANとBluetoothをmini PCI-eハーフで追加<h2>Windows10 パソコンの新調</h2>
<div class="box">
<a href="https://4.bp.blogspot.com/-v0uJcPzu0fU/VzR5Dbg_dAI/AAAAAAAAQxU/GLySxPG1II0awxNeEGcKA46AdQim3_p3gCKgB/s1600/blogger-image--1943038947.jpg"><img src="https://4.bp.blogspot.com/-v0uJcPzu0fU/VzR5Dbg_dAI/AAAAAAAAQxU/GLySxPG1II0awxNeEGcKA46AdQim3_p3gCKgB/s160/blogger-image--1943038947.jpg" /></a>
<p>メインパソコンをやうやう新調し、長々とお世話になった <a href="https://outcloud.blogspot.com/search/label/MB%3AGA-965P-DQ6">GA-965P-DQ6</a> 機から <a href="http://www.lenovo.com/jp/catalog/dt/2012/m92ptiny_tm_1026.html" target="_blank">Lenovo の Think Centre M92p Tiny</a> になりました。
<p>日本橋をぶらついて、中古品を相場よりややお得に買うことができたようです。
</div>
<p>早速やったことは…</p>
<ol>
<li>HDD から SSD に換装、Windows10 の再インストール
</li>
<li>メモリは最大の 16GB に
</li>
<li>無線LANと Bluetooth を拡張カードで追加
</li>
</ol>
<p>3番目の拡張カードの追加に随分と調査を要しました。
<h2>mini PCI-e ハーフの無線LANカードの選定に悩む</h2>
<div class="box">
<a href="https://3.bp.blogspot.com/-NWswpYFTh3k/VzR5A0OhS6I/AAAAAAAAQxQ/fapCn7N2zj4MXHfltxPE_RIKCPqCF69vACKgB/s1600/blogger-image-2024047142.jpg"><img src="https://3.bp.blogspot.com/-NWswpYFTh3k/VzR5A0OhS6I/AAAAAAAAQxQ/fapCn7N2zj4MXHfltxPE_RIKCPqCF69vACKgB/s160/blogger-image-2024047142.jpg" /></a>
<p>今回苦慮したのが無線LAN(と Bluetooth)の追加です。
<p>M92p Tiny は PS/2 端子を省いた製品のためデバイスの接続はほぼ USB 端子の一択になります。<strong>前後に5つしかない USB 端子を余裕を持って使う</strong>ためには内臓の mini PCI-e ハーフ(x1)スロットを活用したいところです。
<p>そうそう、この端子の存在は<a href="http://www.lenovo.com/jp/catalog/dt/2012/m92ptiny_tm_1026.html" target="_blank" rel="nofollow" title="lenovo">製品仕様ページ</a>には書かれてないんですけどね…
</div>
<hr>
<div class="box">
<iframe src="//rcm-fe.amazon-adsystem.com/e/cm?t=itozyun-22&o=9&p=8&l=as1&asins=B00EQM8IHA&ref=tf_til&fc1=000000&IS2=1&lt1=_blank&m=amazon&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<p>ところで Lenovo のノート製品の拡張スロットには、lenovo 認証製品しか使用できないという制限があります。
<p>この制限がデスクトップ製品にまで及ぶのか?情報が見つからず、散々悩んだ末に拡張カードは相性保証のある店舗で購入しました。(このブログの読者諸賢は<del>人柱</del>動作確認も済んだので1000円ほど安い Amazon で購入すればよいですね)
<p>さらに折よいことに、店舗では Bluetooth もサポートするという Intel の 7260 を扱っていました。
</div>
<hr>
<p>幸いに無線LANも Bluetooth も動作を確認できました。ただ一点、筐体がスチールのため、電波の掴みが悪いように思います。
<p>そうそう、拡張カード固定用のネジの径ですが、通常より細いものが必要のようです。僕はガラクタ箱を漁って丁度よいネジを用意できました。
<h2>お会計</h2>
<table>
<thead>
<tr>
<th>項目<th>型番等<th>価格
<tbody>
<tr>
<th>デスクトップPC 中古<td>Lenovo Think Centre M92p Tiny Core i5-3470T<td class=r>34,980
<tr>
<th>SSD<td>SanDisk Ultra II 240GB R:550MB/s W:500MB/s<td class=r>8,980
<tr>
<th>メモリ<td>Castor SoDDR3-8GB-1600<td class=r>8,360<br>
(4,180 * 2)
<tr>
<th>無線LANカード<td>Intel Dual Band Wireless-AC 7260<td class=r>3,780
<tr>
<th>無線LAN用アンテナ<td>ジャンク<td class=r>324
<tfoot>
<tr>
<th>計<td><td class=r>56,424
</table>
<hr>
<div class="box">
<a href="https://1.bp.blogspot.com/-cectVdkegm0/W4FzgaJ9K4I/AAAAAAAARvk/sw2KEiCFMXYETYPMAWDI45LcHdjvld-4QCLcBGAs/s1600/M92pTiny_Manual_p98.PNG">
<img src="https://1.bp.blogspot.com/-cectVdkegm0/W4FzgaJ9K4I/AAAAAAAARvk/sw2KEiCFMXYETYPMAWDI45LcHdjvld-4QCLcBGAs/s160/M92pTiny_Manual_p98.PNG"></a>
<p>これだけ小さいと帰省などで気軽に持ち運べていいですね。
<p>フルHDビデオの編集の編集をしてみましたが、サクサクと出来ています v(^-^
<p><a href="https://download.lenovo.com/ibmdl/pub/pc/pccbbs/thinkcentre_pdf/m82m92p_hmm.pdf" target="_blank" rel="nofollow" title="pdf">サービスマニュアル</a>を読むと内臓の USB 端子が一ついます。ここになにかしら内臓機器を追加することができるかもしれません。(当該ページをキャプチャしました。2018/08/25)
</div>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-50244443926267698922016-03-29T20:44:00.007+09:002023-07-25T19:34:57.738+09:00Firefox OS 2.2用の CSS ハックを紹介! Web ページの日本語が Firefox OS 2.2で表示され無い問題の対策<div class="note">
<p>この記事で紹介した CSS ハックより適切なものを独自に見つけて、現在は次のハックを使っています。(2023/07/25)
<pre class="prettyprint lang-css"><code>@supports (-moz-appearance:none) and (display:contents) and (not (ruby-position:over)) and (not (-moz-osx-font-smoothing:auto)) and (not (text-align-last:auto)){
@media (-moz-os-version:windows-win8) and (-moz-overlay-scrollbars){
body, textarea, input {
font-family:sans-serif; /* CSS hack for just Firefox OS 2.2 */
}
}
}
</code></pre>
</div>
<h2>Firefox OS 2.2で日本語が表示されない問題に遭遇</h2>
<div class="box">
<a href="https://2.bp.blogspot.com/-BKXYEQ9HxhM/VvpETayUwkI/AAAAAAAAQsM/E-4Ad6u5jQEfVqOGN33yMrGwATnMAl3NA/s1600/firefoxos_2.2.jpg">
<img src="https://2.bp.blogspot.com/-BKXYEQ9HxhM/VvpETayUwkI/AAAAAAAAQsM/E-4Ad6u5jQEfVqOGN33yMrGwATnMAl3NA/s200/firefoxos_2.2.jpg"></a>
<p>Firefox の WebIDE から Firefox OS シミュレータでブログを表示したところ、大部分の日本語が表示され無い問題に遭遇しました。
<p>この問題は 2.2 だけで発生し、2.1~1.3 では発生しません。
<p>CSS が適用される前には一瞬だけ日本語が表示されるので、そもそも日本語表示ができないということではなさそうです。
<p>これをもとに <code>font-family</code> 指定を変えつつ見ていくと <strong>Roboto があると日本語が表示され無い</strong>、ことが判明しました。
</div>
<h2>Firefox OS だけの上書きは出来ず…</h2>
<pre class="prettyprint lang-css"><code>body, textarea, input {
font-family : Avenir , "Open Sans" , "Helvetica Neue" , Helvetica , Arial , Verdana , Roboto , "游ゴシック" , "Yu Gothic" , "游ゴシック体" , "YuGothic" ,
"ヒラギノ角ゴ Pro W3" , "Hiragino Kaku Gothic Pro" , "Meiryo UI" , "メイリオ" , Meiryo , "MS Pゴシック" , "MS PGothic" , sans-serif;
}
<del>@-moz-document url-prefix() {
body, textarea, input {
font-family : Avenir , "Open Sans" , "Helvetica Neue" , Helvetica , Arial , Verdana, "游ゴシック" , "Yu Gothic" , "游ゴシック体" , "YuGothic" ,"ヒラギノ角ゴ Pro W3" , "Hiragino Kaku Gothic Pro" , "Meiryo UI" , "メイリオ" , Meiryo , "MS Pゴシック" , "MS PGothic" , sans-serif;
}
}</del>
</code></pre>
<p>以上から、グローバルへの <code>font-family</code> 指定を Firefox だけ上書きすることにしました。
<p>問題は Firefox OS 2.2 でだけ起きているのでもっとピンポイントで上書きで来たらよかったのですが、JavaScript を使わないとするとこんなところでしょうか...
<div class="links"><a href="http://www.webdeveloper.com/forum/showthread.php?256857-moz-document-url-prefix%28%29" target="_blank">@-moz-document url-prefix()</a>
</div>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-74700895810064695442016-03-10T22:52:00.003+09:002021-09-11T19:21:28.835+09:00IEの独自CSS拡張-ms-filterとの正しいお付き合い<p>今更ですが...
<p>Windows 版の IE4 から登場し CSS3 Opacity 等を先駆けて(不十分に)実現した IE 独自 filter (以下 独自 filter)について。重要そうな点について寡聞にしてズバリな言及を見なかったので書いておきます。
<h2>独自 filter の切り方</h2>
<div class="box">
<a href="//1.bp.blogspot.com/-lxFnqPEClMM/Vt_SJFedyuI/AAAAAAAAQqs/LXjSVA0gm4A/s1600/ActiveX%25E3%2581%25AE%25E5%2588%25A4%25E5%25AE%259A.gif">
<img src="//1.bp.blogspot.com/-lxFnqPEClMM/Vt_SJFedyuI/AAAAAAAAQqs/LXjSVA0gm4A/s160/ActiveX%25E3%2581%25AE%25E5%2588%25A4%25E5%25AE%259A.gif"></a>
<p>しばしば ActiveX を切っていると独自 filter は使えない、といわれます。
<p>しかし詳しく見ていくと MSXML(ActiveX 版 <code>XMLHttpRequest</code>) などは使えるのに独自 filter は使えない、という状況も発生するようです。
<p>独自 filter だけを切るには、インターネットオプションから画像のように“バイナリ ビヘイビアーとスクリプト ビヘイビア-”を無効にします。(Windows XP sp3, IE8 で確認)
</div>
<h2>安全な独自 filter 有効/無効の確認</h2>
<p>独自 filter の判定には随分試行錯誤してしまいました。既に一般的な情報なら悪しからず...
<pre class="prettyprint lang-js"><code>// 1.
IE_FILTER_ENABLED = !!window.ActiveXObject;
// 2.
IE_FILTER_ENABLED = (function(t){
try {t = new ActiveXObject('DXImageTransform.Microsoft.gradient');}
catch(e){}
return !!t;
})();
</code></pre>
<p>1. では実際に ActiveX が有効か?の判定はできないようです。
<p>2. のように実際にオブジェクトを生成し戻り値を見ないと ActiveX や今回でいえば独自 filter が使えるか?判定できません。
<div class="box">
<a href="https://1.bp.blogspot.com/-enqUewMq4ms/VuK7-XekHMI/AAAAAAAAQq4/FFZ5hiai5x8jOuzwNvtirST4VC6aFP4OQ/s1600/activex_alert.jpg"><img src="https://1.bp.blogspot.com/-enqUewMq4ms/VuK7-XekHMI/AAAAAAAAQq4/FFZ5hiai5x8jOuzwNvtirST4VC6aFP4OQ/s160/activex_alert.jpg" /></a>
<p>しかし 2. の方法ではブラウザのセキュリティ設定によっては、スクリプトの実行に関するアラートが出てしまってユーザーを少なからず困惑させてしまいます。
</div>
<h3>安全な確認法</h3>
<p>そこで僕の結論は、<strong>隠し要素を生成して DXImageTransform.Microsoft.Shadow を設定し要素のサイズを測って判定</strong>です。
<p>ドロップシャドウが描画されれば、要素のサイズが影の分大きくなるので判断できるというわけです。
<pre class="prettyprint lang-js"><code>(function(){
var temponload = window.onload; // window. が無いと Presto Opera でエラー(2021/09/11追記)
onload = function(e, d, b, c){
if( temponload ) temponload(e);
temponload = null;
if( <u>window.onload</u> === arguments.callee ){ // 同上
onload = new Function();
onload = null;
};
d = document;
b = d.body;
c = b.className || '';
e = d.createElement('div');
b.appendChild(e);
e.style.cssText = 'position:absolute;top:0;left:0;width:1px;height:1px;line-height:1px;filter:dropshadow() progid:DXImageTransform.Microsoft.Shadow();';
b.className += ( c ? ' ' : c ) + ( e.offsetHeight > 1 ? 'pbLCD-AX' : '' );
e.style.cssText = '';
b.removeChild(e);
};
})();
</code></pre>
<div class="links"><a href="https://github.com/pbrocky/pb-100/blob/master/pbDisplayCSS/0.x/checkActiveX.js" target="_blank">pb-100/pbDisplayCSS/0.x/checkActiveX.js</a></div>
<hr>
<p>ちなみに line-height:1px は IE5.5 以下用の指定です。
<p>また IE5 でも正しく判定できるように dropshadow() を併せて指定し、隠し要素の削除の前に filter スタイルの削除も行っています。filter の利いたまま要素の削除を行うと IE5 では不具合に見舞われます。また IE5 では <code>elm.removeAttribute( 'style' );</code> が機能し無いため <code>elm.style.cssText = '';</code> を使用します。
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-25295545010555962272016-03-09T22:40:00.025+09:002022-11-25T14:58:37.072+09:00Presto Operaの調教記録<div class="note"><p>「<a href="#8">Closure CompilerでminifyするとOpera7で動かない</a>」の問題の発生バージョンを修正。(2022/11/25)
<p>「<a href="#8">Closure CompilerでminifyするとOpera7で動かない</a>」のオブジェクトリテラルの問題は、空文字列の添え字で、実行時にトラブルに見舞われます。(2022/11/20)
<p>「<a href="#8">Closure CompilerでminifyするとOpera7で動かない</a>」に、ラベル付き <code>break</code> で構文エラーになる件を追記。ページ内索引を追記。(2022/05/30)
<p>記載の誤りの修正。語尾の統一などの言い回しの修正。リンク切れページのインターネットアーカイブスへの変更。(2022/03/21)
<p><a href="#10">ダウンロードリンク集</a>の追記。(2020/10/20)
</div>
<p>再利用を前提とした俺色・クロスブラウザ HTML ベ-スのためのメモの Prestro Opera 編。問題に遭遇・解決のたびに追記していきます。
<p>たまに NDS ブラウザで自サイトを表示して<i>うふふっ</i>てできるようにボチボチやります。
<ol>
<li><a href="#1">バージョンを調べる</a>
<li><a href="#2">サイドバーライブラリのスモールスクリーンモード対応</a>
<li><a href="#3">複雑なセレクタでパースに失敗し以降のCSSが全て無視される</a>
<li><a href="#4"><code>background-image</code> の制限</a>
<li><a href="#5">ドキュメントの下に巨大な余白が発生する</a>
<li><a href="#6"><code>border-color</code> の解釈に失敗する</a>
<li><a href="#7"><code>Object</code> にキーを数値でセットする</a>
<li><a href="#8">Closure CompilerでminifyするとOpera7で動かない</a>
<li><a href="#9">Changelogより</a>
<li><a href="#10">ダウンロードリンク集</a>
</ol>
<a name="1"></a>
<h2 id="1">1. バージョンを調べる</h2>
<p>Opera 8 以降で利用可能です。Opera 7 はユーザーエージェント文字列等を使って判定しています。<a href="http://help.dottoro.com/ljifbjwf.php" target="_blank" rel="nofollow">Dottoro Web Reference > JavaScript > client-side > browser > methods > version (opera)</a>
<pre class="prettyprint lang-js"><code>window.opera.buildNumber();
window.opera.version();
</code></pre>
<a name="2"></a>
<h2 id="2">2. サイドバーライブラリのスモールスクリーンモード対応</h2>
<div class="box">
<a href="//4.bp.blogspot.com/-EaNJOIrEy4Q/Vt_NmZrYCFI/AAAAAAAAQqc/rWfVE1lFjUM/s1600/SmallScreen.jpg"><img src="//4.bp.blogspot.com/-EaNJOIrEy4Q/Vt_NmZrYCFI/AAAAAAAAQqc/rWfVE1lFjUM/s160/SmallScreen.jpg"></a>
<p>Opera 9.64 でスモールスクリーンモードを有効にするとビューポートサイズに関わらず、handheld 用スタイルが適用されます。
<p><a href="/2022/03/sidebarfixer.html">サイドバーをスクロールに合わせていい感じに固定してくれる、サイドバー sticky 系のコード</a>を使用している際に、マルチカラム用からシングルカラム用への挙動の切り替えをビューポートサイズを元にしている場合、handheld 用のシングルカラムでありながらコードが走ってしまうことになります。
<p>ビューポートサイズではなく、サイドバー要素とその親要素の位置関係などを元にマルチカラムか?シングルカラムか?検出するように修正します。
</div>
<pre class="prettyprint lang-js"><code>if( windowW < 800 ){/* single column */}
/* ↓調教 */
if( elmSide.offsetTop === elmSide.parentNode.offsetTop ){/* single column */}
</code></pre>
<p>この問題は Opera のスモールスクリーンモードに限らず遭遇しそうな上、js での検出も難しくはないのできちっとしておきたいところです。
<a name="3"></a>
<h2 id="3">3. 複雑なセレクタでパースに失敗し以降のCSSが全て無視される</h2>
<p>Opera 10.10, 9.64 で確認、7.0 では発生しなかった。<code>:not()</code> の括弧内の属性セレクタにタグ名指定があったところから以降の全ての CSS が無視されているようでした。
<p>タグ指定は冗長で不要だったため外したところ全ての CSS 指定が適用されました。
<p>問題の起きる Opera の下限と上限がはっきりすれば CSS ハックとして使えるかもしれません。
<pre class="prettyprint lang-css"><code>.links a[href^="/"]:not(<u>a</u>[href^="//"]):before {
content : "+";
}
/* ↓調教 */
.links a[href^="/"]:not([href^="//"]):before {
content : "+";
}
</code></pre>
<p>ちなみに上の指定は同一ドメイン内のリンクに対してスタイルを指定しています。
<a name="4"></a>
<h2 id="4">4. <code>background-image</code> の制限</h2>
<ol>
<li>背景画像に 2064px 以上の画像を使用すると、2064px を超える範囲の表示が無視され 2064px の範囲内で端の部分が表示される。Opera 9未満。Nintendo DS ブラウザでも確認。
<li><del>背景画像にアルファ値付きの PNG 画像を使用すると透過が無視される。Opera 7 で確認。</del>この情報は誤りです。(202/05/30 訂正)
<li>Opera 7.0~7.1でアニメーション gif がアニメーションしない。7.2 で解決する。<a href="https://web.archive.org/web/20051224084309/https://www.opera.com/docs/changelogs/windows/720b/" target="_blank" rel="nofollow">GIF animation fixes</a>
<li>画像の右と下に 2px づつの余白が必要。Opera7.2
</ol>
<a name="5"></a>
<h2 id="5">5. ドキュメントの下に巨大な余白が発生する</h2>
<p>Opera 9.64 でドキュメントに2ページ分程度の余白ができてしまう謎現象に遭遇しました。
<p>スクロールバーを一番下(付近)まで下げたのち、リサイズ、リロードすると高さが正しくなります。
<p>まったく見当が付かず、css を半分づつ削除しながら現象の発生を観察していくと次の指定を特定、コメントアウトすると解決しました。
<pre class="prettyprint lang-css"><code>/* ie6- の ,links a:link に以下の指定が当たってしまうので [href]をつける */
.links a[href]:before {
content : ">";
/* position : absolute; win + opera9.64 で不可.ページにスクロール位置によって発生する余白が出来てしまう... */
/* top : 0;
left : 0;
display : block; */
position : relative;
left : -0.5em;
width : 1em;
height : 1.4em; /* for iOS8 */
line-height : 1.4; /* for iOS8 */
text-align : center;
font-weight : bold;
}
.links a[href*="web.archive."]:before {
content : "*";
}
</code></pre>
<a name="6"></a>
<h2 id="6">6. <code>border-color</code> の解釈に失敗する</h2>
<p><code>border-color</code> を使って4辺の枠線の色を変えていたところ、この指定が反映されなかった。Opera7.2
<p><code>border-top:1px solid #ccc</code> のように指定方法を変えたところ色が反映された。
<a name="7"></a>
<h2 id="7">7. <code>Object</code> にキーを数値でセットする</h2>
<blockquote cite="http://web1.nazca.co.jp/macde/js2chlog/1158468856.html" title="+ JavaScript の質問用スレッド vol.51 +"><h3>156 名前:Name_Not_Found 投稿日:2006/09/22(金) 14:42:49 ID:???</h3>
<p>確実にチラシの裏だが聞いてくれ
<pre class="prettyprint lang-js"><code>var obj = {};
var x = 1;
obj[x] = something;
</code></pre>
<p>上のなんの変哲もないコードで、Opera8系列が「極稀に」クラッシュすることを突き止めた。
<p>理由はさっぱりわからないが、数字をキーにしてオブジェクトへアクセスすることを繰り返すと頻繁に落ちてしまうようだ。<code>obj["a" + x]</code> に変更したところ完全に問題なく動いている。
<p>特に理由が無い限り、Operaサポートする宿命を負った哀れな人は、上のようなコードを避けることを強くお勧めする</blockquote>
<a name="8"></a>
<h2 id="8">8. Closure CompilerでminifyするとOpera 7で動かない</h2>
<p><del><code>--compilation_level WHITESPACE_ONLY --formatting pretty_print</code> だと OK。</del>この件は、コンパイル結果のオブジェクトリテラルの添え字に、空文字列(<code>""</code>)が居ると Opera 8未満で意図した挙動をしません。より詳しい挙動は「<a href="https://itozyun.github.io/web-doc-base/test/javascript-implementation.html" target="_blank" rel="me nofollow">Javascript 実装状況と深刻なバグ</a>」で確認できます。<del>数値や数値文字が居ると Opera 8 未満で構文エラーになる。</del>(2022/03/21, 2022/11/20 空文字列、バージョン、実行時のトラブルに修正, 2022/11/25 7.5→8に修正)
<p>コンパイルによってラベル付き <code>break</code> が登場すると Opera 7.5x未満で構文エラーになる。(2022/05/30, 2022/11/25 8→7.5xに修正)
<a name="9"></a>
<h2 id="9">9. Changelogより</h2>
<ul>
<li><a href="https://web.archive.org/web/20061206011745/https://www.opera.com/docs/changelogs/windows/900/" target="_blank" rel="nofollow">Removed support for "javascript:" URLs in CSS.</a> CSS 内に Javascript を書ける独自拡張の削除
<li><a href="https://web.archive.org/web/20071114013918/https://www.opera.com/docs/changelogs/windows/921/" target="_blank" rel="nofollow">Fixed support for the WMP for Firefox plug-in.</a> Windows Media Player プラグインを Firefox に続きサポート。
<li><a href="https://web.archive.org/web/20071121112815/https://www.opera.com/docs/changelogs/windows/950b1/" target="_blank" rel="nofollow">Added support for the CSSOM ElementLayout.{getClientRects,getBoundingClientRect} methods (demos)</a> 待望の <code>getClientRects, getBoundingClientRect</code> サポート。
</ul>
<a name="10"></a>
<h2 id="10">10. ダウンロードリンク集</h2>
<div class="links"><a href="https://web.archive.org/web/20160715183827/http://www.opera.com/docs/changelogs/windows" target="_blank" rel="nofollow">Opera Changelogs</a>
<a href="https://web.archive.org/web/20051123091022/http://www.opera.com/docs/specs/opera7/js/dom/css/" target="_blank" rel="nofollow">Support for the DOM 2 View, Style, CSS, and CSS2 modules in Opera 7</a>
<a href="http://software.oldversion.com/windows/opera/" target="_blank" rel="nofollow" class="uc">oldversion.com</a> ダウンロードリンク
<a href="https://web.archive.org/web/20120303121716/http://browsers.evolt.org/?opera/win" target="_blank" rel="nofollow">browsers.evolt.org</a> ダウンロードリンク
<a href="http://get.opera.com/ftp/pub/opera/" target="_blank" rel="nofollow">get.opera.com</a> ダウンロードリンク
</div>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-23950047509556530252016-02-21T23:35:00.004+09:002021-09-12T14:53:19.322+09:00<meta>タグによるviewport指定の2016年春決定版!jsで上書きするべきケースも紹介<p>長々書いていますが記事の<strong>新規部分は最近の Android 標準ブラウザでも遭遇するバグへの <code>target-densitydpi=medium-dpi</code> での対策</strong>だけです。
<h2>はじめに</h2>
<p>気が付けば <code><head></code> 内にはズラズラといろいろなことを書くようになりました。
<p><code><meta></code> タグの <code>viewport</code> にどんな指定をすればよいのか?自分でも怪しかったのでここしばらくで根を詰めて調べてみました。
<p>モバイルブラウザのデフォルトの拡大縮小機能を生かす場合と切る場合、この2通りについてそれぞれ指定法を紹介します。
<p>また残念ながら <code>viewport</code> を javascript で上書きするべきケースも併せて紹介します。
<dl>
<dt>拡大縮小を禁止する
<dd>Web アプリケーションなどでタッチ操作を完全に制御している。
<dd>Web 文書でもアクセシビリティに手当てがされているので拡大縮小を禁止する。例えば <samp><small title="小さい A">A</small>A<big title="大きい A">A</big></samp> などの昔ながらの文字サイズ変更ボタンがある。
<dt>拡大縮小を許可する
<dd>一般的な Web 文書用。
</dl>
<h2>拡大縮小を禁止する</h2>
<p>考慮することの少ない拡大縮小を禁止するケースから紹介していきます。
<h3>javascriptが切られている場合に配慮する</h3>
<p>Web 文書の場合でも文字サイズを切り替える手段を提供していれば拡大縮小を禁止することができます。
<p>しかし javascript によって手段を提供している場合 javascript が切られているケースに対処が必要です。そこではじめに拡大縮小が可能な <code><meta></code> タグを指定した上で javascript でそれを上書きします。
<pre class="prettyprint lang-html"><code><meta name="viewport" content="width=device-width,target-densitydpi=medium-dpi,initial-scale=1,minimum-scale=1,shrink-to-fit=no">
<script>
document.write('<meta name="viewport" content="width=device-width,target-densitydpi=medium-dpi,minimum-scale=1,maximum-scale=1.0,shrink-to-fit=no">');
</script>
</code></pre>
<p><code>onload</code> 後の <code>viewport</code> の書き換えが可能なのは一部の環境みたいです。そのようなわけで必ず <code><head></code> 内の javascript で上書きします。
<p>ちなみに以上の反対で <code><noscript></code> 内に書いた <code><meta></code> で指定を上書きする手も考えられますが、これは不正な HTML となってしまいます。
<div class="note">
<h3><code>font-size</code> ベースのレイアウト</h3>
<p>レイアウトを <code>font-size</code> ベースで行っていれば、Web 文書への文字の拡大縮小ボタンの設置はとても容易になります。
<blockquote title="解像度に依存しないモバイルユーザーインターフェース" cite="http://web.archive.org/web/20120716033656/http://www.extjs.co.jp/blog/2010/08/24/resolution-independent-mobile-ui">
<p>このテクニックの基本的なコンセプトは、全てのインターフェース要素のサイズ設定単位に、活字の相対的なサイズを表す単位である「<code>em</code>」を利用することにあります。(中略)
<p><code>font-size</code>は CSS において子要素に継承されるプロパティであるため、<code>em</code> を使ってサイズを設定した任意の要素について、その親要素の<code>font-size</code>を変更することにより子要素のサイズを変更することが可能となります。</blockquote>
</div>
<h2>拡大縮小を許可する</h2>
<pre class="prettyprint lang-xml"><code><meta name="viewport" content="width=device-width,target-densitydpi=medium-dpi,initial-scale=1,minimum-scale=1,shrink-to-fit=no"/>
</code></pre>
<h3><code>width=device-width</code> を指定</h3>
<p>副作用の出る環境もあるため指定され無い場合もある。副作用の出る環境に対しては javascript で <code><meta></code> を上書きして対策する。
<h3><code>target-densitydpi=medium-dpi</code> を追加</h3>
<p>次の記事には <code>medium-dpi</code> が <code>target-densitydpi</code> のデフォルト値とある。
<p>しかし <code>target-densitydpi=medium-dpi</code> を明示した場合と無い場合で Android 2.3.5 の標準ブラウザで挙動が変わりました。指定しない場合縦向きから横向きにした際に画面がズームインする。
<blockquote title="FFBlog viewportのtarget-densitydpi=device-dpiで、ひどいことが起こった" cite="http://www.flexfirm.jp/blog/article/354">
<p><code>medium-dpi</code> 中解像度。160dpiまで。属性を指定しなければ、通常はこれが適用される。</blockquote>
<p>好みにで <code>high-dpi</code> を指定してもよいが、デフォルトの文字サイズがかなり小さくなってしまった。
<p>また先にの記事にも言及があるように <code>target-densitydpi=device-dpi</code> には深刻なバグがあるため決して指定しない。
<h3>Android 4以降の標準ブラウザで<code>viewport</code>指定を無視して初期表示が拡大縮小する</h3>
<p>Android 4 以降の標準ブラウザでは、要素を画面外にスライドさせたときにページ制作者が意図せずに画面が縮小されてすべての画面範囲が再び画面に収まる挙動があった。この症状は次の対策を行ったところ解消した。
<ol>
<li><code>target-densitydpi=medium-dpi</code> を指定する
<li>ユーザーが気にならない程度にはじめに一度だけ 10px 画面をスライドさせて 0 位置に戻す(症状は2度目以降のスライドでは起こらなかったことから発見する、アニメーション用に指定した CSS プロパティが関係する模様)
</ol>
<div class="note">
<p>上で言及している原因の推測と対策に納得がいかなかったところ、次の記事の対策が筋がいいように思う(未確認、2016-10-05 追記)。
<blockquote cite="http://kimizuka.hatenablog.com/entry/2016/04/28/101422" title="ナウでヤングなviewportの書き方調査 & まとめ 2015 春"><p>一昨年の年末、Android 4.0.4とかを対応していた際に、
<code>user-scalable</code>を指定すると一部 Android で初期表示がおかしくなるという現象に出くわしたので、
それ以降<code>user-scalable</code>は動的に JS で動的に設定するという方針だったのですが、
最近の Android では不要な処理なのかもしれません。</blockquote>
</div>
<h3>shrink-to-fit=no を追加</h3>
<p>iOS9.0 限定の不具合に対策するために追加する。詳しくは次の記事などで。
<blockquote title="iOS9でviewportのinitial-scaleが無効になる時の対策" cite="https://qox.jp/blog/ios9_viewport_workaround/"><p>iOS9のSafariでは、初期の画面倍率を無視してページ全体を表示するよう縮小して表示しているようです。</blockquote>
<h3>iOS5以下に対してjavascriptで対策すること</h3>
<p>iOS5 以下に対して拡大縮小を一切禁止にする。<code>width=device-width</code> を指定しなければよい、とする<a href="http://blog.ousaan.com/index.cgi/links/20130925.html" target="_blank" rel="nofollow">記事</a>もあるが、iOS3 & 4 では改善を確認できない。
<blockquote title="user-scalable=noを使う理由と弊害(スマホのviewportを見直す)" cite="http://2ndidea.com/accessibility/pros-cons-of-user-scalable-no/">
<p>iOS5以下で、以下のような <code>viewport</code> 指定をしているとき、縦向き(ポートレート)から横向き(ランドスケープ)にすると、1.5倍拡大される(というより320pxの <code>viewport</code> を保つ)仕様があります。
<p>これも、拡大・縮小を禁止(<code>maximum-scale=1.0,minimum-scale=1.0</code>)にすることで解決できます。</blockquote>
<h3>Android 2.x以下に対してjavascriptで対策すること</h3>
<p>Android 2.x 以下に対して拡大縮小を禁止しないと画面にズーム用のボタンが出現して邪魔だ、という理由で…
<h3>IE Mobile 10に対してjavascriptで対策すること</h3>
<p>CSS 内の <code>@viewport</code> 指定の上書きを行う。この問題は手元の IE Mobile 11 では確認していません。また <code>@-ms-viewport</code> を使っていなければ不要のようです。
<blockquote title="@viewport - CSS | MDN" cite="https://developer.mozilla.org/ja/docs/Web/CSS/Reference/@viewport"><p>[1] Windows Phone 8 の古いバージョンにある IE モバイル 10 は、 <code>device-width</code> のところに不具合がある。 <code>@-ms-viewport</code> を使ったとき、物理的なピクセルによる画面幅ではなく、CSS ピクセルとして評価してしまう。</blockquote>
<div class="links"><a href="https://developer.mozilla.org/ja/docs/Web/CSS/Reference/@viewport" target="_blank" rel="nofollow">@viewport - CSS | MDN</a>
<a href="https://timkadlec.com/2013/01/windows-phone-8-and-device-width/" target="_blank" rel="nofollow">Windows Phone 8 and Device-Width - TimKadlec.com</a>
</div>
<h2>ほか</h2>
<p>拡大縮小を禁止すると <code>position:fixed</code> が使えるようになる、とか <code>click</code> イベントの発生が早くなるとか。
<p>先々は CSS 側に <code>@viewport</code> 指定で書いていく。<a href="https://developer.mozilla.org/ja/docs/Web/CSS/Reference/@viewport" target="_blank" rel="nofollow">@viewport - CSS | MDN</a>
<p>お好みで <code>minimal-ui</code>。(iOS7.1 だけ)
<p><code>onload</code> 後の <code>viewport</code> の変更を反映してくれるダイナミック <code>viewport</code> が Opera 10(?だったかな, Windows Mobile 6.5 IS12)で可能。Webkit 系でも可能の模様。
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-72859025584141647272016-01-18T22:30:00.000+09:002021-07-13T15:04:03.312+09:00フロントエンジニアのためのブログ運営(再開)のススメ<p>昨年のはじめ、弱小会社のおひとりさま Web プログラマの僕はいい加減人を育てないと氏ねると思っていました。
<p>手始めにオレオレフレームワークのソースコードに jsdoc コメントで“Web 開発の世界へようこそ!”から始まるポエムをしばらく書きつけていましたとさ。
<blockquote cite="http://git.osdn.jp/view?p=pettanr/clientJs.git;a=blobdiff;f=0.6.x/js/01_core/01_X.js;h=15819675b13e2a964b26abfa70b44c1bb51d38e7;hp=98e7f4c7f115d4be4ac0ea7291314588d5bb6470;hb=HEAD;hpb=6002fdac540134f01738f95246c0ea66302bd702" title="git.osdn.jp Git - pettanr/clientJs.git/blobdiff - 0.6.x/js/01_core/01_X.js"><p>- * <h4>はじめに:Web 開発の世界へようこそ!</h4>\r<br>- * DHTML と XHR 等を活用した Ajax によってその真価を発揮した javascript は、現在では RIA に SPA や 3D ゲームなど、あらゆるアプリケーションがブラウザ上で動きつつあります。\r</blockquote>
<p>幸いにしてハッと我に返った僕は休眠していたブログを再開してそこに書くことに…
<div class="links"><a href="https://outcloud.blogspot.jp/p/pettanr-api-docs-supplementary-reader.html">ぺったんR APIドキュメントの副読本</a>
<a href="http://git.osdn.jp/view?p=pettanr/clientJs.git;a=blobdiff;f=0.6.x/js/01_core/01_X.js;h=15819675b13e2a964b26abfa70b44c1bb51d38e7;hp=98e7f4c7f115d4be4ac0ea7291314588d5bb6470;hb=HEAD;hpb=6002fdac540134f01738f95246c0ea66302bd702" target="_blank">git.osdn.jp Git - pettanr/clientJs.git/blobdiff - 0.6.x/js/01_core/01_X.js</a>
</div>
<p>かくして(僕にしては)コンスタンスに記事をあげつつ新年を迎えることができました。
<p>振り返って、記事を書きブログをカスタマイズすることは当初考えていたより多くの効用がありました。
<p>ということで、ブログ運営(再開)のススメです。
<h3>Web 文書と Web アプリケーションの違いがよくわかる</h3>
<p>Web アプリケーション(とくに SPA)ではクロスブラウザライブラリを使ってブラウザ間の違いをねじ伏せていくことが可能です。
<p>しかしクロスブラウザな DOM 操作ライブラリはこれだけでなかなかに大きいものでモバイル通信環境で Web ページを重くします。
<p>そこで DOM 操作ライブラリの使用を諦め、異なるブラウザ同士で共通して動く部分だけをすくいあげていくような“頑張らないデザイン”を心がけました。
<p><q>機事あれば必ず機心あり</q>で js は極力控えめに留めています。
<p>両極端な開発を行ったことで html, css, js などのまったく同じ技術を使いながら、改めて大きな違いを感じました。
<div class="note">
<h4>DOM操作ライブラリがないとlightboxすら難しくなるが…</h4>
<p>DOM 操作ライブラリを使わないことにすると lightbox のような画像の拡大表示の実装すら難しくなります。特にブラウザのカバー範囲とメンテナンスの困難さが上がります。
<p>結局 lightbox より簡単な、そのブロック要素内で拡大する短いコードを書きました。
<div class="links"><a href="/2015/11/bloger-minify-final.html">Blogger究極軽量化の完成、画像拡大は非lightboxで</a>
</div>
</div>
<h3>デザインセンスが少しだけ上がった</h3>
<p>新デザインに変えて半年間、記事を書きつつ少しづつデザインも微修正していきました。「なかなかいけている」と自画自賛していましたが、ある日ふと野暮ったさが抜けないことに気づきました。
<div class="box">
<a href="http://4.bp.blogspot.com/-z4O0plGuoO8/VpzVDKPzeBI/AAAAAAAAQlE/IZs83ycFMN8/s1600/OutCloud_2016-01-18.jpg">
<img src="http://4.bp.blogspot.com/-z4O0plGuoO8/VpzVDKPzeBI/AAAAAAAAQlE/IZs83ycFMN8/s160-c/OutCloud_2016-01-18.jpg" /></a>
<a href="http://1.bp.blogspot.com/-NZpBxe_KhVA/VlkwshvIaoI/AAAAAAAAQfw/yxBu43clQF0/s1600/fix_start.png">
<img src="http://1.bp.blogspot.com/-NZpBxe_KhVA/VlkwshvIaoI/AAAAAAAAQfw/yxBu43clQF0/s160-c/fix_start.png" /></a>
<a href="http://1.bp.blogspot.com/-G9g34TiNyko/Tsj7fzmItvI/AAAAAAAAJfo/whckf6HX5qg/s1600/outOfCloud.png">
<img src="http://1.bp.blogspot.com/-G9g34TiNyko/Tsj7fzmItvI/AAAAAAAAJfo/whckf6HX5qg/s160-c/outOfCloud.png" /></a>
</div>
<p>(左から、現在のスクリーンショット、野暮ったいと思ったときのもの、新デザインになる前の旧デザイン)
<p>それから僅かに2時間程度ですが久しく真剣にデザインを考えて自分なりに答えを出すことができました。
<div class="links"><a href="/2015/11/DowdyToCool.html">非デザイナーがチャチャッと野暮ったいブログを修正してみた</a>
</div>
<p>この後もしばしば微修正を繰り返しています。ミニマルなデザインにしているにもかかわらず、いつになったら手を離れるのでしょう…
<h3>オールキャストが登場するページを作って一挙に理解度を点検できる</h3>
<p>ブログのカスタマイズがひと段落したところで、記事中に登場する html css 表現が一堂に会したページを制作しました。
<div class="links"><a href="/p/spec.html">ブログテンプレートのスペック</a>
</div>
<p>こういったページを用意しておくとなにかと便利です。新しいブラウザに出会ったらオールキャスト・ページを開いて簡単に自分がこれまで書いてきた html css を確かめることができます。
<p>Web アプリケーションの開発を続けていると、Webドキュメント寄りの知識があやふやになっているように感じていました。
<p>今回このページを用意したことで、理解度を点検し自信を持って開発していけると思いました。
<h3>ブログに jsdoc からこぼれた話を書いていくと思いのほか頭が整理される!</h3>
<p>昨年の春にブログを再開した動機は、ソースコードに jsdoc で書いていた内容をより書きやすく読みやすい所に移動したい、というものでした。
<p>フロントエンド開発には膨大なノウハウが必要です。なぜこのような形に至ったのか経緯などを記録しておくことが重要です。
<p>しかし jsdoc では書き出して確認するのもひと苦労の上、出力も美しいものではありませんでした。
<p>現在はブログの方に長々と書いてAPIドキュメントは短いテキストとブログ記事へのリンクだけを書いています。
<p>なんと言っても html css を自分で完全にコントロール出来るので、仕上がりが美しいです。
<p>その上、リストや表組や AA を駆使してややこしい調査結果も頭から吐き出して整理できるので、頭がとてもクリアになる効用に気が付きました。
<p><a href="/2015/11/htmlaudio.html">モバイルオーディオの調査記事</a>などは、このブログテンプレートがなければやり遂げることが出来なかったかもしれません。
<h3>おまけ:この記事を見てブログ運営をはじめたいと思ったら</h3>
<p>お勧めのブログサービスの紹介です。僕も使っている Google の Blogger です。
<ol>
<li>ナビゲーションバーを消すことが公式に認められている
<li>カスタマイズの自由度が高く html に関してはほぼ隅々までいじることができる
<li>無料ブログサービスでありながら広告が表示されない(自分でアドセンスを設置することは可)
<li>無料ブログサービスでありながらブログ記事のインポート・エクスポート機能を提供している
<li>Web API 経由で記事の更新などができる
</ol>
<p>ほぼ思い通りにデザインを作り込むことができるので html css の訓練には申し分ありません。
<p>CGI やファイルストレージはありませんが、Wordpress の1割程度の自由度はあると思います。
<p>もちろん全てのブログが Google に集まってしまうのもまずいですが、他の無料ブログサービスでも Blogger に比肩するものが現れてこないかなぁと思います。
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-8213609950957088372015-12-31T23:52:00.000+09:002016-01-05T14:33:49.430+09:00ぺったんRのゆく年くる年<p>この冬休みはストレスから風邪をこじらせて臥せっています。でも頑張って書いておきます。
<p>そういえば去年も休みに入ると同時に風邪で寝込みました。来年の暮れは健康で迎えたいです…
<h3>11.6(金)7(土) 関西オープンフォーラム2015ブース出展</h3>
<div class="box">
<a href="http://2.bp.blogspot.com/-gpukt9jbhdk/VoUhsVPchrI/AAAAAAAAQkg/DruygIv5zR0/s1600/pettanR_KOF_kinichi.png">
<img src="http://2.bp.blogspot.com/-gpukt9jbhdk/VoUhsVPchrI/AAAAAAAAQkg/DruygIv5zR0/s160/pettanR_KOF_kinichi.png" /></a>
<p>ぺったんR チームは<a href="https://k-of.jp/2015/session/829" target="_blank">関西オープンフォーラム2015にブース出展</a>させていただきました。
<p>2011 年から鋭意製作中(現在5年目!)の Web アプリケーション『ぺったんR』をデモし、これをつかった<a href="https://pettan.herokuapp.com/scrolls/17/play" target="_blank">イベント実況</a>を行いました。
<p>ちなみに<a href="https://k-of.jp/2014/session/602.html" target="_blank">2014年にもブース出展</a>しております。このときはメインプログラマーである <a href="https://twitter.com/yasushiito" target="_blank">yas 氏</a>も僕も参加せずぺったんRの強力な後援者である<a href="https://twitter.com/tueda" target="_blank">弊社社長</a>に参加していただき、僕は自宅で英気を養っていましたとさ…
</div>
<div class="links"><a href="https://pettan.herokuapp.com/scrolls/17/play" target="_blank">きたぞ!関西オープンフォーラム - ぺったんR体験版</a>
<a href="https://pettan.herokuapp.com/scrolls/24/play" target="_blank">KOF2015でぺったんRによるイベントレポート演習 - ぺったんR体験版</a>
</div>
<blockquote title="ぺったんRチーム | KOF 2015:関西オープンフォーラム2015" cite="https://k-of.jp/2015/session/829"><p>ぺったんRはwebブラウザで漫画風コンテンツを配信・作成するツールです。その紹介とデモを行います。</blockquote>
<blockquote title="きたぞ!関西オープンフォーラム - ぺったんR体験版" cite="https://pettan.herokuapp.com/scrolls/17/play"><p>KOF2015!いよいよ開催!<p>ぺったんR特設会場からお送りします<p>ぺったんRってなんでしょうね?
さっそくいきましょう</blockquote>
<h4>キャラクター大国・日本の中心で愛を叫ばない、咳き込む…</h4>
<div class="box">
<a href="http://1.bp.blogspot.com/-LVwBXMr0UnE/VoUhsOBDpZI/AAAAAAAAQkc/_aYVR0O0I9Q/s1600/pettanR_KOF.png"><img src="http://1.bp.blogspot.com/-LVwBXMr0UnE/VoUhsOBDpZI/AAAAAAAAQkc/_aYVR0O0I9Q/s160/pettanR_KOF.png" /></a>
<p>ぺったんRは Web ブラウザと親和性の高いマンガ風リッチコンテンツを作るための CMS アプリケーションです。
<p>日本はマンガやゲーム等はもとより、同人や企業や団体、行政などのいたるところでキャラクターが日々生まれている<strong>キャラクター大国</strong>です。
<p>しかしこれらキャラクターをマンガやアニメ等を制作して活躍させるのはなかなかにできることではありません。
<p>ぺったんRは キャラクターにしゃべらせたり活動させる、ストーリーの中で動かす、といったことがそこそこ手軽にできるリッチ・コンテンツエディタを中心としたシステムです。
</div>
<h4>twitter より遅いけどブログより早いメディア</h4>
<div class="box">
<a href="http://3.bp.blogspot.com/-i29EEGtRqr0/VoUhsd6LW6I/AAAAAAAAQkk/Vm7QOHIdmMA/s1600/pettanR_sakura.png">
<img src="http://3.bp.blogspot.com/-i29EEGtRqr0/VoUhsd6LW6I/AAAAAAAAQkk/Vm7QOHIdmMA/s160/pettanR_sakura.png" /></a>
<p>またリッチでありながら速報性の高いメディアとなることも目標としています。
<p>例えばイベントの実況コンテンツを写真とキャラクターを組み合わせてスムースに制作し速やかにソーシャルストリームに流す、といったユースケースを想定します。
<p>KOF はよい機会でしたので各ブースを取材しこれをぺったんRコンテンツ化させていただきつつ高速リリースのボトルネックを探りました。
</div>
<h4>ブース出展の反響</h4>
<p>2日間を通して10名強の方に足を止めていただきました。貴重なお時間を頂戴しありがとうございました。
<p>まずあまりにもデモサイトのレスポンスが悪かったのでコマ制作を体験していただくことは諦めました。
<p>また“カオス・ジャパン構想”についても時期尚早と見送りました。
<ol>
<li>「こんなマンガ(風)になりました」と各ブースに報告して回ったところ好感触でした
<li>キャラクター大国・日本と親和性が高い、という説明に関心してくださった方が2~3名程度
<li>ぺったんR フレームワークに関心してくださった方おひとり「Virtual DOM 化した jQuery」にビビッときた模様
</ol>
<p>KOF はエンジニアが中心のイベントですので、技術やターゲットに関する関心を頂戴しました。
<p>今後はキャラクターを抱えている方達にアピールする機会を模索していきたいです。
<h3>ぺったんR フレームワークの2015年</h3>
<p>『ぺったんR』のために制作しているフレームワークは弊社社長の絶大なるエールと発注企業様の清水の舞台的ご理解により業務でも本格的に使わせていただいております。
<p>オレオレフレームワークでありながら早々にこのような機会が巡ってきたのは大変な幸運です。
<p>js プログラマーだけで3.5人強という(弊社にしては)大所帯に加え、内部・外部仕様文書ほぼ無し、量多し、という開発ですがおかげさまで安全圏で進行しています。
<p>フレームワークは EventDispatcher クラスを拡張しながら~というオーソドックスなものですので、案件による得手不得手は出ずらい印象です。
<p>なによりフレームワークに触れている時間が飛躍的に増えたことで、フレームワーク自体の質も一挙に高めることができました。
<h4>ぺったんR フレームワークの2016年</h4>
<p>UI フレームワーク層の進捗は遅々としたものながらスクロールとジェスチャー周りがようやく動き始めました。
<p>スクロールといえば、GPU アクセラレーションを効かせながら無限スクロールさせる、という課題がまだ残っています。今年の中頃に一度挑んで玉砕しています…難しめですがこれをし遂げないとユーザーは気持ちよく画像ファイルを探索することが出来ないでしょう。
<p>また SPA の次の段階 SPMA (シングルページ・メニー・アプリケーションズ) についても、ぺったんR はまさにそれですので準備していかないといけません。
<p>なんてことをどこかのアドベントカレンダーに紛れ込んで書こうかなと思っていましたが、書きかけてまとまらなかったし、それよりも実装でがんばります。
<p>ではでは、本年も大変にお世話になりました。新しい年も良しなに。
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-22307511547399592412015-12-06T23:25:00.006+09:002021-05-01T14:35:14.577+09:00ぺったんRフレームワークのアニメーションメソッド<div class="note">
<p>アニメーション中の要素の、その子要素に加えた変更がリアル DOM ツリーに適用されない件に関する注意を追記しました。合わせてマークアップの修正もしました。(2021/05/01)
<p><a href="https://osdn.jp/projects/pettanr/scm/git/clientJs/commits/3d10dbbb167c89638f3bea6c267de8763274d30c" target="_blank">2016-01-08</a>の更新から <code>fallback</code> の選択肢に <code>right</code>, <code>bottom</code> を追加しました。
<p><a href="https://osdn.jp/projects/pettanr/scm/git/clientJs/commits/a205577d1e16a34301f1199dcf9c699aa2c37fb9" target="_blank">2015-12-19</a>の更新から <code>rotate</code>, <code>skew</code>, <code>scale</code>, <code>scroll</code> に対応し引数を変更しました。
</div>
<h2>概要</h2>
<p>アニメーションのための低レベルなメソッドです。位置指定については px 指定しかできません。(%, em 等は使えません)
<p>GPU サポートの効くプロパティ(<code>transform</code>, <code>opacity</code>)に絞って絹のように滑らかなアニメーションを実現します。
<p><code>transform</code> が無い環境用に複数のフォールバックを用意しています。
<pre class="prettyprint lang-js"><code>// アニメーション登録
xnode.animate({
from : { x : 0, y : 100 },
to : { x : 100, y : 0 },
duration : 500,
easing : 'circular',
lazyRelease : 250 });
// アニメーション停止
xnode.stop();
// 即時にアニメーションできるか?
var bool = xnode.call( 'canAnimateNow' );
// アニメーション状態 0~7
var num = xnode.call( 'animeState' );
// アニメーション進行状況 0~1
var num = xnode.call( 'animeProgress' );
// GPU レイヤーで描画されてる
var bool = xnode.call( 'inGPU' );
</code></pre>
<h2><code>.animate()</code>の引数</h2>
<table>
<thead>
<tr>
<th>key<th>説明<th>値の型<th>デフォルト値
<tbody>
<tr>
<th><code>from</code><td>開始値を指定する<td>Object 下表参照<td>{}
<tr>
<th><code>to</code><td>終了値を指定する<td>Object 下表参照<td>{}
<tr>
<th><code>duration</code><td>アニメーションする時間<td>Number ミリ秒<td>0(ms)
<tr>
<th><code>lazyRelease</code><td>GPU レイヤーの解除を遅延する時間<td>Number ミリ秒<td>0(ms)
<tr>
<th><code>easing</code><td>イージング関数<td><code>'quadratic'</code>, <code>'circular'</code>, <code>'back'</code>, <code>'bounce'</code>, <code>'elastic'</code> または関数<td><code>'circular'</code>
<tr>
<th><code>fallback</code><td>フォールバック動作の指示<td>Number ビットフラグ 下表参照<td>0
</table>
<h3><code>from</code> と <code>to</code> の値</h3>
<table>
<thead>
<tr>
<th>key<th>説明<th>値の型<th>デフォルト値
<tbody>
<tr>
<th><code>x</code><td>x 座標を指定<td>px 指定の数値<td>0(px)
<tr>
<th><code>y</code><td>y 座標を指定<td>px 指定の数値<td>0(px)
<tr>
<th><code>rotate</code><td>要素の回転、基準は要素の中心<td>degree<td>0(°)
<tr>
<th><code>skewX</code><td>要素を歪める、基準は要素の中心<td>degree<td>0(°)
<tr>
<th><code>skewY</code><td>要素を歪める、基準は要素の中心<td>degree<td>0(°)
<tr>
<th><code>skew</code><td><code>skewY</code>, <code>skewY</code> を同時に指定する<td>degree<td>0(°)
<tr>
<th><code>scaleX</code><td>要素を拡大する、基準は要素の中心<td>0 以上の数値<td>1
<tr>
<th><code>scaleY</code><td>要素を拡大する、基準は要素の中心<td>0 以上の数値<td>1
<tr>
<th><code>scale</code><td><code>scaleX</code>, <code>scaleY</code> を同時に指定する<td>0 以上の数値<td>1
<tr>
<th><code>scrollX</code><td>実装中<td><td>
<tr>
<th><code>scrollY</code><td>実装中<td><td>
</table>
<p><code>from</code> のメンバーや <code>from</code> 自体が省略可能です。省略した場合、現在値またはデフォルト値が新たな開始値になります。
<h3><code>fallback</code> の値</h3>
<table>
<thead>
<tr>
<th>代替手段<th>説明<th>ビットフラグ
<tbody>
<tr>
<th>DX Transform<td>rotate, skew, scale に対して DXImageTransform を使用<td>32
<tr>
<th><code>bottom</code><td><code>transfrom</code> のない環境で <code>top</code> に替えて <code>bottom</code> を使用<td>16
<tr>
<th><code>right</code><td><code>transfrom</code> のない環境で <code>left</code> に替えて <code>right</code> を使用<td>8
<tr>
<th><code>zoom</code><td><code>scale</code> に対して IE 独自拡張の <code>zoom</code> プロパティを使用。<code>scaleX</code> <code>scaleY</code> が同じ値の場合に限る<td>4
<tr>
<th><code>fontSize</code><td><code>scale</code> に対して <code>fontSize</code> プロパティを使用。フォントサイズベースで要素をレイアウトしていること。<code>scaleX</code>, <code>scaleY</code> が同じ値の場合に限る。<td>2
<tr>
<th><code>width</code> & <code>height</code><td>未実装。子要素がないか、あってもテキストが無く % でレイアウトを組んでいる場合に互換性がある。<td>1
</table>
<p><code>opecity</code> のない IE8 以下に対して <code>filter:alpha</code> の使用、<code>transfrom</code> のない環境で <code>left</code>, <code>top</code> の使用は <code>fallback</code> に関わらず行われます。
<h3>制約</h3>
<p>GPU サポートの効くプロパティとそうでないプロパティを混在させることはできないため、アニメーションできるプロパティをバッサリと絞っています。
<p>そのうえ、GPU サポートの制約によって<strong>先祖・子孫関係にある要素を同時にアニメーションできません</strong>。
<p>このため、先行してアニメーション中の先祖(親)要素または子孫要素があった場合に要素はアニメーションを待機します。
<h4>待機の例</h4>
<p>要素 B は、先祖(親)要素 A や 子孫要素 C~F がアニメーション中の場合、それらが終わってからアニメーションを開始します。
<pre class="aa">
(A)-+-(B)-+-(C)
| |
| +-(D)
+-(G) |
+-(E)---(F)
</pre>
<p>よって待機時間が極端に長くなってしまう<strong>1秒を超える長時間のアニメーションを行うには不向き</strong>です。
<h4>先祖子孫制約を回避する</h4>
<p>制約を見越して要素のレイヤー関係を設計します。無用な親子関係を作らずルート要素に対してフラットに並べることができないか、検討します。
<pre class="aa">
(Root)-+-(A)
|
+-(B)
|
+-(C)
</pre>
<h2>animeState:アニメーション状態変化</h2>
<ol start="0">
<li>(アニメーション未登録)
<li>登録直後
<li>待機<br>自身のアニメーション開始を、待機または後続待機中の先祖子孫要素によって阻害されている
<li>後続待機<br>自身のアニメーション開始をアニメーション中の先祖子孫要素によって阻害されている
<li>強制停止(GPU転送予約)
<li>GPU解除待ち
<li>アニメーション開始可能
<li>アニメーション中
</ol>
<p><code>duration</code> が 0 でも <code>lazyRelease</code> を指定しておけば要素は状態4に進みます。
<p><code>duration</code>, <code>lazyRelease</code> がどちらも 0 の場合、<code>transform</code>, <code>opacity</code> の設定のみ行うことができます。状態は 4 → 0 に変化します。但し親要素がアニメーション中の場合、変更の反映は親のアニメーション終了を待ちます。
<h2>イベント</h2>
<ol>
<li><code>X.Event.ANIME_START</code>
<li><code>X.Event.ANIME_END</code>
<li><code>X.Event.GPU_RELEASED</code>
</ol>
<h2>動作</h2>
<h3>待機とアニメーションの開始</h3>
<p>先祖・子孫関係にある複数の要素がアニメーション登録された場合、次のルールに従ってアニメーション開始・待機します。
<ol>
<li>アニメーションを開始する優先権は先に登録されたものにある
<li>登録されたばかりの要素は自分より登録が先で待機(& 後続待機)中の要素の中に親子関係のものがいないか検査される
<ul>
<li>いる -> 待機フラグを立てる、この段階では誰に後続してアニメーションするのか、判然としない
<li>いない -> 3. へ
</ul>
<li>アニメーション中の要素(開始可能含む)の中に親子関係のものがいないか?調べる
<ul>
<li>いる -> アニメーション中の要素に後続する要素がいることをチェックし(following)後続待機フラグを立てる
<li>いない -> 4. へ
</ul>
<li>アニメーションが開始可能
</ol>
<p>以上の検査はアニメーション登録後から一番最初のアニメーションの際に行われる。その結果には <code>animeState</code> でアクセスできます。
<p>しかし、即座にアニメーションを開始できるか?を判別して処理を切り替えたい場合に不都合です。
<h3>即時に開始できるか調べる</h3>
<pre class="prettyprint lang-js"><code>var bool = xnode.call( 'canAnimateNow' );
</code></pre>
<p>アニメーションを開始する前に、要素がただちにアニメーション可能か?確認することができます。
<div class="note">
<p>後述する理由で、子要素以下の変更が出来ない為に、<strong>アニメーション中の親要素に追加された子要素は、親のアニメーション終了までリアル DOM ツリーへの変更適用(commit)が行われず、要素のサイズ取得(<code>xnode.width()</code>)で0が返ります</strong>。アニメーションする可能性のある要素の子要素の、<code>xnodeChild.call( 'canAnimateNow' )</code> が <code>true</code> ならば、直ちにサイズの取得が出来ます。(2021/05/01 に追記)
</div>
<h3>待機と後続待機がある理由</h3>
<pre class="aa">
(A)-+-(B)-+-(C)
| |
| +-(D) *
+-(E)
</pre>
<p>要素 D のアニメーション中に B が、続いて C がアニメーション登録されたとする。(D ← B ← C )
<p>B は子要素 D のアニメーション終了を待機するが C にはアニメーション中の先祖子孫要素がいないため直ちにアニメーション開始可能である。
<p>仮に C がアニメーションを開始すると、B は子要素 C の終了を待たなくてはならなくなる。
<p>この結果アニメーションの順番が登録順と異なってしまい具合が悪いです。(D ← C ← B )
<p>これを防ぐために、D の終了を待つ B は後続待機となり、後続待機(& 待機)を親に持つ C は待機になる。
<p>ちなみに B, C に続いて E のアニメーションが登録された場合、B C D と親子関係にない E のアニメーションは即座に開始される。
<h3><code>translateX</code> <code>translateY</code> だけをセットしてアニメーションはしない</h3>
<pre class="prettyprint lang-js"><code>xnode.animate( { from : { x : 100, y : 100 } } );
</code></pre>
<p>アニメーションをすぐには開始しないが表示位置や <code>opacity</code> は変更しておきたいケースがあります。
<p>このような場合には開始値だけを与えて <code>.animate()</code> します。
<p>一見すると <code>.css()</code> を単に <code>.animate()</code> で代替にしているようにみえます。
<p>実は浅からぬ意味があり <code>.animate()</code> と <code>.css()</code> や <code>translateX</code> と <code>left</code> がバッティングしないために <code>translateX</code> <code>translateY</code> の変更には <code>.animate()</code> を使用すべきです。
<p>先祖要素が GPU 化していない場合、変更は直ちに反映されます。
<h2>GPU レイヤーの遅延解除</h2>
<p>要素を GPU メモリに転送することで GPU による高速な描画が可能になります。
<p>この転送にはコスト(時間)がかかります。対象要素が大きい場合などに画面がチラツキます。
<p>iPod touch 1th~2th は GPU 描画をサポートする最も非力な端末で特にチラツキが顕著です。(もちろん最新の端末でも頻度は落ちますが発生します)
<p>このような端末でもレイヤーの遅延解除を活用することでチラツキを抑えることが出来ます。
<h3>アニメーション終了後、即座に GPU レイヤーの解除を行わない</h3>
<p>スクロールのようなケースでは、サッサッと矢継ぎ早にアニメーションが発生します。
<p>そのたびに GPU の解除と再転送を行うのは無駄な上にチラツキが頻発し UX を損ないます。
<p>アニメーションの終了から GPU の解除までに若干のタイマーを挟むと、まだ GPU レイヤーにあるうちに次のアニメーションが起こるためチラツキが発生しません。
<p>しかし、<strong>要素が GPU レイヤーにあるうちは <code>transform</code>, <code>opacity</code> の以外の値・属性・子要素以下の変更は出来ません</strong>。より正確にはリアル DOM ツリーに変更が適用(commit)されません。ですので、いつまでも GPU レイヤーに要素を留めておくことは、現実的ではありません。
<h3>GPU レイヤーの強制解除</h3>
<p>GPU レイヤーの遅延解除中の要素が他の要素のアニメーション開始を阻害している場合、GPU レイヤーは解除されます。
<h3>アニメーション発生前に GPU 転送だけを行う</h3>
<pre class="prettyprint lang-js"><code>// GPU レイヤー化だけを行う 0.5秒後に解除
xnode.animate( { lazyRelease : 500 } );
</code></pre>
<p><code>lazyRelease</code> だけを設定して <code>xnode.animate()</code> する。
<h2>アニメーションの中断</h2>
<p>登録直後からアニメーション中のどの段階でも、<code>xnode.stop(opt_bitFlag)</code> でアニメーションの中断が出来ます。引数に 1~3 の数字を指定して座標と透過度と GPU レイヤーの状態を制御できます。
<ol>
<li><code>RESET</code>
<li><code>KEEP_GPU</code>
<li><code>RESET | KEEP_GPU</code>
</ol>
<table>
<thead>
<tr>
<th>状態 (<code>animeState</code>)<th>引数<th>動作
<tbody>
<tr>
<th rowspan=4>待機、開始前、強制停止 (~4,6)<td>-<td>アニメーションをキャンセル、開始値を保持、GPU は解除
<tr>
<td><code>RESET</code><td>アニメーションをキャンセル, <code>x=0,y=0,opacity=1</code>, GPU は解除
<tr>
<td><code>KEEP_GPU</code><td>開始値を保持してアニメーションをキャンセル GPU はキープ
<tr>
<td><code>RESET | KEEP_GPU</code><td>アニメーションをキャンセル, <code>x=0,y=0,opacity=1</code>, GPU はキープ
<tr>
<th rowspan=4>アニメ中 (7)<td>-<td>アニメーションを停止、現在値を保持、GPU は解除
<tr>
<td><code>RESET</code><td>x=0,y=0,opacity=1 アニメーションを停止, GPU は解除
<tr>
<td><code>KEEP_GPU</code><td>アニメーションを停止、現在値を保持、GPU はキープ
<tr>
<td><code>RESET | KEEP_GPU</code><td>アニメーションを停止, <code>x=0,y=0,opacity=1</code>, GPU はキープ
<tr>
<th rowspan=4>GPU 解除遅延中 (5)<td>-<td>GPU レイヤーを即時に解除
<tr>
<td><code>RESET</code><td><code>x=0,y=0,opacity=1</code>, GPU は解除
<tr>
<td><code>KEEP_GPU</code><td>何もしない
<tr>
<td><code>RESET | KEEP_GPU</code><td><code>x=0,y=0,opacity=1</code> にする
</table>
<h2>要素の座標</h2>
<p><code>animate()</code> の移動量は <code>xnode.x()</code>, <code>xnode.y()</code> に反映されません。
<p><code>translateX</code> <code>translateY</code> が <code>elm.offsetLeft</code>, <code>elm.offsetTop</code> に反映されないためです。(今日知った、、、2015.12.15)
<p>これでは CSS-P 代替モードで動作している場合だと値が一致しないですね、、、
<h2>謝辞</h2>
<p><code>DXImageTransform</code> によるフォールバックは次の記事からコードを取り込ませていただきました。御礼申し上げます。
<div class="links"><a href="http://p2b.jp/2009/12/24/CSS3-Transform-for-IE8" target="_blank">CSS3のtransformをIE8でも使いたい</a>
<a href="http://d.hatena.ne.jp/rti7743/20100904/1283594390" target="_blank">お前の血は何色だ!! > クロスブラウザーな回転</a>
</div>
<p>ちなみに rti7743 氏の次のコメントの問題には遭遇しませんでした。
<blockquote title="rotate.js" cite="http://rtilabs.rti-giken.jp/files/2011_09_16/rotate.zip"><pre class="prettyprint lang-js"><code>//skewの補正(rotate しながらskew すると補正がおかしくなります。 これがわからない)</code></pre></blockquote>
<h2>メモ書き</h2>
<p><code>willChange</code>?
<p><code>transform</code> のサポートレベルはまちまちで、最も動作する px指定に限定
<p>CSS transitions は使わない。<code>transitionend</code> イベントが起こらない環境があるっぽい、、、コードが複雑になるわりに、最後まで動作が安定しなかった、、、izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-49292794636842111902015-12-05T00:00:00.000+09:002015-12-14T22:55:21.881+09:00関西フロントエンドUG Advent Calendar 2015・5日目!<p>男もすなる<a href="http://qiita.com/advent-calendar/2015/kfug" target="_blank">あどべんとかれんだー</a>といふものを、おじさんもしてみむとてするなり。
<p>ということで今年一年のあいだに度々お世話になった“<a href="http://kfug.connpass.com/" target="_blank">関西フロントエンドUG</a>”の記事を書いていたので何か捕捉したり書いたりします。
<p>まずはこちらから…
<div class="links"><a href="http://outcloud.blogspot.jp/2015/05/kansaifront.html">関西フロントエンドUG座談会#1にて『GPUアニメーションとUIデータバインドについて』LTしてきました 2015/05/01</a>
</div>
<p>…早速捕捉することが見つかりました。次の部分間違いです、訂正します。
<blockquote title="GPUレイヤーを効かせたアニメーションを Web アプリケーションにも! > ネイティブアプリケーションのようなアニメーション"><p>ネイティブアプリケーションのようなスムースなアニメーションのためには DHTML 時代の setInterval と css-p ではなく、GPU サポートを効かせた CSS3 Transitions と CSS3 Animations が主役です。 </blockquote>
<h3>CSS3 Transitions と CSS3 Animations は危ないかも</h3>
<div class="box">
<a href="http://1.bp.blogspot.com/-836Ljtr-vIA/VUP3vp3HK_I/AAAAAAAAP54/WRpR1nrqyZk/s1600/pettanR_121123_new_panel_elm_console.png"><img src="http://1.bp.blogspot.com/-836Ljtr-vIA/VUP3vp3HK_I/AAAAAAAAP54/WRpR1nrqyZk/s160/pettanR_121123_new_panel_elm_console.png" /></a>
<p>CSS3 Transitions の transitionend イベントが起こらないケースがあるようです。
<p>CSS3 Transitions はあてにせず js で requestAnimationFrame のコールバックから transform スタイルを書き換えるようにしましょう。
<p>かくいう僕も慌ててオレオレフレームワークの DOM アニメーションを絶賛書き換え中 & 午前様です。
<p>イベントの件がなくとも transitionDuration の指定時間と実際の時間が結構ずれるのでシビアな用途では微妙でした。
<p>いろんなところで言及されていますが、css だけで使える便利なアニメーションは、アニメーションし損なっても全然 OK なところにだけ使っておきます。例えば、この記事のサムネイル画像に埋め込んだクリックで拡大機能とか。
</div>
<p>捕捉ここまで。絶賛年末進行で午前様なので、このくらいでマジ勘弁してください…
<pre class="AA">
゚ 。 ,∧_∧ ゚。
゚ ・(゚´Д`゚ )。
(つ ⊃
ヾ(⌒ノ
` J
</pre>
<h3>備忘メモ</h3>
<p>座談会#1では、新進気鋭のフレームワークの話でさんざ盛り上がったあとに「LTはオレオレフレームワークです!」と言ったら会場が沸きました。ぇへへ。
<p>肝心のLTでは渾身のネタ「オレオレフレームワークを使えば ie4 でも jQuery ライクに書いてライトボックスとか実装できます!」は軽く失笑が漏れるくらいで、おじさんちょっと寂しかったな…
<h4>タッチ & トライ ES6</h4>
<p>この他に7月14日開催の“<a href="http://kfug.connpass.com/event/16279/" target="_blank">タッチ & トライ ES6</a>”は聞き耳を立てているだけで ES6 が分かりそうだったのでノコノコ参加させていただきました。
<blockquote title="タッチ & トライ ES6 > セッション内容"><p>#3 「jQueryとクラス設計でスライダーをつくる」 @usagizmo さん
<p>ES6でクラス構文が扱えるようになり、見通しのよいクラス設計が行えるようになりました。DOMと絡めたES6活用方法の一例をご紹介します。</blockquote>
<p>ライブコーディングをした @usagizmo 氏のおかげでなんとなくどんなものか分かりました。
<p>最後のところで class 構文を使ってもコンテキストを維持するために結局まだ self=this; いるじゃん、という結論に終わってましたが…
<p>この記事のために <a href="https://github.com/usagizmo/es6-slider/commit/0d066d81da188a1dbec1a79f077d216cbb569473" target="_blank">Github を確認すると次のように訂正</a>が。
<blockquote title="GitHub > remove self / data-index · usagizmo/es6-slider@0d066d8">
<pre class="prettyprint lang-js"><code> setPanels() {
<del>- var self = this;
- self.panels = [];
- self.$el.find('.slider-panel').each(function() {
- self.panels.push(new SliderPanel(self, $(this)));</del>
+ this.panels = [];
+ this.$el.find('.slider-panel').each((i, el) => {
+ this.panels.push(new SliderPanel(this, i, $(el)));
});
}
</code></pre>
</blockquote>
<p>アロー関数が全然ハッピーに見えないのは僕の心が曇っているからなのかなぁ…
<p>ではでは主催者・発表者・参加者の皆様、お疲れ様でした。
<p>ということでアドベントカレンダーの5日目でした、お粗末。メリィーホニャララ!
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-85761770811066046182015-11-28T17:51:00.003+09:002022-03-02T12:16:35.307+09:00非デザイナーがチャチャッと野暮ったいブログを修正してみた<h3>はじめに、cssのリファクタリング</h3>
<div class="box">
<a href="//1.bp.blogspot.com/-NZpBxe_KhVA/VlkwshvIaoI/AAAAAAAAQfk/WJzjy1h3rPA/s1600/fix_start.png">
<img src="//1.bp.blogspot.com/-NZpBxe_KhVA/VlkwshvIaoI/AAAAAAAAQfk/WJzjy1h3rPA/s160/fix_start.png"></a>
<p>ここしばらくでブログの css の整理をしました。
<p>若干の変更を加えつつ、主に冗長な指定を修正し使われていない指定を外していきました。
<p>なぜリファクタリングが必要になったかといいますと…
</div>
<ol>
<li>スマートウォッチからフルHD向け指定まで計5パターンも!レイアウトを切り替えている、フルHD > PCとタブレット横向き > タブレット縦向き > スマホ > ウォッチ
<li>印刷用CSS
<li>Blogger ではテンプレートが書き出した id や class をフックしてセレクタを書くので階層が把握し難い...(ここまで言い訳)
<li>Sass 等を利用していない
<li>一つの .css ファイルにズラズラ書いている
<li>スマートウォッチ用では背景色が白から黒になり、文字色、特にリンク色指定の上書きでゴチャゴチャしている
</ol>
<p>相変わらず Sass に手を出していませんが css を分けてコードを見通しやすくできました。(サーバに上げる際はバッチファイルで一本化して minify しています)
<p>満足してしばらく眺めているとイマイチ野暮ったいことに気づきました (;・`д・´)
<h4>一本化バッチファイル</h4>
<pre class="prettyprint lang-bat"><code>@echo off
type nul > all.css
type css\*.css >> all.css
</code></pre>
<h3>どこをどう直せばオサレになるの…?</h3>
<p>昨夜遅く、僕は“タイポグラフィ中心のかっこいい日本語のサイト”を検索しその答えを探しました。
<p>一番最初の画像はその時点でのスクリーンショットになります。
<p>読者の皆さんもどこを直したらいいか?ぜひ考えて教えてください m(_ _)m
<h4>僕の答えは…</h4>
<p>そして昨夜のうちに至った結論は次の2点なります。
<p>施策のたびにスクリーンショットを残しています、効果をご確認アレ。
<h5>見出しの太字を辞める</h5>
<div class="box">
<a href="//4.bp.blogspot.com/-2bs9IgNu07w/VlkwsWKqVGI/AAAAAAAAQfo/KLOM7xfSaSY/s1600/fix_font_weight.png">
<img src="//4.bp.blogspot.com/-2bs9IgNu07w/VlkwsWKqVGI/AAAAAAAAQfo/KLOM7xfSaSY/s160/fix_font_weight.png"></a>
<p>ブログタイトル(<h1>)と記事の見出し(<h2>, <h3>)に太字を使っていたのをノーマルにしました。
<p>見出しの太字については特に考えもなく、見出しなので目立てばよいとデフォルトスタイルのままでした。
<p>この指定が野暮ったい印象の最大の元凶だったと思います。
</div>
<h5>ヘッダーの背景色を辞める</h5>
<div class="box">
<a href="//4.bp.blogspot.com/-qEat9jK8iPo/Vlkwr-4pbJI/AAAAAAAAQfY/px4MmQktnZY/s1600/fix_color.png">
<img src="//4.bp.blogspot.com/-qEat9jK8iPo/Vlkwr-4pbJI/AAAAAAAAQfY/px4MmQktnZY/s160/fix_color.png"></a>
<p>ヘッダーの黒系の背景色(#333333)が重たくのしかかっているように感じたのでメイン部分と同じ白系にしました。(完全な白では眩しいので若干グレーにしています)
<p>替わりにボーダーをひいてアクセントとし、ブログタイトルのフォントサイズも少し小さくしました。
<p>このようにヘッダーをすっきりとさせるデザインはしばしば見かけ憧れていました。そしてこのほどようやく取り入れることができました。
<p>ちなみに本ブログにテーマカラーはなくこの色(#333333)に思い入れがあるわけではありません。
</div>
<h3>フルHD向けスタイルについて</h3>
<div class="box">
<a href="//2.bp.blogspot.com/-9YefW93PDCc/VllOYOKtvuI/AAAAAAAAQgQ/_tAx5s_4Prc/s1600/fhd_old.png">
<img src="//2.bp.blogspot.com/-9YefW93PDCc/VllOYOKtvuI/AAAAAAAAQgQ/_tAx5s_4Prc/s160/fhd_old.png"></a>
<p>最後にフルHD向けスタイルのご紹介です。この手の話をあまり聞かないようなのでどうぞこの機会に見ていってくださいな。
<p>本ブログは自身の Web 開発時に参照するためパソコンからフルHD画面での閲覧が多くなります。
<p>そこで画面サイズが十分に大きい場合にメインコンテンツを2カラムで表示します。
</div>
<div class="note">
<h4>リキッドレイアウト</h4>
<p>似た発想に<a href="http://www.mdn.co.jp/di/articles/2657/?page=16" target="_blank">リキッドレイアウト</a>(2011頃登場?)があります。
<p>大型化するディスプレイスペースを有効利用するため、カラム幅を表示領域に比例させます。
<p>しかしこのレイアウト手法が登場した当時はメインカラムが広くなると一行の文字数が増えてしまい可読性が落ちる、という欠点がありました。
<p>現在では文字サイズをベースとしたメディアクエリと columns 指定によって簡単に可読性が維持されます。
<pre class="prettyprint lang-css"><code>@media screen and (min-width: 96em) {
/* 2カラム */
.Pb {
-webkit-column-count : 2;
-webkit-column-gap : 2.6em;
-moz-column-count : 2;
-moz-column-gap : 2.6em;
column-count : 2;
column-gap : 2.6em;
}
/* 左カラム最初の<h3>のマージンを0にして右カラムに揃える */
.Pb>*:first-child {
margin-top : 0;
}
}
</code></pre>
</div>
<h4>フルHD向けスタイルの調整</h4>
<div class="box">
<a href="//2.bp.blogspot.com/-LO7AVfTOFmA/VllOYEs2O9I/AAAAAAAAQgU/UW4OhUqloX4/s1600/fhd_new.png">
<img src="//2.bp.blogspot.com/-LO7AVfTOFmA/VllOYEs2O9I/AAAAAAAAQgU/UW4OhUqloX4/s160/fhd_new.png"></a>
<p>今回の変更ではフルHD画面では左に寄っている見出し文字を中央寄せしました。
<p>PC(とタブレット横向き)用にはサイドナビとのバランスで見出し文字は左に寄せます。(シングルカラムのタブレット縦向き用では中央寄せします)
<p>一方のフルHD画面では広くなったメインカラムとのバランスで中央寄せが良いと判断しました。
</div>
<h3>最後に</h3>
<h4>スマートウォッチ向けスタイル</h4>
<p>スマートウォッチ向けスタイルにつきましては次の記事にて。
<div class="links"><a href="//outcloud.blogspot.jp/2015/10/smartwatch.html">Web サイトのスマートウォッチ対応はお済みですか?</a>
</div>
<p>ではでは~
<h4>今年初めのブログの様子</h4>
<div class="box">
<a href="//1.bp.blogspot.com/-G9g34TiNyko/Tsj7fzmItvI/AAAAAAAAJfo/whckf6HX5qg/s1600/outOfCloud.png">
<img src="//1.bp.blogspot.com/-G9g34TiNyko/Tsj7fzmItvI/AAAAAAAAJfo/whckf6HX5qg/s160/outOfCloud.png"></a>
<p>今年の前半にブログデザインの修正に着手する前のキャプチャが出てきた。
<p>隔世の感があります…
</div>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-54933112758138121252015-11-23T13:04:00.003+09:002021-07-13T15:05:18.727+09:00Blogger究極軽量化の完成、画像拡大は非lightboxで<div class="note">
<p>『PicaThumbnail』のソースコードは <a target="_blank" href="https://github.com/itozyun/web-doc-base/blob/master/src/js/7_Library/PicaThumnail.js">Github</a> でご覧いただけます。2016.10.5
<p>“クリックでオリジナル画像へのリンク付きサムネイル画像をその場で拡大表示する”ちっちゃなやる気のないライブラリは『PicaThumbnail』と命名しました。2016.1.6
</div>
<h3>ワンコインSIM対応の超軽量Webサイト制作は佳境へ…</h3>
<p><a href="https://outcloud.blogspot.jp/2015/05/bloggerminify.html">半年ほど前に本ブログを超軽量カスタマイズ</a>して以降も少しづつ使い勝手を修正してきました。
<p>また運用ではサムネイルサイズの画像しか貼らないことを基本にしています。
<p>これにより1ページ辺りの転送量は数十KB、ワンコイン SIM のような低速回線でも快適にページを読み込むことができます。
<h4>PageSpeed Insights で分析</h4>
<p>本題の前に Google の PageSpeed Insights で分析しました。
<p>ほとんどのアドバイスは非独自ドメインの Blogger 管理者にはどうにもならないものでしたが一点だけ参考になるものがありました。
<p>アドバイスを受けて js の読み込みに加え css の読み込みも <body> タグの後に持ってきました。
<p>css のダウンロード完了より先にコンテンツが表示されるようになったため、低速回線でのフラストレーションが解消します。
<p><a href="https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery">PageSpeed Insights</a> では、 <html> タグの後に <link> タグを書くように勧めています。しかし blogger のテンプレート編集機能でエラーになるため <body> の後としています。
<blockquote title="Google Developers > PageSpeed Insights > CSS の配信を最適化する の 小さな CSS ファイルのインライン化の例" cite="https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery">
<p>ページが読み込まれた後で元の small.css が読み込まれます。javascript ですべての <style> 要素と <link> 要素をドキュメントに挿入することで、CSS ルールの適用順序は維持されます。</blockquote>
<p>js で <style> と <link> をドキュメントに挿入しなおす、そうです。大丈夫なのでしょうか…
<p>本ブログは css ファイルがひとつなので適用順問題はありません。
<h3>残る課題、lightbox エフェクト</h3>
<div class="box">
<a href="http://3.bp.blogspot.com/-pX4krJAaVqc/TRYSFUocbCI/AAAAAAAAG7o/2jP_ch9Noms/css3lightbox.png" target="_blank">
<img src="//3.bp.blogspot.com/-pX4krJAaVqc/TRYSFUocbCI/AAAAAAAAG7o/2jP_ch9Noms/s200-c/css3lightbox.png" /></a>
<p>この間放置してきた最後の課題に“サムネイル画像からオリジナル画像へ、ページ内で拡大表示したい”というものがあります。
<p>そんなニーズを叶えてくれるもののひとつが lightbox を初めとする lightbox 系ライブラリです。
<p>はじめにサムネイルだけを読み込んで巨大なオリジナル画像のロードはユーザーの操作後にできるので、圧倒的にページの読み込みが速くなります。
<p>一応、Blogger には独自の lightbox が組み込まれていますが <a href="https://outcloud.blogspot.jp/2015/04/bloggerminify.html">Blogger 製の全ての js をコメントアウトしている</a>ため使うことが出来ないのがそもそもの発端になります。
</div>
<div class="note">
<h5>2度目以降の訪問でのオリジナル画像のニーズ</h5>
<p>ところで文章が中心のページでは特に、2度目以降の訪問のオリジナルサイズの画像表示のニーズは減っているはずです。
<p>トップページでも記事の冒頭でもついつい大きな画像を置いてしまいがちですが、大きな画像を見てもらいたいというのはそもそもページ制作者のエゴかもしれませんね。
</div>
<h4>lightbox 系は超軽量ページにとってはややヘビー</h4>
<p>これらのライブラリの中には軽量を謳うものもあり、事実軽量です。しかし転送量で数十KBを達成した本ブログからするとややヘビーです。
<p>オーバーレイやアニメーションをクロスブラウザで確実に行うには、どうしてもそれなりの規模のコードが必要になってしまいます。
<p>このような理由から、自作するにしろ既存のライブラリを使うにしろ決心がつかず課題を放置していました。
<h3>オーバーレイ式をやめその場で拡大する</h3>
<p>先週になって lightbox のようなオーバーレイ方式ではなくその場でカラム一杯に画像を拡大することに思い至りました。
<p>これでしたらオーバーレイに比べて遥かに簡単でコードも僅かです。
<p>また、<strong>コンテンツを覆い隠すこともないので文章中心のページには lightbox より適している</strong>と思います。
<p>既に同様のライブラリはありますが lightbox 系のように適当な名前はついていないようです。
<blockquote title="dogmap.jp > サムネイル画像を拡大表示する 2006年9月1日" cite="http://dogmap.jp/2006/09/01/%E3%82%B5%E3%83%A0%E3%83%8D%E3%82%A4%E3%83%AB%E7%94%BB%E5%83%8F%E3%82%92%E6%8B%A1%E5%A4%A7%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B/">
<p>Live Thumbnail
<p>クリックすると、その場で画像を拡大表示。もう一度クリックすると画像を縮小表示。画像脇のレイアウトが崩れるが、見ていて面白い。</blockquote>
<p><a target="_blank" href="http://dogmap.jp/2006/09/01/%E3%82%B5%E3%83%A0%E3%83%8D%E3%82%A4%E3%83%AB%E7%94%BB%E5%83%8F%E3%82%92%E6%8B%A1%E5%A4%A7%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B/">先の引用記事</a>で言及されている Live Thumbnail はリンク先が消えていて Web アーカイブにも記録が無いため実物を確認することは出来ませんでした。
<h4>動作</h4>
<p>コンパクトとわりきりを主眼に動作を決めて2日ほどでささっと実装しました。
<ol>
<li>window.onload でオリジナル画像へのリンク<a>を見つけ、その直下に<img>だけがいればクリックイベントを追加します
<li>クリックイベントでは img.src をオリジナル画像に置き換えます
<li>画像の表示サイズは親要素によって制限されるため <a> タグの親ブロック要素(div,p,blockquote)のサイズを“計測し転送量の動的最適化”します
<li>画像にテキストが半端に回りこんでレイアウトを崩さないように、オリジナル画像がカラムに対して必ず 100% になる対策
</ol>
<div class="note">
<h5>画像転送量の動的最適化</h5>
<p>Blogger に投稿した画像は Picasa ウェブアルバムに保存されます。
<p>この Picasa ウェブアルバムの提供している大変便利な機能として <a target="_blank" href="http://mattintosh.blog.so-net.ne.jp/picasa_thumbnail_switch">url にパラメータを追加</a>することで変換済画像を取得することが出来ます。
<pre class="prettyprint lang-js"><code>// オリジナル画像
img.src="//3.bp.blogspot.com/(略)/css3lightbox.png";
// 画像の横幅を指定して縮小
img.src="//3.bp.blogspot.com/(略)/w480/css3lightbox.png";
</code></pre>
<p>これによりブラウザウィンドウより大きな画像を無用に読み込むことがありません。
<p>最近では <picture> 新要素で js が切られていても近いことができますね。
</div>
<h4>わりきった機能</h4>
<p>ダウンロード速度を計測して取得する画像サイズをさらに細かく調整する機能がありません。
<ol>
<li>ダウンロード速度を元に devicePixcelRatio を勘案したり無視する仕組みが無い
<li>ブラウザウィンドウのリサイズによって画像がぼやけたときに再取得を行う仕組みが無い
</ol>
<p>ライブラリのサポートがないと大変な機能をわりきりました。
<ol>
<li>画像をピンチやマウスホイールでさらに拡大する・縮小する
<li>CSS Transition をサポートしない、またはサポートが不十分なブラウザでは変形のアニメーションがない
<li>3D transform ではなく width を変化させているため、アニメーションが最適化されていない
<li>コンテンツエリアを越えてブラウザウィンドウまで画像を引き伸ばし表示する機能が無い
<li>画像のロード状況を監視してアニメーションやリサイズしたりエラー表示する仕組みが無い
</ol>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-54141191002010836222015-11-14T15:34:00.004+09:002021-09-11T19:15:40.531+09:00モバイルブラウザオーディオ調査・伝説の最期編<div class="note">
<p>Web Audio の対応形式を HTML Audio インスタンスを生成して canPlay で判定しちゃいけないんだ…(2016/10/05)
<div class="links"><a href="http://qiita.com/gonshi_com/items/e41dbb80f5eb4c176108" target="_blank">WebAudioAPIを使っているはずなのに、マナーモードで音が出る!?</a>
</div>
<blockquote><p>HTML Audio、もしくはHTML Videoをページ内で1つでも使用していた場合、
そのページでは WebAudioAPI の音がマナーモード時にも鳴ってしまう ということが判明しました。</blockquote>
<hr>
<p><del>Windows 8.1 + Firefox 44.0.2 で発生している HTML Audio で再生開始時のシークに失敗する問題の手当てしました。その時の音声ファイルは mp3 CBR でした。2016.3.9</del> 本件は後に、プロジェクトで使っている mp3 の ID3 タグで独自の拡張をしていたためブラウザによってトラブルが起こることが判明する。2020.6.17
<div class="links"><a href="http://git.osdn.jp/view?p=pettanr/clientJs.git;a=blobdiff;f=0.6.x/js/07_audio/02_XHTMLAudio.js;h=ca59f5f1f85d5d2a776cdc2a11e4fde4f9139274;hp=b5abcd2a3597964903d9ef0b69e8469d70544713;hb=bfca1aa94da405643253af65c421f6665d6e6262;hpb=bafa8683f87b2f909d1301fca80684bf9ff221ed" target="_blank">ぺったんR - OSDN > コミット詳細 02_XHTMLAudio.js (diff)</a>
</div>
<hr>
<p>端末スペックによって iOS9 以降でも HTML Audio で再生したいケースがあるため、iOS7 以降について追調査結果を記入しコードも更新しました。2016.1.5
<div class="links"><a href="https://osdn.jp/projects/pettanr/scm/git/clientJs/commits/3c54df5e0d4f20eb32cfd73480cbc9ae8358ebbf#fd-0.6.x/js/07_audio/02_XHTMLAudio.js" target="_blank">ぺったんR - OSDN > コミット詳細 02_XHTMLAudio.js (diff)</a>
</div>
</div>
<p>天駆ける龍の如く怒涛の調査結果を投下します。実際のソースは OSDN でご確認ください。
<div class="links"><a href="https://osdn.jp/projects/pettanr/scm/git/clientJs/tree/master/0.6.x/js/07_audio/" target="_blank">OSDN > ぺったんR > /0.6.x/js/07_audio/</a>
</div>
<h2>はじめに、モバイルブラウザオーディオの闇を晴らす</h2>
<p>この間、個人や企業のリリースしたモバイルオーディオライブラリを読み込み、ブログ記事を拝見し、自腹で中古端末を揃えて動作確認を行ってきました。
<p>とくに Android は OS バージョン毎の差異は元より端末メーカーが独自に加えたシステムの変更によってオーディオの挙動が変わるものまでありました。
<p>音声が鳴らず首をかしげるもの(AOSP4.1.1 HTL21 例外的に load() が必要)から、甚だしきはクラッシュ(Web Audio が有効で意図せずそれを呼び出していた AOSP4.4.2 ARROWS NX F-01F)も経験しました。
<p>賢いオーディオライブラリがないとたまらない、ということがはっきりしました。
<h3>膨大な差異情報こそ大人なソーシャルゲーム開発の肝</h3>
<p>とある企業のリリースしたライブラリは、超メジャーな自社ソーシャルサービスにも使われているといいます。しかし、調査を進めていくとサービスの規模に相応しく多様な端末に対応するには、細かくパラメータを与えて動作を分岐させる必要があります。
<p>そしてこのパラメータ情報を伏せて当たり障りのない部分をリリースしているようにも見えます。
<p>このような膨大な差異情報は大手ソーシャルゲームメーカーと弱小開発会社や個人の間に立ちふさがる絶壁です。
<p>僕は弱小開発会社の従業員で、ささやかなオープンソースプロジェクトに携わる個人ですので、ちゃっちゃと情報を放流します。
<p>はてさて大手さんの集積した情報とどれほど開きがあるやら~、そしてその開きの程を僕が知ることは無いでしょう…
<h3>ライブラリ作者のみなさまへ</h3>
<p>国産ゲームライブラリの作者のみなさん、オーディオ API にモヤモヤしたコメントや空のメソッドを並べてる暇で、pettanR からまるっともってくればいいじゃない?応援してます。
<p>pettanR は元々ドローイング・デザイン系の Web アプリケーションの GUI のためのプロジェクトなのですけど、おかげさまでオーディオ機能が充実しつつあります…ちょうどいいので<a href="http://www.xenophy.com/sencha-blog/8632" target="_blank">sencha touch みたく</a>ゲームも作ってみたい。
<h2>用語の解説</h2>
<h3>ブラウザについて</h3>
<h4>AOSP</h4>
<p>Android 4.4.2 までの Android 標準ブラウザ。2.3 からサポートした HTML Audio は、4.0 以降同時再生数が一音になり、4.2 以降は音声のロードにタッチが必要になった。
<p>メーカーのカスタマイズによって Web Audio が使えるようになっていたり、オーディオの周りの挙動が変化しているものもあって多難。
<h4>Chrome WebView</h4>
<p>Android 4.4.3 からの Android 標準ブラウザ。オーディオ周りの挙動が微妙に変化している。Android 5.0 以降でついに Web Audio をサポートする。
<blockquote title="latest log > Android 4.4 Browser が大幅に機能強化しているようです" cite="http://uupaa.hatenablog.com/entry/2014/04/15/163346">
<p>Android 4.4 (KitKat) からは、 AOSP Stock Browser(通称 Android Browser)のサポートが終了し、代わりに、Chrome WebView (Chromium) をラップしたブラウザが提供されています。
<p>(中略)UserAgent が書き換え可能なため、旧来のAOSPブラウザの UserAgent を偽装した形で配布されているケースがあります。</blockquote>
<h3>HTML Audio で遭遇する不具合たち</h3>
<p>HTML Audio で遭遇する不具合の回避手段について。命名は僕です。
<h4>seekFix</h4>
<p>一部の環境でシーク時に再生が止まる問題を回避する。
<h4>durationFix</h4>
<p>一部の環境で play() 後しばらく経過しないと正しい曲の長さが取れない問題を回避する。
<p>この中には正しい duration が取れないうちに currentTime にセットするとエラーになるものまである。(iOS4, iOS6, Win+Opera12)
<h4>currentTimeFix</h4>
<p>ごく一部の環境で currentTime が更新されず(getterのみ、setter は可能)正しい現在位置が取得できない問題を回避する。Date.now() 的な値を使って再生位置を求める。
<h4>pauseFix</h4>
<p>ごく一部の環境で pause() しても再生が止まらない問題を回避する。
<h4>endedFix</h4>
<p>一部の環境で ended イベント時にシークができなくなる問題を回避する。解決できる環境と発生頻度が改善する程度の環境がある。後者も音声の最後に無音を追加して ended に至らないようにすることで完全に解決できる。
<h4>timeupdateFix</h4>
<p>ごく一部の環境で seeking waiting が発生せず、前回から currentTime が更新されていないのに timeupdate が発生する。直前の currentTime を控えておいて現在のものと比較して timeupdate か seeking か判定する。(Windows Phone 7.8)
<h2>Web Audioのサポートモバイルブラウザ(公証)とその実際</h2>
<p>Web Audio の使える環境ではひとまずはそちらを使うことにします。一般に後発の Web Audio の方が問題が少なく使用可能です。
<p>しかし、まれに Web Audio の腐ったブラウザがリリースされることがあるため HTML Audio にフォールバックする体制を続ける必要があるように思います。(<del>Windows8 + Firefox40以降でしばらくすると Web Audio が止まる、41 でも確認</del>)(逆に Windows8.1 Opera 35.0 は HTML Audio がおかしい。)
<p>しかし、Android2.2 以降にインストールできる Firefox の Web Audio は 2.x では上手く動作しないときがあります。2.x 時代の端末では性能が足りていないようです。
<h3>表1:Web Audioのサポートの開始</h3>
<table>
<thead>
<tr>
<th>ブラウザ<th>対応OS<th>Web Audioのサポート(公称)
<tbody class="c">
<tr>
<th>Safari<th>iOS<td>6.0+
<tr>
<th>標準ブラウザ<th>Android1.0+<td>5+
<tr>
<th>Webkit Opera<th>Android4.0+<td>?
<tr>
<th>Blink Opera<th>Android4.0+<td>15?
<tr>
<th>Firefox<th>Android2.2+<td>23+(25)
<tr>
<th>Chrome<th>Android4.0+<td>28+(29)
<tr>
<th>Opera<th>PC<td>15+(22)
<tr>
<th>Firefox<th>PC<td>23+(25)
<tr>
<th>Chrome<th>PC<td>10+(14)
</table>
<div class="links">
<a href="https://developer.mozilla.org/ja/docs/Web/API/Web_Audio_API">https://developer.mozilla.org/ja/docs/Web/API/Web_Audio_API</a>
<a href="https://en.wikipedia.org/wiki/HTML5_Audio">https://en.wikipedia.org/wiki/HTML5_Audio</a>
</div>
<h3>表2:Web Audioのサポートの実際</h3>
<table>
<thead>
<tr>
<th>OS(端末)<th>ブラウザ<th>Web Audio
<tbody class="c">
<tr>
<th>iOS7 (iPad 2G)<td>Safari<td>△#1
<tr>
<th>iOS8 (iPad mini 3G)<td>Safari<td>○
<tr>
<th>Android2.3.5 (SBM101SH)<td>Frefox 31.0<td>○?#2
<tr>
<th>Android3.1 (L-06C)<td>Frefox -<td>?
<tr>
<th rowspan="3">Android4.1.1 (Dospara)<td>Chrome 44.0<td>○
<tr>
<td>Opera 32.0<td>○
<tr>
<td>Frefox 41.0<td>○
<tr>
</table>
<ol>
<li>はじめて再生する音声の音が割れる、リロードすると解消する
<li>Android2.x に対しても最新の機能を提供する Mozilla 偉い!でもたまに不安定なときがあるような…
</ol>
<p>1.の音割れについては解決策が phina.js で紹介されていました。ハイレベルな開発陣が集まっている凄いプロジェクトです(汗
<div class="links"><a href="https://github.com/phi-jp/phina.js/issues/129" target="_blank">iOS 9 で WebAudio 使うと音が割れる? ・ Issue #129 ・ phi-jp/phina.js ・ GitHub</a>
<a href="http://lilting.ch/3323.html" target="_blank">【間に合わせ】iOS9系でのWebAudioの音割れ対処について</a></div>
<h2>オーディオ API 性能表</h2>
<h3>表3:HTML Audio の性能</h3>
<table>
<thead>
<tr>
<th>OS(端末)<th>ブラウザ<th>スコア<th>タッチ不要<th>2音以上再生<th>裏に回った検出<th>最後に無音不要<th>ボリューム<th>メモ
<tbody class="c">
<tr>
<th>iOS4.2.1 (iPod 2G)<td>Safari<td>2<td>x<td>x<td>◎<td>○#11<td>?<td>-
<tr>
<th>iOS6.1.5 (iPod 4G)<td>Safari<td>1<td>x<td>x<td>◎<td>x#12<td>?<td>-
<tr>
<th rowspan="3">Android2.3.5 (SBM101SH)<td>AOSP<td>3<td>◎<td>◎#2<td>x<td>○#6<td>?<td>#5
<tr>
<td>Opera12.10<td>3<td>◎<td>◎#2<td>x<td>◎<td>?<td>#3 #4
<tr>
<td>Firefox31.0<td>3<td>◎<td>x<td>◎<td>◎<td>?<td>#13 #16
<tr>
<th>Android3.1 (L-06C)<td>AOSP<td>3<td>◎<td>◎<td>x<td>△#7<td>?<td>-
<tr>
<th>Android4.0.4 (ST15i)<td>AOSP<td>2<td>◎<td>x<td>x<td>?<td>?<td>-
<tr>
<th>Android4.1.1 (Dospara)<td>AOSP<td>2<td>◎<td>x<td>x<td>○#8<td>?<td>#10
<tr>
<th rowspan="2">Android4.2.2 (F-10D)<td>AOSP<td>2<td>x<td>x<td>x<td>○#8<td>?<td>#10
<tr>
<td>Chrome28<td>2<td>x<td>x<td>◎<td>○#9<td>?<td>-
<tr>
<th>Android4.4.4<td>Chrome WebView<td>1<td>x<td>x<td>x<td>○#9<td>?<td>-
<tr>
<th>WP7.8 (IS12)<td>IEM9<td>1<td>x<td>x<td>x<td>◎<td>x#14<td>#15
<tr>
<th>WP8.1 (lumia925)<td>IEM11<td>3<td>x<td>○#1<td>◎<td>◎<td>?<td>-
</table>
<ol>
<li>2音以上の場合、シークが不安定かもしれない
<li>4音以上は現実的ではないかも
<li>audio.currentTime が更新され無いため Date.now() 等を使って現在時間を決定する
<li>可変ビットレートな音声ファイルでシークが不安定になる。mp3 CBR を使用する
<li>シークが若干(0.5秒程度)遅れる
<li>ended に達すると音が鳴らなくなる -> <del>リロードで解決</del> audio.loop を使って解決
<li>ended に達すると音が鳴らなくなる -> リロードで解決、但し 2.x 4.x より遅延が大きく1秒弱程度ある
<li>ended に達した際にしばしば currentTime が変更できなくなる -> <del>リロードで解決、また audio.play() を currentTime の更新前に実施しておくと頻度が低下する</del> audio.loop を使って解決
<li>ended に達した際に audio.play() が必要
<li>ogg のシークが不安定、mp3 m4a は安定する
<li>ended に達すると音が鳴らなくなる、audio.play() で解決、ended イベントは発しないので timeupdate イベント時に currentTime で判断する
<li>ended に達すると音が鳴らなくなる、audio.play() で頻度が改善、ended イベントは発しないので timeupdate イベント時に currentTime で判断する
<li>Web Audio をサポートしているが、ブラウザが不安定になるため使用しない
<li>audio.volume に 1 以外を設定すると音が聞こえない
<li>最後の曲が再生できない、シークが不安定
<li>シーク時に再生がしばしば止まる問題、audio.play() で解決、Windows8.1 + Gecko40 でも発生。
</ol>
<h2>タッチイベントで audio.play() するタイミング</h2>
<p>タッチイベントのコールバック内で audio.load() または audio.play() を実施する。
<p>このタッチを行う適切なタイミングは各環境で異なる。ついでにいうと audio.src = src 以降に発生するイベントも各環境で異なる。
<p>次の表のタッチトリガーイベント列のイベントをきっかけとして(ボタン等で)ユーザーにタッチを促すのが良かった。
<h3>表4:タッチ要求のトリガーイベントと audio.duration の変化</h3>
<table>
<thead>
<tr>
<th>環境<th>タッチトリガーイベント<th>durationの変化<th>durationFix
<tbody class="c">
<tr>
<th>Chrome18 (HTL21)<td>stalled<td>0 -> 100s -> n #1<td>要
<tr>
<th>Chrome28 (F-10D)<td>stalled<td>0 -> 100s -> n #2<td>要
<tr>
<th>Chrome32 (ドスパラ)<td>canplaythrough #3<td>0 -> n<td>要
<tr>
<th>Chrome36 (ドスパラ)<td>canplaythrough<td>0 -> n<td>-#4
<tr>
<th>AOSP4.2.2 (F-10D)<td>canplaythrough<td>NaN -> n<td>-
<tr>
<th>Chrome WebView 4.4.4<td>canplaythrough<td>NaN -> 0 -> n<td>要
<tr>
<th>iOS4.2.1<td>suspend<td>NaN -> n<td>要
<tr>
<th>iOS6.1.5<td>suspend<td>NaN -> n<td>要
<tr>
<th>iOS7.1(シミュレータ)<td>suspend<td>0 -> n<td>要
<tr>
<th>iOS8.1(シミュレータ)<td>loadedmetadata<td>-<td>-
<tr>
<th>WP7.8 IEM9<td>canplay<td>NaN -> n<td>要
<tr>
<th>WP8.1 IE11<td>canplaythrough<td>-<td>-
<tr>
<th>XP Opera12.17<td>タッチ不要<td>NaN -> Infinity -> NaN -> n<td>要
</table>
<ol>
<li>しばらくの間 100s というダミーの値が duration に入っている、その間はシークができない。
<li>Chrome 18 から 28 の間のいつから 100s のときもシークができるのか?は不明。
<li>Chrome 32以降 stalled が発生しなくなる、31 では 100s が出現しない。
<li>Chrome 36以降 durationFix が不要になる、45 でもタッチは必要。
</ol>
<h2>インスタンス生成~準備完了までのステップ</h2>
<p>おおまかにいってタッチによる再生の有無に durationFix の有無をかけた計4パターンが必要です。
<h3>表5:タッチと durationFix のマトリクス</h3>
<table class="c">
<thead>
<tr>
<th><th>durationFix が必要<th>durationFix が不要
<tbody>
<tr>
<th>タッチが必要<td>1<td>2
<tr>
<th>タッチが不要<td>3<td>4
</table>
<p>計4種類の生成~準備プロセスはそれぞれ次の段階を通過する。
<h3>表6:タッチトリガーイベント発生から再開始生完了まで</h3>
<table>
<thead>
<tr>
<th>経路<th>1.タッチトリガーイベント発生(表4参照)<th>2.タッチイベント発生<th>3.duration取得<th>4.Ready イベント発生
<tbody class="c">
<tr>
<th>1<td>タッチ要求<td>play()<td>currentTimeにセット<td>timeupdate
<tr>
<th>2<td>タッチ要求<td>play()<td>→<td>timeupdate
<tr>
<th>3<td>play()<td>→<td>currentTimeにセット<td>timeupdate
<tr>
<th>4<td>→<td>→<td>→<td>canplaythrough等
</table>
<h3>1. タッチ:要, durationFix:要な環境</h3>
<p>例: iOS6, iOS4, WP7.8, Chrome WebView 4.4.4
<ol>
<li>audio.src のセット
<li>タッチトリガーイベント発生(表4参照)を待って再生開始ボタン等の表示
<li>タッチイベント内で audio.play() する、ここでは currentTime のセットは行えない
<li>duration が取れたら currentTime に触ることができる、currentTime をセットする
<li>timeupdate イベントを待って再生開始完了
</ol>
<h3>2. タッチが必要な環境</h3>
<p>例: AOSP 4.2
<ol>
<li>audio.src のセット
<li>タッチトリガーイベント発生(表4参照)を待って再生開始ボタン等の表示
<li>タッチイベント内で audio.play() と currentTime のセットを行う
<li>timeupdate イベントを待って再生開始完了
</ol>
<h3>3. durationFix が必要な環境</h3>
<p>例: WindowsXP + Opera12
<ol>
<li>audio.src のセット
<li>canplaythrough 等を待って audio.play() する、ここでは currentTime のセットは行えない
<li>duration が取れたら currentTime に触ることができる、currentTime をセットする
<li>timeupdate イベントを待って再生開始完了
</ol>
<h3>4. もっとも制限の少ない環境</h3>
<p>例: PCブラウザ
<ol>
<li>audio.src のセット
<li>canplaythrough 等を待って audio.play() と currentTime のセットを行う、再生開始完了
</ol>
<h2>Audio インスタンスを触るポイント</h2>
<h3>生成~ロード~play()</h3>
<ol>
<li>audio = new Audio( url ) または new HTMLAudioElement( url ); Safari3.2- では document.createElement( 'audio' );
<li>audio.preload = 'auto'; autoplay が優先されるけど一応
<blockquote title="MDN > 開発者向けのWeb技術 > HTML > HTML 要素リファレンス > audio 要素 " cite="https://developer.mozilla.org/ja/docs/Web/HTML/Element/audio">
<p>autoplay 属性はこの属性(preload)より優先します。これは、音声を自動的に再生したい場合は明らかにブラウザが音声をダウンロードしなければならないためです。
<p>仕様書では autoplay 属性と preload 属性を両方とも指定することを認めています。()内は僕
</blockquote>
<li>audio.autoplay = true; Android 4.0 - 4.1 で必要
<li>audio.src = src;
<li>audio.load() 省略できる環境が多い。必要な環境:AOSP4.1.1 HTL21
<li>audio.play()
</ol>
<h3>シーク</h3>
<ol>
<li>timeupdate イベント内でないとシークできない iOS
<li>play() 前にセットするとエラーになる
<li>シークの際に play() も読んでおかないと再生が停止する
</ol>
<h3>破棄</h3>
<p>audio.src = '';audio.load() を実施すると安定する?
<h2>emded イベント時にシークが無効になるブラウザと対策</h2>
<p>解決法の無いものもあるので音声の最後に無音部分を追加して回避する。
<p>また同じ問題は Android5.0 + Web Audio でも起きるかもしれない。
<h3>AOSP2.x, AOSP4.x</h3>
<p>audio.loop = true を設定する。
<p>但し ended イベントが起きなくなるため、timeupdate の際に currentTime が 0 付近に戻るのを検出して ended を代替する。
<h3>AOSP3.1</h3>
<p>リロードを実施する、次の再生まで遅延が大きく1秒弱程度待つことになる
<pre class="prettyprint lang-js"><code>audio.src = '';
audio.src = src;
</code></pre>
<h3>Chrome WebView 4.4.4</h3>
<p>ended イベントの際のシークには audio.play() を呼んでおく。
<h3>iOS4</h3>
<p>ended に達すると音が鳴らなくなる。(ended イベントは発しないので timeupdate イベント時に audio.currentTime === audio.duration で判断する)
<p>ended イベントの際のシークには audio.play() で解決する。
<p>シークの際に常に audio.play() を行う。
<p>ちなみに シークの際の audio.play() は iOS8.3 でも必要な模様。
<h3>iOS6, iOS7.1</h3>
<p>ended に達すると音が鳴らなくなる。(ended イベントは発しないので timeupdate イベント時に audio.currentTime === audio.duration で判断する)
<p>解決せず…audio.play() で頻度が改善する模様。
<p>ちなみに iOS7.1 iPhone 4s(シュミレータ)では、そのまま1分弱待つと再生を再開する。iOS8.1 iPhone 4s(シュミレータ)では遭遇していない。
<p>iOS7.1 は pause -> ended となる場合と seeked -> pause -> progress -> stalled となる時がある。この時は duration が 0 になっている。
<h2>その他の問題</h2>
<h3>iOS8.3でtimeupdateのcurrentTimeのズレ</h3>
<p>play(シーク)後に seeking と seekend に挟まれて発生する timeupdate イベントの際の currentTime の値が正しくない。
<p>意図せず再生開始値より低い値になるのでループした等を誤検出しないように注意する。
<h2>参考</h2>
<h3>Web Audio</h3>
<h4><a target="_blank" href="http://qiita.com/sou/items/5688d4e7d3a37b4e2ff1">Qiita > Mobile Safari, Chrome for Android での Web Audio API 覚え書き</a></h4>
<blockquote><p>iOS 7.1 で decodeAudioData に処理が入った瞬間にスクリーンを長押しする(スクロールを繰り返す)と decoeAudioData の処理がキャンセルされることがある</blockquote>
<h4><a target="_blank" href="">因果日記+ >【javascript】モバイル向けブラウザでも音を鳴らしたい【WebAudio】</a></h4>
<blockquote>
<p>■Android標準ブラウザではWebAudiAPIは使えない<br>
→使える機種もあるので厄介。(SH-02Eとか)
<ol>
<li>使い終わったインスタンスはload()しておくとやや安定
<li>(iOS)srcの差し替えはタッチイベントの中でやらなくていいので、(略)、GMの切り替えはsrcを代入しなおせばいい
</ol>
<p>おっぱいは正義。</blockquote>
<h4><a target="_blank" href="https://html5experts.jp/miyuki-baba/3766/">HTML5Experts.jp > ネットワークのないところでも使え、サクサク動く。これからのWebゲームアプリが備えるべき機能とは「HTML5 Conference 2013」</a></h4>
<blockquote><p>・Chrome for Android31 までは HE-AAC が低速再生される不具合があった<br>・ver32 で fix 済み(【セッション映像】8:19)</blockquote>
<h3>HTML Audio</h3>
<h4><a target="_blank" href="http://himaxoff.blog111.fc2.com/blog-entry-97.html">無職のプログラミング > HTML5 Audio オブジェクトを JavaScript で制御する方法</a></h4>
<blockquote>
<p>引数なしで new Audio() とすると、Operaでエラーになるそうなので注意。
<p>Firefox3.6では再生終了後のpause()は無視されて、最初からの再生処理が実行されてしまう
<p>Firefox3.6では一度も play() していない状態で currentTime = 0 を実行するとエラーになる。
<p>GoogleChrome7 では currentTime = 0 直後に play() すると、pause()した位置前後の音が混ざることがある。</blockquote>
<h4><a target="_blank" href="http://kentablog.cluscore.com/2011/05/ie9-html5-audio.html">ケンタテクブロ > IE9 の HTML5 Audio について</a></h4>
<blockquote><p>IE9の動作
<ol>
<li>JavaScriptでAudioオブジェクトを作ることができないので、Audioタグを使う必要がある
<li>(略)「clientaccesspolicy.xml」か「crossdomain.xml」が必要となる。
</ol></blockquote>
<h4><a target="_blank" href="http://bbs.wankuma.com/index.cgi?mode=al2&namber=64886&KLOG=109">C# と VB.NET の質問掲示板 > IE9でHTML5 autio タグが無効になる</a></h4>
<blockquote><p>IE9でも動かす場合は、JavaScriptでAudioオブジェクトを作るのではなく、
HTML内にAudioタグを作成して、そのAudioに対してJavaScriptで操作
<p>IEのバージョン9.0.8112.16421では、Audioオブジェクトのnewも対応してました。</blockquote>
<h4><a target="_blank" href="http://wiki.bit-hive.com/tomizoo/pg/HTML5%20audio%A5%BF%A5%B0%20%A5%D6%A5%E9%A5%A6%A5%B6%B4%D6%A4%CE%B0%E3%A4%A4">とみぞーノート > HTML5 audioタグ ブラウザ間の違い</a></h4>
<blockquote><p>HTML5で使えるaudioタグをJavaScriptから扱う場合の、ブラウザ間での動作の違いのまとめ。とりあえず、autoplay,loopプロパティについて。
<p>FireFox3.6, Android 2.3.6については、src変更後、load()を呼び出さないと切り替わらなかった。</blockquote>
<h4><a target="_blank" href="http://lab.sonicmoov.com/smartphone/android/android-htmlaudio-error-event/">AndroidのHTML Audioでerrorイベントが送出されないので、Androidのソースコードを調べてみた</a></h4>
<blockquote><p>Android 4.3までのブラウザで HTML Audio の error イベントが送出されない問題は、(少なくとも今回調べたAndroid 4.2では)特定端末の問題ではなくAndroid自体の問題であることがわかりました。また、error イベントの代替となる方法を見つけることもできました。</blockquote>
<h2>おわりに、モバイルオーディオは終わらない</h2>
<p>DHTML の枯れてしまったことに比してモバイルブラウザのメディア周りはまだまだ悩みが尽きることはありません。
<p>そのような背景もあり記事はとくに断り無く最新の調査結果を加筆修正していきます。Enjoy!
<h2>反響</h2>
<ol>
<li><a target="_blank" href="https://lilting.ch/3323.html">【間に合わせ】iOS9系でのWebAudioの音割れ対処について</a>
<li><a target="_blank" href="https://github.com/ayamada/vnctst-audio4#link">vnctst-audio4</a> <q>モバイルブラウザ回りについてのまとめ記事。とても参考になる。「ぺったんR」というソフト内のライブラリらしい</q>
<li><a target="_blank" href="http://makoto1212.hatenablog.com/">苦しんで覚えるHtml5Audioの世界</a>
</ol>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-32927769478613833192015-10-03T23:54:00.001+09:002021-07-13T15:04:03.305+09:00Webサイトのスマートウォッチ対応はお済みですか?<p>「えぇ、まだですって!それはいけません!」
<p>スマートウォッチからの Web アクセスがうなぎのぼりだそうです。一方で天然ものうなぎは減っています。また 2020 年にはスマートウォッチからのアクセスが Web 利用の過半数に、手脂のついたカマボコ板はオワコンだそうですよ。かくいう私もようやく最近になって <a href="/2015/09/open-sesame-lumia925simtray.html">ガラケーからスマートフォンに切り替えた</a>というのに…世の中の進歩が速すぎます。
<p>「で …するの?しないの?」
<p>ということで急遽このブログにもスマートウォッチ対応を実施することになりました、とさ。
<h2>さくっとスマートウォッチ対応</h2>
<div class="box">
<a href="http://2.bp.blogspot.com/-Ty3x8MnBOHQ/Vg_p8kPnouI/AAAAAAAAQXA/Mk-29piFHh8/s1600/blogger-image-204123424.jpg">
<img src="//2.bp.blogspot.com/-Ty3x8MnBOHQ/Vg_p8kPnouI/AAAAAAAAQXA/Mk-29piFHh8/s120-c/blogger-image-204123424.jpg"></a>
<p>当ブログではすでにスマートフォン対応を終え、これらの端末に対してはシングルカラムで表示するようにしています。
<p>この状態からさらに横 <del>320px</del> 240px 以下の画面サイズに対しては左右の余白を削って 0px にしてしまいます。コンテンツ領域が増えてスマートウォッチの限られた画面を活かすことができますね。
</div>
<pre class="prettyprint lang-css"><code>@media handheld, screen and (max-width: 240px) {
/* for smart watch */
}
</code></pre>
<h3>借景テクニックを使って表示エリアを確保しつつ余白も設ける</h3>
<p>しかし余白がゼロだと読者に窮屈な印象を与えてしまっていけません。Web デザイン・タイポグラフィの肝は余白のコントロールです。
<p>そこでメインカラムの背景を黒にし文字色を白とします。ビジュアルバンドか個人ホームページ時代のページというわけじゃありません。なんということでしょう!この配色だとディスプレイの黒縁を余白として借用することができるのです。これはわが国の伝統的造園法である<strong>“借景”を髣髴とさせるスゴ技だぁ!</strong>
<p>早速スマートウォッチを取り出し…残念ながら持っていないのでスマートウォッチに見立てた Xperia mini を取り出して確認。狙い通りパーフェクトです。これで 2020 年のおもてなし体勢は完璧です!本当にありがとうございました!
<p>「ところで、貴 HP のEインク・ディスプレイ対応はお済ですか? …おゃ!?」izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-38596466363597745512015-10-02T23:48:00.002+09:002015-10-03T22:06:01.634+09:00大探検!HTML5オーディオスプライト・後編<p><a href="http://outcloud.blogspot.jp/2015/04/audiosprite1.html">前編</a>・<a href="http://outcloud.blogspot.jp/2015/05/audiosprite2.html">中編</a>に続いて後編をお届けします。
<p>メディア API のパワーをあらゆる端末で引き出して、メーカーの思惑の斜め上を行きましょう!そうしよう!
<h3>Jukebox.js</h3>
<a href="https://github.com/martensms/martens.ms/tree/master/raw">martensms/martensms-website zynga-jukebox.zip</a>
<blockquote cite="http://qiita.com/nakajmg/items/7be91626113bfc10846a" title="スマホで音声再生をスムーズに行うためにオーディオスプライトを作成/使用する > Zynga Jukebox">
<p>開発が止まっていてメンテされない(zyngaのgithubからも消え去ってる)のが残念ですが、かなり強力なライブラリです。
<p>ダウンロードは作者のgithubリポジトリからできます。
<p>Zynga Jukeboxは機能的にかなりスマホ向けになっていて、オーディオスプライトの再生に特化しています。</blockquote>
<p>オーディオスプライトライブラリとしては珍しく Flash によるフォールバックを用意しています。
<p>このために最も多くのブラウザのサポートを謳っています。
<h4>Android1.6標準ブラウザをサポート!?</h4>
<p>Jukebox.js のコード中に次のコメントを見つけました。
<p>てっきり <a title="Android 3.x/2.x 用の Flash Player バージョン" href="https://helpx.adobe.com/jp/flash-player/kb/228683.html">Android2.x 以降かと</a>思いましたが、1.6 用の Flash Player ってリリースされたのでしょうか?
<pre class="prettyprint lang-js"><code>/*
* Flash Audio Support
* Hint: All Android devices support Flash, even Android 1.6 ones
*/
</code></pre>
<p>Android1.6 用 Flash Player を必死で探してしまいましたよ、勘弁してください…</p>
<h5>Android1.6 + Opera12 は new Audio でクラッシュ</h5>
<p>ついでに触れますと 1.6 用サードパーティー製ブラウザでは唯一 Opera12 が提供されています。そしてモバイル Opera12 は HTMLAudio をサポートしている、とされています。
<p>しかし Audio.src に url を指定したタイミングで Opera が問答無用でクラッシュします。HTMLAudioElement が存在しても Android1.6 以下の Opera に対しては new Audio(url) してはいけません。
<p>そうそう new Audio('') ではクラッシュしないので canPlayType() できちゃいます、要注意です。
<h3>その他のマイナーブラウザ</h3>
<h4>Windows Phone 7.5, IE Mobile 9</h4>
<p>HTML5 に対応する初の モバイル用 IE です。そのメディアAPIの実装具合はごれほどのものでしょう?
<ol>
<li>iOS 等と同じくタッチイベント内で play() する
<li>ロードがかなり進行しても duration が NaN のまま、play() してしばらくすると正しい duration が取れる
<li>currentTime がしばらく 0 のままで、duration が取れてから更新可能になる(みたい)
<li>currentTime が更新されないままでも timeupdate が発火する、つまり waiting や seeking イベントが出ない、直前の currentTime と比較して waiting や seeking イベントを補う
<li>loadeddata, canplaythrough がない
<li>currentTime が数値として扱えていない? +0 したら正しく動いた
</ol>
<p>HTML5 対応を謳いつつも見えにくいところで個性が炸裂しています。独自路線のマイクロソフトはまだまだ健在でした。
<p>本当にありがとうございまいた。
<h3>メディアAPIはバッドノウハウの宝庫</h3>
<p>PC 向けブラウザは概ね共通のコードで動きますが、中には不可解な挙動をするものもありました。
<p>残念なモバイルブラウザも含めこれらの多くは正常に機能するようにパッチが可能なことも分かりました。
<p>またはメディアファイルを工夫すること、音声の最後に無音を追加する、mp3 VBR でなく mp3 CBR にする、などで正常に動作するものもありました。
<h4>初期の Android はカンブリア大爆発のようにユニークな端末が多いような…</h4>
<p>モバイルの世界では OS の更新は早々に止まってしまいます。
<p>続いてアプリもインストールが難しくなると端末は魅力を大きく損なってしまいます。
<p>しかし、最新ブラウザが提供されなくなって以降も Web 開発者の努力によって端末が活躍し続けることが可能なのです。
<p>とっとこ新しい端末を売りつけたいメーカーの斜め上をいって、Web 技術者の矜持を見せつけましょう。enjoy!
<h4>ここしばらくの話</h4>
<p>音声単体では意図した動作をするのですが、アプリケーション内で画面描画と組み合わさると、音声が止まる、、、
<p>そうでなくとも記事を書き出したときには知らなかった差異とパッチ法が、ここ2日でガッツリやったところアレヨアレヨと出てきまして…
<p>そこで発見した情報は全て盛り込めていませんが、一旦記事を放流します。
<p>今現に困っている方は、pettanR のソースをご確認ください。または僕の twitter まで、ではでは。
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-78563194879936901152015-09-22T16:12:00.000+09:002015-10-11T20:56:49.567+09:00Lumia925でSIMアダプタを残してSIMトレイが開かない時の非常手段<div class="box">
<a href="http://4.bp.blogspot.com/-DtEr-ZFYCvU/VgDouN37saI/AAAAAAAAQVw/PjWIf5xa6CY/s1600/blogger-image--1293736694.jpg"
><img src="http://4.bp.blogspot.com/-DtEr-ZFYCvU/VgDouN37saI/AAAAAAAAQVw/PjWIf5xa6CY/s120-c/blogger-image--1293736694.jpg" /></a>
<a href="http://1.bp.blogspot.com/-By4-erfTnKA/VgDow-LPD2I/AAAAAAAAQV4/gosw1qMlTp8/s1600/blogger-image-761608715.jpg">
<img src="http://1.bp.blogspot.com/-By4-erfTnKA/VgDow-LPD2I/AAAAAAAAQV4/gosw1qMlTp8/s120-c/blogger-image-761608715.jpg" /></a>
<p>通常サイズからナノ、そしてマイクロへ―、SIM の尋常ならざる小型化を横目にみつつ、いつか痛い目を見る予感があったような、なかったような…
<p>これは Nokia Lumia 925 で SIM トレイが引き出せなくなり Wi-Fi 専用機化する危機から生還した男の記録である。
</div>
<h3>久々のうっかりさん</h3>
<p>メインの携帯電話をいよいよスマートフォンにすべくこの8月に Lumia 925 を購入しました。国内ではユーザー数の少ない Windows Phone 8 端末です。
<p><a href="http://outcloud.blogspot.jp/2015/06/nifty.html">届いたばかりの NifMo の SIM</a> を Micro → Nano な SIM 変換アダプタを使って Lumia 925 に抜き挿ししていたところ、うっかり変換アダプタだけを残して SIM トレイを閉めてしまいました。
<p>これ以降は 1mm 程引き出したところでトレイが止まってしまう、という事態に陥りました。
<p>変換アダプタの空洞に SIM を読み取る端子が引っかかっている、のが原因です。
<p>無理やり引き抜くと端子を破壊してしまい Wi-Fi 専用機化してしまうことは想像に難くありません。
<h3>一般的な解決策は通用せず酷い気分で眠りにつく</h3>
<p>慌ててググりプラ板を使う一般的な解決策を試したのですが、Lumia 925 の SIM スロット周りは意地悪く配置された障害のせいでプラ板を挿し込むことが難しいと分かってきました。
<p>夜中を回っていたのでこれ以上深追いはせず酷い気分で眠りにつきました。
<p>とりあえず寝る、昨夜の僕が唯一した正しい判断でした。
<h4>一般的な解決策とLumia925のトラブル情報</h4>
<p>変換アダプタにまつわるトラブルの一般的な解決策としては、薄いプラ板を挿し込んで端子を押し上げつつ引抜く、というものがあります。
<p>しかし Lumia 925 はトレイのカバーとロック用の突起が障害となりとてもプラ板を挿し込みにくい形状です。
<p>ネット上では、案の定、端子を破壊してしまった、という情報があります。この情報には事前に触れていたのですが、気付いた時にはこのザマですよ、、、</p>
<blockquote cite="http://mmt-blog.jugem.jp/?eid=1143" title="NOKIA LUMIA925 SIMスロット修理 | MOUMANTAIオンラインショップ">
<p>NOKIA LUMIA925 SIMスロット修理のご依頼。端子が破損しておりカードを認識しませんので交換をいたします。
</blockquote>
<p>こちらのショップには修理の様子が紹介されていますが、おゃぉゃ、どのような状況で故障したかは書かれていませんねぇ、、、
<h3>すがすがしい晩夏の朝、しかしベッドの横にはトレイの開かないLumia925が…</h3>
<p>昨夜のことはすべて悪夢であったらよかったのですが、残念な Lumia 925 は厳然としてそこにいました。
<h4>金属製のトレイのカバーを外す</h4>
<div class="box">
<a href="http://1.bp.blogspot.com/-muIzrtXyUTE/VgDos4QOJQI/AAAAAAAAQVo/U8kg6H26RYA/s1200/blogger-image--1589508341.jpg"><img src="http://1.bp.blogspot.com/-muIzrtXyUTE/VgDos4QOJQI/AAAAAAAAQVo/U8kg6H26RYA/s120-c/blogger-image--1589508341.jpg" /></a>
<p>かくしてスッキリした頭で対策を練ると、トレイとトレイのカバーが分離することに気づきました。十分な睡眠の効果が早速に発揮されました。
<p>トレイとトレイカバーは両面テープのようなもので接着されていました。次の写真のような細工用のカッターを刺し込んで剥がします。
</div>
<h4>トレイの2箇所をカット</h4>
<div class="box">
<a href="http://2.bp.blogspot.com/-GsJqzG4q-6w/VgD04Y_d8KI/AAAAAAAAQWI/GNdhZxdIyxQ/s1600/blogger-image--1813384459.jpg"><img src="http://2.bp.blogspot.com/-GsJqzG4q-6w/VgD04Y_d8KI/AAAAAAAAQWI/GNdhZxdIyxQ/s120-c/blogger-image--1813384459.jpg" /></a>
<p>この状態でさらに観察と思案を重ねトレイの2箇所を思い切ってカッターで切り落とすことにします。
<p>写真の図の赤でマークした部分です。
</div>
<ol>
<li>最初の障害であるトレイのカバーは薄いため切断は難しくありません
<li>ロック用の突起は厚い上に奥にあるため作業しづらいです、根気よく慎重にカッターを小刻みにあてて切断します
</ol>
<p>この処置でプラ板を真っ直ぐに挿入できるようになりました。睡眠によって冷静な思考と大胆な行動ができるようになっています。
<h4>プラ版の加工、そして祈り・・・</h4>
<div class="box">
<a href="http://1.bp.blogspot.com/-pmXpSFyJXhw/VgD2v_PpbzI/AAAAAAAAQWU/IVoUpU-G-kQ/s1600/blogger-image-2029373471.jpg"><img src="http://1.bp.blogspot.com/-pmXpSFyJXhw/VgD2v_PpbzI/AAAAAAAAQWU/IVoUpU-G-kQ/s120-c/blogger-image-2029373471.jpg" /></a>
<p>続いて何度かプラ板を出し入れしましたが、あとほんの1,2ミリを挿し込むことができず、端子を押し上げることができないようです。
<p>このプラ版は梱包用の透明ケースから切り出したもので、ここまで挿し込めば端子を解除できるだろう、というおおよその位置にテープを貼ってあります。
<p>プラ板の形状を図のように加工した上で祈る気持ちで挿入しました。
</div>
<ol>
<li>やすりなどでプラ版の断面を斜めに加工する
<li>プラ版の先を僅かに楕円形にして、3つの端子に接触するタイミングをずらす
</ol>
<p>形状を工夫するに飽きたらず祈りを上乗せするあたり、十分な睡眠のあとに死角はありません。
<p>昨夜のうっかりさんが嘘のようで、無事 Lumia 925 はその性能を取り戻しましたとさ♪
<h3>さいごに</h3>
<p>文章にしてみればたったこれだけのことなのですが、最初は“もう無理ゲー、つらたん”とでも言いたい絶望的気分からの出発でした。
<p>Nokia の開発陣に心の中で何度も罵声を浴びせつつ、ネット検索で正常な Lumia 925 のトレイの画像を見ては内部の状況を推理する、困難な歩みの数時間でした。(これにはとても助けられました!)
<p>これに懲りた僕は SIM 変換アダプタを削って端子が引っかかりにくくしてみました。しかしあてが外れるのが怖く、効果の程は試していません。
<p>さて、本記事がどなたかのご参考になりましたら幸いです。それではまたいずこかのクラウド番外地でお会いしましょう、グッドラック!izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-68899096062375620002015-06-21T21:09:00.000+09:002015-06-21T23:39:01.510+09:00スクリプトを無視するWebブラウザ<p>「ジブン、ただのハイパーテキストのビュワーっすよ、リッチ・ウェブ・アプリケーション とかぁ、マジしんないっス、フヒヒ」
<p>たまに Web ブラウザがそんなことを言うときがあります、というお話です。
<h3>負荷が上がるとスクリプトの実行を無視する?</h3>
<p>Web ブラウザはまれに script を無視しているような挙動をする時があります。そんなときはエラーもなくただ処理が消滅します。ブラウザを変えると正しく動くためそれと分かります。
<p>古めの PC ブラウザや、最近のものでもモバイルブラウザで遭遇しました。
<p>DOM オブジェクトの大量生成など富豪な書き方をしているときに遭遇しやすいようです。また Flash と js の接続時(ExternalInterface)も注意しなくてはいけないポイントです。
<p>これは<strong>システムの負荷が上がるとスクリプトの実行を無視する</strong>、ということのように視えます。
<p>しかし、それを明示している文章は寡聞にして見ません。
<p>仮にこの推測に立つなら現象には、端末のスペック、同時に実行している他のアプリケーション、ブラウザの他のタブのコンテンツまで影響してくることになります。
<p>これらのほとんどは Web プログラマの手の届かないことでお手上げにも思えます。
<p>しかし現実に動いている同様な製品が存在する以上、そうも言ってられないわけで…
<h3>予防的コーディングの実施</h3>
<p>取りうる手としては、予防的な書き方を常に実施していくことが考えられます。
<ol>
<li>分割可能なところで処理を中断しタイマーで再開する
<li>富豪的な書き方を避け、オブジェクトの再利用を行う、GC を過信するような書き方は NG
<li>DOM 操作等の重そうな処理では重点的に無駄な操作がないか、チェックする
<li>いざ症状に遭遇したときに疑うべきところを最小にするために重そうな追加機能を辞める、または最後に回す
</ol>
<p>さて、これらのことは、Web 開発に不慣れなメンバーには難しいかも知れません…
<p>チームに js ギークがいればいいですが、そうでないなら…泣きましょう…
<h4>1.分割可能なところで処理を中断しタイマーで再開する</h4>
<p>予防的な書き方の最初で触れたタイマーの利用についてです。
<p>高負荷(っぽい)なブラウザ API の処理から戻った際に、続けてすぐにアプリケーション層の処理を走らせることはせずに、タイマーにスケジュールだけをします。そして一瞬置いて実行します。
<p>なぜこのような書き方をするか、というと…
<p>js エンジンの内部では関数スタック・アクティベーションオブジェクト・ガベージが積みあがっていきます。
<p>一度のコールバックで全てを終えようと無理をせず、これらの一時データをリフレッシュが済んでからタイマーで再開します。
<h5>レガシーなタイマー関数が大活躍する</h5>
<p>このような時に使われるのが、setTimeout や setInterval といったタイマー関数です。随分古くからある関数です。
<p>このとおり単に時計として以外にも様々な状況で利用されるべき重要な関数です。特性について習熟しておきます。
<p>また、タイマー関数は(タイマー関数に限らず)使い辛い、書き辛いことこの上ないです。必ずラップして API を整え、さっとタイマーを挟める状態にします。
<h5>補足1</h5>
<p>この積み上がりがどれだけシステムリソースを圧迫するか?外からはなかなか視えない上、よしんば高度な開発ツールで見えたとしても、それはあくまでその環境での話になります。所以、とりあえず予防的に書けるところは書いておけ、となります。
<a href="https://web.archive.org/web/20120215004242/http://d.hatena.ne.jp/nopnop/20080323/1206274563" target="_blank">nopnopの日記 > フラウザごとのスタックの深さ</a>
<h5>補足2</h5>
<p>ただし、ユーザーのクリックイベント時にしか実行できないモバイルの音声再生や、(こちらはあまり使われませんが)別ウィンドウのポップアップなど、分割できないものもあります。(別ウィンドウはユーザーのインタラクションに際して行われないとポップアップブロックが働いてしまう)
<h4>ぺったんR フレームワークでは</h4>
<p>ぺったんR には setTimeout をラップした <a href="http://pettanr.osdn.jp/jsdoc/X.Timer.html" target="_blank">X.Timer</a> があります。
<p>また <a href="http://pettanr.osdn.jp/jsdoc/EventDispatcher.html" target="_blank">X.EventDispatcher.prototype.asyncDispatch</a> というイベントディスパッチをタイマー付きで行うメソッドは便利で多用しています。マジお勧め!
<h3>最後に</h3>
<p>ブラウザの気持ちになって考える、とは度々言われることです。
<p>フロントエンジニアを目指す人はブラウザのレンダリングエンジンや js エンジンに関する情報も都度に摂取して、ブラウザの気持ちになれるようにしましょう。
<p>僕は Flex 案件の際に、既存の html コンテンツを再利用できるように TextFeild.htmlText を拡張したことがあります。泣きながら。知ってる人はご存知の通り、Flash の元もとの html 機能は酷くプアなものです…
<p>その際に、Web ブラウザの気持ちがすこ~し分かった気がします。ではでは。
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-47877706043338666712015-06-16T11:46:00.000+09:002017-01-08T16:47:37.684+09:00ぺったんRフレームワークのコールバックのお作法<div class="note">
<p>pettanR ライブラリへの修正をコミットしました。(2016-10-21)
<div class="links"><a target="_blank" ref="nofollow" href="https://osdn.net/projects/pettanr/scm/git/clientJs/commits/66ccef8a1fdd3994dd3c75dcfede668ea55f1d2e">Version 0.6.218, Fix the bug of X.Net & X.Audio. </a></div>
<hr>
<p>MyLoader のサンプルを動かしたところバグとタイプミスを発見したため修正いたしました。また pettanR ライブラリ本体にも修正が入りましたが現時点で OSDN には未コミットです…(2016-10-19)
</div>
<p>本記事はほぼぺったんR フレームワークに固有の内容になります。一般的な事柄ではありません、悪しからず。
<p>だらだら書きましたが、まとめると次の表です。
<table>
<thead>
<tr><th>コールバック<td>第2引数<td>第3引数<td>第4引数
<tbody>
<tr><td rowspan="2">this+関数<td>object<td>function<td>
<tr><td colspan="3"><pre class="prettyprint lang-js"><code>btn.listen('click', this, callback); //登録
callback.call(this);//発火
</code></pre>
<tr><td rowspan="2">this+関数+付加引数<td>object<td>function<td>array
<tr><td colspan="3"><pre class="prettyprint lang-js"><code>btn.listen('click', this, callback, ['user', 1]);//登録
callback.apply(this, ['user', 1]);//発火
</code></pre>
<tr><td rowspan="2">this<td>object<td><td>
<tr><td colspan="3"><pre class="prettyprint lang-js"><code>btn.listen('click', this);//登録
this.handleEvent();//発火
</code></pre>
<tr><td rowspan="2">this+付加引数<td>object<td>array<td>
<tr><td colspan="3"><pre class="prettyprint lang-js"><code>btn.listen('click', this, ['user', 1]);//登録
this.handleEvent.apply(this, ['user', 1]);//発火
</code></pre>
<tr><td rowspan="2">-<td>-<td><td>
<tr><td colspan="3"><pre class="prettyprint lang-js"><code>btn.listen('click');//登録
btn.handleEvent();//発火
</code></pre>
<tr><td rowspan="2">付加引数<br><td>array<td><td>
<tr><td colspan="3"><pre class="prettyprint lang-js"><code>btn.listen('click', callback, ['user', 1]);//登録
btn.handleEvent.apply(btn, ['user', 1]);//発火
</code></pre>
<tr><td rowspan="2">関数<td>function<td><td>
<tr><td colspan="3"><pre class="prettyprint lang-js"><code>btn.listen('click', callback);//登録
callback.call(btn);//発火
</code></pre>
<tr><td rowspan="2">関数+付加引数<td>function<td>array<td>
<tr><td colspan="3"><pre class="prettyprint lang-js"><code>btn.listen('click', callback, ['user', 1]);//登録
callback.apply(btn, ['user', 1]);//発火
</code></pre>
</table>
<h3>this のコントロール手段提供を全ての非同期 API に徹底</h3>
<p>一般に js 開発ではメモリ効率の良い prototype 継承を多用します。その際に重要になるのがコールバック時の this コンテキストのコントロールです。
<p>ぺったんR フレームワークではコールバックの登録の際に this コンテキストを指定できる仕組みを全ての非同期 API に徹底しています。
<p>僕はこの特徴がぺったんR フレームワーク上で作られたコードに<strong>独特なアトモスフィア</strong>を与えているように思いますが…
<p>さて、今回はそんなぺったんR フレームワークのコールバック登録作法のご紹介です。
<h3>非同期動作の最中にインスタンスを破棄してみる</h3>
<p>本題の前に<a href="http://outcloud.blogspot.jp/2015/06/callback-hell.html">以前にご紹介したサンプル</a>ですが、実は一か所で手抜きをしています。
<p>ぺったんR フレームワークの X.Class で作られたクラスは kill メソッドを持ちます。(this.kill() の働きは名前の通りインスタンスの破棄です)
<p>この kill が一連の非同期動作の途中で呼ばれた場合の処理を追加します。処理を入れない場合…
<ol>
<li>通信はキャンセルされず無用なアクセスが発生してしまいます
<li>その上、通信(X.Net)へのイベントリスナは解除されていないため破棄された MyLoader インスタンスにコールバックまでされてしまいます
<li>また、フェイズが“タイマーで1秒後にアラートする”に移っていた場合はタイマーの解除も必要です
</ol>
<h4>破棄(kill)時の通信・タイマー解放処理を追加した非同期サンプル</h4>
<pre class="prettyprint lang-js"><code>var MyLoader = X.EventDispatcher.inherits('MyLoader', X.Class.NONE, {
textLoader : null,
jsonLoader : null,
result : '',
timerID : 0,
Constructor : function(url) {
this.textLoader = X.Net({
xhr : url
}).listen([X.Event.SUCCESS, X.Event.ERROR], this);
this.listen(X.Event.KILL_INSTANCE);
},
handleEvent : function(e) {
switch( e.type ) {
case X.Event.SUCCESS :
if (e.target === this.textLoader) {
this.jsonLoader = X.Net({
xhr : e.response,
dataType : 'json'
}).listen([X.Event.SUCCESS, X.Event.ERROR], this);
delete this.textLoader;
} else {
this.result = e.response;
this.timerID = X.Timer.once(1000, this, this.doAlert);
delete this.jsonLoader;
};
break;
case X.Event.ERROR :
if (e.target === this.textLoader) {
this.result = 'get text error';
delete this.textLoader;
} else {
this.result = 'get json error';
delete this.jsonLoader;
};
this.timerID = X.Timer.once(1000, this, this.doAlert);
break;
case X.Event.KILL_INSTANCE :
this.textLoader && this.textLoader.kill();
this.jsonLoader && this.jsonLoader.kill();
this.timerID && X.Timer.remove(this.timerID);
break;
};
},
doAlert : function() {
alert(this.result);
}
});
</code></pre>
<p>う~~ん、これは開発用のオプションでいいと思うけど、イベントリスナの登録先を覚えておいて kill 時に解除を忘れたら警告する仕組みが欲しいかも…ちなみに自身に登録されたイベントリスナは kill 時に全て破棄されます。
<pre class="prettyprint lang-js"><code>var loader = new MyLoader('hoge.txt');
// 以下は他のインスタンス等によって通信をキャンセルする場合
loader.kill();
loader = null;
</code></pre>
<h3>コールバックの登録の仕方</h3>
<p>ようやく本題に入ります。
<h4>1. this コンテキスト+関数</h4>
<pre class="prettyprint lang-js"><code>dispatcher.listen( 'ready', this, this.onready );
</code></pre>
<p>これを解除するには、登録時と同じ組み合わせを渡します。
<pre class="prettyprint lang-js"><code>dispatcher.unlisten( 'ready', this, this.onready );
</code></pre>
<p>kill 時にも全てのリスナが解除されます。
<pre class="prettyprint lang-js"><code>dispatcher.kill();
</code></pre>
<h5>コールバックの戻り値</h5>
<p>コールバックの戻り値で解除することもできます。
<pre class="prettyprint lang-js"><code>dispatcher.listen( 'ready', this, onReady );
function onReady(){
return X.Callback.UN_LISTEN; // コールバックの戻り値で解除
}
</code></pre>
<p>コールバックの戻り値にはこの他に、X.Callback.STOP_PROPAGATION や X.Callback.PREVENT_DEFAULT などがあります。これらの実態は数値(ビットフラグ)で |(論理和) で並べて複数指定することもできます。
<pre class="prettyprint lang-js"><code>function onReady(e){
return X.Callback.UN_LISTEN | X.Callback.STOP_PROPAGATION | X.Callback.PREVENT_DEFAULT;
}
</code></pre>
<h5>listenOnce</h5>
<p>一度呼んだら解除するように登録の時点で指定することもできます。
<pre class="prettyprint lang-js"><code>dispatcher.listenOnce( 'ready', this, this.onready );
</code></pre>
<h4>2. this コンテキスト+関数+追加引数</h4>
<p>続いてコールバックに追加の引数(配列)を指定してみます。コールバックのデフォルトの引数の後に追加される点に注意が必要です。
<p>このパターンの解除は面倒です。あらかじめ配列を控えて置いて解除時に併せて指定する必要があります。
配列を与えなかった場合一致するリスナが見つからず解除に失敗します。(dispatcher.kill() で解除するケースでは配列を控える必要はありません。)
<pre class="prettyprint lang-js"><code>var supp = [ 'init', 3 ];
dispatcher.listen( 'ready', this, onReady, supp );
function onReady(e, supp1, supp2){
//
}
dispatcher.unlisten( 'ready', this, onReady, supp );
</code></pre>
<p>そうそう、配列ライクなオブジェクトである arguments を誤って与えないように注意しましょう。
<p>大関技として、配列の内容を変えればリスナ登録後にも引数の内容を変えることができます。とはいえ、コードが追いずらくなるので辞めておきましょう。
<p>いずれにせよ配列を控えるのが面倒なうえに、this コンテキストにアクセスできれば十分なケースが多いため、このパターンはフレームワーク内でもあまり使われません。
<h4>3. EventListenr オブジェクト</h4>
<p>イベントリスナとしてオブジェクトだけを登録することができます。その際は handleEvent という名前のメソッドにコールバックします。
<p>handleEvent メソッドの存在確認はイベントディスパッチ時に行うため次の場合でも動作します。
<ol>
<li>登録時点では関数が無い > X.Type.isObject(o) === true であれば登録される。
<li>途中で handleEvent = null 等になった > コールバックは呼ばれない、呼ばれなくても listenOnce の場合解除される。
<li>handleEvent が別の関数で上書きされた > 上書きされた関数が呼ばれる
</ol>
<pre class="prettyprint lang-js"><code>dispatcher.listen( 'ready', this, this.handleEvent );
// 上と下は等価です
dispatcher.listen( 'ready', this );
this.handleEvent = function(e){
switch(e.type){
case 'ready' :
//
break;
case 'click' :
case 'complete' :
};
};
</code></pre>
<p>先のような書き方をすると、一つの関数にイベント毎の処理をズラズラと並べることができます。
<h4>4. 複数のイベントを一挙に登録</h4>
<p>また、同一のイベントリスナで複数のイベントタイプを監視したい場合、イベントタイプを配列で渡すこともできます。
<pre class="prettyprint lang-js"><code>dispatcher.listen( 'ready', this )
.listen( 'click', this )
.listen( 'complete', this );
// 上と下は等価です
dispatcher.listen( ['ready', 'click', 'complete'], this );
// 解除も配列で
dispatcher.unlisten( ['ready', 'click', 'complete'], this );
</code></pre>
<h4>5. 省略形 その1</h4>
<p>this を与えなかった場合、コールバックの this はイベントディスパッチャー自身になります。この決まりごとにより次の省略した書き方ができます。
<pre class="prettyprint lang-js"><code>dispatcher.listen( 'ready', dispatcher, onReady );
// 上と下は等価です
dispatcher.listen( 'ready', onReady );
function onReady(e){
// this === dispatcher
};
dispatcher.unlisten( 'ready', onReady ); // 解除
</code></pre>
<p>解除の際も同様に省略できます。
<h4>6. 省略形 その2</h4>
<p>handleEvent をコールバックにする場合も同様に省略が可能です。とてもあっさりしてしまって初見では何が何やら…
<pre class="prettyprint lang-js"><code>dispatcher.listen( 'ready', dispatcher );
// 上と下は等価です
dispatcher.listen( 'ready' );
dispatcher.handleEvent = function(e){
// this === dispatcher
};
dispatcher.unlisten( 'ready' ); // 解除
</code></pre>
<p>この書き方が板についてしまったらあなたも立派なぺったんR 使いです、ファイトォ~!
<h4>this コンテキスト+メソッド名</h4>
<p>この他にメソッド(function)ではなくメソッド名(string)を指定する方法も用意しています。handleEvent と同じく途中で関数が書き換わった場合に新しい関数でコールバックします。
<p>prototype を置き換えていくようなハイパー動的なコーディングスタイルを想定してみましたが… Closure Compiler の ADVANCED_OPTIMIZATIONS と相性が悪そうだしでこの方向は追求しません…
<h4>イベントリスナは2重に登録できない</h4>
<p>同じ引数でイベントリスナを登録することはできません。2回目以降の登録は無視されます。
<pre class="prettyprint lang-js"><code>dispatcher.listen( 'ready', this, onReady )
.listen( 'ready', this, onReady ); // 無視
</code></pre>
<p>また存在しないイベントリスナの解除は単に無視されます。エラー等はありません。
<h3>EventDispatcher(EventTarget)の細かな動作</h3>
<p>ところで、EventDispatcher の働きといえばイベントリスナをハッシュや配列に蓄えて dispatch されたらコールバックするだけのものです。
<p>こういうと語るほどのこともないと思われるかもしれません。しかしいざ実装してみるとオヤ?と思う点が多々発生します。
<p>ということで EventDispatcher の細かな動作についてみていきますと…
<h4>イベントディスパッチ(発送)中のイベントの登録</h4>
<p>ぺったんR では次の挙動を踏襲しています。また浮上フェーズがないため(jQuery でも行っている IE イベントモデルとの互換性のため)ディスパッチ中に追加されたリスナが現在のイベントディスパッチ中に発火することはありません。</p>
<a href="https://developer.mozilla.org/ja/docs/Web/API/EventTarget.addEventListener" target="_blank">
MDN > 開発者向けのWeb技術 > Web API インターフェイス > EventTarget > EventTarget.addEventListener イベント発送中のリスナーの追加</a>
<blockquote title="MDN > 開発者向けのWeb技術 > Web API インターフェイス > EventTarget > EventTarget.addEventListener イベント発送中のリスナーの追加" cite="https://developer.mozilla.org/ja/docs/Web/API/EventTarget.addEventListener">
<p>EventListener がイベント処理中に EventTarget に追加された場合、それが現在のアクションによって実行されることはありませんが、浮上フェーズのように、後の段階のイベントフローで実行されるかもしれません。
</blockquote>
<p>ディスパッチ中に登録されたイベントリスナは一旦登録待ちリスト控えて全てのディスパッチ後に改めて登録しています。ディスパッチ内でディスパッチされることもあるので、現在の EventDispatcher の全てのディスパッチを待ちます…ホラ、結構ややこしいでしょう?</p>
<h4>イベントディスパッチ(発送)中のイベントの解除</h4>
<p>ぺったんR では次の挙動を踏襲しています。</p>
<a href="https://developer.mozilla.org/ja/docs/Web/API/EventTarget.removeEventListener" target="_blank">
MDN > 開発者向けのWeb技術 > Web API インターフェイス > EventTarget > EventTarget.removeEventListener 注記</a>
<blockquote title="MDN > 開発者向けのWeb技術 > Web API インターフェイス > EventTarget > EventTarget.removeEventListener 注記" cite="https://developer.mozilla.org/ja/docs/Web/API/EventTarget.removeEventListener">
<p>イベントリスナーが イベントを処理中であるイベントターゲットから削除された場合、現在のアクションによってそのイベントリスナーが実行されることはありません。
<p>イベントリスナーは、決して削除された後に実行されることはありません。
<p>イベントターゲット上にある現在のどのイベントリスナーも指定していない引数付きの removeEventListener は、何の効果もありません。
</blockquote>
<p>ディスパッチ中に解除されたイベントリスナは解除待ちリストに控えてそのディスパッチ中には呼ばれないようにします。リスナ配列の index がずれると嫌なので、現在の EventDispatcher の全てのディスパッチを待って実際の解除が行われます。
<p>さて、イベントディスパッチ中に同じイベントリスナで登録と解除が行われたらどうすればよいでしょう?解除待ちリストと登録待ちリストを夫々操作して…結構ややこしいです。一度解除されたイベントリスナが解除待ちリストから抜けたことでやっぱり呼ばれるケースも発生します。</p>
<p>頭が少し湯立ちました…
<h3>東西 EventDispatcher 比べ</h3>
<p>以上を踏まえてここでぺったんR 以外の EventDispatcher を見てみましょう。
<p>今回取り上げますは CreateJS というライブラリの一部になります。ブラウザゲームを作るためのライブラリとして紹介されているのを目にします。<q title="イナヅマTVログ > gskinner先生のCreateJS、もうすぐ" cite="http://www.inazumatv.com/contents/archives/6715">ActionScript界の神、gskinner先生</q>が開発されているそうです。
<h4>CreateJS の EventDispatcher.js</h4>
<p>僅かに400行と少し、コメントがきっちり・たっぷり書かれているのでコードはさらにその半分になります。
<p>ちゃっちゃっと眺めることのできるコード量です。
<p>一方のぺったんR は800行、コメントは少な目…EventDispatcher 相当の機能に加えクロスブラウザで EventTarget オブジェクトを触るメソッドもあるとはいえでかいです…
<blockquote title="EaselJS > EventDispatcher.js" cite="http://www.createjs.com/docs/easeljs/files/createjs_events_EventDispatcher.js.html"><pre class="prettyprint lang-js"><code>// p._dispatchEvent = function(eventObj, eventPhase) {
// 略
arr = arr.slice(); // to avoid issues with items being removed or added during the dispatch
for (var i=0; i<l && !eventObj.immediatePropagationStopped; i++) {
var o = arr[i];
if (o.handleEvent) { o.handleEvent(eventObj); }
else { o(eventObj); }
if (eventObj.removed) {
this.off(eventObj.type, o, eventPhase==1);
eventObj.removed = false;
}
}
</code></pre></blockquote>
<p>さて、イベント発火中のイベントリスナ解除の扱いを見てみますと…解除したイベントもコールバックしています。
<p>速度が身上のゲームライブラリですので些細なことは気にしない感じでしょうか…
<p>10人10EventDispatcher,,, ではでは~☆ミ
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-31279114488492588802015-06-13T05:45:00.002+09:002022-03-09T10:43:43.409+09:00location.hashにとある日本語が入るとFirefoxだけデコード失敗<h3>location.hashにエンコードした日本語をセット→Firefoxだけデコードに失敗</h3>
<p>いまさらながら <a href="http://d.hatena.ne.jp/shinichitomita/20071006/1191645993" target="_blank">location.hash と iframe を使ったクロスドメイン通信</a>を書いてみました。
<p>その際に Firefox で日本語の扱いに嵌った記録と解決法です。ちなみにバージョンは 38.0.5, Windows 版です、一応。
<h4>問題</h4>
<p>エラーの起きていた部分を抜き出します。
<pre class="prettyprint lang-js"><code>location.hash = encodeURIComponent('日本語。');
decodeURIComponent(location.hash);
</code></pre>
<p>先のコードが Firefox だけデコードに失敗します。その際のエラーメッセージは <samp>URIError: malformed URI sequence</samp> でした。
<p>もちろん、<code>decodeURIComponent('#日本語。')</code> とした場合は失敗しません。
<p>詳しく見ていくと "。" でエラーが起きていました。(できましたらもうちょっと親切なエラーメッセージをお願いします…)
<p>Firefox では、location.hash に日本語文字列等のエンコード済のものを渡しても勝手にデコードされます。
<p>しかし "。" については "%u3002" にエスケープされます。この他には "、" がエスケープされました。
<pre class="prettyprint lang-js"><code>location.hash = encodeURIComponent('日本語。');
// location.hash
"#日本語%u3002"</code></pre>
<h4>解決</h4>
<p>Gecko だけ unescape すると意図した動作を得られました。そこで現在はデコード部分を以下のようにしています。
<pre class="prettyprint lang-js"><code>X.UA[ 'Gecko' ] ? unescape( str ) : decodeURIComponent( str );</code></pre>
<p>location.hash と日本語については kQuery の ofk 氏が<a href="http://d.hatena.ne.jp/ofk/20090915/1252993893" target="_blank">素晴らしくまとめて</a>くださっています。
<p>今回はこの情報に Firefox だけ unescape を追加してね、ということでした。ではでは。
<blockquote title="?D of K > ブラウザごとのlocation.hashの挙動のまとめ > まとめ" cite="http://d.hatena.ne.jp/ofk/20090915/1252993893"><ul>
<li>アンカーを付けたリンクを生成する場合は必ずencodeURIComponentでencodeして付与する。
<li>location.hashに代入する場合も必ずencodeURIComponentでencodeして代入する。
<li>以上が守られたlocation.hashの値を取得する場合はFirefox以外はdecodeURIComponentでdecodeする。</ul>
</blockquote>
<p>解決してみればたったコレだけのことなのですが、他をいろいろと疑って大変でした…
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-71305705691446988812015-06-07T07:04:00.000+09:002020-05-30T09:39:09.473+09:00携帯電話とデータ通信の見直し中、Niftyにいこうかな<h3>母、スマホになる</h3>
<p>母がいつの間にか au に移り、初のスマートフォンを持ったようです。
<p>今までは Softbank 同士無料テレホタイムに電話の用事を済ませていたのですが、いつの間にかそれが出来なくなっていました。
<p>次の帰省の折に母の端末に無料通話アプリを入れるとして、コレを機に自身の契約も見直してみます。(電話帳情報を要求してくるウザイアプリを入れるのもなんですね…)
<p>思えば2000年頃にシティフォンが初めて手にした携帯電話だったように思います。その後は J-Phone > ボーダフォン > Softbank ときて孫さんのお世話に…(ちなみにネットも 平成電電倒産 > Yahoo ADSL 平成電電から移籍プランで孫さんのお世話に…)
<p>大手キャリアを使い続けた場合、キャリアを頻繁に乗り換えて特典に浴しているユーザーの割を喰うことになるのでいい加減潮時です。
<h3>現在の契約は…</h3>
<p>現在の固定費は、softbank で月々1,236円(基本料+メールオプション) これにワンコインデータ通信 SIM が469円(250Kbit/秒)で、合わせて1,705円(税抜)になります。
<table>
<thead>
<th>通信事業者
<th>項目
<th>料金
<th>備考
<tbody>
<tr>
<th rowspan="3">softbank
<td>携帯電話基本料
<td>934円
<td>ホワイトプラン、2年縛り無、通話料は数百円程度
<tr>
<td>メールオプション
<td>300円
<td>これだけでもとっとと辞めようかな…
<tr>
<td>ユニバーサル利用料
<td>2円
<td>
<tr>
<th rowspan="2">DTI
<td>データ通信
<td>467円
<td>ServersMan SIM LTE 250Kbit/秒、今はほとんど使っていない…
<tr>
<td>ユニバーサル利用料
<td>2円
<td>
<tfoot>
<tr>
<th>計
<td>
<td>1,705円(税抜)
<td>
</table>
<p>これまでは携帯電話と Android 端末の2台を持ち歩いていました。しかし、携帯電話とデータ通信端末が別々だと充電などの扱いが面倒で…
<p>またこのほかにもう一枚、中速で転送量の縛りのないデータ通信を契約しています。これは今回の見直しからは外れます。
<h3>ワンコイン SIM の感想:ServersMan SIM LTE</h3>
<p>値段に比して、通信速度は妥当で特に不満は無かったです。契約中に<a href="http://www.dti.co.jp/release/140416.html" target="_blank">価格据え置きで速度が上がった(150Kbit/秒 → 250Kbit/秒)</a>のも嬉しかったです。
<p>Web ブラウジングに使うこともよくあったけど納得できました。
<p>また、一般のデータ通信 SIM で速度制限がかかると鬼のように低速になります。そんな時にワンコイン SIM に切り替えるとそのスピードに感激します。
<p>特にスマホ対応のされたサイトでは妥当な速度で読み込まれることが多く感心しました。自分の作るページもそうでありたい、と勉強になります。
<p>Web 業界の方は低速 SIM をひとつ契約して普段使いするといいですよ。また端末スペックを遅めにしたりブラウザもデフォルトのを使うといいですね。
<h3>元々が安いと MNP 転出料と新規契約料がネックに…</h3>
<p>新しい契約先は<a href="http://www.yodobashi.com/ec/pd/100000001002645735/" target="_blank">月々1,180円で音声通話に加えデータ通信が200Kbit/秒の Nifty(ヨドバシカメラ限定)</a> が候補です。MNP を条件にしました。
<p>もともとの通信料が安いので、縛り違約料(今回は0円)、Softbank の MNP 転出料(3,240円)、Nifty 契約料(3,240円)、の合わせて6,480円が大きく効いてきますね…
<p>6,480円を月々の差額525円(税抜)で割ると13ヶ月で元が取れる計算になります。(¥1,705 - ¥1,180 = ¥525)
<div class="box">
<a href="//2.bp.blogspot.com/-w9u6wCO2yDI/VXLkApj5ifI/AAAAAAAAQKc/z84xOzXVKlg/s1600/l_sk_nifty_01.jpg"><img src="//2.bp.blogspot.com/-w9u6wCO2yDI/VXLkApj5ifI/AAAAAAAAQKc/z84xOzXVKlg/s100/l_sk_nifty_01.jpg" /></a>
<p>ちなみに Nifty は<a href="http://www.itmedia.co.jp/news/articles/1106/06/news012.html" target="_blank">25周年記念サイトのパソコン通信「NIFTY-Serve」の再現サービス</a>が面白くてアカウントを作りました。いい印象があります。
</div>
<blockquote title="懐かしくて泣ける?新鮮?「NIFTY-Serve」復活を見つめる目" cite="http://www.itmedia.co.jp/news/articles/1106/06/news012.html"><p>記念サイトの目玉は、往年の「NIFTY-Serve」を体験できるコーナーだ。1996年ごろのNIFTY-Serveがもとになっており、当時のフォーラムにGOすることもできる。</blockquote>
<h4>次の次の移動を考えると…</h4>
<p>仮に Nifty より微妙に使い勝手がよく100円程度安いプランが出てきた場合、プラン変更の元を取るまでに単純計算で数年を要すことになります。便利・廉価になるのはいいとして段々腰が重くなります。
<p>さて、どうしたものか…
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-91599385737084988632015-06-06T18:15:00.001+09:002021-09-11T19:15:40.532+09:00俺式、js開発で陥りがちなコールバック地獄にならない法<div class="note">
<p>MyLoader のサンプルに誤りがあったため修正しました。(2016/10/21)
</div>
<p>ダラダラ書いていますが要約すると…
<ol>
<li>非同期な API をイベントターゲット風に加工する
<li>イベントリスナの登録の際にコールバックの this コンテキストを指定する仕組みを用意する
<li>シングルトンでは js の欠点が露呈しにくい。クラス(風)の中で非同期処理を書いて検討する
</ol>
<h3>コールバック地獄怖い</h3>
<p>コールバック地獄には一度痛い目に遭ったことがあります…あとを引き取ったコードにはコールバックの深い深い入れ子が…。
<p>その時に <a href="http://qiita.com/yuku_t/items/1b8ce6bba133a7eaeb23">jQuery.Deferred</a> なども見てみましたが、クロージャを完全に排除できていなかったため関心を持てませんでした。
<h4>jQuery.Deferred での非同期な関数の加工</h4>
<p>mixpanel という web 解析サービスにデータを投げその完了を受け取る。これを jQuery.Deferred のスタイルで加工する<a href="http://qiita.com/yuku_t/items/1b8ce6bba133a7eaeb23">例</a>。
<blockquote title="結局jQuery.Deferredの何が嬉しいのか分からない、という人向けの小話 > Deferredインタフェースを備えたmixpanel関数" cite="http://qiita.com/yuku_t/items/1b8ce6bba133a7eaeb23"><pre class="prettyprint lang-js"><code>var dfdMixpanel = function (event, props) {
var dfd = jQuery.Deferred();
mixpanel.track(event, props, function () {
dfd.resolve();
});
return dfd.promise();
};</code></pre></blockquote>
<p>jQuery.Deferred にしろその他のライブラリにしろ、結局のところ非同期な処理を加工して使用しています。僕は<strong>おなじ加工するのならイベントターゲット風に加工してしまう</strong>ことを好みます。
<p>イベントターゲット風に加工した上で、イベントリスナの登録の際にコールバックの this コンテキストを指定する仕組みを用意する。これが僕のコールバック地獄の回避法になります。
<p>複雑な処理も綺麗に書けて、精神衛生上とてもよろしい開発ができています。
<div class="note">
<h5>先駆例</h5>
<p>先の仕組みの先駆例として、有名どころでは Closure Library があります。
<p><a href="http://www.dotapon.sakura.ne.jp/blog/?p=581" target="_blank">次に引用した記事</a>が Closure Library での this コンテキスト付きイベントリスナ登録について分かりやすく解説してくださいっています。
<p>このような先駆例がありながら、未だに多くのコードで醜いクロージャの入れ子が見られるのはどうしてなんでしょう…
<p>僕がクロージャの入れ子を追えるのは、バリバリ開発していて脳汁が出ているときだけです。
<blockquote title="DOTAPON Blog > jQuery→Closure Libraryの移行に便利な、機能対応リスト – Tiny iOSの事例" cite="http://www.dotapon.sakura.ne.jp/blog/?p=581">
<p>イベントをスコープ付きで割り当てる
<pre class="prettyprint lang-js"><code>// jQuery
$(elem).on('click', $.proxy(func, scope));
// Closure Library
goog.events.listen(
elem,
goog.events.EventType.CLICK,
func,
scope
);
</code></pre></blockquote>
</div>
<h4>クロージャが共犯という話</h4>
<p>クロージャはコールバック地獄の共犯者です。
<p>このような認識から極度にクロージャを避けるコーディングスタイルに辿りつきました。クロージャを使っているのはどうしても避けられないフレームワークのコアの一部分などに限られます。
<p>また、<a href="http://outcloud.blogspot.jp/2015/05/reusable-closure.html">クロージャには関数スコープ分のコストが掛かります。</a>その上どのタイミングで破棄されているのか?分かり辛いのが嫌いです。
<p>そんなクロージャは私感ですが、インスタンスなどと比べあまり意識されること無く多用されているように思います。
<p><a href="http://utage.headwaters.co.jp/blog/?p=1116" target="_blank">次の記事</a>はそんなクロージャの仕組みとコストについて判りやすく解説しています。ぜひ目を通しておきましょう。
<blockquote title="Utage Blog > 【JavaScript】メモリの浪費を避けるコーディング > ■クロージャ" cite="http://utage.headwaters.co.jp/blog/?p=1116">
<p>アクティベーションオブジェクトとは関数のコールが発生した際に、自動的に生成されるオブジェクトです。アクティベーションオブジェクトには、引数、ローカル変数だけでなく、argumentsオブジェクト、thisが格納されます。
<p>アクティベーションオブジェクトはGCの対象となっているので、通常は関数の実行終了時にメモリ上から解放されます。ただし、対象の関数がメモリ上に生存している間は保持され続けます。(略)
<p>この性質を利用して、スコープチェーンによりローカル変数の値を参照し続けるデータ構造を、クロージャと呼びます。</blockquote>
<h3>なぜコールバック地獄になるか?</h3>
<p>なぜコールバック地獄が起きるのか?これには javascript とブラウザ API に夫々次の問題があるように思います。
<ol>
<li>インスタンスでなく DOM などが this として返るから
<li>DOM を拡張してメソッドやオブジェクトを生やすのはタブー
<li>コールバックの指定の仕方が複数ある
</ol>
<h4>1.DOM が this としてかえる</h4>
<p><strong>prototype 継承を活かし this コンテキストをコントロールするのがハイパフォーマンスな js 開発の肝</strong>です。
<p>しかし、DOM からのコールバックでは this コンテキストが変わってしまっているので(HTMLElement や window 等)インスタンスのメンバーにアクセスできません。ちなみに ActionScript3 などはコンテキストが失われないため、随分綺麗に開発できますね。
<div class="note">
<p>ちなみに、メモリに優しいという点でハイパフォーマンスですが protoype チェーンを辿るので最速というわけではありません。
<div class="links"><a href="http://ledyba.org/2012/08/23223004.php" target="_blank">ψ(プサイ)の興味関心空間 > Chromeではメソッドをオブジェクトに直接入れてはいけない!?</a>
</div>
</div>
<h5>コンテキストを指定できるようにラップする</h5>
<p>僕は HTMLElement はもとよりタイマーや XHR までラップしてそのまま利用することはありません。
<p>これらの登録部分には一貫した方法でコールバック中の this コンテキストを指定する仕組みを入れています。次に(1)タイマーと (2)HTMLElement の例をそれぞれ紹介します。
<h6>(1)タイマーの例</h6>
<pre class="prettyprint lang-js"><code>// 生jsの場合
var timerID = setTimeout(function(){myCallback.call(myContext)}, 100);
// pettanR (俺々フレームワーク)の場合
var timerID = X.Timer.once(100, myContext, myCallback);
</code></pre>
<p>そうそう、あまり意識されることはありませんが、タイマー( setTimeout ) や継承( prototype と __proto__ 周り ) にもしっかりとブラウザ毎の差異があります。
<p>そこで僕は API は必ずラップして触るようにしています。クロスブラウザと将来の変化に対応力がありますが、パフォーマンスとのトレードオフにはなってしまいます。
<p>トレードオフを埋め合わせて余りある気の利いたラップをしたいところです。
<h6>(2)HTMLElement の例</h6>
<p>#myButton を管理下におくインスタンスのメソッド中で定義している、という想定のため、生 js の例では this を that 名で保持しそれにアクセスできるクロージャを返しています。
<p>こんな入り組んだ function がずらずらっと続くコードの相手をしたことがありましたが、最近はトントそんなこともないので、生 js の方が動くのか?実は自信がないです…
<pre class="prettyprint lang-js"><code>// 生jsの場合
document.getElementById('myButton')
.addEventListener('click', (function(that){
return function(){
myCallback.call(that);
};
})(this), false);
// pettanR (俺々フレームワーク)の場合
X('#myButton').listen('click', this, myCallback);
</code></pre>
<div class="note">
<h5>ご参考:handleEvent</h5>
<p>this コンテキストを失いたくない場合 <a href="http://d.hatena.ne.jp/uupaa/20101024/1287850660" target="_blank">addEventListener のコールバックにオブジェクトを渡す</a>、という手もあります。必ず handleEvent 関数にコールバックされるという縛りもありますが、条件が揃えば素直で高速です。
<blockquote title="latest log > イベントハンドリングなら handleEvent を使えば、Function#bind や $.proxy はたぶん要らない" cite="http://d.hatena.ne.jp/uupaa/20101024/1287850660"><p>イベントハンドリングに関しては、Function#bind や $.proxy() でゴニョゴニョせず、 handleEvent ベースで思考すると JavaScript をもっと楽しめると思います。
<p>IE以外ならDOM標準の機能を使うため、内部で余計なクロージャを何個も作ったりせずにすみますし、JavaScript に限らず、イベントハンドリング周りはボトルネックになりがちなので、本来はできるだけ軽く仕上げなきゃだめな部分です。</blockquote>
<p><q>IE以外なら</q>、とありますがこの他にも使用可能なブラウザに制限があります。<a href="http://nanto.asablo.jp/blog/2007/03/23/1339502" target="_blank">次の記事</a>で言及されている Safari2 以下に加え、Opera8 以下(または7以下?) と NetFront3.4 でも使えなかったように思います。
<blockquote title="Days on the Moon > DOM Events とブラウザの実装 > EventListener インターフェースを実装するオブジェクト" cite="http://nanto.asablo.jp/blog/2007/03/23/1339502"><p>Safari 2 では関数オブジェクトしか EventListener として使えませんが、Safari のナイトリービルドでは handleEvent メソッドを持つオブジェクトも EventListener として使えるようです。</blockquote>
</div>
<h4>2. DOM を拡張してメソッドやオブジェクトを生やすのはタブー</h4>
<div class="box">
<iframe src="http://rcm-fe.amazon-adsystem.com/e/cm?t=itozyun-22&o=9&p=8&l=as1&asins=4798128457&ref=tf_til&fc1=000000&IS2=1<1=_blank&m=amazon&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<p>DOM もプロパティを生やすことのできるオブジェクトですので、これを拡張して使っていくのは妥当なことに思えます。
<p>ActionScript3 では Sprite という描画要素クラスを拡張しながら開発しますし。
<p>しかし、DOM に生やしたプロパティへのアクセスは低速です。またメモリリークの懸念もあるため一般に行われていません。
<p>『JavaScript Ninjaの極意』の次の部分は、多分そういうことを述べているんじゃないでしょうか…
</div>
<blockquote title="『JavaScript Ninjaの極意』ジョン・レシグ > 第13章 イベント処理 p341" cite="9784798128450"><p>それぞれの要素ごとに情報を格納する方が自然だと思われるかもしれないが、データを1個のストアに集めることによって、Internet Explorer で発生する可能性のあるメモリリークを予防できる(IE では、DOM ノードへのクロージャを持っている DOM 要素に関数をアタッチすると、そのページから離れた後でメモリを回収できなくなる可能性があるのだ)。</blockquote>
<h4>3.コールバックの指定の仕方が複数ある</h4>
<p>これはあまり指摘を見ませんが、非同期な操作に対してコールバックの指定の仕方が 2 ないし 3 通りある、というのもどうかと思っています。
<h5>(1)イベントターゲット・スタイル</h5>
<pre class="prettyprint lang-js"><code>elm.addEventListener('click', callback, false);
// ie5-8
elm.attachEvent('click', callback);
</code></pre>
<p>ちなみにイベントターゲットについては<a href="https://developer.mozilla.org/ja/docs/Web/API/EventTarget" target="_blank">次の MDN の記事を参照</a>。
<blockquote title="MDN > 開発者向けのWeb技術 > Web API インターフェイス > EventTarget" cite="https://developer.mozilla.org/ja/docs/Web/API/EventTarget">
<p>EventTarget is an interface implemented by objects that can receive events and may have listeners for them.
<p>Element, document, and window are the most common event targets, but other objects can be event targets too, for example XMLHttpRequest, AudioNode, AudioContext, and others.</blockquote>
<h5>(2)DOM 0 イベント・スタイル</h5>
<pre class="prettyprint lang-js"><code>xhr.onreadystatechange = function(){}
</code></pre>
<h5>(3)イベントターゲットでないもの</h5>
<p>終了時や成功時のコールバックと、エラー時のコールバックを渡すアレです。
<p>最初期から存在する setTimeout などはいいとしても、最近のものでは AudioContext.decodeAudioData や window.requestFileSystem などもそうです。
<pre class="prettyprint lang-js"><code>AudioContext.decodeAudioData(audioData, successCallback, errorCallback);
</code></pre>
<p>これらイベントターゲットでないものもイベントターゲット風に加工して使用することができます。
<p>ところで、どうしてイベントターゲットでないのでしょうか?誰か教えてください m(__)m
<h3>非同期処理が連続する MyLoader クラスを書いてみる</h3>
<p>次の例を元に url を与えるとアラートする MyLoader クラス(風)を定義してみます。
<p>pettanR というオレオレフレームワークを使用しています。
<blockquote title="rikubaの日記 > switch文によるコールバック地獄回避" cite="http://d.hatena.ne.jp/rikuba/20140428/1398681132">
<p>url.txtに書かれているURLを取得し、そのURLのリソースの内容を取得し、1秒後にその内容をalertするという例(のための例)を考える。
<p>まずは普通に書いてみる。
<pre class="prettyprint lang-js"><code>var client = new XMLHttpRequest;
client.open('GET', 'url.txt');
client.onload = function (event) {
var url = client.response;
client.open('GET', url);
client.onload = function (event) {
setTimeout(function () {
alert(client.response);
}, 1000);
};
client.send(null);
};
client.send(null);
</code></pre></blockquote>
<p><em>大規模開発ではクラス(風)を定義しながら~ということが多いため、クラス(風)で綺麗に書けるか?検討する</em>のがよいと思います。
<p>ちなみに<strong>シングルトンで済むケースでは js の欠点がほとんど顕在しません。</strong>その上ずっと簡単に書けると思います。
<pre class="prettyprint lang-js"><code>var MyLoader = X.EventDispatcher.inherits(
'MyLoader',
X.Class.NONE,
{
url : '',
textLoader : null,
jsonLoader : null,
result : '',
Constructor : function( url ){
this.url = url;
this.textLoader = X.Net( { xhr : url } )
.listen( [ X.Event.SUCCESS, X.Event.ERROR ], this, this.handleEvent );
},
handleEvent : function( e ){
switch( e.type ){
case X.Event.SUCCESS :
if( e.target === this.textLoader ){
this.jsonLoader = X.Net( { xhr : e.response, dataType : 'json' } )
.listen( [ X.Event.SUCCESS, X.Event.ERROR ], this, this.handleEvent );
} else {
this.result = e.responce;
X.Timer.once( 1000, this, this.doAlert );
};
return;
case X.Event.ERROR :
this.result = e.target === this.textLoader ? 'get text error' : 'get json error';
X.Timer.once( 1000, this, this.doAlert );
};
},
doAlert : function(){
alert( this.result );
}
}
);
</code></pre>
<p>元にしたコードから大分長くなってしまっていますが、エラーハンドリングや MSXML(ActiveX 版 XHR) や XDomainRequest へのフォールバックもオレオレ・フレームワーク内できちんとしていますので一旦これで勘弁してください…
<pre class="prettyprint lang-js"><code>var loader = new MyLoader('hoge.txt');
</code></pre>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-71427940738524527562015-05-22T21:49:00.000+09:002021-07-13T15:06:53.245+09:00Bloggerを究極軽量化してワンコインSIMで爆速表示する<p><ins datetime="2015/12/06 12:35">コメントフォームが IE7 以下で動かなかったのを修正しました。てっきり Google さん側で弾いているのかと思っていました…(2015/12/06)</ins>
<p><ins date="2015/11/23">“画像のライトボックス表示機能が動作しない”も<a href="https://outcloud.blogspot.jp/2015/11/bloger-minify-final.html">「Blogger究極軽量化の完成、画像拡大は非lightboxで」</a>で対策できました。(2015/11/23)</ins>
<h3>軽量 Web 時代、再び―</h3>
<p>ADSL や光回線といったネットワーク環境の大容量化に歩を合わせて最近の Web サイトは1ページ辺りの読み込み量が 1MB を超えることもザラです(Web アプリケーションではないですよ!)。
<p>一方で、固定回線に比べて低速であったり通信量制限のあるモバイル通信の拡大、さらにはワンコインデータ通信 SIM の登場によって、軽量な Web の重要性が再び増しつつあります。
<p>原稿用紙にして数枚分のテキストを流通させるために、ゥン MB はないですよね…何千ページか閲覧する内に速度制限が掛かっていてはたまりません。
<h4>早速 Blogger を軽量にしていきます</h4>
<p><a href="http://outcloud.blogspot.jp/2015/04/bloggerminify.html">前回の記事で超軽量化を達成</a>した僕の blogger ですが、一方でいくつかの問題が発生しました。
<blockquote title="BloggerでGoogle製jsの読み込みを辞めて超軽量化、但しコメントフォームは動かす" cite="http://outcloud.blogspot.jp/2015/04/bloggerminify.html"><ol>
<li><del>ブログアーカイブの Ajax メニューが動作しない。</del>解決、というより回避!
<li>画像のライトボックス表示機能が動作しない。
<li><del>js が無効の場合もコメントフォームが表示され動作しない。</del>解決!
</ol></blockquote>
<p>本記事では上の 3 つの問題のうち 2 つをいい感じに解決しました。さらに 50% 程度の高速化ができました。
<p>以下にご紹介します、何かの参考になりましたら幸いです。
<h3>ブログアーカイブの調整</h3>
<div class="box">
<a href="http://4.bp.blogspot.com/-06ChPHwsFXA/VV8dktqd5yI/AAAAAAAAQJw/bkxlJqhEdAg/s1600/blog_archive.png"><img src="http://4.bp.blogspot.com/-06ChPHwsFXA/VV8dktqd5yI/AAAAAAAAQJw/bkxlJqhEdAg/s160/blog_archive.png" /></a>
<p>ブログアーカイブ・ウィジェットはユーザーのクリック操作によって動的に月毎の記事情報を取得して記事タイトルとリンクを表示していました。
<p>blogger.com が提供する一切の javascript を読み込まなくなったことでこの部分の動作も停止しました。
<p>独自に javascript を書いてこの部分を再び動作させることも検討しましたが、画像のように年~月までのデザインとしたため不要になりました。
</div>
<p>そんなブログアーカイブのテンプレート部分は次の通りです。
<pre class="prettyprint lang-xml"><code><b:widget id='BlogArchive1' locked='true' type='BlogArchive'>
<b:includable id='main'>
<div class="footer-sub-inner">
<b:if cond='data:title != &quot;&quot;'>
<h3><data:title/></h3>
<b:else/>
<h3>記事アーカイブ</h3>
</b:if>
<b:loop values='data:data' var='i'>
<div class="archive-item">
<span><data:i.name/></span>
<b:loop values='data:i.data' var='j'>
<a expr:href='data:j.url'>&#160;<data:j.name/><b:if cond='data:j.post-count != 1'><small>(<data:j.post-count/>)</small></b:if></a>
</b:loop>
</div>
</b:loop>
</b:includable>
</b:widget>
</code></pre>
<h3>究極軽量化!コメントフォームを動的に読み込み</h3>
<blockquote title="Bloggerの記事のプレビューを爆速にするカスタマイズ > コメントフォームを削って転送量の測定" cite="http://outcloud.blogspot.jp/2015/04/hispeedpreview.html">
<p>今回のカスタマイズによって、無駄なリクエストを無くして高速に投稿のプレビューができるようになりました。
<p>さらに、コメントフォーム用 iframe の生成を読者による操作の後に行うようにすれば、プレビュー画面といわず常に高速にページを表示することだってできます。</blockquote>
<h4>js が切れているとコメントできない</h4>
<p>まず Blogger のコメントフォームは残念なことに javascript が切られていると動作しません。
<p>このためか Blogger のデフォルトではフォームは javascript によって動的に表示されています。これならば、javascript を切っているユーザーに対してフォームを表示することはありません。
<p>前回のカスタマイズでは <script> タグを全廃した結果 javascript の有無に関わらず常にフォームを表示するようになっていました。
<p>これをユーザーのクリックによって(javascript で)フォームを表示するようにしました。
<p>javascript を切っているユーザーに対して無用にフォームを読みこむことは無くなり、閲覧だけのユーザーにフォームは読み込まれません。
<h4>コメントフォームを表示しない → 転送量が 30KB 程度に</h4>
<p>ところでコメントフォームを表示すると 30KB 程度のコンテンツを追加で読み込みます。記事ページの総読み込み量は 60KB 程度、つまりコメントフォームが転送量の約半分を占めていました。
<p>そんなコメントフォームの改造によって 1 ページ辺りの転送量は僅かに 30KB になってしまいました。
<p>フォーム周りのテンプレートは以下の通りです。div タグの onclick 属性で諸々書き出しているためちょっと複雑になっています。
<pre class="prettyprint lang-xml"><code><b:if cond='data:post.allowNewComments'>
<div id="Cf" class='Ch' expr:onclick="&quot;this.className=this.onclick='';this.innerHTML='&lt;h3&gt;&quot; + data:postCommentMsg + &quot;&lt;/h3&gt;&lt;p&gt;&quot; + data:blogCommentMessage + &quot;&lt;/p&gt;&lt;iframe frameborder=0 scrolling=no name=If&gt;';If.location.href='&quot; + data:post.commentFormIframeSrc + &quot;';&quot;">
<a href="javascript:void(0)" hidefocus="true"><noscript>javascript が無効のため</noscript>コメントを投稿<noscript>できません&#12290;</noscript>
</a>
</div>
<data:blogTeamBlogMessage/>
<b:else/>
<data:post.noNewCommentsText/>
</b:if>
</code></pre>
<p>次のコードは IE7 以下で動作しません。
<pre class="prettyprint lang-xml"><code><del><b:if cond='data:post.allowNewComments'>
<div class='comment-form comment-form-hidden' expr:onclick="&quot;this.className='comment-form';this.removeAttribute('onclick');this.innerHTML='&lt;h3&gt;&quot; + data:postCommentMsg + &quot;&lt;/h3&gt;&quot; + data:blogCommentMessage + &quot;&lt;iframe frameborder=0 scrolling=no src=&quot; + data:post.commentFormIframeSrc + &quot;&gt;'&quot;">
<a href="javascript:void(0)">コメントを投稿する <data:blogTeamBlogMessage/>
<noscript>javascript が切れているためコメントできません&#12290;</noscript>
</a>
</div>
<b:else/>
<data:post.noNewCommentsText/>
</b:if>
</del></code></pre>
<p>そうそう、Blogger にはポップアップ・ウィンドウ型のコメントフォームもありますが、こちらは機能過多でヘビーなため早々に検討から外しました。
<h3>その他の軽量化</h3>
<p>コメントフォームの軽量化に加えて一般的な js と css の minify も行っています。
<p>また js ファイルは今のところコードハイライターだけのため、これは記事ページと固定ページだけで読み込んでいます。
<p>ちなみに css の minify は <a href="http://cssminifier.com/" target="_blank">CSS Minifier</a> と比較して若干圧縮率の高かった <a href="http://css.github.io/csso/csso.html" target="_blank">CSS optimizer</a> を使用しています。
<p>この他にテンプレートの xml に対してもコメントの除去とタブの削除の minify を行っています。これによって微々たるものですが 2KB 程度の転送量を減らしています。
<h3>ここでホリエモンの“テキストの時代だ”の件</h3>
<p>2013 年の記事ですが html 書きとして<a href="http://matome.naver.jp/odai/2136713291397662901" target="_blank" rel="nofollow">ホリエモンの指摘したこの件</a>は折に触れ考えています。
<blockquote title="
ニュース長すぎ、EPUBはクソ規格--ホリエモンがニコニコ超会議で語った全文2 > 堀江「Epubはクソ規格だ」" cite="http://matome.naver.jp/odai/2136713291397662901"><p>たとえば日刊サイゾーっていうのがある。日刊サイゾーのアプリを入れてるんだけど、めちゃくちゃサクサク読めるわけ。テキストと写真がちょっとしか載ってないから、いますごい読みやすいんですよ。
<p>で、僕はテキストの時代だと思ってる。映像も画像もそれはリンクで飛ばせば、Facebookのタイムラインみたいに、サムネイルだけ載ってますみたいな。僕はその程度でいいと思うんですよ。テキストだと表示も早いし、アプリもさくさく動く。</blockquote>
<p>テンプレート xml から空白ノードを除去したり(空白ノードだって僅かながらマシンリソースを喰いますから)画像も意識的に小さいものを貼って、軽量化・高速化には心を砕いています。
<p>テキストの軽快さには敵うものではありませんが、30KB ならなかなかいい線いっているのではないでしょうか…?
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-75832707089963795872015-05-16T11:44:00.002+09:002021-09-11T19:15:40.531+09:00再利用できるクロージャを使ったWebアプリケーション開発<div class="note">
<h3>2015.6.2 追記</h3>
<blockquote title="オブジェクトプールを使った静的メモリ JavaScript > メモリ撹拌の削減によるガベージコレクションの影響回避" cite="http://www.html5rocks.com/ja/tutorials/speed/static-mem-pools/"><p>このようにオブジェクトが頻繁に生成/破棄される状態を「メモリ撹拌」と呼びます。アプリケーション実行時にメモリ撹拌が発生するのを避けることで、GCの処理時間を削減することができるのです。</blockquote>
<p>いろいろ書いたけど、クロージャについて<q cite="http://www.html5rocks.com/ja/tutorials/speed/static-mem-pools/">メモリ撹拌の削減</q>を行うテクニック、ということにします。
</div>
<h3>大規模開発ではクロージャは駄目!</h3>
<p>百花繚乱の js フレームワークやライブラリですがそのソースコードを眺めていくと、再利用可能クロージャ ( reusable closure ) を目にすることが増えました。
<p>今回は、そんな再利用可能クロージャについてご紹介したいと思います。
<p>ところで大規模開発ではクロージャ駄目!絶対!とはしばしば言われることです。
<p>最近は、ブラウザの実装がこなれてきたことへの安心感か、腐ったブラウザと格闘した世代が開発から離れたのか、目くじら立てて言われることも少ないように思います。
<p>Web 開発者の集まりなどでそんな話をしますと怪訝な目をされてしまうこともあるので、アッチョンブリブリケです。
<h4>クロージャのデメリット</h4>
<p>一応デメリットについてあげてみます。
<ol>
<li>関数スコープのコストが掛かかってしまう
<li>DOM と循環参照していないか?直感的に分かりづらい、働きづめのヒートアップした頭では本当によく分からない、勘弁してください
</ol>
<blockquote title="JavaScript 「再」入門 > メモリリーク" cite="https://developer.mozilla.org/ja/docs/Web/JavaScript/A_re-introduction_to_JavaScript"><p>クロージャの良くない副作用として、Internet Explorer で簡単にメモリリークを発生させることがあります。
<p>クロージャでは、思わぬメモリリークが容易に発生します。</blockquote>
<blockquote title="Google JavaScript Style Guide 和訳 > クロージャ" cite="http://cou929.nu/data/google_javascript_style_guide/#id19"><p>使っても良い. ただし慎重に.
<p>ただし一点注意すべき点は, クロージャはその閉じたスコープへのポインタを保持しているという点です. そのため, クロージャを DOM 要素に付加すると循環参照が発生する可能性があり, メモリリークの原因となります. </blockquote>
<p>
<a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/A_re-introduction_to_JavaScrip" target="_blank">“JavaScript 「再」入門”</a> と
<a href="http://cou929.nu/data/google_javascript_style_guide/#id19" target="_blank">“Google JavaScript Style Guide 和訳”</a> は、Javascript 開発全般についてよくまとまった記事ですので、目を通しておくと良いです。
<h5>クロージャのコスト</h5>
<div class="box">
<div class="caption" style="width:160px">
<figure>
<a href="https://4.bp.blogspot.com/-M7pPTKAKVzU/WHHwIn9QBXI/AAAAAAAARMc/z1xVKQ4YEnc1k0SElLLhQkf3S70mT6uHQCLcB/s1600/jsninja.jpg"><img src="https://4.bp.blogspot.com/-M7pPTKAKVzU/WHHwIn9QBXI/AAAAAAAARMc/z1xVKQ4YEnc1k0SElLLhQkf3S70mT6uHQCLcB/s200/jsninja.jpg" width="160" height="200" /></a>
<figcaption><a href="http://amzn.to/2i4latL" target="_blank" rel="nofollow" title="amazon">JavaScript Ninjaの極意 ジョン・レシグ</a></figcaption>
</figure>
</div>
<p>みんな大好き jQuery の作者ジョン・レシグの著した『Javascript 忍者の極意』では、一章を裂いてクロージャの利用を勧めています。またクロージャをうまく使えていないケースがある、と指摘しています。
<p>一方で、クロージャのコストについては、次に示す一箇所での言及に留まっています。
<p>しかし大規模開発では特に留意しなくてはいけない点に思います。
</div>
<blockquote title="『JavaScript Ninjaの極意』ジョン・レシグ > 第5章 クロージャ p104" cite="urn:isbn:9784798128450"><p>ここでひとつ指摘しておくべき、重要な注意事項がある。この構造のすべてを、どこかで見ることができるわけではない。これらの情報すべてを包む「クロージャ」オブジェクトが存在するわけではないのだ。それでも、この方法で情報を収納し参照するには、直接的なコストがかかる。クロージャを介して情報をアクセスする関数は、いわば重い「足かせ」によって、それらの情報をひきずっているのだ。信じられないほど便利なクロージャだが、その代償として、オーバーヘッドがかかる。すべての情報をメモリに保存しなければならないし、そのメモリが、もう本当に不要だと(ガンベージコレクションを行っても安全だと)Javascriptエンジンが確信するまで(あるいはページがアンロードされるまで)そのメモリで情報を保存しなければならないのだ。</p></blockquote>
<p>さて、<a href="https://web.archive.org/web/20130118123735/http://yabooo.org/archives/70" target="_blank">次は2008年</a>ですが具体的なクロージャのコストについて実際に計測されていて素晴らしい記事です。
<p>是非目を通しておきましょう、Web アーカイブになります。
<blockquote title="日本野望の会 > Javascriptでカプセル化のコスト" cite="https://web.archive.org/web/20130118123735/http://yabooo.org/archives/70"><p>今回はカプセル化を先のような方法で行うとどのようなコストがかかるのかということ探ってみました。
<p>次に生成1つあたりのメモリコストの違いですが
これはでかいですね。これを計算してみると1つあたりのメモリコストは<strong>1,110 bytes</strong>となっているようです。</blockquote>
<h5>循環参照とガベージコレクション</h5>
<p>富豪的なプログラミングに目を瞑るなら、最大の難点は循環参照を作っていないか気を配らなくてはいけない、という点です。
<p>これ自体ナイーブな問題ですが首尾よく解決したとして、続いてブラウザのガベージコレクションに目を移しますと…
<p>その能力はブラウザ毎にまちまちでページを離れるまでガベージコレクションされないような挙動のブラウザも報告されています。
<p>また、今後もテストの網を潜り抜け問題のあるブラウザがリリースされないとも限りません。
<p>そして、対応ブラウザのすべてについてガベージコレクションが健全か?調べるよりは、ちゃっちゃと再利用可能クロージャを使ってしまうのが最新の流行のようですよ。
<h4>クロージャを使うケース</h4>
<p>本題に行く前に、積極的にまたは安全にクロージャを使うケースを上げてみます。
<ul>
<li>スコープに新しい名前を追加したくない場合で関数が破棄されることが明らかなとき
<li>blog 等の参考コード
<li>実装の不備を回避するため使うのが妥当なケース
<ol>
<li>IE独自イベントモデル
<li>IE8- と Opera11- の XHR と MSXML
<li>setInterval, rAF 等のタイマー系は?
</ol>
</ul>
<h5>ケース1・IE独自イベントモデル</h5>
<div class="box">
<div class="caption" style="width:154px">
<figure>
<a href="https://1.bp.blogspot.com/-JF4eIARXpuE/WHHzluraTsI/AAAAAAAARMo/40a0Ml7-yCAlNy2aMjD-52PIKp4OousYgCLcB/s1600/js5th.jpg"><img src="https://1.bp.blogspot.com/-JF4eIARXpuE/WHHzluraTsI/AAAAAAAARMo/40a0Ml7-yCAlNy2aMjD-52PIKp4OousYgCLcB/s200/js5th.jpg" width="154" height="200" /></a>
<figcaption><a href="http://amzn.to/2jgRvyM" target="_blank" rel="nofollow" title="amazon">『Javascript 第5版』オライリー</a></figcaption>
</figure>
</div>
<p>IE5 ~ IE8 の独自イベントモデルに於いて、イベントオブジェクトに event.currentTarget に相当するものがなく、現在どの HTML 要素でイベントが起こっているか分かりません。そのため HTML 要素とコールバック関数を束縛するクロージャを使う必要があります。<br><cite>『Javascript 第5版』 オライリー p430 17.3.6 attachEvent() と this キーワード</cite>
</div>
<h5>ケース2・IE8- と Opera11- の XHR と MSXML</h5>
<p>IE8 以下と Opera11 以下の XHR (と MSXML) ではイベントオブジェクトが用意されないため、Event.type が分からない不備があります。
<p>このためにイベントタイプとコールバック関数を束縛するクロージャを使用するのが適当かもしれません。
<h5>ケース3・setInterval, rAF 等のタイマー系は?</h5>
<p>また、setInterval, setTimeout, requestAnimationFrame, setImmediate などのタイマー系については関数だけを登録できてコールバック時の this コンテキストは window になってしまいます。
<p>これらタイマー系については、複数のタイマーを登録しても Web ブラウザに対してはひとつのタイマーだけを登録する<a href="http://d.hatena.ne.jp/amachang/20060924/1159084608">高速化手法</a>がありますので、その際に合わせて this コンテキストを設定できるようにしてしまうのが綺麗でしょう。</p>
<p>現在 amachang 氏の書いたコードを拝見することはできませんが、<a href="http://d.hatena.ne.jp/sawat/20070329" target="_blank">sawat 氏によるデモは公開</a>されていてタイマーをまとめる効果を実感できます。</p>
<blockquote title="sawatの日記 > [JavaScript]setIntervalを実験する" cite="http://d.hatena.ne.jp/sawat/20070329"><p>無駄に多くのsetIntervalを使ってアニメーションをすると、setInterval03.jsを使わない場合は、Firefoxだとかなりグダグダな感じになってしまう。しかし、setInterval03.jsを使うとほぼ期待通りの間隔で実行させることができるみたいだ。</blockquote>
<h3>再利用可能クロージャ</h3>
<p>いよいよ本題に入ります。一般的なクロージャと再利用可能クロージャを見比べてみます。
<h4>this コンテキストを縛る一般的なクロージャ</h4>
<p>以下にコールバックの this コンテキストを上書きする、というよくあるクロージャを示します。
<pre class="prettyprint lang-js"><code>function createCallback( func, context ){
return function(){
return func.apply( context, arguments );
};
};
</code></pre>
<h4>再利用可能クロージャのサンプル</h4>
<pre class="prettyprint lang-js"><code>function createCallback( cbHash ){
return function(){
return cbHash.func && cbHash.func.apply( cbHash.context, arguments );
};
};
</code></pre>
<p>これが、再利用可能クロージャの最も簡単な例になります。一般的なクロージャのサンプルコードと大きく違いはありません。
<p>createCallback に対して、コンテキストとコールバック関数ではなく、それらを格納したハッシュ cbHash を与えているのが唯一の違いです。
<p>しかしこの変更によって cbHash のメンバーを適宜に書き換えることで一旦不要になったクロージャを再利用することができます。
<p>以上を基本に、各ライブラリ・フレームワークの特徴にあわせた味付けがされています。
<h4>実用的な再利用可能クロージャの例</h4>
<p>次が実際の再利用可能クロージャのコード例になります。create/collect メソッドだけで再利用可能クロージャの操作ができます。
<p>クロージャの回収と再利用や cbHash の操作が隠蔽されていることをご確認ください。
<pre class="prettyprint lang-js"><code>var ReusableClosure = (function(){
var POOL = []; // pool cb and cbHash key
function createCallback( cbHash ){
return function( arg0 ){
if( arg0 === POOL ) return cbHash;
return cbHash.func && cbHash.func.apply( cbHash.context, arguments );
};
};
return {
create : function( context, func ){
var ret = POOL.pop(), cbHash;
if( ret ){
cbHash = ret( POOL );
cbHash.context = context;
cbHash.func = func;
return ret;
};
return createCallback( { context : context, func : func } );
},
collect : function( cb ){
var cbHash = cb( POOL );
cbHash.context = cbHash.func = null;
POOL.push( cb );
}
};
})();
// 生成
var cb = ReusableClosure.create( myObject, readyHandler );
// 破棄
ReusableClosure.collect( cb );
</code></pre>
<h3>最後に</h3>
<p>“再利用可能クロージャを目にすることが増えました”“ちゃっちゃと再利用可能クロージャを使ってしまうのが最新の流行”という記述がありますが、僕の知る限り使われているのは、pettanR だけでした。ちょっと盛りました。てへ、ペロ。
<p>でも、僕の職場では pettanR は大変著名な js フレームワークで、木曜の飲み会でもその話題で持ちきりでしたよ。
<p>また、記事のそこここで断定口調を使っていますが、「僕は~と思う」、に適宜に読み替えてください。
<p>このような胡散臭い記事を鵜呑みにしてしてはいけません、ではでは。
<h4>参考記事</h4>
<div class="links"><a target="_blank" href="http://utage.headwaters.co.jp/blog/?p=1116">Utage Blog >【JavaScript】メモリの浪費を避けるコーディング</a>
<a target="_blank" href="http://www.html5rocks.com/ja/tutorials/memory/effectivemanagement/">Gmail スケールの効率的メモリ管理術</a>
<a target="_blank" href="http://www.html5rocks.com/ja/tutorials/speed/static-mem-pools/">オブジェクトプールを使った静的メモリ JavaScript</a>
</div>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-32466863658340868642015-05-11T20:28:00.001+09:002015-05-11T20:28:30.027+09:00encodeURI / decodeURI, encodeURIComponent / decodeURIComponent の正規表現不使用版<h3>RegExp FREE!</h3>
<p>encodeURI / decodeURI, encodeURIComponent / decodeURIComponent をサポートしない環境向けに<a href="http://sourceforge.jp/projects/pettanr/scm/git/clientJs/commits/b072c0d95a33cb58007a5d2f50a5a9b4bd1f9341#fd-0.6.x/js/01_core/00_builtin.js" target="_blank">これらの関数を補うコード</a>を書きました。</p>
<p>既に同様のコードは公開されていますが、本コードは正規表現を使っていないためより広範な環境で利用できます (ノ ̄ω ̄)ノ♪</p>
<a target="_blank" href="http://sourceforge.jp/projects/pettanr/scm/git/clientJs/blobs/b072c0d95a33cb58007a5d2f50a5a9b4bd1f9341/0.6.x/js/01_core/00_builtin.js">0.6.x / js / 01_core / 00_builtin.js</a>
<p>万が一ご利用の際は先のリンクから適宜に切り出してください。
<p>気が向いたら自分で切り出して Github にあげるかもしれません。そうそう、テストはいい加減ですので悪しからず。
<p>制作にあたっては公開されている次のコードを参照させていただきました。さらに言いますと、仕様を読んでもサッパリなのでコードをじぃっと眺めてえいやっとやりましたとさ…
<h3>Yoshio 氏制作の TransURI.js</h3>
<p>かなり早い段階で発表された<a href="https://web.archive.org/web/20100517081559/http://nurucom-archives.hp.infoseek.co.jp/index.html">ヌルコムアーカイブス編纂ひつ長 Yoshio 氏</a>の手になるコードです。NN4 でも動作確認しているそうでザワザワきますね。
<p>残念ながら infoseek は無料ホームページサービスから撤退したため、<del>fucking 三木谷</del> Web アーカイブスからの引用になります。ありがたいことに Web アーカイブでは現在でもコードが閲覧可能です。
<blockquote title="ヌルコムアーカイブス・デジタル制作室 > TransURI (UTF-8)" cite="https://web.archive.org/web/20080723140256/http://nurucom-archives.hp.infoseek.co.jp/digital/trans-uri.html">
<p>IE5.5 からサポートされた encodeURI() , decodeURI() を他のブラウザで再現
<p>◎ビルトイン関数の decodeURI() よりも高速にデコードされます(IE6.0で確認)</blockquote>
<p>TransURI.js はブラウザが encodeURI 等を備える場合の手当てがありません。
<h3>ofk 氏制作の kQuery より~</h3>
<p><a href="http://kquery.if.land.to/" target="_blank">kQuery</a> を開発されていた <a href="http://d.hatena.ne.jp/ofk/" target="_blank">ofk</a> 氏によって encodeURI 等がない環境に対してだけ関数が追加されるように変更されたコードが公開されています。
<blockquote title="?D of K > IE5で動くjQueryっぽいライブラリができていました" cite="http://d.hatena.ne.jp/ofk/20091120/1258679885"><p>半分ぐらいjQueryからコードを持って来たような気がしますが、IE5でもjQueryっぽく書けるライブラリができていました。正直、あんまりブラウザのチェックとかしていないので、実際に使うのは結構危険です。</blockquote>
<p><strong>正規表現が使える通常の環境</strong>では心の中で手を合わせつつこちらを使うとよいでしょう。複雑な正規表現と同様の処理を js でゴリゴリ書いた場合では、経験上、正規表現が圧倒的に高速です。
<blockquote title="kQuery(w > セレクターベンチマーク > kQuery(おそらく最終版)" cite="http://kquery.if.land.to/slickspeed/src.zip">
<pre class="prettyprint lang-js"><code>/*
* Window
* by http://nurucom-archives.hp.infoseek.co.jp/digital/trans-uri.html
*/
window.encodeURI || (window.encodeURI = function (x) {
return ("" + x).replace(/[^!#$&-;=?-Z_a-z~]/g, function (s) {
var c = s.charCodeAt(0), p = "%";
return (
c < 16 ? "%0" + c.toString(16) :
c < 128 ? p + c.toString(16) :
c < 2048 ? p + (c >> 6 | 192).toString(16) + p + (c & 63 | 128).toString(16) :
p + (c >> 12 | 224).toString(16) + p + (c >> 6 & 63 | 128).toString(16) + p + (c & 63 | 128).toString(16)
).toUpperCase();
});
});
window.encodeURIComponent || (window.encodeURIComponent = function (x) {
return ("" + x).replace(/[^!'-*.0-9A-Z_a-z~-]/g, function (s) {
var c = s.charCodeAt(0), p = "%";
return (
c < 16 ? "%0" + c.toString(16) :
c < 128 ? p + c.toString(16) :
c < 2048 ? p + (c >> 6 | 192).toString(16) + p + (c & 63 | 128).toString(16) :
p + (c >> 12 | 224).toString(16) + p + (c >> 6 & 63 | 128).toString(16) + p + (c & 63 | 128).toString(16)
).toUpperCase();
});
});
window.decodeURI || (window.decodeURI = function (x) {
return ("" + x).replace(/%(E(0%[AB]|[1-CEF]%[89AB]|D%[89])[0-9A-F]|C[2-9A-F]|D[0-9A-F])%[89AB][0-9A-F]|%[0-7][0-9A-F]/ig, function (s) {
var c = parseInt(s.substring(1), 16);
return String.fromCharCode(
c < 128 ? c :
c < 224 ? (c & 31) << 6 | parseInt(s.substring(4), 16) & 63 :
((c & 15) << 6 | parseInt(s.substring(4), 16) & 63) << 6 | parseInt(s.substring(7), 16) & 63
);
});
});
// 手抜き
window.decodeURIComponent || (window.decodeURIComponent = window.decodeURI);
</code></pre></blockquote>
<h4>謝辞</h4>
<p>kQuery は残念ながら開発の停まったプロジェクトですが、その成果は pettanR の js 調教層や DOM 操作層で大変お世話になりました m(__)m
<h3>おわりに</h3>
<p>いままでは encodeURIComponent / decodeURIComponent を使うときはムズムズと心に引っかかるものがあったけどこれで心置きなく使うことが出来ます ヽ(・∀・)ノizhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-33265705470699184782015-05-05T12:04:00.000+09:002015-10-03T22:14:35.418+09:00大探検!HTML5オーディオスプライト・中編
<p><a title="大探検!オーディオスプライト・前編" href="http://outcloud.blogspot.jp/2015/04/audiosprite1.html">前回</a>に続いて、モバイルオーディオを理解するための記事やライブラリと、僕の調査による補足をご紹介していきます。
<p>また、前回の記事に誤りがあったので少し修正しています。何がしか開発中の方は再度ご確認ください。
<p>また、僕の記事は、訂正箇所を明示せずに訂正している場合がありますのでお気をつけて。
<p>~で、本題の前に…
<h3>モバイル Safari の Audio 制限の理由</h3>
<p>この制限の理由について Apple の正式なアナウンスはありません。
<p>従量課金でインターネットに接続しているユーザーに対して、意図せず巨大なオーディオがダウンロードされることを防ぐため、といわれています。
<p>さて、従量課金に絡んで興味深い点があります。
<p>iOS6 からより強力なオーディオ機能、WebAudio がサポートされました。
<p>iOS の WebAudio はユーザーのタッチを基点とせずにオーディオファイルのダウンロードができてしまいます。そして、start() のときにユーザーのタッチが要求されます。
<p>相変わらずメディア周りに制限がある点は同じですが、ユーザーのインタラクション無しに通信が発生している点は、先の推測と矛盾しています。
<p>従量課金説の他に、モバイル Safari のオーディオ機能をリッチにしてしまうと iTunes の地位が低下してしまうから、という指摘もあります。(url失念)
<p>はてさて、モバイル Safari の制限はどういった理由なのか?答えはありませんが、在野の Web 技術者の発奮で、大手の思惑の斜め上を行き、UX をアゲ↑アゲ↑しちゃいましょう。
<h3>BoomBox.js 2014/02/19~</h3>
<blockquote title="サイバーエージェント、ブラウザ向けサウンドライブラリ「boombox.js」をオープンソースとして公開" cite="http://www.nikkan.co.jp/newrls/rls20140220o-10.html">
<p>「boombox.js」は、ブラウザでサウンドを再生する際に使われることの多い、一般的なオーディオ関連のAPIである 「HTMLAudio」「WebAudio」「HTMLVideo」を包括して、一貫性のあるAPIとして提供するブラウザ向けサウンドライ ブラリです。
<p「boombox.js」は、「Ameba」にて提供する「アメーバピグ」をモチーフとしたブラウザ向けゲーム「なぞってピグキッチン」などのサービス開発でも採用されており、今後も「boombox.js」を採用した新たなサービス開発を進めております。>
</blockquote>
<p><a href="https://github.com/CyberAgent/boombox.js/blob/master/README_ja.md">サイバーエージェントが公開しているライブラリ</a>です。
<p>WebAudio, HTMLAudio に加え HTMLVideo も隠し味として使用するオーディオライブラリで、オーディオスプライト機能も提供されます。</p>
<p>次のリンクは素晴らしいまとめですが Github のデザインと干渉してしまって見辛いです。心の中で手を合わせつつ印刷して手元におきましょう。</p>
<a href="https://github.com/CyberAgent/boombox.js/blob/master/correspondence_table.md">CyberAgent/boombox.js ブラウザ対応表(2014-03-18)</a>
<h4>オーディオ + ビデオフォールバック</h4>
<p>このライブラリ・記事の括目な点としては、Android4 以降で Android 標準ブラウザのオーディオ機能の制限が強くなり同時再生数が一音になります。
<p>その際に、Video タグを使用したフォールバックで2音の同時再生を可能にしている点です。ハック感がたまりませんね。
<p>これにより BGM を1トラック鳴らしながら SE を1トラック鳴らすことができリッチなゲーム等のアプリが制作可能です。
<blockquote title="boombox.js/README_ja.md > Reference information > Mobile" cite="https://github.com/CyberAgent/boombox.js/blob/master/README_ja.md"><table cellspacing="0">
<thead>
<tr>
<th align="center">OS/Browser</th>
<th align="center">1 sound</th>
<th align="center">2 sound</th>
<th align="center">multi sound</th>
</tr>
</thead>
<tbody>
<tr>
<td align="center">IOS 5: Safari</td>
<td align="center">✔</td>
<td align="center">-</td>
<td align="center">-</td>
</tr>
<tr>
<td align="center">IOS 6, 7: Safari</td>
<td align="center">✔</td>
<td align="center">✔</td>
<td align="center">✔</td>
</tr>
<tr>
<td align="center">Android 2.x: basic</td>
<td align="center">✔</td>
<td align="center">✔</td>
<td align="center">✔</td>
</tr>
<tr>
<td align="center">Android 4.x: basic</td>
<td align="center">✔</td>
<td align="center">✔ *1</td>
<td align="center">-</td>
</tr>
<tr>
<td align="center">Android 4.x: chrome</td>
<td align="center">✔</td>
<td align="center">✔</td>
<td align="center">✔</td>
</tr>
</tbody>
</table>
<p>*1 HTMLAudio/HTMLVideo 併用
</blockquote>
<p>先の表には Android 4.x について HTMLAudio/HTMLVideo 併用とあります。
<p>しかし今回確認したところ、HTMLAudio の制限が強まるのは Android4 の途中からになります。一方で HTMLVideo の制限が弱まって、ビデオのインライン再生が可能になるため、オーディオ + ビデオフォールバックが成立します。
<p>この境界は、Android4.1.1 Webkit 534.3 と Android4.4.4 Y! Browser Webkit 537.36 の間にありました。Android4.1.1 の HTMLAudio は Android2.3 と同じく制限がありません。より正確な境界はどなたか特定して教えてください m(__)m
<h4>メモリリーク</h4>
<p>またコードを眺めていてそれと分かるメモリリークがありました。長時間滞在型のページで使う前に修正した方が良いでしょう。
<p>次の HTMLAudio と HTMLVideo に対する以下のイベントリスナが dispose() でも解除されていません。
<blockquote title="boombox.js/boombox.js" cite="https://github.com/CyberAgent/boombox.js/blob/master/boombox.js"><pre class="prettyprint lang-js"><code>this.$el.addEventListener(
'ended',
function (e) {
self._onEnded(e);
},
false);
</code></pre></blockquote>
<p>イベントとタイマーに絡んでクロージャを多用していてオブジェクトのライフサイクルがとっても追いづらいです。大規模開発でこのようなコードが使われているとそのうちに目も当てられなく、、、
<h4>currentTime が正しく動かないブラウザ</h4>
<blockquote title="CyberAgent/boombox.js/README_ja.md > currentTime" cite="https://github.com/CyberAgent/boombox.js/blob/master/README_ja.md">
<p>HTMLAudio HTMLVide のシーク設定(currentTime) が設定出来ないブラウザがある場合は、内部でcurrentTimeが設定されても無視されます。</blockquote>
<p>記事中には、currenTime が正しく動かないブラウザがある、とありました。
<p>残念ながらブラウザ名・バージョン等は明示されていません。これについては先の記事でも触れたとおり、Opera Mobile 12 と Desktop 版 Opera12 が不可解な挙動をしました。そこで僕は Opera12 のことを言っているのでは?と考えています。
<h4>Android 版 & Windows PC版 Opera12 で duration, currentTime 周りが独特</h4>
<h5>Opera Mobile 12 で currentTime が更新されない</h5>
<p>Opera Mobile 12(Android4.4.4 & 2.3.5) は 2回目以降の currentTime へのセットから currentTime が更新されなくなります。仕方が無いので現在の再生位置を知るために Date.now などを使用します。また、セットは動作するのでシークは可能です。
<h5>Windows PC版 Opera 12.1x</h5>
<p>あまりにも問題が多いので箇条書きにします…主に Opera 12.17 portable apps 版 WinXP 32bit で調べています。</p>
<ul>
<li>勝手に再生が始まる。その際には timeupdate が発行されない。
<ul>
<li>Opera 12.16 1860 Win8 64bit では勝手に再生はしない。
<li>Opera11、10.54 では WinXP では発生しない。
</ul>
<li>loadeddata イベント後も duration に Infinity が入っている。play() してしばらくすると duration が取れるようになる。Infinity の間は currentTime に set(seek) ができない。
<li>pause() が動かず再生し続ける。音を停止するには Audio.src = '' をする。再び再生するには Audio.src = source とする。但し音が鳴り始めるまでに 2~3 秒程度時間が掛かる。
<li>再生中に currentTime が変化しない。Date を使って再生時間を管理する。
<li>volume=0, muted=true などとすると、その後の音量変更ができない。
</ul>
<h6>予行演習として</h6>
<p>このように独自エンジンの最後となった Opera12 は支離滅裂な乱れっぷりです。
<p>一方でなんらかの手を講じれば、再生・シーク・停止が確実であることも分かりました。そのため pettanR でもパッチコードをあてて調教することができました。
<p>このような挙動の怪しい古いブラウザのサポートは、挙動の怪しい最新ブラウザが登場した場合の予行演習として行えたらいいですね。コードがよくできていれば綺麗に隠蔽できますし、まずければスパゲッティ化するので諸々思い知ります。
<h4>Opera Mobile 12 で可変ビットレートの再生がボロボロ…</h4>
<p>ところで、可変ビットレート(ogg VBR)な音声ファイルでは duration が正しくなく(短い数値が返る)、currentTime へのセットでは意図した再生位置より後ろから再生されます。
<p>このズレは曲の後の方ほど大きくなり、特に無音部分があると大きくなるようです。
<p>可変ビットレートでは曲の長さと位置を正しく扱えない、と推測して固定ビットレート(mp3 CBR)で音声ファイルを用意したところ意図した再生が行われました。
<h4>Opera12 で 2音以上の再生が乱れる</h4>
<p>描画要素が増える等で Opera12 が忙しくなってくると2音以上の再生が乱れる、という症状にも遭遇しました。
<p>この問題は Android 版に加えて、マシンリソースが潤沢なはずのデスクトップ版 Opera12 (WindowsXP, Windows8) でも遭遇しています。
<h3>続く</h3>
<p>ここまでお付き合いくださりありがとうございます。Presto Opera 祭りとなった中編でした。
<p>えぇと、独自エンジンを辞めた Blink Opera には食指が動かずほとんど触っていません。これは <a href="https://vivaldi.com/">Vivaldi</a> も同様です、悪しからず。
<p>さてさて、<a href="http://outcloud.blogspot.jp/2015/10/audiosprite3.html">次回はさらなるマイナーブラウザが登場</a>します、乞うご期待!
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-19306583392895832782015-05-01T22:43:00.000+09:002018-11-03T14:02:05.039+09:00関西フロントエンドUG座談会#1にて『GPUアニメーションとUIデータバインドについて』LTしてきました<blockquote title="関西フロントエンドUG 座談会 #1 > 関西フロントエンドUGって?" cite="http://kfug.connpass.com/event/11936/"><p>フロントエンド技術の移り変わりの激しさに困り果てた関西のエンジニア達により、勢いで結成された会です。</blockquote>
<p>少し時間が経ってしまいましたが、<a href="http://kfug.connpass.com/event/11936/" target="_blank">関西フロントエンドUG 座談会 #1 </a> というイベントで随分キレの悪いライトニングトークをしてきました。キレが悪いのにライトニングだなんてちゃんちゃらおかしいですね…自戒も込めてビデオ置いておきますね…</p>
<h3>イベント所感</h3>
<p>3月14日、Web アプリケーションのフロントエンドについて語り会いましょう、というピンポイントなイベントが大阪で開催され、20数名の参加者を迎えることになりました。
<p><a href="http://www.ueo.co.jp/" target="_blank">小さい会社</a>で一人だけ js と actionscript の専従という僕にとっては、濃ゆい話の聴ける・できる、またとない機会でした。
<p>ちょっと気になっている js 界隈のワードについて「どうよ?」と問いかけるとすぐに何がしかのレスがあり小気味よかったです。
<p>その上僕の住居から目と鼻の先のご近所での開催ということで自転車でさっと乗りつけて、さっと所用のため家に戻ることのできる、という至便さです。
<h4>となりの芝ではフレームワークを替え替え</h4>
<p>そうそう、案件の度にフレームワークを替えたりしていくつか試した、というお話には随分違うものだなぁ、と思いました。
<p>僕の職場ではとある企業様とお付き合いが数年目で、現在はほぼ年中その開発に取り組ませてもらっています。その Web アプリケーションのコードは長期間熟成の複雑怪奇なジャングルで、ネットスケープ・ナビゲーター 4.x 時代のコードが残っていてですねぇ…
<h3>『GPUアニメーションとUIデータバインドについて』LT の様子ビデオ</h3>
<p>さて、所用というのは他でもなく、イベント開催直前まで粘っても完成しなかった LT 用のビデオを、途中で抜けて完成させて舞い戻る、というものでした。
<p>そのために自己紹介と40分間の js フレームワーク談義のあとは、alt js、css フレームワークと談義は続きますが、僕は一度退場しました。
<p>そして、必死の作業によってライトニングトークは 2人目の途中から、出来立てホヤホヤのビデオと共に帰ってくることができました。
<iframe width="560" height="315" src="https://www.youtube.com/embed/zV_JxK-79D0" frameborder="0" allowfullscreen></iframe>
<p>ボソボソとしゃべっていて分かりずらいことこの上ないですね…
<h4>LT で流していたビデオ</h4>
<iframe width="560" height="315" src="https://www.youtube.com/embed/9e8WJg4ZxGM" frameborder="0" allowfullscreen></iframe>
<p>こちらはそのビデオを抜き出したものになります。
<h3>GPUレイヤーを効かせたアニメーションを Web アプリケーションにも!</h3>
<p>颯爽と現れ js 界隈の話題をさらっていく数々のフレームワーク達。しかしその背景には困難さを増す js 大規模開発の現状が透けてみえます。
<p>そのような困難さが一服したときには、よりネイティブアプリケーションに近づくために、アニメーション効果もばっちり押えておきたいですね。
<h4>ネイティブアプリケーションのようなアニメーション</h4>
<p>Mac OSX のアプリケーションや Windows8 のモダンスタイルのように適切に設定されたアニメーション効果は、ユーザーの理解を助け操作にリズムを生みます。
<p>ネイティブアプリケーションのようなスムースなアニメーションのためには DHTML 時代の setInterval と <acronym title="CSS ポジショニング">css-p</acronym> ではなく、GPU サポートを効かせた CSS3 Transitions と CSS3 Animations が主役です。
<blockquote title="ハイパフォーマンス・アニメーション - HTML5 Rocks" cite="http://www.html5rocks.com/ja/tutorials/speed/high-performance-animations/"><p>モダンブラウザは4つの項目を手軽にアニメーションすることができます。位置(position)、大きさ(scale)、回転(rotation)、透明度(opacity)です。もし、それ以外のものをアニメーションするなら、それはご自分の頑張り次第ですが、絹のようになめらかな60fpsの動画を実現できる可能性は少ないでしょう。
</blockquote>
<p><a href="http://www.html5rocks.com/ja/tutorials/speed/high-performance-animations" target="_blank">先の記事</a>によると僅かに transform(translate, rotate, scale) と opacity が GPU レイヤーが得意とするプロパティのようです。
<p>しかしこの GPU サポートは何かと曲者です。なんと要素が GPU レイヤーで描画されている間に、<a href="https://msdn.microsoft.com/ja-jp/library/cc409712.aspx" target="_blank">ダイナミックコンテント</a>を行うと、transitionend イベントが起きなくなってしまう問題が発生します。
<blockquote title="Dynamic HTML > ダイナミックコンテント" cite="https://msdn.microsoft.com/ja-jp/library/cc409712.aspx"><p>Dynamic HTMLでは、ロードした後でもドキュメントのコンテントを変更できる。(中略)<p>これらを使えば、エレメントの挿入や削除から、個々のエレメント内のテキストや属性の変更まで行える。</blockquote>
<p>ダイナミックコンテントは聞き慣れないかもしれません。<a href="https://msdn.microsoft.com/ja-jp/library/cc409712.aspx" target="_blank">先の記事</a>が IE4 時代のものですが、DHTML(ダイナミックコンテント含む) について大変良くまとまっています、読みましょう。
<h4>牧歌的 DHTML の時代は終わり―</h4>
<p>この症状に遭遇したとき Backbone.js ライクなデータバイドを独自に実装して使用していました。そしてしばしば、要素がアニメーションの最中に XHR が完了しコンテンツを書き換えていました。
<p>安全に要素を書き換えるには、アニメーションの終了を待つか?または elm.style を操作してアニメーションを中断させる必要があります。
<p>これはなかなか頭の痛い問題で、アニメーション中の要素に対してはちょっとコンテンツを書き換えて要素のサイズを測る、といったことができません。
<p>css-p と setInterval を使っている間はいつでも要素の内容を変更できました。しかし現在の Web 開発はネイティブのパワーを引き出すために以前のような気軽さを手放さなくてはなりません。
<blockquote title="pettanR > クライアント関連 > X.Node.Anime の追加" cite="http://sourceforge.jp/projects/pettanr/forums/27899/31275/74655/"><p>コミットログには書き忘れましたが、今回のコミットで 10_XNodeAnime.js を追加しました。
<p>xnode.animate( start, end, duration, easing ) として要素の x, y, 透明度 についてアニメーションが可能です。</blockquote>
<div class="note">
<h5>もうひとつの終わり―</h5>
<p>またこの問題はブラウザを問わず Mac OSX と iOS で頻出します。一方の Windows8 では起きないか、またはほとんど発生しません。
<p>案の定、開発を Windows8 で、客先でのデモをお客様の Mac で行っていたため、肝心なところでなぜか止まるという失態を何度もやらかしました。
<p>試金石にしようと貪欲にいきましたが、いくらかの知見と引き換えに、お客様も失ってしまいましたとさ…
</div>
<h3>この他に言っておきたかったこと</h3>
<ol>
<li>自己紹介 → <a href="/p/profeel.html">これ</a>
<li>pettanR について、はまたいずれ
<li>求人 → <a href="http://www.ueo.co.jp/recruit/" target="_blank">これ</a>
</ol>
<p>ではでは~izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-9870234084867439812015-04-28T20:15:00.000+09:002015-10-02T23:55:07.936+09:00大探検!HTML5オーディオスプライト・前編<h3>HTML5 へのドリームを打ち砕くモバイルブラウザ Audio のめくるめく制限</h3>
<p>かつては flash 等のプラグインに頼っていたオーディオ機能を、Web ブラウザ自体が備えるようになりました。
<p>しかし iOS や Android 用のモバイルブラウザは Audio や Video 機能に制限が多く、デスクトップ版ブラウザで動いたからといって予断を許しません。
<p>有名な制限として、iOS4.0(2010年6月21日, iPhone 3G以降, iPod touch 第二世代以降, iPadは初代から)からモバイル Safari が Audio をサポートします。
しかし、ユーザーによるタッチイベント内で load() しないと音声ファイルをダウンロードできない、という制限があります。
<p>一方の Android は 2.3(2010年12月16日)以降でデフォルトブラウザが Audio に対応します。
この時点では iOS のような制限はありませんが、Android4 の途中から iOS と同じく同時再生数が一音になりユーザーによるタッチも必要になります。
<h4>オーディオスプライトの登場</h4>
<p>これら Audio 制限をうまくなだめてブラウザゲーム等で利用していくためにオーディオスプライトというテクニックが登場します。
<p>さらにオーディオスプライトライブラリがいくつか登場し、そもそもオーディオイベントのタイミングが大きく異なる、などの悩ましい問題をまるっとひっくるめて解決してくれまず。(ときどきし損なっています…)
<p>お仕事でオーディオ機能を使用するにあたって、それらライブラリや記事を拝見しつつ手元の端末で調査を行いました。
<p>結構な分量になってしまいますので、何回かに分けて調査結果をご紹介していきます。
<p>本記事ではリンク先で言及されていない点や現在の状況について補足しますので、リンク先を参照しつつご笑覧ください。
<h3>UnitePlayer.js 2011.12.12~</h3>
<blockquote title="UnitePlayer.js 作ったよ > UnitePlayer はモバイルとゲームに特化した HTML5 な音楽再生プレイヤー" cite="http://uupaa.hatenablog.com/entry/2011/12/12/213233">
<p>UnitePlayer は、モバイルブラウザ上で動作するゲームに音をもたらします。
<p>扱いが難しい Mobile Safari や Android ブラウザの音周りをフォーマット化し、とっても扱いやすくします。</p></blockquote>
<p><a href="http://uupaa.hatenablog.com/">uupaa</a> 氏制作のオーディオスプライトライブラリです。</p>
<a href="http://uupaa.hatenablog.com/entry/2011/12/12/213233">UnitePlayer.js 作ったよ</a>
<p>よくまとまった良記事ですのでまず目を通しておきましょう。uupaa 氏の記事は全般に渡って調査量が半端なく読み応えがあります。他の記事にもどんどん目を通しましょう。例えば WebAudio に関する次のページなどはオーディオに触るにあたってぜひ読んでおきたいところです。</p>
<a href="https://gist.github.com/uupaa/f3ecf8c50412641b4f43">uupaa / Audio.WebAudio.Browser.Compat.md</a>
<p>UnitePlayer.js のライセンス表記がブログ記事中にはなかったので戸惑いましたが、Google Code の <a href="https://code.google.com/p/uupaa-js-spinoff/">uupaa-js-spinoff</a> に従うなら <q cite="">MIT License</q> になりそうです。
<p>2011年の記事のため、現状と異なる点に注意が必要です。僕の調査で判明した情報を補っていきますと…
<h4>Android2.x ~ 4.? デフォルトブラウザは再生時間を補正</h4>
<blockquote title="UnitePlayer.js 作ったよ > ゴニョゴニョ" cite="http://uupaa.hatenablog.com/entry/2011/12/12/213233">
<p>Android は再生時間が短い(0.1~0.5秒)と再生されたりされなかったりと不安定になるため、内部で再生時間を延長する等の補正を行なっています</p></blockquote>
<p>Android ブラウザについて、短い音声の再生には、再生時間を少しだけ長く指定する必要があります。
<p>コードを拝見すると、Android に対しては 0.2 秒を、さらに一秒未満の音声に対しては 0.4 秒を追加しています。手元の Android 2.3.5 端末でもこの処理は適当で音が途切れる問題が解消されました。
<blockquote title="UnitePlayer.js Compressed Source Code" cite="https://code.google.com/p/uupaa-js-spinoff/wiki/UnitePlayer_API#.js_Compressed_Source_Code">
<pre class="prettyprint lang-js"><code>x = /Android/.test(n) ? parseFloat(n.split("Android")[1]) || 2.3 : 0,
</code></pre>
<pre class="prettyprint lang-js"><code>x && (g && (g += 0.2), 1 > g - e && (g += 0.4));
</code></pre>
</blockquote>
<p>記事の時点では、Android4.x が登場していませんが、僕の調査ではこの補正は Android4.1.1(ドスパラパッド, Webkit 534.3) に対しては必要で、Android4.4.4(Nexus7, Y! Browser, Webkit 537.36) では不要でした。Webkit バージョン 534.3 ~ 537.36 のどこかでメディア周りの挙動が大きく変わったようです。
<h4>Android 上で動作する Mobile Firefox の再生でノイズ</h4>
<blockquote title="UnitePlayer.js 作ったよ > Mobile Firefox に関する制限" cite="http://uupaa.hatenablog.com/entry/2011/12/12/213233">
<p>ogg は再生できますが mp3 は再生できません
<p>ogg の再生でノイズが乗り正常に再生不能です
</blockquote>
<p>Mobile Firefox のバージョンが示されていませんが、記事の日付を元に version 8.0(リリース2011年11月8日)ではないかと思われます。僕の手元の Android2.3.5 + Firefox31 では正常に動作します。
<h5>Fennec はいつから正常化したの?</h5>
<p>どのバージョンでオーディオ機能が正常化したのか?特定したうえで Flash に切り替えたり No Audio にしたいところです。そのためにこの間の Audio 関連のアップデートを見ていきますと、次の更新が見つかりました。
<blockquote title="Firefox Notes - Mobile (August 28, 2012)" cite="
http://website-archive.mozilla.org/www.mozilla.org/firefox_releasenotes/en-US/mobile/15.0/releasenotes/"><p>HTML5
Native support for the Opus audio codec added</p></blockquote>
<blockquote title="Firefox Notes - Mobile (April 11, 2013)" cite="
http://website-archive.mozilla.org/www.mozilla.org/firefox_releasenotes/en-US/mobile/20.0.1/releasenotes/"><p>HTML5 Various <audio> and <video> improvements</p></blockquote>
<a href="http://blog.pearce.org.nz/2012/12/html5-video-playbackrate-and-ogg.html">HTML5 video playbackRate and Ogg chaining support landed in Firefox</a>
<p>また Firefox は 25 以降でボリュームの調整が可能になったそうです。
<h4>Android 上で動作する Opera Mobile でロジックが組めない</h4>
<blockquote title="UnitePlayer.js 作ったよ > Opera Mobile に関する制限" cite="http://uupaa.hatenablog.com/entry/2011/12/12/213233">
<p>audio.addEventListener でイベントハンドラがコールバックされません
<p>コールバックされないため、まともにロジックが組めません。再生するぐらいしかできません</blockquote>
<p>Opera Mobile のバージョンが示されていませんが、記事の日付を元に Opera Mobile 11 ではないかと推察されます。
<p>僕が調査した Opera Mobile 12 ではイベントハンドラがコールバックされます。
<p>しかし currentTime と duration に<del>奇怪な</del>個性的な挙動があり、併せて再生できる音声ファイル形式にも大きな制限がありました。(症状と解決法は次回に譲ります。)
<h3>つづく…</h3>
<p>結構な分量になってしまったので前編はここまで、<a href="http://outcloud.blogspot.com/2015/05/audiosprite2.html">中編</a>に続きます。
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-82825520880727350772015-04-27T22:21:00.003+09:002021-07-13T15:06:53.246+09:00Bloggerの記事のプレビューを爆速にするカスタマイズ<p><q>コメントフォーム用 iframe の生成を読者による操作の後に行うようにすれば、プレビュー画面といわず常に高速にページを表示することだってできます。</q> を<a href="http://outcloud.blogspot.jp/2015/05/bloggerminify.html">実施しました</a>。2015.5.22
<h3>Blogger のプレビュー画面の判定法</h3>
<p><a href="http://outcloud.blogspot.jp/2015/04/bloggerminify.html">前回のカスタマイズ</a>で著しく高速化・軽量化した My Blogger をさらに高速&軽量にしてみます。</p>
<p>僕は Blogger の記事の執筆を Web エディタの HTML モードで行っているため、所以、プレビューと編集画面を何度も行き来しています。
<p>そんな折に気付いたのですが、このプレビュー画面は <code>data:blog.url == data:blog.homepageUrl</code> でありながら、アイテムページである、という特殊なフラグが立っているのです。
<p>カスタマイズに慣れている方ならご存知の通り通常であれば <code>data:blog.url == data:blog.homepageUrl</code> はインデックスページになります。
<p>このフラグによって現在がプレビューページだということが検出できるので、プレビューに不要なウィジェットを削除してしまえば、プレビュー画面を高速に表示することが出来ます。
<p>そこで今回はコメントフォームを削除しました。該当部分のテンプレートは次になります。
<pre class="prettyprint lang-html"><code><!-- preview でコメントフォームを表示しない -->
<b:if cond='data:blog.pageType == &quot;item&quot; and data:blog.url != data:blog.homepageUrl'>
<b:include data='post' name='comment-form'/>
</b:if>
</code></pre>
<p>そうそう、いつの間にか条件式に and と or が使えるようになっていました。このおかげで若干テンプレートが簡潔に書けるようになりました、ありがたいですね。</p>
<h3>コメントフォームを削って転送量の測定</h3>
<div class="box">
<a href="http://4.bp.blogspot.com/-gICgYshMnvM/VT42p501U-I/AAAAAAAAPyU/svOsUVgAiq4/s1600/no_comment_form.png"><img src="http://4.bp.blogspot.com/-gICgYshMnvM/VT42p501U-I/AAAAAAAAPyU/svOsUVgAiq4/s200/no_comment_form.png" /></a>
<p>この状態で転送量を見てみますと僅かに 24.9KB, 7 リクエスト。これは個人ホームページ時代の簡素な Web ページを見ているようです。
<p>一方で一旦記事を公開しコメントフォームを読み込んだ状態では、66.7KB, 13 リクエストとコメントフォームが大きな割合を占めていることが分かります。</p>
</div>
<p>今回のカスタマイズによって、無駄なリクエストを無くして高速に投稿のプレビューができるようになりました。
<p>さらに、コメントフォーム用 iframe の生成を読者による操作の後に行うようにすれば、プレビュー画面といわず常に高速にページを表示することだってできます。
<p>ともかくもこのカスタマイズを活用すれば、通信料に上限があったり低速なネットワーク環境での Blogger の運用性が向上しますね!izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-28067970368732920612015-04-26T17:49:00.001+09:002021-07-13T15:06:53.244+09:00BloggerでGoogle製jsの読み込みを辞めて超軽量化、但しコメントフォームは動かす<div class="note">
<p>Blogger の挙動が変わり <head> タグの最初の子に css が追加されるようになりました。これを無効にする方法を<a href="#ins_2017_5_10">追記</a>しました。2017.5.10
<p>不具合に対策し<a href="/2015/05/bloggerminify.html">続き</a>を書きました。2015.5.22
</div>
<h3>いざ、禁断のカスタマイズへ</h3>
<p>Google のブログサービス、Blogger をアグレッシブにカスタマイズしたところ、とあるページにて <strong>総リクエストサイズを 27%</strong> にすることが出来ました。
<p>とはいえ通常は手をつけないような思い切ったカスタマイズを行っているため、どこにどんな不具合が出るやら。
<p>僕は好奇心に負けてカスタマイズしてしまいました。リスクと効果を天秤に掛けて割に合わないことをしていると思います…
<p>本記事はカスタマイズ方法の紹介に留まらず、万が一(どころでなく十が一)の復旧のために書き残しています。
<p>もしこの記事を参考にカスタマイズを行う場合は諸々のリスクを覚悟し、バックアップを取る・テスト用のブログでテストを重ねる、など慎重に進めましょう。Enjoy!
<p>また現在確認している不具合は次になります。どちらも対処が可能ですが一旦放置しています(汗
<ol>
<li>ブログアーカイブの Ajax メニューが動作しない。
<li>画像のライトボックス表示機能が動作しない。
<li>js が無効の場合もコメントフォームが表示され動作しない。
</ol>
<h3>デフォルトの CSS を読み込まない</h3>
<p></head> の手前で以下のように書きます。必要な自前の CSS は <link> タグなどで読み込みます。
<pre class="prettyprint lang-html"><code>&lt;style type=&quot;text/css&quot;&gt;
&lt;!-- /*<b:skin></b:skin>
</code></pre>
<a name="ins_2017_5_10"></a>
<h4>追記 2017.5.10</h4>
<p>おそらく今日から <head> タグの最初の子として css(<link type='text/css' rel='stylesheet' href='https://www.blogger.com/static/v1/widgets/1691512649-css_bundle_v2.css' />)が追加されるようになっています。これをコメントアウトで無効化するには次のようにします。
<pre class="prettyprint lang-html"><code>&lt;!-- <head> --&gt;&lt;head prefix='og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#'&gt;
</code></pre>
<h3>デフォルトの js を読み込まない</h3>
<p></head> の部分を次のようにして head の閉じタグの直前に挿入される <script> を無効化します。
<pre class="prettyprint lang-html"><code>&lt;!-- </head> --&gt;&lt;/head&gt;
</code></pre>
</body> の部分を次のようにして body の閉じタグの直前に挿入される <script> を無効化します。
<pre class="prettyprint lang-html"><code>&lt;!-- </body> --&gt;&lt;/body&gt;
</code></pre>
<h3>コメントフォームの DHTML を切って静的に埋め込む</h3>
<div class="note"><p>以下の内容には、js が切られている場合もコメントフォームが読み込まれてしまう不具合があります。コメントフォームのために約30KBの html, css, js がロードされます。
<p>この不具合に対策済のコメントフォームの究極軽量化については『<a href="/2015/05/bloggerminify.html">Bloggerを究極軽量化してワンコインSIMで爆速表示する</a>』を確認ください。(2017/10/06 追記)
</div>
<p>コメントフォームのためのメタタグは次のようなものです。
<pre class="prettyprint lang-html"><code><a expr:href='data:post.commentFormIframeSrc' id='comment-editor-src' style='display:none'/>
<iframe allowtransparency='true' class='blogger-iframe-colorize blogger-comment-from-post' frameborder='0' id='comment-editor' name='comment-editor' src='' width='100%' height="276"/>
<data:post.friendConnectJs/>
<data:post.cmtfpIframe/>
<script type='text/javascript'> BLOG_CMT_createIframe(&#39;<data:post.appRpcRelayPath/>&#39;,&#39;<data:post.communityId/>&#39;);
</script>
</code></pre>
<p>src が空の iframe に対して js でコメントフォームの url を設定しています。
<p><data:post.friendConnectJs/> と <data:post.cmtfpIframe/> で js のインポートをしています。これらを読み込まなくても src さえ正しく設定されればコメントフォームは動作しています。
<p>これを次のようなタグに変更します。
<pre class="prettyprint lang-html"><code><iframe allowtransparency='true' frameborder='0' expr:src='data:post.commentFormIframeSrc' width='100%' height='276'/></code></pre>
<h4>いつの間にかブログ ID が取得できるように</h4>
<p>下の code は記事へのコメント投稿は動作しましたが静的ページでコメントフォームを読み込めませんでした。上のコードは投稿と静的ページ、どちらでも動作します。
<pre class="prettyprint lang-html"><code><del><iframe allowtransparency='true' frameborder='0' expr:src='&quot;//www.blogger.com/comment-iframe.g?blogID=&quot; + data:blog.blogId + &quot;&amp;postID=&quot; + data:post.id' width='100%' height="276"/></del>
</code></pre>
<p>ところで、いつの間にかブログ ID が取得できる(<code><data:blog.blogId/></code>)ようになっていますね。
<p>今まではこのタグが使えなかったため、手動で blogID を書いていました…(遠い目
<h4>iframe のハッシュにコメントフォームの css 情報を埋め込む</h4>
<p>ちなみにオリジナルのコメントフォームでは、iframe の src にはハッシュフラグメントにスタイル定義が埋め込まれていました。
<p>控えていたものを次に貼っておきます。但し、実際に指定が iframe 内に反映されているか?は試していません、悪しからず。
<pre class="prettyprint lang-js"><code>// ハッシュ文字列
'#{"color"%3A"rgb(0%2C 0%2C 0)"%2C"backgroundColor"%3A"rgb(0%2C 0%2C 0)"%2C"unvisitedLinkColor"%3A"rgb(0%2C 0%2C 238)"%2C"fontFamily"%3A"\"Hiragino Kaku Gothic Pro\"%2C\"\uff2d\uff33 \uff30\u30b4\u30b7\u30c3\u30af\"%2COsaka%2C\"\u30d2\u30e9\u30ae\u30ce\u89d2\u30b4 Pro W3\"%2C\"\u30e1\u30a4\u30ea\u30aa\"%2CMeiryo%2Csans-serif"}'
// decodeURIComponent & format
{
"backgroundColor": "rgb(0, 0, 0)",
"color": "rgb(0, 0, 0)",
"fontFamily": "\"Hiragino Kaku Gothic Pro","MS Pゴシック",Osaka,"ヒラギノ角ゴ Pro W3,"メイリオ",Meiryo,sans-serif\"",
"unvisitedLinkColor": "rgb(0, 0, 238)"
}
</code></pre>
<h3>転送量を計測してみます</h3>
<table cellspacing="0">
<thead>
<tr><th>比較<th>軽量化前<th>軽量化後<th>減量率
<tbody>
<tr><td>jsリクエスト数<td>9 件<td>4 件<td>44.4%
<tr><td>jsリクエストサイズ<td>289.9 KB<td>43.5 KB<td>15.0%
<tr><td>総リクエスト数<td>26 件<td>20 件<td>76.9%
<tr><td>総リクエストサイズ<td>347.0 KB<td>93.7 KB<td>27.0%
</table>
<p>以下に計測に使用した Firefox + Firebug のスクリーンキャプチャを添付します。
<div class="box">
<a href="http://4.bp.blogspot.com/-JxvUMlsmHgA/VTyVrLs7zuI/AAAAAAAAPxc/ewK_DU7DCC0/s1600/loadFull_all_347KB.png"><img src="https://4.bp.blogspot.com/-JxvUMlsmHgA/VTyVrLs7zuI/AAAAAAAAPxc/ewK_DU7DCC0/s60/loadFull_all_347KB.png"></a>
<p>軽量化前の全てのリクエストです。
</div>
<div class="box">
<a href="http://3.bp.blogspot.com/-d3qs1vZscxc/VTyVrEXLQZI/AAAAAAAAPxg/3mW3QuDtZQc/s1600/loadFull_js_290KB.png"><img src="https://3.bp.blogspot.com/-d3qs1vZscxc/VTyVrEXLQZI/AAAAAAAAPxg/3mW3QuDtZQc/s60/loadFull_js_290KB.png"></a>
<p>軽量化前の js のリクエストです。
</div>
<div class="box">
<a href="http://3.bp.blogspot.com/-AncegnZTONc/VTyVrK28rAI/AAAAAAAAPxY/F9NsqnhmoB8/s1600/loadMini_all_94KB.png"><img src="https://3.bp.blogspot.com/-AncegnZTONc/VTyVrK28rAI/AAAAAAAAPxY/F9NsqnhmoB8/s60/loadMini_all_94KB.png"></a>
<p>軽量化後の全てのリクエストです。
</div>
<div class="box">
<a href="http://3.bp.blogspot.com/-o3-VoHtAQuo/VTyVsPlnhTI/AAAAAAAAPxk/53J6ZcM2f6E/s1600/loadMini_js_44KB.png"><img src="https://3.bp.blogspot.com/-o3-VoHtAQuo/VTyVsPlnhTI/AAAAAAAAPxk/53J6ZcM2f6E/s60/loadMini_js_44KB.png"></a>
<p>軽量化後の js のリクエストです。
<p>ひとつは自分で追加したコードハイライターのもの。残りの三つはコメントフォームの iframe が呼び出しているものです。
</div>
<h4>javascript のグローバル空間の様子</h4>
<div class="box">
<a href="http://1.bp.blogspot.com/-lFn9BRkwzvk/VTyZ8RAlhxI/AAAAAAAAPx8/3r-w1KS4PJE/s1600/loadFull_DOM.png"><img src="https://1.bp.blogspot.com/-lFn9BRkwzvk/VTyZ8RAlhxI/AAAAAAAAPx8/3r-w1KS4PJE/s60/loadFull_DOM.png"></a>
<p>軽量化前の Firefox の DOM パネルの様子です。
<p>グローバル空間に様々なプロパティがぶちまけられています。これではブラウザアドオンや外部スクリプトと干渉しないかとヒヤヒヤものです。
</div>
<div class="box">
<a href="http://4.bp.blogspot.com/-3A4C_b7Um4U/VTyZ9v6az6I/AAAAAAAAPyA/Z18OI1PF070/s1600/loadMini_DOM.png"><img src="https://4.bp.blogspot.com/-3A4C_b7Um4U/VTyZ9v6az6I/AAAAAAAAPyA/Z18OI1PF070/s60/loadMini_DOM.png"></a>
<p>軽量化後の Firefox の DOM パネルの様子です。コードハイライターのオブジェクトが追加されているだけです。
</div>
<h3>最後に</h3>
<p>数百Kbit/秒 という転送速度のワンコインデータ通信 SIM が登場してしばらく経ちます。ISDN 時代の再来のような軽量な Web 開発の重要性が再び増しつつあるのではないでしょうか?
<p>さぁ、今こそあなたの Blogger も肥大化した <script> を捨て去るときです!なんちゃって…izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-58066858007288253472015-04-25T15:41:00.002+09:002022-02-26T19:26:38.179+09:00Virtual DOMや非同期なDOM操作のメリットと悩ましい点<div class="box"><a href="//4.bp.blogspot.com/-MucXmjQQKJQ/VPvzYA8GrlI/AAAAAAAAPu0/uL4fY7khq7I/s1600/pettanR_panelEditor.png"><img src="//4.bp.blogspot.com/-MucXmjQQKJQ/VPvzYA8GrlI/AAAAAAAAPu0/uL4fY7khq7I/s200/pettanR_panelEditor.png"></a>
<p>ここしばらく耳にするようになった Virtual DOM ですが、実は拙作 <a href="http://sourceforge.jp/projects/pettanr/" target="_blank" title="ぺったんR プロジェクト日本語トップページ - SourceForge.JP">pettanR</a> というプロジェクトのために開発している UI フレームワーク、その DOM 操作レイヤーでも Real DOM 操作を非同期化していて Virtual DOM (っぽい)実装になっています。
<p>ここで、<em>“っぽい”</em>としたのは、diff/patch という発想が無いことによります。
</div>
<blockquote cite="http://qiita.com/mizchi/items/4d25bc26def1719d52e6" title="VirtualDom - なぜ仮想DOMという概念が俺達の魂を震えさせるのか - Qiita">
<p>このHTMLの生成する元となるツリー構造は、生のDOM(HTMLのインスタンス)である必要はなく、DOMと1対1に対応する単純な構造体で表現し、それを仮想DOMと呼びます。</p>
<p>Virtual DOM実装といった場合、仮想DOMの構造体表現と、それを用いたdiff/patchアルゴリズムを指します。</p></blockquote>
<p>ちなみに、pettanR の DOM 操作レイヤーの API は一見 jQuery によく似ていて、DOM 操作を非同期化した jQuery とでもいった風です。DOM 操作レイヤーの最初のコミットは 2013-07-19、このレイヤーを完全非同期化したのは <a href="http://sourceforge.jp/projects/pettanr/forums/27899/31275/71905/" target="_blank">2014-02-16</a> からとなっています。しかし <a href="http://sourceforge.jp/projects/pettanr/" target="_blank" title="ぺったんR プロジェクト日本語トップページ - SourceForge.JP">pettanR</a> の紹介はまたに譲ることとします。
<p>本記事では自身でも非同期な DOM をやってみた経験から、メリットとデメリットについて触れてみます。
<h3>非同期化した DOM のメリット</h3>
<p>メリットとしてまず思いつくのが、DOM 操作の非同期化によって、最終的な値だけが Real DOM に渡される、という点です。
<p>あまりに酷い例ですが、以下のように、通常であれば 2 度 HTML 要素のプロパティにアクセスしてしまう書き方をしても、実際に要素に触るのは一度、ということになります。
<pre class="prettyprint lang-js"><code class="js">$('#msg').css('color','red');
if( !disabled ) $('#msg').css('color','green');</code></pre>
<p>ところで以上のような変更を蓄えておいて適当なタイミングで一挙に patch、という最適化は当のブラウザ自身がやっていることです。これを js (フレームワークまたはライブラリ)レベルでも似たようなことをしている、と書くとちょっと微妙にきこえてきませんか?
<p>DOM 操作を非同期化することには、patch を纏める他にもメリットがあります。
<p>説明のために、次に、要素を生成し、属性などをセットし、文書ツリーに追加する、というよくある流れを示します。
<h4>生 javascript の例</h4>
<pre class="prettyprint lang-js"><code class="js">var elm = document.createElement('div');
elm.style.opacity='0.5';
parent.appendChild(elm);</code></pre>
<h4>jQuery の例</h4>
<pre class="prettyprint lang-js"><code class="js">var $elm = $('div')
.css('opacity',0.5)
.appendTo(parent);</code></pre>
<p>jQuery を使った場合、opacity に対応していない IE8 以下に対しても filter を使った半透過を施してくれて素晴らしいですね。プログラマは filter 指定の詳しい書き方を忘れてしまっても構いません。
<p>さて、ここでおやっと思った方いらっしゃいますね、そうです、実は先に示した順番では filter が意図したように働かないのです。IE の filter には要素が文書ツリーに追加された後に filter を指定しないと働かない、という欠陥があるためです。
<p>プログラマは filter 指定の方法を忘れることはできますが、IE8 以下では先に文書ツリーに追加しそのあとから css (filter) をいじる、ということを依然として憶えていなくていけません。
<pre class="prettyprint lang-js"><code class="js">$elm.appendTo(parent).css('opacity',0.5);</code></pre>
<p>一方の 非同期 DOM では、Virtual DOM への変更が即座に Real DOM には反映されません。つまり、非同期 DOM フレームワークがブラウザを判定して最善のタイミングと方法を切り替えてオッケー、ということになります。
<ol>
<li>どのタイミングで文書ツリーに追加するか?その際の documentFragument 使用の有無は?
<li>属性やスタイル・イベントをセットするタイミングは?
</ol>
<p>IE8 以下では、先に文書ツリーに追加した後で css を更新します。一方他の多くのブラウザは、全ての属性を設定した後で文書ツリーに追加する、という最も自然なタイミングで操作するのが有利です。
<p>また、新規に生成した要素に子要素がある場合ですが、通常は全ての子要素を追加した上で、最後に文書ツリーに追加するのが有利とされます。一方で<a href="https://msdn.microsoft.com/ja-jp/library/bb250448.aspx" target="_blank" title="Internet Explorer リーク パターンを理解して解決する">古い IE には、要素の文書ツリーへの追加タイミングに絡むメモリリーク</a>もあります。
<p>このようなことをプログラマーが覚えておくのは大変ですが、非同期化された DOM であれば、フレームワーク内で適切に処理してくれるので、プログラマーは忘れることができます。
<h3>非同期化された DOM の悩ましい点</h3>
<p>メリットの一方で、非同期化することで遭遇した悩ましい点も紹介します。
<pre class="prettyprint lang-js"><code class="js">$("<img>").appendTo(document.body).on("load",onLoad).attr("src","hoge.jpeg");</code></pre>
<p>以上のようなコードの場合、jQuery では <img> の生成→ <body> に追加→ load イベントの監視→ src 属性の設定 という記述した順序で行われます。結果 onLoad 関数が(エラーの場合を除いて)確実に呼ばれることが期待できます。
<p>一方の非同期 DOM ではいろいろあれで、Real DOM への操作の順序をフレームワーク利用者が細かくコントロールする手段を用意しないかもしれません。これがどう悩ましいかといいますと、プログラマーが以下のような順序を期待したとします。
<pre class="prettyprint lang-js"><code class="js">var elm = document.createElement("img");
elm.setAttribute("src", "hoge.jpg");
elm.addEventListener("load", onLoad, false);
document.body.appendChild(elm);
</code></pre>
<p>この場合、hoge.jpg がキャッシュから読み込まれると src の設定で直ちにロード完了してしまい、onLoad が呼ばれないかもしれません。そしてプログラマーは(これはかなりひねくれてますが)onLoad が呼ばれないケースがあることを期待している奇抜な人かもしれません。
<p>このように細かく操作の順番をコントロールする手段をフレームワーク利用者に提供するには、非同期 DOM は操作を単に蓄えるのではなく、操作の順番も控える必要があります。
<p>これはさすがに割に合わないように思われ、pettanR では常にイベントの監視(addEventListener)が先としています。そして load イベント等の引き金になる src 等の属性は後のほうで行う、と決めうちにしています。
<p>IE7 以下には、要素生成時に設定しておかないと無視される属性(form 部品の name や iframe の frameborder など)もあるので、生成時に適用する属性と最後に適用する属性(src 等通信イベントに絡むもの)を分けなくてはいけません。
<pre class="prettyprint lang-js"><code class="js">// for IE7-
var elm = document.createElement('<iframe name="hoge" frameborder="0">');</code></pre>
<h3>最後に</h3>
<p>“決めうちにしてしまう”こう書いてふと頭をよぎるのが、<a href="http://postd.cc/zero_framework_manifesto/" target="_blank">JSフレームワークはもうこりごり</a>という記事です。
<blockquote cite="http://postd.cc/zero_framework_manifesto/" title="JSフレームワークはもうこりごり">
<p>イベントの伝達方法やサポートされるタグの種類等、ブラウザ間における基礎的な要素に関してでさえ仕様が合致し
ていなかったのです。</p>
<p>そのためフレームワークとは、欠点をカバーするだけではなく、ブラウザの動作仕様を規定する独自モデルを構築するものでした。</p>
</blockquote>
<p>こういったブラウザの欠点は解消しつつあるように思います。
<p>一方で最近の、Web ブラウザ内でネイティブの力を引き出していこう、という流れは、GPU という今まで隠蔽されていたものを表に引きずり出して、Web 開発に新たな困難さをもたらしているように思います…
<p>これを丸く治めるためにはフレームワークはアリだと僕は思います。これについてはまた改めて書きたいと思います。ではでは。
<p>そうそう、ブログのデザインをいじって今はとってもいい気分です。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-31945435410902894002015-04-01T10:29:00.000+09:002015-12-03T17:47:00.860+09:00IE4以上をサポートするjQuery0系の開発に注力<div class="box"><a href="http://4.bp.blogspot.com/-1vQE4xE6GTc/VRoU7N4h3bI/AAAAAAAAPw0/oY3b3RXPooo/s1600/jquery0.png"><img src="http://4.bp.blogspot.com/-1vQE4xE6GTc/VRoU7N4h3bI/AAAAAAAAPw0/oY3b3RXPooo/s200/jquery0.png" /></a>
<p>jQuery チームによって本日発表された新しい jQuery のロードマップでは、1系(2006~) 及び 2系(2012~)の開発は終了し、0系の開発に注力するという.</p>
<p>
初めて耳にする0系だがこれは、jQuery1.0α(2006年6月)の公開以前に開発されていたリリース候補の一つであったそうだ.これを元に、<q>最新のブラウザから ie4 まで、DHTML をサポートする全てのブラウザをサポートするべく開発を進める</q>、としている.このほどはその0系のアルファ版が公開された.</p>
</div>
<h3>ブラウザ戦争の覇者 ie4 のサポート</h3>
<p>jQuery が公開された2006年と言えば、ie6(2001年8月27日) のリリースから5年が経過し、10月には ie7 の公開を控えている.すでに ie4(1997年9月30日)のブラウザシェアはごくわずかだった.<p>
<p>この時期に W3C DOM (ie は 5 以降で対応)をサポートしない ie4 のサポートに取り組んでいたというのは妙な話に聞こえるかもしれない.</p>
<p>これに対する jQuery チームの答えは次のようなものだ.</p>
<blockquote>
<p>Windows Mobile 5.0 (2005年8月23日発表) のデフォルトブラウザ、 Mobile IE は ie4 をベースとしていた.</p>
<p>当時 Web 開発者の間では、Microsoft は独自 DOM への野心を捨てきれずモバイルブラウザで巻き返しをはかっているのではないか、と囁かれていた.</p>
</blockquote>
<p>このような認識から、リリース候補の中には、ie4 以上で動作するものがあったという.ところで、Windows Mobile 5.0 端末といえば、日本では WILLCOM W-ZERO3 (2005年12月)が有名だ.</p>
<p>しかし、今日のような満足な開発環境の揃わない中では(初期の開発はメモ帳で行われていたという)、IE4 への対応は困難を極めた.</p>
<p>結局 jQuery 1.0 は、IE5.5 対応としてリリースされた(2006年6月).そして 1.3 以降は ie6 の以上対応となる.</p>
<p>通常の Web 開発では、テストや開発の工数が膨れ上がるのを避けるため、ブラウザシェア等を判断材料に対応ブラウザを選定するのが一般的だ.</p>
<p>しかし、現在のように開発・テスト環境が充実し、ベストプラクティスやライブラリ・フレームワークが流通するようになると、Web 開発にかかるコストは劇的に下がっていると jQuery チームはいう.</p>
<p>そしてこの機に対応ブラウザを、DHTML をサポートする全ての Web ブラウザに拡大したい、としている.</p>
<h3>グレイスフルデグラデーションの崖</h3>
<p>この数ヶ月間の jQuery チームは、jQuery が基本ライブラリのデファクト・スタンダードになったことで、jQuery の対応ブラウザか否かで、UX(ユーザーエクスペリエンス)に大きな落差が出来てしまう、という問題に注目してきた.</p>
<a href="http://2.bp.blogspot.com/-HwhDPdIZV4c/VRoIllHigQI/AAAAAAAAPwk/VBbOitxqxEY/s1600/GracefulDegradation.png" ><img src="http://2.bp.blogspot.com/-HwhDPdIZV4c/VRoIllHigQI/AAAAAAAAPwk/VBbOitxqxEY/s480/GracefulDegradation.png" /></a>
<p>図・グレイスフルデグラデーションに沿ってブラウザの機能に応じて段階的にインタラクションを減らしていくが、jQuery の対応ブラウザから外れると、突然にグラデーションが途切れて UX が落ち込んでしまう.</p>
<p>jQuery から見放されたブラウザは web コンテンツへのアクセスが途端に限定される.</p>
<p>とくに、新しいブラウザが提供されない型遅れのモバイル端末などでは、新たな OS のインストールも難しいため、ついに Web サービスの利用に支障をきたすと端末は価値を大きく損なってしまう.</p>
<p>web サイトが0系を使って構築されれば、このような事態は起こらない、としている.</p>
<h3>最新ブラウザのユーザにも恩恵</h3>
<p>とはいえ、ie4 のようなブラウザシェアの極端に落ち込んだ環境をサポートするコストによって、jQuery のイノベーションは減速し、結果、大多数の最新ブラウザのユーザは割りを喰うことにならないか?</p>
<p>このような質問に対して jQuery チームは、現在のあなたはたまたま最新のブラウザを使う恩恵に与れているだけで、未来に渡ってそうであり続ける、などとは思わないことだ、と前置きした上で、</p>
<p>ie4 のサポートは W3C DOM 以降のモダンブラウザを使うユーザーにも恩恵はある、という.</p>
<p>具体的には、<q>ie4 の独自 DOM に対応するため DOM 抽象化レイヤーや、かねてから研究していた DOM 操作の非同期化を導入したが、コードが整理され全般的なパフォーマンスも向上する見込み</q>、ということだった.</p>
<p>さらに将来にわたって、バグやその他の理由で非標準準拠な挙動をするブラウザが現れても、DOM 抽象化レイヤーで吸収していく基盤ができた、という.</p>
<p>また、DOM をサポートしながらも、jQuery が動作せず恩恵を受けられなかったブラウザ、これらにもサポートを広げていくそうだ.(IE5.x 相当の IE for CE や NetFront 3.4 以降などがそれにあたる.)</p>
<h3>セキュリティに関して</h3>
<p>ところで、古いブラウザをサポートし続けることで、ユーザーがセキュリティリスクの高まってしまったブラウザを使い続けることを間接的に後押ししてしまわないか、という意見があるかもしれない.</p>
<p>最後にこの点に関する JQuery チームの見解を紹介しよう.</p>
<blockquote>
<p>セキュリティに関して js ライブラリ開発者の立場から言えることは限られる.個人的には、ネットサーフィンにはウィルスの出回っていない Windows CE の IE for CE を使うのが今のところ最も安全に思う.</p>
</blockquote>
<p>最近の製品では Windows CE 6(ブラウザは IE6 相当)搭載のネットブック AKRT シリーズ (パチンコ屋の景品交換で手に入るようだ)は、XP サポート終了後のパソコンとしてお勧めだそうだ.</p>
<p>デファクト・スタンダードである jQuery が0系に置き換わっていけば、間もなくこれに、SigmarionII(H/PC2000, Windows CE 3, IE for CE は ie4sp2 ベース) や SigmarionIII(Windows CE 4, IE for CE は ie5.5 ベース)、モバイルギア MC-R450(同CE3)、MC-R550(同CE3) などが加わるだろう.</p>
<h3>関連リンク</h3>
<div class="links"><a href="http://blog.jquery.com/" target="_blank">jQuery ZERO roadmap | Official jQuery Blog</a></div>
<p>現在、該当 blog 記事は公開を一時取り下げているようです.</p>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-33994979560440886442014-03-08T21:52:00.001+09:002015-05-22T17:27:14.628+09:00iGoogle と Google Reader が終了して<p>再開にあたって、古いですがまずはこの話題から…</p>
<h3>Google サービスの終了</h3>
<p><a href="http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CCgQFjAA&url=http%3A%2F%2Fwww.google.co.jp%2Fhelp%2Fig%2Fproduct%2F&ei=DQIbU4KDBcf0oATTpoIQ&usg=AFQjCNHKcbscQ5UrdJT4_ofi7vruv9dEnw&sig2=kDfO6JhmDG8ooSwksH_FwA&bvm=bv.62578216,d.cGU&cad=rja">iGoogle(2005年5月~2013年11月1日)</a> と Google Reader(2005年10月~2013年7月) がそれぞれ終了しました.</p>
<p>特に Google Reader 推しで iGoogle と併せて gadgetOS なんて珍奇なものを作りかけていた僕にとっては、自分のトレンドオンチっぷりにもう笑うほかありません orz</p>
<h4>全てのフィード・エントリを無限に蓄え続けている</h4>
<p>そんな Google Reader の終了に際しては、代替サービスの機能比較・紹介記事が上がったりしていました.</p>
<p>その中でも、言及している記事を見なかったのが、<strong>Google Reader は、全てのフィード・エントリを無限に蓄え続けていていつでも遡ることができる</strong>が、他の代替サービスはどうなの?という点です.</p>
<p>なんと、フィードの提供の止まった(終了した)サイトでも、購読者が存在する限りデータを持ち続けているとか.さすが Google 兄貴.</p>
<p>代替サービスに移行したときに、Google アカウントを紐付けてあげるとバックグラウンドで Google Reader API から過去のエントリーを全て読み込む、なんてことは、していないだろうな、多分.</p>
<p><em>さぁ、諸君!こうして、われわれは、またひとつ記憶を失ったのだよ.</em></p>
<p>ふぅ.</p>
<h3>お久しぶりです</h3>
<p>さて、いつの間にか、最後の日記から 2 年と少しが過ぎていました.</p>
<p>その後の僕は、おかげさまで職を得て、現在は概ね楽しくやっております.</p>
<p>趣味の開発の方はといいますと、2 年前の最後の日記を書いた頃には知人と一緒に始めたプロジェクト用に、js で Web アプリのフロントを書き始めていました.</p><p>半年くらいで終えて、gadgetOS に戻るだろう、と高をくくっていましたが、案の定現在も絶賛開発中です(汗)</p>
<p>Web API を抽象化する OS (のような Web アプリ)、という gadgetOS のテーマは共同プロジェクトでも追求していきます.</p>
<h4>俺と Flash と艦コレと</h4>
<div class="box">
<a href="http://1.bp.blogspot.com/-7t5ypZ5SL5E/VV7oCrbaG7I/AAAAAAAAQJk/X_tYvIqUZpE/s1600/pic_main.png"><img src="http://1.bp.blogspot.com/-7t5ypZ5SL5E/VV7oCrbaG7I/AAAAAAAAQJk/X_tYvIqUZpE/s200/pic_main.png" /></a>
<p>あの当時は僕的には Flash の復権に期待があったことも、オンチついでに書いておきます.そして幸いにも共同プロジェクトを始める、という形で js に足を突っ込んでいきました.</p>
<p>このとき(2011年11月)の僕は、jQuery を少し使える程度のものでした.そして、最近になってようやく、ましな js を書けるようになってきた、と思います.</p>
<p>今後は、この間に溜まった js ネタをメインにぼちぼち書かせていただきたいと思います.今後ともひとつよろしくです.</p>
<p>なんて書きながら、そういえばお仕事では半分以上は Flash ( Flex ) でしたよ、、、(汗)</p><p>艦コレでも使われている Flash は、まだまだ現役です.Flash ともども、ひとつよろしくです.</p>
</div>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-86482777339456666192014-01-19T15:08:00.000+09:002015-11-17T01:34:54.823+09:00iBook G3 クラムシェルに MacOSX 10.3 をインストールiBook G3 クラムシェルに、この機種で最終のバージョン、MacOSX 10.3 をインストールする。<br /><br />インストールディスクは、昨年末にオークションで購入したもの。送料込みで 2600 円くらい。<br /><br />インストール完了後に、最終メジャー・バージョン 10.3.9 にする。<br />これはまだ、以下からダウンロードできる。<br /><br />Mac OS X 10.3.9 統合アップデート<br />http://support.apple.com/kb/DL496?viewlocale=ja_JP<br /><br />これ以降のソフトウェアのアップデートは機能しないので、自分でなんとかする。<br /><br />IE for Mac についてはこの時点で最終の 5.2.2。<br /><br />この時点で、Safari のバージョンは 1.3.0。最終バージョンの 1.3.2 にするためのアップデートは公式から落とすことはできない。<br />そこで以下のページからアップデータを落として適用した。<br /><br />Browsers > Safari for Mac<br />http://www.oldapps.com/mac/safari.php<br /><br />10.3.9 用の iTunes は 7 が最終ということなので、7.7.1 をインストール。<br /><br /><br /><br />Index<br />https://web.archive.org/web/20081216170542/http://www.apple.com/jp/ftp-info/date.html<br /><br />Security Update 2005-004<br />https://web.archive.org/web/20081217040146/https://www.apple.com/jp/ftp-info/reference/securityupdate2005004.html<br /><br />http://supportdownload.apple.com/download.info.apple.com/Apple_Support_Area/Apple_Software_Updates/Mac_OS_X/downloads/061-1748.20050419.SyNcU/SecUpd2005-004Pan.dmg<br /><br /><br />Security Update 2005-005 (Client)<br />https://web.archive.org/web/20081217040234/https://www.apple.com/jp/ftp-info/reference/securityupdate2005005client.html<br /><br />http://wsidecar.apple.com/cgi-bin/nph-reg3rdpty1.pl/product=05901&platform=osx&method=sa/SecUpd2005-005Pan.dmg<br /><br /><br />Pro Application Support 3.0 (Mac OS X 10.3.9)<br />https://web.archive.org/web/20081217040005/https://www.apple.com/jp/ftp-info/reference/proapplicationsupport30macosx1039.html<br /><br /><br />Security Update 2005-006 (Mac OS X 10.3.9)<br />https://web.archive.org/web/20111209232134/http://www.apple.com/jp/ftp-info/reference/securityupdate2005006macosx1039.html<br /><br />http://supportdownload.apple.com/download.info.apple.com/Apple_Support_Area/Apple_Software_Updates/Mac_OS_X/downloads/061-1872.20050602.SCRT6/SecUpd2005-006Pan.dmg<br /><br /><br />Security Update 2005-007 (Mac OS X 10.3.9 Client)<br />https://web.archive.org/web/20081217041246/https://www.apple.com/jp/ftp-info/reference/securityupdate2005007macosx1039client.html<br /><br />http://supportdownload.apple.com/download.info.apple.com/Apple_Support_Area/Apple_Software_Updates/Mac_OS_X/downloads/061-1967.20050815.Ce39U/SecUpd2005-007Pan.dmg<br /><br /><br /><br /><br />Security Update 2005-008 (Mac OS X 10.3.9)<br />https://web.archive.org/web/20081217041247/https://www.apple.com/jp/ftp-info/reference/securityupdate2005008macosx1039.html<br /><br />http://wsidecar.apple.com/cgi-bin/nph-reg3rdpty1.pl/product=08249&cat=1&platform=osx&method=sa/SecUpd2005-008Pan.dmg<br /><br /><br />セキュリティアップデート 2005-009 (Panther Client)<br />wsidecar.apple.com/cgi-bin/nph-reg3rdpty2.pl/product=16064&cat=57&platform=osx&method=sa/SecUpd2007-008Pan.dmg<br />support.apple.com/downloads/DL732/ja_JP/SecUpd2005-009Pan.dmg<br /><br /><br />Security Update 2006-001(10.3.9 Client)<br />https://web.archive.org/web/20081217041311/https://www.apple.com/jp/ftp-info/reference/securityupdate20060011039client.html<br /><br />http://supportdownload.apple.com/download.info.apple.com/Apple_Support_Area/Apple_Software_Updates/Mac_OS_X/downloads/061-2285.20060301.pnCSec/SecUpd2006-001Pan.dmg<br /><br /><br />Security Update 2006-002 (10.3.9 Client)<br />https://web.archive.org/web/20081217041259/https://www.apple.com/jp/ftp-info/reference/securityupdate20060021039client.html<br /><br />http://wsidecar.apple.com/cgi-bin/nph-reg3rdpty1.pl/product=09966&cat=1&platform=osx&method=sa/SecUpd2006-002Pan.dmg<br /><br /><br />Security Update 2006-003 (10.3.9 Client)<br />https://web.archive.org/web/20081217041310/https://www.apple.com/jp/ftp-info/reference/securityupdate20060031039client.html<br /><br />http://supportdownload.apple.com/download.info.apple.com/Apple_Support_Area/Apple_Software_Updates/Mac_OS_X/downloads/061-2464.20060511.Tgrcry/SecUpd2006-003Pan.dmg<br /><br /><br />Security Update 2006-004 (10.3.9 Client)<br />https://web.archive.org/web/20081217040122/https://www.apple.com/jp/ftp-info/reference/securityupdate20060041039client.html<br /><br />http://wsidecar.apple.com/cgi-bin/nph-reg3rdpty2.pl/product=11230&cat=1&platform=osx&method=sa/SecUpd2006-004Pan.dmg<br /><br /><br />Security Update 2006-005 (10.3.9)<br />https://web.archive.org/web/20081217041147/https://www.apple.com/jp/ftp-info/reference/securityupdate20060051039.html<br /><br />http://wsidecar.apple.com/cgi-bin/nph-reg3rdpty2.pl/product=11712&cat=1&platform=osx&method=sa/SecUpd2006-005Pan.dmg<br /><br /><br />Security Update 2006-006 (10.3.9 Client)<br />https://web.archive.org/web/20081217040627/https://www.apple.com/jp/ftp-info/reference/securityupdate20060061039client.html<br /><br />http://wsidecar.apple.com/cgi-bin/nph-reg3rdpty2.pl/product=11769&cat=1&platform=osx&method=sa/SecUpd2006-006Pan.dmg<br /><br /><br />Security Update 2006-007 (10.3.9 Client)<br />https://web.archive.org/web/20081217040306/https://www.apple.com/jp/ftp-info/reference/securityupdate20060071039client.html<br /><br />http://wsidecar.apple.com/cgi-bin/nph-reg3rdpty2.pl/product=12175&cat=1&platform=osx&method=sa/SecUpd2006-007Pan.dmg<br /><br /><br />Security Update 2007-001 (Panther)<br />https://web.archive.org/web/20081217040036/https://www.apple.com/jp/ftp-info/reference/securityupdate2007001panther.html<br /><br />http://wsidecar.apple.com/cgi-bin/nph-reg3rdpty2.pl/product=12687&cat=57&platform=osx&method=sa/SecUpd2007-001Pan.dmg<br /><br /><br />Daylight Saving Time Update (Panther)<br />https://web.archive.org/web/20081217040827/https://www.apple.com/jp/ftp-info/reference/daylightsavingtimeupdatepanther.html<br /><br /><br />Security Update 2007-002 (Panther)<br />https://web.archive.org/web/20080205090614/http://www.apple.com/jp/ftp-info/reference/securityupdate2007002panther.html<br /><br />http://wsidecar.apple.com/cgi-bin/nph-reg3rdpty2.pl/product=13015&cat=57&platform=osx&method=sa/SecUpd2007-002Pan.dmg<br /><br />Security Update 2007-003 (10.3.9 Client)<br />https://web.archive.org/web/20070520205058/http://www.apple.com/jp/ftp-info/reference/securityupdate20070031039client.html<br /><br />Security Update 2007-004 (10.3.9 Client)<br />https://web.archive.org/web/20070603050453/http://www.apple.com/jp/ftp-info/reference/securityupdate20070041039client.html<br /><br /><strike>DL不可! http://wsidecar.apple.com/cgi-bin/nph-reg3rdpty2.pl/product=13657&cat=57&platform=osx&method=sa/SecUpd2007-004Pan.dmg</strike><br /><br />Security Update 2007-004 v1.1 (10.3.9 Client)<br />https://web.archive.org/web/20081217040958/https://www.apple.com/jp/ftp-info/reference/securityupdate2007004v111039client.html<br /><br /><strike>DL不可! <br />https://web.archive.org/web/20081217040958/http://wsidecar.apple.com/cgi-bin/nph-reg3rdpty2.pl/product=13799&cat=57&platform=osx&method=sa/SecUpd2007-004Pan.dmg</strike><br /><br /><br />Security Update 2007-005 (10.3.9 Client)<br />https://web.archive.org/web/20080205091410/http://www.apple.com/jp/ftp-info/reference/securityupdate20070051039client.html<br /><br /><blockquote>Security Update 2007-004 での改良箇所も今回のセキュリティアップデートに含まれています。</blockquote><br />http://wsidecar.apple.com/cgi-bin/nph-reg3rdpty2.pl/product=13992&cat=57&platform=osx&method=sa/SecUpd2007-005Pan.dmg<br /><br /><br />Security Update 2007-006 (10.3.9)<br />https://web.archive.org/web/20081217040110/https://www.apple.com/jp/ftp-info/reference/securityupdate20070061039.html<br /><br /><br /><br /><br />Security Update 2007-008 (10.3.9 Client)<br />https://web.archive.org/web/20090106034253/http://www.apple.com/jp/ftp-info/reference/securityupdate20070081039client.html<br /><br />Security Update 2007-007 での改良箇所も今回のセキュリティアップデートに含まれています。<br /><br />http://supportdownload.apple.com/download.info.apple.com/Apple_Support_Area/Apple_Software_Updates/Mac_OS_X/downloads/061-3785.20071114.HH6gr/SecUpd2007-008Pan.dmg<br /><br /><br /><br />ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-21626742839816230012014-01-18T19:24:00.000+09:002015-11-17T01:34:54.652+09:00iBook G3 クラムシェルに 512MB RAM の増設はじめに購入した機体(ディスプレイが点灯しない)の中に、AirMac カードがあり、これをもう一台に移植。また装着されていた RAM も 256MB になるみたいだ。( K4S561632C-TC75 x 8, 256MBits )<br /><br />2 台目に 512MB RAM を増設。この状態で MacOS 9.0.4 の起動を確認。<br /><br />続いて、AirMac カードを使えるようにする。<br />以下のページから、AirMac 2.0.2 for Mac OS 9 をダウンロード。MacOS9 用のアップデータがダウンロードできなくなっているので、これもいつ落とせなくなるか。落としておいたほうがよさそう。<br /><br />MacOS9 用のアップデータがダウンロードできなくなっている<br />http://web.archive.org/web/20111209232632/http://www.apple.com/jp/ftp-info/reference/macos_9.1_update.html<br /><br />アーカイブ - AirMac 2.0.2 for Mac OS 9 に関する情報とソフトウェアのダウンロード<br />http://support.apple.com/kb/DL1143?viewlocale=ja_JP<br /><br /><blockquote>Mac OS 9.0.4 以降<br />AirMac カードを内蔵した AirMac 対応コンピュータ<br />Lucent 社の WaveLAN PC カードか Orinoco PC カードを装備した PowerBook G3 コンピュータ<br /></blockquote><br />MacOS9 用のアップデータは、9.0.x → 9.1.x、9.1.x → 9.2.1、9.2.1 → 9.2.2 の 3 つがある。<br />これは公式では落とすことができない。<br /><br />Mac OS 9.x, Mac OS 9.x for PM G4, iMac, iBook, PowerMac G4 MDD, Mac OS 9.x Updates<br />http://macintoshgarden.org/apps/macintosh-system-922-1021-power-macintosh-g4-mirrored-drive-doors-mdd<br /><br />以上のページから飛んだ、以下でダウンロードイメージが公開されている。<br /><br />Mac OS 9 Updates shared by "nilbureaubitbucket"<br />http://www.mediafire.com/?64da0g3iih922#5npqdoak8hwdo<br /><br />OS9.2.2 までアップデート。その後、IE4.5, Netscape4.7, iCab3.0.5 をインストールしてみた。<br /><br />そして現在、MacOSX 10.3 をインストール中。<br />MacOSX は以前に 10.1 のインストールディスクを入手して、iMac DV にインストールしている。<br />それより、安定性・速度が向上しているそうで楽しみ。<br /><br />追記 2014.01.19<br />バッテリーが認識されていなかったので、ディスプレイが点灯しない機体からバッテリーを取り出して交換。こちらのバッテリーは、互換バッテリーだった。<br />ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-29409470281526140152014-01-18T15:24:00.000+09:002020-12-26T15:10:58.049+09:00イーサネットコンバータ MZK-SC300D を設定<p>中国語が飛び交うリサイクルショップで、イーサネットコンバータ MZK-SC300D を購入。1500円。LAN ポートしかない端末を Wifi に繋げるための装置を、イーサネットコンバータという。
<p>設定画面は開けるのだけど、Wifi に接続することがなかなかできなかった。Pocket Wifi の WPS の 暗号方式が TKIP だったのが問題で、AES にしてようやく接続に成功する。
<p>あわせて、b-mobile WiFi のルータ BM-MF30 にも DTI の新しい設定を入れてあげる。
<p>以下のページが助けになった。ここを参考に、DHCP モードを無効にした。
<p>また、PC の起動時にしか IP を割り当ててもらえないみたい。また設定を変えてから再び繋がるようになるまでにかなり時間がかかったり、ウンともスンとも言わなくなってリセットをすることもしばしばあった。
<blockquote title="PLANEX MZK-SC300Dの設定" cite="http://tomosu.travel-way.net/iroiro/iroiro_planex_lanconfig.html"><p>実売で格安で売られている無線LANクライアント(受け側機器)です。
<p>webで見てみると、
<p>”使えない”、”繋がらない”、”設定出来ない”
<p>等々・・・
<p>酷評が散見されますが、我が家では下記状況で問題なく使えています。
<p>ただ、確かに取説にはない設定方法など、トラップがかなりあるのでそこを備忘録も兼ねて
<p>webネタにしてみました。</blockquote>ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-44365011251632534892014-01-18T14:57:00.000+09:002015-11-17T01:34:54.745+09:00WindowsXP に ActiveSync4.5 のインストール に失敗いつの間にか、シグマリオン2 が 3 台 に シグマリオン3 が 2 台、IS02 と Windows CE 機が充実していた。このうち、シグマリオン2 と 3 を Wifi から使いたいと思い、CF 型 Wifi カードを物色していた。<br /><br />ひとつは、随分以前に U-Front で 10 円で買った WLI-CF-S11G。格安だったのはカバーが剥がれているから。まだ、動作確認ができていない。<br /><br />もうひとつは、この正月に HARD OFF で買った、WLI2-CF-S11。500 円。<br /><br />ドライバのインストールには、ActiveSync が必要なのが面倒で今までセッティングできなかった。<br /><br />ActiveSync は最終の 4.5 と 4.2 が Microsoft でダウンロードできる。<br /><br />このうちで Windows CE version 3.0 をサポートする 4.2 をダウンロードする。<br /><br /><blockquote>ActiveSync 4.2 でサポートされているモバイル デバイスのオペレーティング システムは次のとおりです。<br />• Microsoft® Windows Mobile® 5.0<br />• Messaging and Security Feature Pack for Microsoft® Windows Mobile® 5.0<br />• Microsoft® Windows Mobile® 2003 Second Edition<br />• Microsoft® Windows Mobile® 2003<br />• Microsoft® Pocket PC 2002、Microsoft® Windows® CE OS version 3.0<br />• Microsoft® Smartphone 2002、Microsoft® Windows® CE OS version 3.0<br /></blockquote><br />インストールすると、ウィザードは、Microsoft Active Sync 4.2 のインストールを完了する前に中断しました。<br />と表示されて失敗する。<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-aRJkwXXsKmE/UtoU80kEU3I/AAAAAAAAMf8/lU48-YLGc_4/s1600/ActiveSyncInstallFailed.gif" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-aRJkwXXsKmE/UtoU80kEU3I/AAAAAAAAMf8/lU48-YLGc_4/s200/ActiveSyncInstallFailed.gif" /></a></div><br />Windows Update をしてみたり、いろいろやってみたけど駄目で、nLite で機能を削っていたのが原因みたいだ。<br /><br />■EeePC 901 nLiteでXP PRO軽量化<br />http://119.245.145.163/index.php?e=721<br /><br /><blockquote>・WindowsMobileのActiveSyncがインストールできない</blockquote><br />この方は結局かなりの Windows コンポーネントを残してインストールイメージを作り直している。<br />僕も、nLite で削りまくることに腐心していた時期があった。かなり頑張ってそのときにはベターな設定が出せても、使い方が変わる内に困ることがあった。<br /><br />ワンセグテレビチューナが認識しなかったり、Webカメラが使えなかったり。使っているうちに不具合が出てきたり。<br /><br />この次に、nLite するときは、以上の記事を参考にあっさりめのカスタマイズをしたいです。<br /><br /><br /><br />ちなみに 4.5 のサポートは、<br /><blockquote>The following mobile device operating systems are supported by ActiveSync 4.5:<br />• Microsoft® Windows Mobile® 6.0<br />• Microsoft® Windows Mobile® 5.0<br />• Messaging and Security Feature Pack for Microsoft® Windows Mobile® 5.0<br />• Microsoft® Windows Mobile® 2003 Second Edition<br />• Microsoft® Windows Mobile® 2003<br />• Microsoft® Pocket PC 2002, Microsoft®<br />• Microsoft® Smartphone 2002, Microsoft®<br /></blockquote><br />ActiveSync 4.5 - 日本語 http://www.microsoft.com/ja-jp/download/details.aspx?id=15<br />ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-92170792543751381422013-09-16T14:01:00.000+09:002015-11-17T01:34:54.842+09:00S10M で K6-2 500MHz を 1.3v 動作させるS10M の 1.3v で K6-2 500MHz AFX を動作させる.3.5 x 100MHz で BIOS 画面を拝むが、Windows98 が安定しない。<br />結局 290MHz で安定している。この状態では CPU ファンが不要で cpu のヒートスプレッダに触ってもほとんど熱を感じない。<br />CPU ファンは、騒音源のファンを外してヒートシンクのみとしてみた。<br /><br />メモリやチップセットのヒートシンクの方が熱くこちらの冷却のほうが重要かもしれない。<br /><br />AYX 電源をケースについてきた IW-P250A2-0 から職場の廃棄を頂いた ZU-400N に。<br />この ATX 電源は筐体内部に向って風が吹き込むので、これをヒートシンクに当てて CPU と各パーツの冷却とする。<br /><br />おかげでとても静かな PC になった。ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-87542517254486257782013-09-12T18:30:00.000+09:002015-11-17T01:34:54.833+09:00ST100 のメモリを 2G に昨夜 memtest86 でエラーにあう 2GB x 1 のUFront で 300円で買ったやつ 本日、試してみるとエラーはでていない 昼に日本橋のじゃんぱらでPC-2 5300 のメモリを購入 1GB x 2枚 一枚が 880円 夜、 slot1 を綿棒で拭くと本日購入したメモリを認識してくれた。 slot1 が壊れたのかと、ずっとslot2 だけを使ってきたけどこれで解決。 DiverMax でST100 用の driver を収集。 XP のクリーンインストールまで行きたいけど、Epson の cd は実家だ キーボードの加減で、エラーのビープ音しか出ないときがある。 CR2032 の消耗具合によっても起動にこけるらしい かなりのじゃじゃ馬、、、ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-41235207309082965842013-09-12T16:24:00.000+09:002015-11-29T19:25:13.810+09:00GA-586HX に火入れ<div class="box">
<a href="http://4.bp.blogspot.com/-kgG3bl4w7VE/UjFpxrlCxEI/AAAAAAAAL3U/nSzPIntia-0/s1600/gh586_top.jpg">
<img src="http://4.bp.blogspot.com/-kgG3bl4w7VE/UjFpxrlCxEI/AAAAAAAAL3U/nSzPIntia-0/s160-c/gh586_top.jpg" /></a>
<a href="http://3.bp.blogspot.com/-i4qmcKaonoQ/UjFpyjjBNYI/AAAAAAAAL3c/zJMn0J21CSU/s1600/gh586_front.jpg">
<img src="http://3.bp.blogspot.com/-i4qmcKaonoQ/UjFpyjjBNYI/AAAAAAAAL3c/zJMn0J21CSU/s160-c/gh586_front.jpg" /></a>
<a href="http://2.bp.blogspot.com/-CDkuyvmJwhk/UjFpzGTfXoI/AAAAAAAAL3k/mCqt3wzQFMQ/s1600/gh586_bios.jpg">
<img src="http://2.bp.blogspot.com/-CDkuyvmJwhk/UjFpzGTfXoI/AAAAAAAAL3k/mCqt3wzQFMQ/s160-c/gh586_bios.jpg" /></a>
</div>
<p>¥10で U-Front で購入したまま置いていた GA-586HX Rev1.51 に火入れをしてみる
<p>こいつに火入れするために、しばらく前に買っておいた ATX電源→ATマザー用電源変換ケーブル がある。
<p>楽天で二つ買っておいた。
<p>はじめ、ATX電源→AT変換アダプタの使い方に悩む
<div class="links">
<a href="http://hp.vector.co.jp/authors/VA037406/html/data/index.htm" target="_blank">Sazanami Online:コネクタ資料 1</a>
</div>
<p>AT側は二つの端子に分かれていて、GND (黒い線)が内側に来る向きにする。
<p>メモリを差し替えたりいじっているうちになんとか、BIOS が起動してくれる
<p>EDOメモリは同じ容量のものをペアにしながら挿していく、ようだ。人生初 EDO。
<p>BIOS は version 2.6、最新は 2.9
<p>CPU は Pentium の 100Mhz だと思う。1.5 x 50Mhz 設定で 75Mhz でテストした。
<p>ビデオカードは、GA-5200/PCI と、ISA の IXPET4000 がそれぞれ動作。
<p>ET4000 で調べると 1989 年の製品になる。これは萌えるw
<div class="links">
<a href="http://ascii.jp/elem/000/000/698/698677/" target="_blank">GPU黒歴史 DOS時代最速のET4000 子孫のET6300の意外な末路</a>
</div>
<p>以下のリンクは、GA-586HX の入手時に控えていたもの。
<p>サイトが閉鎖していたので、web archive へのリンクとなっているものもある。
<div class="links">
<a target="_blank" href="http://www.gigabyte.com/products/product-page.aspx?pid=1555#sp">GIGABYTE - Motherboard - Legacy - GA-586HX:</a>
<a target="_blank" href="http://download.gigabyte.asia/FileList/Manual/motherboard_manual_586atv_e.pdf">motherboard_manual_586atv_e.pdf</a>
<a target="_blank" href="http://web.archive.org/web/20070626183052/http://www.ga586hx.de/en/usb.html">GA-586HX unofficial</a>
<a target="_blank" href="http://web.archive.org/web/20091027120434/http://geocities.com/hackedmobo/ga586hx/gaps2.htm">The Hacked GA-586HX Home Page - Cat & Mouse</a>
<a target="_blank" href="http://web.archive.org/web/20090106135457/http://sometime.minidns.net/~pcstory/oldmb/ga586hx.htm">GIGABYTE GA-586HXの真実</a>
<a target="_blank" href="http://www.oocities.org/hackedmobo/ga586hx/index.html">The "How I Hacked My 2+ Years Old GA-586HX To Run A AMD K6-2 350 CPU At 366MHz And A AMD K6-III CPU At 400MHz" Home Page</a>
</div>
<div class="box"><a href="http://3.bp.blogspot.com/-ZYdTxrPlKPo/SNYQH9X7X1I/AAAAAAAAPsw/CNwUaEnJRpw/s1600/SH510005.JPG">
<img border="0" src="http://3.bp.blogspot.com/-ZYdTxrPlKPo/SNYQH9X7X1I/AAAAAAAAPsw/CNwUaEnJRpw/s160-c/SH510005.JPG" /></a>
<p>やってきたときに画像があった。2007-01-12
</div>ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-15189916046614747652013-09-08T14:31:00.000+09:002015-11-17T01:34:54.630+09:0030DVにwindows98をインストールドライバを当てる<p>徹夜をしてようやく S10M に Windows98 をインストールした。</p><p>もともと 98SE で販売された製品のマザーボードのせいか?LAN に最後まで解消されない問題が、、</p><h3>DVD ドライブが認識されない問題</h3><p>インストール時の途中から DVDドライブにアクセスできなくなり、ドライバ適用のときに windows 98 CD が見つからずデバイスのインストールができない問題に遭遇</p><p>MS-DOS で format C: や setup している間は動いているが、ファイルを HDD にコピーし終えて再起動して以降、DVD ドライブが windows から見えていなかった。</p><p>IDE1 につないでいた DVD ドライブを IDE2 に。HDD を IDE2 → IDE1 とすることで解決。 いろんなところを疑って、何度もwindows を再インストールする羽目になってしまった、、、</p><p>以上に気付いたのはずっと後で、setup 用のファイルを HDD に置くことで凌いでインストールした。</p><h3>LAN アダプタにドライバが当たると以降 windows98 が起動しなくなる</h3><p>ドライバー適用後に再起動を促されると winddows98 が起動しなくなる問題に遭遇。</p><p>切り分けて LAN 適用時に問題が出ることがわかる。これが判明するまでに、何度も再インストールを繰り返すことに、、、</p><p>インストールの他に BIOS のアップデート。</p><p>Windows98sp1 の適用 フラッシュメモリを使えるようにする</p><p>CPU ファンが五月蝿い</p><p>ActiveSync3.5 en をインストールするも TCP/IP が無いと怒られる。Sigmarion2 と繋ぐことができない。</p><dl><dt>MB <dt> <dd>S10M Acer (オークションで購入) <dt>CPU</dt> <dd>K6-2 300Mhz ( S10M とセット ) </dd><dt>メモリ</dt> <dd>PC100 128MB x 2枚 ( S10M とセット ) </dd><dt>DVD ドライブ</dt> <dd>LG-GSA-H10A ( DVD マルチ、奥行きが少なくてよい、ドスパラにて 780 円 ) </dd><dt>HDD</dt> <dd>HITACHI 80MB ( うえださんよりもらいもの )</dd><dt>電源・ケース</dt> <dd>うえださんよりもらいもの</dd> </dl> <p><a href="http://zigsow.jp/portal/own_item_detail/224621/">意外と珍しいSiS540チップセット搭載Socket7マザーボード(;=゚ω゚)=333 - acer S10M (Socket7) by ふっけんさん</a> </p> <p><a href="http://type-y.com/2009/08/socket-7-acer-s10m.html">Socket 7 のマザーボード「Acer S10M」をジャンクで買ってみた</a></p> <p><a href="https://web.archive.org/web/20080801055714/http://blogs.dion.ne.jp/datniodeath/archives/883481.html">その4:HITACHI Prius 30DV TE1?? : 哀愁のSocket7 編</a>ジャンパーを画像に起こしてくださっている</p> <p><a href="http://www.geocities.jp/deepsocket7/s7mother.htm">7枚のSocket7</a> <a href="http://www.geocities.jp/deepsocket7/s10mFSB.htm">CPUコア電圧の設定法を紹介している</a></p> <p><a href="http://www.hitachi.co.jp/Prod/comp/OSD/pc/flora/download/type/flora30dv.htm">ダウンロード シリーズ別一覧 FLORA 30DV</a>BIOS アップデータがある。基本的にドライバは古く SiS で落としたほうがいい。</p> <p><a href="http://w3.sis.com/download/">SiS DOWNLOAD CENTER</a><br>但しドライバとセットでインストールされているアプリもあるので、SiS で手に入れた最終のモノをインストールする前に、適用しておいたほうがいい(らしい、受け売り)</p> <blockquote>IGP Graphics Drivers : SiS540 : Windows 98 File Name 540_105.zip Version v 1.05 Release Date 2002-11-14 Support Products SiS540 , File Size 2,179KB Audio Driver : SiS7018 : Windows 98 File Name 7018_119.zip Version v 1.19 Release Date 2002-09-23 Support Products SiS630E , SiS630 , SiS630ST , SiS730S , SiS730SE , SiS540 , SiS630S , SiS630ET , File Size 7,424KB Network Driver : SiS900 & Integrated SiS LAN : Windows 98 File Name sl119.zip Version v 1.19 Release Date 2006-06-29 Support Products SiS655TX , SiS655FX , SiS650GX , SiS755FX , SiSM661FX , SiSM661MX , SiS961 , SiS962 , SiS963 , SiS964 , SiS962L , SiS963L , SiS964L , SiS645DX , SiS651 , SiS630ST , SiS645 , SiS650 , SiS635 , SiS630S , SiS630ET , SiS630E , SiS630 , SiS746 , SiS745 , SiS965L , SiS966L , SiS740 , SiS735 , SiS730S , SiS648 , SiS900 , SiSM650 , SiS741 , SiS648MX , SiS730SE , SiS540 , SiS755 , SiS746FX , SiS748 , SiS655 , SiS648FX , SiS760 , SiS661FX , File Size 3,910KB IDE Driver : SiS530/620 IDE Driver : Windows 98 File Name uide102.zip Version v 1.02 Release Date 1999-04-15 Support Products SiS530 , SiS620 , File Size 376KB</blockquote>ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-20867631516342805792013-08-28T00:15:00.000+09:002020-10-18T15:26:17.649+09:0030DVにwindows98 をインストール<p>起動 CD を作る
<p>起動 FD を<a href="http://www.allbootdisks.com/download/98.html" target="_blank" rel="nofollow">ここ</a>から落とす
<p>Windows98.img UltraISO で win98.iso に上の FD イメージからブート情報を載せた iso を作る <a href="http://www.geocities.jp/le_grand_concierge/_geo_contents_/Win98CleanInstall/Win98CleanInstall.htm" target="_blank" rel="nofollow">Win98CleanInstall.htm</a>
<p><samp>BX9XH-7PWKG-GWYQR-YBDQD-GVPBW</samp> <a href="http://www.gegon.szm.com/pc&os/serialnum/SERIAL.htm" target="_blank" rel="nofollow">serialnum/SERIAL</a>ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-32621706078743213652013-03-04T22:34:00.000+09:002020-07-01T19:49:29.750+09:00メイン機のビデオカードの交換<div class="box"><a href="http://4.bp.blogspot.com/-Ndhg7wBkszw/UTSh9U1fcCI/AAAAAAAAKiI/VxAWrnzC94E/s1600/NX6600-VTD256EH.jpg"><img src="https://4.bp.blogspot.com/-Ndhg7wBkszw/UTSh9U1fcCI/AAAAAAAAKiI/VxAWrnzC94E/s160/NX6600-VTD256EH.jpg"></a>
<p>GV-RX30S128D-RH (128MB・980円・バルク)から NX6600-VTD256E(780円・ジャンク・softmap) に交換。特にGV-RX30S128D-RH 自体に不満があったわけではないけどロープロファイルなのでガタガタした状態でつかっていたので。
<p>この少し前に CPU を Core 2 Duo E6600 (2.40GHz 4MB・2480円) に換装した。</p>
</div>
<blockquote cite="https://web.archive.org/web/20160405081015/http://news.mynavi.jp/news/2005/06/23/007.html" title="MSIからファンレスGeForce 6600カード「NX6600-VTD256EH」"><p>エムエスアイコンピュータージャパンは、グラフィックスカードの新製品「NX6600-VTD256EH」を発表した。同社のグラフィックスカード製品としては、「寂、」以来となるファンレスカード。6月下旬の発売開始予定で、価格はオープンプライス。店頭予想価格は17,500円前後。
<p>「NX6600-VTD256EH」は、メインストリーム向けのNVIDIA GeForce 6600 GPUを採用したグラフィックスカード。インタフェースはPCI Express x16。動作クロックはコアが300MHz、メモリが550MHzとされている。グラフィックメモリには"高品質メモリチップ"とされる3.6nsのDDRメモリを256MB(128bit接続)搭載している。冷却機構は、従来の「寂、」が採用していたヒートレーンから一転、通常のヒートシンクが採用されているが、そのヒートシンクのサイズは、メモリチップ冷却用を含めると全体の2/3近くを覆う巨大なものとなっている。
<p>NX6600-VTD256EHの出力端子はDVI-IとアナログRGB(D-Sub15ピン)、Sビデオ出力の3系統。製品には、同社オリジナルオーバークロック機能「D.O.T. EXPRESS」が搭載されているほか、NVIDIA PureVideoに対応。また、3Dゲームタイトル「URU」「XIII」「Splinter Cell Pandora Tomorrow」や、DVD再生ソフト「PowerCinema」、同社オリジナルソフトウェア等がバンドルされており、買ったその日から活用できるセットだ。</blockquote>ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-252473013066408472013-02-27T08:37:00.000+09:002020-07-01T19:42:16.350+09:00ダイレクトブラウザ<h2>931N</h2>
<a href="http://3.bp.blogspot.com/-6__Q1warylc/USieefsCp2I/AAAAAAAAKhg/ATiTBjqJiCY/s1600/931N.jpg"><img src="https://3.bp.blogspot.com/-6__Q1warylc/USieefsCp2I/AAAAAAAAKhg/ATiTBjqJiCY/s200/931N.jpg"></a>
<h2>940N</h2>
<a href="http://2.bp.blogspot.com/-zU6h-tbMYFM/USieeU0Rx4I/AAAAAAAAKhc/dkHzjsxapng/s1600/940N.jpg"><img src="https://2.bp.blogspot.com/-zU6h-tbMYFM/USieeU0Rx4I/AAAAAAAAKhc/dkHzjsxapng/s200/940N.jpg"></a>
<h2>940SH</h2>
<a href="http://2.bp.blogspot.com/-_51LoSoUL0I/USidIrMJmfI/AAAAAAAAKhQ/KbNc8HzGZH8/s1600/940sh.jpg"><img src="https://2.bp.blogspot.com/-_51LoSoUL0I/USidIrMJmfI/AAAAAAAAKhQ/KbNc8HzGZH8/s200/940sh.jpg"></a>
<h2>941SH</h2>
<a href="http://3.bp.blogspot.com/-bACrRfwFkqA/USic_n7sDEI/AAAAAAAAKhI/PlrFoFmXFEI/s1600/941sh.jpg"><img src="https://3.bp.blogspot.com/-bACrRfwFkqA/USic_n7sDEI/AAAAAAAAKhI/PlrFoFmXFEI/s200/941sh.jpg"></a>
<h2>943SH</h2>
<a href="http://3.bp.blogspot.com/-G9CZPuNqzQY/USif6LQ0ZdI/AAAAAAAAKh0/9Vxgmetbk2Y/s1600/943sh.jpg"><img src="https://3.bp.blogspot.com/-G9CZPuNqzQY/USif6LQ0ZdI/AAAAAAAAKh0/9Vxgmetbk2Y/s200/943sh.jpg"></a>
<blockquote cite="http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1244128857" title="ダイレクトブラウザ対応のシャープ機種を探しています"><pre>>■搭載・・・940SH/941SH/931N/940N
>※2009年12月現在
他には<del>934SH</del><ins>940SH</ins>などが該当します(使用中)。</pre></blockquote>
<blockquote cite="http://blog.so-net.ne.jp/Al_Nasrain/2011-06-24" title="Wi-Fiフリー機のダイレクトブラウザ [〓プリモバと第三世代]"><p>943SH/941SH/940SH/940N/931N の5機種がWi-Fiフリーのケータイだ。</blockquote>ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-54034637893795230542012-12-24T00:33:00.000+09:002021-05-04T16:09:03.483+09:00ST100の修理<p>ST100 が起動しなくなったで様子を見てみた。
<ul>
<li>メモリが2枚刺しだと起動しないみたい。
<li>ジャンク300円で購入していた2GBのもの一枚に交換。もともとは 512MB * 2。
</ul>
<p>時間がないので、ここまで。ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-81097861424077106792012-01-11T20:58:00.000+09:002021-05-04T16:07:28.983+09:00親のPCが不調につき一台購入して送る<div class="box"><a href="http://3.bp.blogspot.com/-ZKq3tx14eyc/Tw14kGWCnEI/AAAAAAAAJ9g/qiecGy43dxA/s1600/Epson_ST100.jpg"><img src="http://3.bp.blogspot.com/-ZKq3tx14eyc/Tw14kGWCnEI/AAAAAAAAJ9g/qiecGy43dxA/s160/Epson_ST100.jpg"></a>
<p>EPSON ST100 再生中古 ¥19,900。
<p>OS は、再生中古用の Windows 7 Home Premium がついてきたが、モバイル Core2Duo 1.6Mhz T5500 T5500 (2M Cache, 1.66 GHz, 667 MHz FSB), DDR2 1GB のスペックには厳しいと思う。
<p>ちょうど、別のお店で、EPSON 用の XP professional リカバリCD が ¥980 で見つける。
<p>無事インストールができた(みたい)。
<p>ドライバー等は、EPSON のサイトから DL できた。
<p>インストールの設定に、PS2 のキーボード & マウスが必要なので難儀した。
<p>マシンの選定、購入、インストールでこの連休の時間をとられてしまった。
<p>Core2Duo の中古機デスクトップなら、1万円程度でチラホラみかけるので、ずいぶん安くなったものだと思う。</div>ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-34721073879841281992011-11-01T05:22:00.000+09:002015-05-01T23:13:54.185+09:00Google Developer Dayでライトニングトークしてきます<p>これから家を出ます。</p>
<p>高速バスの中で原稿を詰めます。</p>
<p>ではでは~</p>
<a href="http://googledevjp.blogspot.com/2011/10/google-developer-day-2011-japan-ignite.html">http://googledevjp.blogspot.com/2011/10/google-developer-day-2011-japan-ignite.html</a>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-58963312205603033692011-10-03T06:50:00.004+09:002011-10-03T06:57:58.957+09:00制作記録 2011/10/02 メディアコンソールとシェル<h3>バックグラウンド メディアコンソール</h3>
<div class="clearfix">
<a href="http://2.bp.blogspot.com/-eRbYFWL5SjA/TojZYKA7oVI/AAAAAAAAI0g/pqb-dvsamBY/s1600/gOS_111002.png" style="float: left; margin: 0 1em 1em 0;"><img height="208" src="http://2.bp.blogspot.com/-eRbYFWL5SjA/TojZYKA7oVI/AAAAAAAAI0g/pqb-dvsamBY/s320/gOS_111002.png" width="320" /></a>
<p>バックグラウンドで音楽を再生したり、ビデオを再生する、コンソールに着手しました。</p>
<p>大抵の場合、アプリケーション自体がプレイヤーを持たずに、システムのプレイリストに追加していくのがいいんじゃないか、という発想です。</p>
<p>同時に二つの音楽が鳴っても聞きづらいですし。</p>
</div>
<h3>シェル</h3>
<p>また、このオーディオコンソールを書いていて気付きましたが、ファイルビューワーはfinder(とそれを継承したアプリ)にしか提供されないようになっていました。</p>
<p>しかし、ファイルビューワーは他のアプリケーションでも使いたいです。</p>
<p>その上、生成されたら他のアプリケーションからもファイルのドロップを受け取りますし、ドラッグもします。なので、システムで全てのファイルビューワーを把握してドラッグドロップに備える必要があります。大幅に書き換えが要ります。</p>
<p>これまでは、finderはアプリケーションという頭で、カーネルとアプリケーションしかありませんでした。しかしファイルビューワーなどを管理していく、ということからシェルが必要ということに気付きました。ようやく。</p>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-37727446250369621062011-09-22T12:39:00.003+09:002020-02-11T14:44:03.690+09:00Wiki for 3arrows制作日記 6 WYSIWYGエディターの試作<div class="note"><p>jsdo.it が終了していたので、リンクを web.archive.org に変更し、そこで撮影したスクリーンショットを追加しました。(2020/2/11)</div>
<p>CMS やブログサービスが提供している WYSIWYG エディターは <code><br></code> で改行してしまい <code><p></code> タグで段落を囲んでくれない。クラスで見栄えを指定できないといった不満が、Web に携わる人にはあるかと思います。
<p>自分のサイトに用意した CSS のクラスや、その適用ルール(<code><p></code> タグの下に <code><img></code> がある場合は、イメージを左右に寄せるクラスを選べるとか)を簡単な json とかで用意して、WYSIWYG エディターの動作をカスタマイズしたいとか。そんなことを半年前から、考えていました。</p>
<div class="links"><a href="/2011/03/html-editor.html">html Editorについてちょっと考え始める</a> 2011/03/03</div>
<p>またはそんな動機じゃなくても、なにか特殊な俺様エディタを作りたいとか。
<p>Javascript 製の WYSIWYG エディターはいくつか公開されていますが、いったいどうやっているのでしょう?カーソルを動かしたり、入力したり、スクロールしたり、を実装すると思うと頭が痛くなります。
<h2><code><iframe></code>を<code>designMode</code>にするらしい</h2>
<p>実は多くの Javascript 製の WYSIWYG エディタは <code>designMode</code> というブラウザ自体が持つリッチテキスト編集機能を使っているようです。Javascript をひたすら駆使して頑張っている、というわけではないのです。
<p>幸いにして、日本語で試作を公開しているページがあります。コードも短いのでいいですね。
<div class="links"><a href="http://archiva.jp/web/javascript/wysiwyg.html" target="_blank" rel="nofollow nooenner">簡易WYSIWYGエディタを作る</a>
<a href="http://archiva.jp/test/html/wysiwyg.html" target="_blank" rel="nofollow nooenner">サンプルのWYSIWYGエディタ</a>
</div>
<p>このサンプルを触ってみると、件の <code><br></code> での改行はブラウザ自体のテキスト編集機能に由来しているのが分かります。
<h2><code>designMode</code>を使わないWYSIWYGエディタ</h2>
<p>その <code>designMode</code> を使わないで <code><input></code> タグ等を使用したエディタの試作を公開しているページがあります。<a href="http://web.archive.org/web/20101110194816/http://www.fourmeisters.com/blog/yoshi/2007/09/wysiwyg.html" target="_blank" rel="nofollow nooenner"><code>designMode</code> はいくつか問題があるらしい</a>ということで試作に取り組まれたそうです。
<div class="links"><a href="http://web.archive.org/web/20140626095956/http://d.hatena.ne.jp/kawagooch/20101206/1291644876" target="_blank" rel="nofollow nooenner">designModeを使わないWYSIWYGエディターの試作</a>
<a href="https://dl.dropbox.com/u/6667635/editor/index.html" target="_blank" rel="nofollow nooenner">miceditorのサンプル</a>
<a href="http://h2ham.seesaa.net/article/172320476.html" target="_blank" rel="nofollow nooenner">勉強会 Sugamo.cssでの発表の模様</a>
</div>
<ul><li>最小限の機能もまだ備えていませんが、コードが短いので理解しやすいです
<li>ブラウザのサポートが得られる <code>designMode</code> のようにはいかず、操作時の文字のカタツキ・チラツキが起こってしまいます
<li>タグで囲まれた文字の削除がうまくできません
<li>miceditor は MicroEngine という CMS 用の Javascript エディタの候補として試作したそうです。<a href="http://web.archive.org/web/20140723002850/http://d.hatena.ne.jp/kawagooch/20110812/1313138305" target="_blank">MicroEngineのオンラインデモサイト</a>を拝見しましたが、現在は nicedit というエディタが使われていました。
</ul>
<h2>以上のエディタを改造して見ました</h2>
<div class="box">
<a href="https://3.bp.blogspot.com/-9gwxr2fwYhs/XkI4Nd-tsaI/AAAAAAAASKQ/DkoCZVpGbP8Ny9nqBUnE-ndTJvXgdd6egCLcBGAsYHQ/s1600/jsdoit.png"><img src="https://3.bp.blogspot.com/-9gwxr2fwYhs/XkI4Nd-tsaI/AAAAAAAASKQ/DkoCZVpGbP8Ny9nqBUnE-ndTJvXgdd6egCLcBGAsYHQ/s160/jsdoit.png"></a>
<p>琴線に触れるものがあったようで、気が付いたら手元でいじってました。
<!--script type="text/javascript" src="http://jsdo.it/blogparts/3HO1/js?view=design"></script -->
<p class="ttlBpJsdoit"><a href="https://web.archive.org/web/20170312080813/http://jsdo.it/itozyun/3HO1" title="非designModeなWYSIWYGエディターの試作">非designModeなWYSIWYGエディターの試作 - jsdo.it - share JavaScript, HTML5 and CSS</a></p>
</div>
<ul><li><code>textNode</code> の操作を律儀に行うことで、操作時のカタツキを減らせました
<li>タグ内の文字、入れ子のタグに対しても正しく削除を行えます。多分。
<li>エディタとして普通の水準に持っていくには、履歴やテキストのドラッグとかスクロールとか、まだまだたくさんの機能が要りますね
</ul>
<h2>最後に</h2>
<p>オレオレなエディタを作るための取っ掛かりが得られたので、良かったです。
<p>ちなみに、<a href="http://jsdo.it/itozyun" rel="me">jsDo.it</a>デビューでした。開発は Aptana Studio で行ってコピペですが、サクサク公開できて便利ですね!izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-53463496782513590672011-08-20T23:50:00.003+09:002011-08-21T10:48:21.703+09:00制作記録 2011/08/20 子窓とアクションボタン<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-aqQhAVpNgyc/Tk_GnHeWgTI/AAAAAAAAIzI/LjyhdWN-hHc/s1600/gOS_110820.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="230" src="http://4.bp.blogspot.com/-aqQhAVpNgyc/Tk_GnHeWgTI/AAAAAAAAIzI/LjyhdWN-hHc/s320/gOS_110820.png" width="320" /></a></div>
ポップアップした小ウインドウのおかしかった挙動を直した。(削除・移動・センタリング)<br />
<br />
つづいて、正しく動いていなかったアクションボタン(歯車のアイコン)の部分に手を入れた。これは継承元のListBoxコントロールに不備があった。<br />
<br />
続いてアクションボタンからのプロパティ表示。これはfinderに表示されるquickプロパティと同じものを表示するようにした。<br />
<br />
しかし画像のように不要なスクロールバーが出てしまう。リサイズかけると消える。ううむ、、、<br />
<br />
この他にアクティブな窓の切り替えが、窓の位置によってはできない。<br />
<br />
プロパティ表示のためにpopupに手を入れた。このとき、アプリケーションの起動プロセスで、start()が呼ばれるべきタイミングで先にresize()が呼ばれてstart()が続いていたのに気付いて、手当てをした。<br />
<br />
以前から気にしていた部分だけど、今回エラーに出くわしたので、直せてよかった。<br />
<br />
借りてきたビデオをようやく観れた。タクシードライバーと嫌われ松子の一生。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-90789720221400639152011-08-16T02:19:00.000+09:002015-11-17T01:34:54.838+09:00NINTENDO64を買う本体 ¥80 電源 ¥30 コントローラ¥50<br /> ということで買ってしまった。動作保障のないジャンク品。案の定ソフトを持っていないので、動作確認ができない。。。<br /> <br /> AVケーブルはスーファミのものが使えるはずで、気になってRGB接続を調べると、RGB信号の出ていない後期版のようだった。ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-58444550084697333872011-08-15T18:48:00.003+09:002011-08-15T19:00:14.914+09:00制作記録 2011/08/14 デスクトップのメニューバーにボタンをつけた<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-F1BCNQS9rno/TkjpvU4FIUI/AAAAAAAAIYA/qzxXPOnS6XY/s1600/gOS_110814.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="188" src="http://2.bp.blogspot.com/-F1BCNQS9rno/TkjpvU4FIUI/AAAAAAAAIYA/qzxXPOnS6XY/s320/gOS_110814.png" width="320" /></a></div>
デスクトップのメニューバーにシステムの情報にアクセスするためのボタンをつけました。<br />
<br />
画像右上のちっちゃいアイコンがそれです。<br />
<br />
こいつはブート時に各サービスが、デスクトップに対してボタンの表示を依頼します。<br />
<br />
現在は、アカウントサービスとストレージサービスがボタンを発行していて、クリックでそのコンソールを開きます。<br />
<br />
この他にボタンのフラッシュ機能があってwebストレージへのアクセスやiGoogleからurlを受け取ったタイミングでピコッと光ります。<br />
<br />
HDDのアクセスランプのような感じで、システムの様子がモニターできるわけです。<br /><br />この他に、pubDateなどの表示がファイルの詳細表示でunixtimeだったのを修正。しかしソートの際はunixtimeを元に行うようにする。<br /><br />ストレージの同期状態の表示をアカウントコンソールに行うようにする。<br /><br />夜中に走って山まで行くと、2匹の狸が前を通ってった。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-32438602439106455612011-08-12T15:10:00.000+09:002015-11-17T01:34:54.696+09:00ADVANTECH(アドバンテック)組み込みPC PCA-6740L<a href="http://4.bp.blogspot.com/-rCjBblki0zA/TkTDALrsyXI/AAAAAAAAHws/KEYGYUa-UbY/s1600/PCA-6740L_3.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="http://4.bp.blogspot.com/-rCjBblki0zA/TkTDALrsyXI/AAAAAAAAHws/KEYGYUa-UbY/s200/PCA-6740L_3.jpg" width="200" /></a><br /> <br /> <a href="http://1.bp.blogspot.com/-9A9g_BLnbsQ/TkTDAlRiZJI/AAAAAAAAHww/bNMUuNAj1kw/s1600/PCA-6740L_1.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="http://1.bp.blogspot.com/-9A9g_BLnbsQ/TkTDAlRiZJI/AAAAAAAAHww/bNMUuNAj1kw/s200/PCA-6740L_1.jpg" width="200" /></a><br /> <br /> <a href="http://2.bp.blogspot.com/-yOy59oejjrU/TkTDBG_1LOI/AAAAAAAAHw0/ysUU8f7mdMw/s1600/PCA-6740L_2.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="http://2.bp.blogspot.com/-yOy59oejjrU/TkTDBG_1LOI/AAAAAAAAHw0/ysUU8f7mdMw/s200/PCA-6740L_2.jpg" width="200" /></a><br /> <br /> <p>6月末に購入。まだ通電していない。</p><br /> <br /> <p>このタイプのPCでは、実際にマザーボードのISA・PCIバスに挿すと給電されて動作する場合と、そのようなことはNGな場合があるようだ。</p><br /> <br /> <p>PCA-6740Lについては、後者のようで、ボード上のHDDなどに電源を入れるピンから5Vを入れてやるみたい。</p><br /> <br /> <p>ISAなコネクタについては、専用のボードを使ってISAバスを拡張しISAカードをさせるようにするためのもののようです。</p><br /> <br /> <p>CPUはx86で100Mhz程度の動作周波数みたいです。</p>ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-25736257499460198882011-08-12T13:52:00.001+09:002021-07-26T23:40:38.252+09:00ライブドアブログから165件の記事をインポートしました<p>ライブドアブログから、2005年~2008年の間に書いた記事を移動しました。
<ul>
<li>165件の記事
<li>250枚の画像(Picasa に移動)
<li>数件のコメント
</ul>
<p>以上が、無事移動できました。
<p>ご覧の通り、Blogger は余計なものを表示しないサービスで、また、僕自身カスタマイズにもずいぶん習熟しました。
<p>また移行についても、javascript を書いてその助けを借りながら、わりあいにスムースにできました。
<p>コンテンツが Google に集まりすぎていることには、一抹の不安を覚えつつ、次の何かの変化まで平穏に行ってくれればな、と思います。ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-46574760141579037592011-08-04T22:10:00.005+09:002015-05-06T11:12:03.335+09:00制作記録 2011/08/04 Webストレージへコンフィグファイルを保存<div class="box">
<a href="http://4.bp.blogspot.com/-w_Mm7sGUknE/TjqYCI8ghLI/AAAAAAAAHgQ/DCgtLJldwiw/s1600/gOS_110804.png"><img src="http://4.bp.blogspot.com/-w_Mm7sGUknE/TjqYCI8ghLI/AAAAAAAAHgQ/DCgtLJldwiw/s200/gOS_110804.png"/></a>
<p>本日はやうやくユーザーの設定を Web ストレージに保存できるようになった。
<p>しかし、現在できるのは相変わらず壁紙の情報だけで半年以上前から進歩がないといえばない。
<p>でも、実はファイルの読み込みに関しては、Web ストレージのものを読み込める。また設定自体もコンフィグファイルとして保存している。
<p>新しい Web ストレージはファイルツリーを保存しておける優れものなのです。
<p>Google スプレッドシートの貧弱なスペースがWebストレージと言えるか、という向きもあるかもですが、基本的に Web デスクトップにおいてファイルを再現するために必要な情報は、リソースの url とユーザーのアクセス権くらいのものなので、そこはええじゃないかの精神でいいんじゃないでしょうか。
<p>deepcopy したオブジェクトのクラスの削除に戸惑ったのと、hitTestObject で親子関係のオブジェクトでは常に true になるのに嵌った。当然といえば当然か、、、
<p>この他に、Windows の最小サイズを設定した。この間はうっかりウインドウサイズをマイナスに持っていってしまうとエラーしていたので幸せになれた。
<p>Google Docs ドライバー、ストレージドライバー、config サービスの入り組むこの辺の処理は脳が佃煮になります。
</div>
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-17805320360552982142011-08-03T21:40:00.001+09:002015-05-06T10:57:37.269+09:00制作記録 2011/08/03 Webストレージからコンフィグデータ取得・壁紙の書き換え<div class="box">
<a href="http://1.bp.blogspot.com/-pxQk-XnOeHc/Tjk_6TZZdpI/AAAAAAAAHgM/MhlQQVpgeOk/s1600/gOS_110803.png"><img src="http://1.bp.blogspot.com/-pxQk-XnOeHc/Tjk_6TZZdpI/AAAAAAAAHgM/MhlQQVpgeOk/s200/gOS_110803.png"/></a>
<p>Web ストレージ及びローカルストレージ(シェアードオブジェクト)を同期させつつ提供するストレージサービスを進めた。
<p>Google スプレッドシートに置いた、ユーザーデータからファイル及びコンフィグファイルの取得、コンフィグファイルの取得を受けて壁紙の書き換えまでができた。
<p>現在はまだ、Web ストレージへの保存はできなくて、仕方なく Google スプレッドシートを開いてデータを書き込んでいる。またローカルストレージは一切手付かずだ。
<p>この他に、Google Docs のファイルについて、html で取得した内容を見れるようにした。html の表示についてはいずれhtml パーサーを書いてもう少しきちっとしたい。
</div>
<h3>Flex Builder3 の不可解な挙動について</h3>
<p>src 内のフォルダ名を driver から fileDriver に書き換えると、延々kernel.driver. のクラスがないよ!と言われる。
<p>仕方ないので、コピーして控えておいた driver フォルダを突っ込むと了解してくれた。
<p>その後この driver フォルダを消して、名前の変更が済んだ。Flex Builder まじたのんます、、、
izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-90985111544853284832011-08-01T22:00:00.002+09:002011-08-02T09:45:02.383+09:00制作記録 2011/08/01 ウインドウのリサイズ機能をつける<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-BtpEuULslVE/TjahbVsxVgI/AAAAAAAAHfE/etq3oSpTUw8/s1600/gOS_110801.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="266" src="http://3.bp.blogspot.com/-BtpEuULslVE/TjahbVsxVgI/AAAAAAAAHfE/etq3oSpTUw8/s320/gOS_110801.png" width="320" /></a></div>
アプリケーションのリサイズ機能をつけました。ようやくです。。。v(^-^;;<br />
<br />
現在は簡単に機能をつけただけで、リサイズ機能はウインドウ右下の灰色の四角をドラッグして利用します。<br />
<br />
さて、窓のリサイズには、XPのようにまずは枠線だけ表示して新しいサイズを指定していくもの。<br />
<br />
MacOSXのような、マウスのドラッグで都度に描画していくものがあります。<br />
<br />
前者はマシンへの負荷を、後者は見栄えを考慮しているのだと思います。<br />
<br />
ガジェットOSでは後者の方式を採用。理由としては実装が簡単だからでした、、、(汗<br />
<br />
負荷が心配されましたが、今のところは問題なくサクサク動作してくれています。ウインドウを任意のサイズにできるというのは、とても快適です!(滝汗<br />
<br />
他には最前面のアプリ以外は窓枠の色などを変えておきたいと思っていましたが、今回は簡易的にalpha値を変えてみました。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-87157077707450387462011-07-24T01:30:00.000+09:002011-07-24T01:30:17.454+09:00制作記録 2011/07/23 メモリ消費量に驚く新カーネルに書き換えたガジェットOSのメモリをChrome(Iron)で測ったところ、タブで44MB、別にFlashプラグインで30MBくらいということでした。<br /><br />以前のバージョンでは、リーダーを立ち上げた段階で20~30MB程度だった。新カーネルには省メモリにも自信があったのに、これは散々な結果です。<br /><br />ふと、以前のコードのことを考えましたが、あまりのスパゲッティっぷりなので、5秒で回想は辞めました。<br /><br /><br />~ここまでが数日前。<br /><br />このたびは、ふと思い立ってまたIronで測ってみました。ブート直後で同じく44MB。<br />
<br />
<br />
<br />
<br />しかし、しばらくほっておいてまた見てみると16MBになっています。ブート時だけに使われたアレコレが綺麗にガベージコレクションされたみたいです。イエイ!<br />
<br />
<br />
<br />その後も少し操作しましたが、1MB程度の変化で、新カーネル万歳です。<br /><br />ガベコすればOKということならブートが済んだ時点で、Hey! You System.gc()しちゃいなYo!ということかもですが、強制的にガベージコレクションするという安易なところに落ち着かずに、もう少し44MBに膨れた経緯(や結構時間がかかって消えたわけ)を理解する必要がある気がします。<br /><br />
以前のバージョンからメモリ使用量の推移をしばしば睨んでいたのですが、そのときはもっと頻繁に大きくとも数MBづつ推移していました。今回とはタイミングや変化のメモリ量が異なります。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-44919998217929538282011-07-18T09:27:00.005+09:002011-08-01T22:40:04.368+09:00制作記録 2011/07/18 スクロール周りとhtml表示周り<a href="http://1.bp.blogspot.com/-l4rHKlRul4k/TiN34eBAOuI/AAAAAAAAHeQ/o53v70NFZ9Q/s1600/gOS_110718.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 2em;"><img border="0" height="242" src="http://1.bp.blogspot.com/-l4rHKlRul4k/TiN34eBAOuI/AAAAAAAAHeQ/o53v70NFZ9Q/s320/gOS_110718.png" width="320" /></a>
<br />
<a href="http://4.bp.blogspot.com/-qEtEmcoe1s0/TiN4c-cWxEI/AAAAAAAAHeU/V3yoNUJhHoQ/s1600/gOS_110718_2.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 2em;"><img border="0" height="242" src="http://4.bp.blogspot.com/-qEtEmcoe1s0/TiN4c-cWxEI/AAAAAAAAHeU/V3yoNUJhHoQ/s320/gOS_110718_2.png" width="320" /></a>
<a href="http://3.bp.blogspot.com/-kfNCiertFwc/TiN5GBDbb1I/AAAAAAAAHeY/8TAWhVdn11k/s1600/gOS_110718_3.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 2em;"><img border="0" height="242" src="http://3.bp.blogspot.com/-kfNCiertFwc/TiN5GBDbb1I/AAAAAAAAHeY/8TAWhVdn11k/s320/gOS_110718_3.png" width="320" /></a>
IScrollPaneなDisplayObjectをaddChildするだけで、勝手にスクロールバーを表示したり隠したり、スクロールバーが表示された場合は、その幅の分だけでリサイズもかけてくれる、AutoScrollPaneがようやく正しく動くようになった。<br />
<br />
スライダーの位置修正にもtweenをかけて気持ちよくもなった。<br />
スクロールは次のパターンがあり、それぞれ微妙に違う処理が必要になる。
<ol>
<li>スライダーやマウスホイールの操作で動作する場合</li>
<li>iScrollPaneな子要素のサイズ変更で再描画される場合</li>
<li>addChild・removeChildで再描画される場合</li>
<li>AutoScrollPaneがリサイズされた場合</li>
<li>外からちょっとここを表示してといわれた場合</li>
</ol>
<br />
以上をノートに整理して処理を整えて予期したとおりの動作にできた。
<br />
<br />
<br />
html表示周りは、以前の日記の時点ではまだ複数画像の表示が正しく動かなくて、結構嵌った。<br />
<br />
結局はscaleX,scaleYにあてる数字がNumber型でなく、unitになっていたため全て 0 になってしまっていた、という落ちだった orz<br />
<br />
このほかにもbitmapのscaleには癖があるのか、bitmapのスケールをセットした直後にその親のSpriteのスケールを 1 にしてやる必要があった。そうしないと画像が表示されない、、、<br />
<br />
現在もまだ問題があって、tf.htmlTextなtfにtf.widthを指定するタイミングによって出来上がるtfの高さが大きく変わってしまうみたいだ。<br />
<br />
tf.htmlText = _htmlの直前だと画像が切れてしまうし、その後だと巨大な余白が後ろにできてしまう。
TextFieldのhtmlTextはほんとに使い辛い、、、<br />
<br />
Entryの表示時に、ブクマ数などを表示しようとするけど、うまく取れていない。パラメータが間違ってるのかな、、、<br />
<br />
このほかには、ファイルの階層の表示の位置を変えてぶち抜きにしてみた。こいつはファイル名の長さによって自動でリサイズをかけてくれる。tweenでスムースに動いてくれるし、結構気に入っている。<br />
<br />
tweenをFlexデフォルトのtweenからKTweenに変えてみたけど、もっさりしてしまった。シークがないせいかもしれない。で、そそくさと戻した。<br />
<br />
AdobeのチュートリアルのTypedArrayもうまく動作しなくて、そそくさとArrayにした、、、izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-2205038837710041142011-07-10T16:05:00.002+09:002011-07-10T16:35:04.776+09:00制作記録 2011/07/10 html表示周りを何とかする昨日からやってきたhtmlの表示周りがようやく動き始めた。<br />
<br />
この部分は案外厄介だけど、すでに以前のバージョンでは動いているので、新しいAPI用に書き直しつつスマートにしたい、と思っていたけど難儀した。<br />
<br />
HtmlTextのメモ
<a href="http://outcloud.blogspot.com/2010/08/htmltext.html">http://outcloud.blogspot.com/2010/08/htmltext.html</a><br />
<br />
as3には標準で、htmlを表示する機能があるけど、webkitを搭載したairのそれとは大きくかけ離れた貧弱なものだ。それも表示できればまだいい、という感じで、フラッシュの提供者によってコントロールされたhtmlなら問題なく表示できるけど、GoogleリーダーAPIで取得した有象無象なhtmlとなると難しくなる。<br />
<br />
imgによってはエラーが出てしまうのが、TextFieldでは対処できない。またイメージのサイズによってはイメージと文字が被ってしまったり、文字が消えてしまう。<br />
<br />
よってimgについては別途クラスに置き換えてやる。これにはgetImageReferenceを使うけど、情報が少なく使い方が分からない。今回は嵌ったのはgetImageReferenceでリプレイスするクラスのおき場所で、srcのルートか別ライブラリにしておく必要がある。気持ち悪いので、htmlレンダラークラスの中に置いたら、案の定動かなかくてしばらく嵌った。また置き換えるクラスをBitmapを拡張したクラスにしたら、ロード中と実際に取得したイメージが2重に表示されて解消できなかった。<br />
<br />
<br />
また文字が消えてしまう件は、イメージのサイズを表示エリアの70%までとして、リサイズをかける。しかし大抵のimgタグにはwidthやheightが書かれていないので、img取得後に適宜にhtmlを書き換えることとなる。<br />
<br />
<br />
さて、書き換えといっても簡単ではなくて、TextFieldには穏便にhtmlTextを更新する方法がないみたいだ。imgのwidthやheightを更新するにはhtmlTextを再設定する。すると今度はstyleSheetが効かなくなるので(再設定しても無視されるみたい)、結局TextFieldを削除して再生成する。その後再度getImageReferenceを拾って、別に控えておいたBitmapDataを戻していく。<br />
<br />
これまででようやく、imgの表示とイメージサイズ取得後のimgのリサイズができた。<br />
<br />
もっとスマートにできないものかな。。。以前のものから進歩がない。。。<br />
<br />
最後に、imgタグのwidthやheightはブラウザのレンダリング負荷を下げることができるので、ぜひ設定しておきましょう。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-18359294387021505532011-07-07T22:37:00.001+09:002011-07-07T22:48:02.173+09:00制作記録 2011/07/07<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-ApL1K5VPFJk/ThWwnckrXVI/AAAAAAAAHeM/ortQB3oiAME/s1600/gOS_110707.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="210" src="http://4.bp.blogspot.com/-ApL1K5VPFJk/ThWwnckrXVI/AAAAAAAAHeM/ortQB3oiAME/s320/gOS_110707.png" width="320" /></a></div>
本日は、AutoScrollPaneの相手をした。こいつは、自身にaddChildされた表示オブジェクトをチェックして、自動でスクロールバーを出してくれるクラス。<br />
<br />
以前は、他のスクロールバーライブラリを参考にしたものを書いて使っていたけど、このように作っておいたほうが、他の表示要素との相性がいい。<br />
<br />
案の定、描画が壊れまくっていて難儀したけど、ようやく収集してまともに動くようになってきた。<br />
<br />
問題のうちいくつかは根が深そうで、子要素の高さを渡し損ねるときと、スクロールバーに高さの指示を渡し損ねるときがある。<br />
<br />
子要素の高さ については、スクリプトで書き換えた後、一度描画が済んだ後でないと正確な高さが取れない、とかそんな制約でもあったのかな。。。<br />
<br />
高さの指示の方はtraceでは正しい数字が一旦は出るのに、オブジェトをまたぐと数が狂っているという意味不明、、、<br />
<br />
また、起動と同時に表示されるアカウントコンソールでもAutoScrollPaneを使っているけど、stage.stageHeightが起動の直後には取れなくて、1となっていた。(ルートのADDED_TO_STAGE後に実行しているのに)<br />
<br />
仕方なくタイマーで一瞬置いてから描画周りをはじめることにすると、動いている。不本意だ。。。<br />
<br />
画像は、アカウントのコンソールで、この画面でストレージとして使っているWebサービスや、OAuthナサービスを管理する。Google以外のサービスがないのでとても寂しい、、、izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-34445560446924993282011-06-29T21:18:00.001+09:002011-06-30T07:22:09.133+09:00制作記録 2011/06/29 新バージョンを動かしていく<a href="http://4.bp.blogspot.com/-c4xvoi8hihw/TgsF5nXueSI/AAAAAAAAHdk/kr9ieGvevw8/s1600/gOS_110629.gif" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="175" src="http://4.bp.blogspot.com/-c4xvoi8hihw/TgsF5nXueSI/AAAAAAAAHdk/kr9ieGvevw8/s320/gOS_110629.gif" width="320" /></a>
この日曜から新しいガジェットOSが、動かしながらの開発に移りました。<br />
<br />
ここにいたる、およそ一月強の間はこれまでの様に時間が取れず、遅々とした歩みでした。<br />
<br />
僅かな時間を拾いつつ、PCを起動できない時はノートに書き付けながら、考えを整理していました。<br />
<br />
自分がこれまでに書いたコードはあまりにも酷いのでほぼ総書き換えです。(一年後にも同じ目に会いそう、、、)<br />
<br />
また、バックグラウンドで動いている、そのほとんどが画面を持たない、サービスを書いていたのでその段階では一切テストを行えません。<br />
<br />
その後デスクトップやエクスプローラといったシェル部分も書き直して、ようやくテストに入れましたとさ。<br />
<br />
それがこの土曜から日曜にかけてですが、最初はあのブルーバックすら表示されず、こちらの頭は真っ白~、なんて状態が続きました。<br />
<br />
イニシャライズの段階でまだ存在していないサービスを呼んでいたためでした。<br />
<br />
ようやく、画面が青くなっただけで、ほっと一息です。<br />
<br />
その後、デスクトップのメニューバーやドックを動くようにしていきます。この段階でも、シェル、サービス、Uそれぞれに問題の山です。<br />
<br />
続いてファイダーの起動に入っても一進一退で画面は崩れ、イベントリスナーは予期した動きをしないし(僕がそもそも理解していないせいらしく、全く違う方法で書き直す。しかもそちらのほうがシンプルでスマートだった、、、)サービス群もまだまだ問題の山。<br />
<br />
一方の僕は、日曜の深夜から高熱が出てしまい、体調を見て合間にやるという感じでした。<br />
<br />
体調の戻った火曜まででなんとか、ごらんの画像までにこぎつけました。<br />
<br />
もっと以前の、酷いものをキャプって日記を付けようかとも思いましたが、高熱のせいでそこまでの元気はなかったのは幸いだったような。<br />
<br />
さすがに、ここまでに漕ぎ着けるまでは何度も泣きかけましたが、火曜の後半辺りには、そこはかとなく、問題が追いやすいし、堅牢っぽいんじゃね?という気がしてきたので、また一年後の僕か他のだれかに駄目だし食らってると思います。<br />
<br />
画像は詳細表示ですが、今回は(ようやく!)ソートができたり他にもいろいろを、クソ重い(らしい)FlexのDataGridを使わずにチープにやってみています。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-15889239441961943722011-06-20T18:11:00.000+09:002015-11-17T01:34:54.635+09:00¥200で買った無線通信カードWLI2-PCI-G54S<br />Windows7でこのほど動作を確認。アンテナが欠品しているので、適当な金属で延長してやる必要がある。接続ができない。ロープロファイルなのも不便。ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-33230028413334475592011-06-16T18:18:00.001+09:002015-05-01T23:18:02.786+09:00制作一周年
<div class="box">
<iframe frameborder="0" marginheight="0" marginwidth="0" scrolling="no" src="http://rcm-jp.amazon.co.jp/e/cm?t=pbrocky-22&o=9&p=8&l=as1&asins=4839919844&ref=tf_til&fc1=000000&IS2=1&lt1=_blank&m=amazon&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="height: 240px; width: 120px;"></iframe>
<p>いつの間にか、ガジェットOSの制作をはじめて一周年になります。去年の4月にはじめてのGoogleガジェットを作って、5月には制作をはじめていたと思います。</p>
<p>で、現在ですが、ガジェットOSをほとんど最初からガッツリ書き直しています。あんまりにもつくりが酷くて、見るに耐えないYo!と一年前の自分に言ってやりたいです。</p>
<p>さて、ガジェットOSの制作に入るその少し以前には、おなじみOS自作入門なんぞも手に取っていました。</p>
<p>OS自作入門では最初に"Hello World"の表示の仕方までを解説し、その時点でOSができました、としています。その著者のストロングさっぷりには励まされた。</p>
</div>
<p>この場合、Web OSだったら、
<pre class="prettyprint lang-html"><code>
<html>
<body>
<p>
Hello World
</p>
</body>
</html>
</code></pre>
<p>~なhtmlファイルを描いただけで、OSができたぜ!と言っていいことになります。</p>
<p>そのストロングな気持ちを大事に、今後ともシコシコやっていきます。よろしくお願いいたします。</p>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-33671270117109142232011-05-14T06:33:00.000+09:002015-11-17T01:34:54.707+09:00PCケースを拾ったので、メイン機をそこに入れる粗大ごみの日に綺麗なPCケースが出ていたので保護した。本当に綺麗なので、多分サイズのせいで放出されたのだと思う。<br /><br />確定申告22年度分を終えて帰宅した後、メインのGA-965P-DQ6機を早速移動させた。<br />MBをケースにとりつけるための六角スペーサーが必要につきsofmapで購入。348円。高いよ!<br />ケースの共振に悩まされていたけど、それが収まったみたい。フロントUSBとフロントオーディオも使えて快適快適。ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-32513168393677852572011-04-17T13:31:00.012+09:002021-05-04T16:22:44.659+09:00CSSだけでIEのjavascriptの有無を判定してスタイルを切り替える<div class="note">
<h2>追記</h2>
<p>IE6でフリーズしました(>o<)。IE5.5とIE7・8(ie7モード)では動作。この辺りが目にしない理由でしょうか、、
<h2>追記2(05/02)</h2>
<p>ActiveX の有効・無効と Javascript の有効・無効は個別に設定できますが、以下では js 無効なら ActiveX も無効だろう(その逆も)という前提で書かれています。いろいろ察してお読みください。
</div>
<p>CSS だけで IE の javascript の有無を知りたい、というケースがごくごく僅かですがあるかな、ということでご紹介です。
<p>IE の8までは透過やドロップシャドウ、グラデーションといった効果を独自拡張の <code>filter</code> プロパティで実現できて、他のモダンブラウザと近い表現ができます。
<p>しかしこのプロパティは javascript が無効の場合は機能しません。(IETester では、javascript を無効にしても <code>filter</code> は機能するみたいです)
<p>また、IE には CSS expression という独自拡張もあって CSS の未実装機能やバグの手当てに使われています。これも javascript が無効の場合は機能しません。(またIE8では同時期の他のブラウザに比べて CSS のサポート状況が貧弱にもかかわらず、標準準拠のIE8モードでは CSS expression が無効です。このおかげでIE5.5よりたちが悪いときもあります、、、)
<p>そこで javascript が off のため <code>filter</code> が使えない、CSS expression が使えない場合に、スタイルを切り替えて対処する仕組みが必要になるかと思います。
<p>スクリプトを使って(javascript が有効の場合は)、<code><body></code> タグのクラス名に ieJsEnabled を追加する、なんてことをすれば、そのクラスの有無でスタイルを切り替えることができます。
<p>また javascript を使わないで HTML に以下のタグを書くことでも IE で js が無効の場合のスタイルを書くことができます。
<pre class="prettyprint lang-js"><code><noscript><!--[if lt IE 9]><div id="ieJsDisabled"><![endif]--></noscript>
みんなが幸せになるなにか
<noscript><!--[if lt IE 9]></div><![endif]--></noscript>
</code></pre>
<p>で、何かの都合で以上なテクニックが使えない、使いたくない場合、CSS 内で js の判定を行う方法です。
<p>CSS expression が動くということは javascript が有効なので、その CSS expression 内で自身の class 名を書き換えます。CSS expression はことあるごとにスクリプトの評価が起こってただでさえ遅い IE をますます不安定にしてしまうようですが、以下のような書き方の場合、最初の一回の評価以降はクラス名が書き換わって評価されないので大丈夫です。多分。また、同様にして id も書き換えられます。
<pre class="prettyprint lang-css"><code>.ieJsDisabled {
scrollbar-shadow-color : expression(this.className='ieJsEnabled');
}
</code></pre>
<p>もっと汎用的にしたいと、<code>this.className = this.className.replace(/ieJsDisabled/i, 'ieJsEnabled')</code> としてみましたが動きませんでした。CSS expression 内では単純な代入しかできないみたいです。また <code>this.style.</code> ~な書き換えはできませんでした。
<p>ついでに expression のダシに使うプロパティは、あまり影響の出なさそうなもの、ということで <code>scrollbar-shadow-color</code> にしてみました。
<p>一年ほど前から HTML タグを発行するツールを制作して運用しています。当初は IE の javascript 無への配慮がなくて HTML も切り分けができるように書かれていませんでした。しかし今回の方法で、CSS を差し替えるだけで javascript 無にも対応できるようになりました。
<p>以上はここ数日考えていて、昨日から検証して運用しています。もし導入される場合はぜひお手元で検証してから導入してください。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-18101491986128427202011-04-14T06:15:00.001+09:002021-05-04T16:28:16.490+09:00制作記録 2011/04/14<div class="box">
<a href="http://2.bp.blogspot.com/-cstm8jSCS60/TaYPMYtWgvI/AAAAAAAAHEA/XUeu0_Co8sQ/s1600/tinyWiki.110414.png"><img src="http://2.bp.blogspot.com/-cstm8jSCS60/TaYPMYtWgvI/AAAAAAAAHEA/XUeu0_Co8sQ/s160/tinyWiki.110414.png"></a>
<p>本日は深夜から作業した。まず、pureCssPopup でIE6だけスクロールバーが余分に表示されるのは、一度 DOM の操作を入れてやるなどすると、多分再計算されて不要なスクロールバーが消える。この問題は IE5、7、8では起きない。また LightBox でグレー背景用の要素を用意しているのは IE 対策だといまさら気付く。他のブラウザだとグレー背景専用の要素は要らない。<code>filter</code> でグレーの背景とアニメーションを行うのでどうしても必要になる。少なくとも pureCss Lightbox では。。。</p>
<p>続いて、wiki の HTML だけのモックを作る。以前まではさすがに画面が崩れていたり、モチベーションが下がった。まだイマイチ気に食わないので、書き散らした CSS を整理しつつもう少し詰めたい。</p>
</div>
<div class="box">
<a href="http://3.bp.blogspot.com/-b491ISE42d8/TaYPPCd0IfI/AAAAAAAAHEE/I8LEjCIDUcM/s1600/gOS_110414.png">
<img src="http://3.bp.blogspot.com/-b491ISE42d8/TaYPPCd0IfI/AAAAAAAAHEE/I8LEjCIDUcM/s160/gOS_110414.png"></a>
<p>一昨日アップデートしたガジェットOS version0.4.0。いつのまにか opensocial.api が効かなくなっていたのは OAuth patch の上書きでopensocial.api に渡した参照を切っていたためのようだ。上書きの名前空間は gadgets._io. にして opensocial.api を復活させて、パラレルな OAuth も _io でできるように対処した。そのせいなのかは不明だけど、OAuth 認可をやり直さないと正しく動かないようだ。
</div>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-87663386034605300712011-04-12T23:23:00.000+09:002015-11-15T23:00:17.989+09:00version0.4.0<span style="color: #990000;">【注意】</span>Googleリーダー・Googleドキュメントの各サービスにアクセスできなくなった場合は、<a href="https://www.google.com/accounts/b/0/IssuedAuthSubTokens">Googleアカウント情報</a>にアクセスして、http://gadget-os.googlecode.com/svn/trunk/gadgetOS.xmlへのアクセスを一旦取り消した後、再度ガジェットOSからGoogleリーダー・Googleドキュメントの各サービスへのアクセスを許可してください。ご迷惑をおかけしました。<br /><br />NiceReaderのサウンドプレーヤで.m4a(.mp4)形式の再生に対応しました。<br />デスクトップサイドの変更。<br />ほぼ全てのボタンについて効かなくなる不具合があったのを修正しました。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-82358306833298249872011-04-09T23:37:00.000+09:002011-04-09T23:37:12.652+09:00制作記録 2011/04/09本日はm4aの再生に成功。またボタンの不具合を解決できた。ウィンドウの移動やリサイズ、フルスクリーン操作などでボタンが効かなくなるという致命的なものだった。<br />
<br />
昼にバイクを取りにいって、アマゾンからの本を待つ。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-52379302368294831662011-04-09T23:33:00.002+09:002011-04-10T00:03:34.729+09:00SimpleButtonが不安定だったのを解決できたウィンドウなどについているSimpleButton(を拡張したボタン)が、ウィンドウが動くと効かなくなる不具合にずっと悩まされていた。<br />
<br />
(不本意な回避法として、移動がかかるたびにボタンのremoveと再生成をしていた。)<br />
<br />
原因は、downState、overState、upStateなどのマウス操作に合わせて切り替えるイメージとマウスの効くエリアを指示するhitTestStateを使いまわしていたことだった。<br />
<br />
upState = upShape;<br />
hitTestState = upShape;<br />
<br />
みたいな具合。<br />
<br />
こうしてしまうとボタン(やその親)が移動したとき、hitTestStateだけが移動できないで、結果ボタンが効かなくなってしまう。現在のガジェットOSで確認されたい orz<br />
<br />
以上の解決にたどり着くまで、SimpleBututton.asはいったいどうなっているんだ?、とソースを探したけど見つからなかった。<br />
<br />
しかし、<a href="http://help.adobe.com/ja_JP/AS3LCR/Flash_10.0/flash/display/SimpleButton.html">Adobeのマニュアル</a>では、hitTestStateに新しいDisplayObjectを生成して当てていたので、解決できた。またサンプルではボタンに新しいクラスをあてがっている。クラス化していないボタンでも挙動に問題はないけど、以前Dockでクラスを解除した書き方をしたら挙動がおかしくなったので、クラスにしておいたほうがいいのかもしれない。<br />
<br />
downState、overState、upStateについては、イメージ用のオブジェクトを使いまわしても、今のところ問題は出ていない。また、件の移動が起きない場合は、hitTestStateにもオブジェクトを使いまわして構わない。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-65978918146078993052011-04-08T19:46:00.004+09:002011-04-10T11:20:08.681+09:00AcrionScriptのSoundとSimpleButtonのメモ<b>Sound()について</b><br />
<br />
一時停止と再開を繰り返す場合、Sound.play()とするたびにSoundChannelを控えなおさなければいけない。sc = Sound.play()<br />
<br />
つまり再開のためのSound.play()の直前には、SoundChannelにイベントリスナーの解除とかも必要。<br />
<br />
一度だけsc = Sound.play()とすれば、あとはずっとscが有効と思い込んでいたので、sc.positionがずっと0のままではまってしまった、、、当然sc.stop()もきかねぇ~し、、、<br />
<br />
<b>SimpleButtonについて</b><br />
<br />
<del>画面のリサイズなどがかかるたびにボタンが利かなくなる症状があったけど、これはボタンイメージの差し替えのたびにオブジェクトの参照を切ってしまっていたためだった、、、</del><ins><a href="http://outcloud.blogspot.com/2011/04/simplebutton.html">それだけではなかった。こっちも読まれたし。</a></ins><br />
<br />
SimpleButtonを拡張してイメージが変化していくようなクラスでは、upState、overState、downState、hitTestStateのイメージとなるSprite(など)については、(例えば)グローバルにconstで宣言してきっちりキープしていく。<br />
<br />
自分のことを棚にあげてどうしようもなくバグッたクラスだと思っていました。ごめんなさい、、、<br />
<br />
<br />
<b>日記</b><br />
mp3に加えてm4aに対応すべくサウンド周りを書き直している。半年前のコードを見たら、あんまりにも酷すぎて、、、今のコードも半年後にはそう思うのだろうな、、、<br />
<br />
その上、今回みたいなバグも他にもあるかも。SimpleButtonの挙動に苦しんで、結局removeして再生成して回避した。そんな部分を全てスマートに書き直せます。よかったよかった。<br />
<br />
それにしても、今日の朝なんかは、SimpleButtonの異常についてまったく違う解法を考えていたので、(removeして再生成しまくるクラスでラップとか考えてた。エンストしたバイク押しながら)今回冷静になれて思い違いを根治できてよかった。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-26751197275832921882011-04-02T00:47:00.001+09:002011-04-02T01:02:00.107+09:00Wiki for 3arrows制作日記 5<div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-dbja-CZN8bU/TZXudqLgpHI/AAAAAAAAHD8/5dwgE1OUaKg/s1600/tinyWiki.110401.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="231" src="http://1.bp.blogspot.com/-dbja-CZN8bU/TZXudqLgpHI/AAAAAAAAHD8/5dwgE1OUaKg/s320/tinyWiki.110401.png" width="320" /></a></div>Wikiの情報取得後の最後のほうのコードが実行されていないみたいだ。<br />
<br />
functionの中でfunctionを呼びまくったせいかと、イベントdispatchなかたちに切り替えてみた。<br />
<br />
カスタムイベントの文字列にスペースが入るとうまく動かないんですね。<br />
<br />
DOMが重要でないイベントは$(document)に対して起こしてるけど、こんな感じでいいのかな~?<br />
<br />
一部の実行されていない処理については、不本意ながら実行される部分にコードを足したりした。トグルの書き換えの部分。<br />
<br />
編集・削除もできるようになり、作成時や更新時も保持するようにした。<br />
<br />
デバッグテスト投稿のたびにそのときの懸案をとりあえずポストしてみるけど、バグとかで一気にデータをロストしてしまうので、これは怖い、、、<br />
<br />
履歴の保持法はまだ考えていないけど、以上を補えるように考えられたらいいな。<br />
<br />
次はデザインに手を入れてもう少しまともにしたい。今の画面を長時間見てると鬱々としてくる。<br />
<br />
jsのキャッシュが利かないように、urlにタイムスタンプをつけるようにした。幸せになれた。<br />
<br />
jQueryのテンプレートが動いてないと思ったら、registerOnLoadHandlerの前にいたしてしまっていた。ついでにIDも間違ってた、、、<br />
<br />
本日もお疲れさまでした。<br />
<a href="http://code.google.com/p/gadget-os/source/browse/tinywiki/3arrows/tinyWiki.3arrows.view-edit.js?spec=svn482&r=482">http://code.google.com/p/gadget-os/source/browse/tinywiki/3arrows/tinyWiki.3arrows.view-edit.js?spec=svn482&r=482 </a>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com2tag:blogger.com,1999:blog-5003761485377366537.post-60398841775246384732011-04-01T02:29:00.001+09:002011-04-01T02:30:32.398+09:00Wiki for 3arrows制作日記 4<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-L8BESWaDfcA/TZS28qgQm0I/AAAAAAAAHD4/-MTCMLFH1Q8/s1600/tinyWiki.110330.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="218" src="http://3.bp.blogspot.com/-L8BESWaDfcA/TZS28qgQm0I/AAAAAAAAHD4/-MTCMLFH1Q8/s320/tinyWiki.110330.png" width="320" /></a></div>本日は、wikiの新規ページを保存できるようにした。続いて並び替えやトグルの状態が変化してもアップデートをかけるようにする。<br />
<br />
上書きデータの作成がうまくいかないようで、同じIDのクローンページが発生してしまっている、、、<br />
<br />
特にWikiの保存が懸案だったけど、とりあえず動いてくれたのでサクサク進んだ。<br />
<br />
このwikiにも使おうと思っている、cssにIE6で不具合が見つかった。もうこの辺りになってくると、おまじないみたいに手当たりしだいにプロパティをあてがっている、、、<br />
<br />
さらにjQuery.historyも僕の書くhtmlとは相性が悪いのかIE6で挙動が変、、、昨日から非jQueryに書き直しているのだけど、よそ様のサンプルに適用するとIE6でも動くのに、、、<br />
<br />
では、本日はここまで。<br />
http://code.google.com/p/gadget-os/source/browse/tinywiki/3arrows/tinyWiki.3arrows.view-edit.js?spec=svn347&r=347<br />
<br />
部屋の掃除してようやく床が見えてきた。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-91156528981672376322011-03-30T02:26:00.002+09:002011-03-30T02:37:14.105+09:00制作記録 2011/03/30Pure CSS LightBoxやポップアップなどをjsなしでやってのけるPure CSS Popup。<br />
<br />
こいつのためには、htmlを通常コンテンツとポップアップコンテンツに分けることになる。(モダンなブラウザの場合、Popupのためのスイッチとなる要素の直後にポップアップするコンテンツを置いても問題ない。しかしIEでコンテナの幅を設定しているとそれにつかまってしまい画面が崩れる。)<br />
<br />
その上で、さまざまなpopupコンテンツのサイズ、さまざまな画面サイズに対して、適切にスクロールバーを出そうとすると、特にIEで酷いことになる。IE5.5、6、7(8は7モード・標準準拠で8モードだとjsがエラーになる、、、htmlの1行目で 'object' is undefined って、、!?)でそれぞれ症状が違って、スクロールバーが2重に発生したりして、これを解決するcssに行き当たるのに3日を費やしてしまった orz<br />
<br />
その上で、コンテンツが短い場合もフッターが地につくようにするfooter-fixをいれる。これも大変。<br />
<br />
以上を、一度はIEのみ後方互換モードでなら成功していた。それをここしばらくで、IEも標準準拠モードとした。<br />
<br />
後方互換モードといえば、悪名高いボックスモデルのバグがあるけど、IE7やIE8でcss expressionが使えるようになったりと悪くない面もある。その上、position:relative + overflow:auto周りのバグが起きなかったりと(今回だけかも)、割とモダンなブラウザと近い解釈をしてくれたりする。また6~8までの挙動を全て5.5相当にしてしまうこともできるので、それはそれで管理が楽ジャン、と思ってしまう。<br />
<br />
参考 <a href="http://d.hatena.ne.jp/cyokodog-memo/20090331/1238474706">overflow:auto(scroll) 要素内の position:relative(absolute) 要素 注意点</a><br />
<br />
ちなみにガジェットOSのFlash起動前のメッセージも、このPureCSSPopupのコードを流用している。しかしガジェットOSのブート画面には先に出た、コンテンツのコンテナの幅はなくwidyh=100%なので、特に困ったり苦しんだりはしていない。<br />
<br />
さて、これでようやくガジェットを作っていく基礎が済んだ。続いて常に後方互換モードで動いてしまうガジェットに代わってiframe内にDocType=html4.01な文書を生成してそこに画面を作っていくコードに取り組む。<br />
<br />
その前にtinyWikiに成果を反映させないと、、、<br />
<br />
これについては、一度WebOS Goodiesの伊藤さんがライブラリを公開してくださっていた。しかし現在コードへのリンクは切れてしまっている、、、またIEで大量のDOMを移動するとハングする問題が出ていたそうだ。<br />
<br />
それにしても、無茶なことをなんとかjsだけでやろうとすると、iframeがよく出てくる。iframe奥が深い。でもこういう変態なことは基本的に避けて通りたいのだが、、、<br />
<br />
この他にPureCSSLightboxと併せて使うjsを書いていた。これは短いものなので、jQueryなどを使わないように書いてみたけど、ie用の透過とかめんどくさいしまだよく分かっていない。。。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-70030364459443608102011-03-28T21:13:00.000+09:002015-04-25T17:15:33.541+09:00IEでonload前にイメージのサイズを取得できない<p>IE8 以下では、イメージ要素の挙動が他のブラウザとずいぶん違うみたいです。
<p>例えば、次の記事ではロード完了後の画像の実際のサイズの取得の仕方を公開してくださっているが、ブラウザ毎に挙動が様々なことが分かる。</p>
<a href="http://d.hatena.ne.jp/uupaa/20090602/1243933843">JavaScript で、画像本来のサイズ(幅, 高さ)を取得する方法</a>
<p>~で、こちらはロード前に画像のサイズの取得がおかしい、という話。
<p>そもそもロード前に画像のサイズが分かると書くと、それなんてエスパー?といわれそうですが。
<p>単純に img タグの width, Height プロパティから取ろうというだけ。しかし IE では 0 が返ってしまう。</p>
<p>もちろん他のブラウザでは、それぞれタグに書かれている数字がきちんと返る。</p>
<p>また以上の症状は、DOM ツリーの構築が終わりイメージも読み込みが済んだという、window.onload を待たないで、DOMツリーの構築が済んだ段階の onDOMContentLoaded のタイミングでスクリプトを走らせて遭遇した。</p>
<p>仕方がないので、IE の場合は IE 独自プロパティの outerHTML で、イメージのタグの内容を取得して、正規表現で切り出して対処した。</p>
<pre><code class="js">var imgHtml = img.outerHTML;
w = imgHtml ? imgHtml.replace(/.*width=['"]?([0-9]+)['"]?.*/, '$1') : img.width;
h = imgHtml ? imgHtml.replace(/.*height=['"]?([0-9]+)['"]?.*/, '$1') : img.height;<code></pre>
<p>ちなみにクロスブラウザな onDOMContentLoaded のためには以下の記事を読みライブラリを使わせていただいた。</p>
<a href="http://www.metareal.org/2007/07/10/domready-js-cross-browser-ondomcontentloaded/">window.onload 前でも DOM 処理が可能なら通知してくれる domready.js</a>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-23635263279676748072011-03-13T23:14:00.000+09:002011-03-13T23:14:47.045+09:00制作してない日記この3日、ほとんどなにも手につきませんでした。<br />
<br />
幸いにしてこちらに被害は出ていませんが、原発のニュースがずっと気になっていました。<br />
<br />
(福島1号)原発に海水を入れる、このニュースで少し落ちつきました。原発への回復不能な処置は、原発推進にとっても後退を意味します。そういった配慮から対処が後手後手にまわる不安がずっとありました。<br />
<br />
以上の報道のあったあとの本日も、気がつくと口が渇き、足も震えていたときもあったので、久しく駆け足をしてきました。頭がこわばっていたのでしょう、首から上がバキバキなってほぐれるのが分かりました。<br />
<br />
3号についても、1号と同じ対処が必要になるそうで、依然予断を許しません。明日は良いニュース多めでありますように。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-28069130630433224222011-03-11T03:31:00.000+09:002015-11-17T01:34:54.681+09:00HDDレコーダー LDR-H51を購入・HDD換装健康診断の帰りに、HDDレコーダーを清掃工場そばのリサイクルショップで購入。<br /><br />DVDドライブが不調ということだが他は動くそうだ。¥1000。残念ながら地デジ対応ではないしネットワーク機能もない。CFとSDスロットを備えている。<br /><br />ただいまHDDドライブを交換し動作確認が済む。WDの160GBからseagateの320GBに。この320GBのHDDは、RaidのHDDを購入してから宙に浮いていたのでちょうどいい!<br /><br />DVDドライブの再生、録画確認はまだ。DVDドライブは独自のコネクタで接続されていて、適当なものと交換、ということはできないようだ。<br /><br />160GBの中古HDDだけの値段でも悪くないなぁ!ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-19417005476062553762011-03-11T00:54:00.000+09:002015-11-17T01:34:54.640+09:00GA-965P-DQ6をデュアルチャネルにGA-965P-DQ6につなげている、マルチメディアリーダー(¥100で購入)を有効にするためにマニュアルを落としてピンアサインを確認する。<br /><br />その際にデュアルチャネルの設定の仕方も分かる。メモリが2枚の場合、DIMM1とDIMM3に挿すのね。これまで1と2に挿してたよ。シングルチャネルなのはずっと相性のせいかと思っていた。<br /><br />これでいよいよ僕のPC環境もデュアルチャネル時代に突入です。ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-81590734182015731212011-03-09T07:08:00.000+09:002011-03-09T07:08:54.252+09:00制作記録 2011/03/08一昨日は、junkで買った液晶モニタを直したりそんな工作の日だった。<br />
<br />
昨日は、Google Apps Scriptでのハローワークのページの取り込みを進めた。<br />
<br />
今日は深夜に起きて、ここまでwikiをいじっていた。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-68839569079704097802011-03-09T06:14:00.003+09:002011-03-09T09:35:01.386+09:00Wiki for 3arrows制作日記 3<div class="separator" style="clear: both; text-align: center;"><a href="https://lh4.googleusercontent.com/-q1LVbzXOM1Y/TXaTna6AR3I/AAAAAAAAHDQ/RHhB4qqTEwo/s1600/wiki.3arrows.120308.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="212" src="https://lh4.googleusercontent.com/-q1LVbzXOM1Y/TXaTna6AR3I/AAAAAAAAHDQ/RHhB4qqTEwo/s320/wiki.3arrows.120308.png" width="320" /></a></div>今回は、Wikiの設定(色・ロック・共有編集可・共有編集不可)部分を主に作りこんだ。<br />
<br />
フォーム部品を使う場合にIEでの挙動が心配なのだけど、<del>3arrowsがIE8でうまく動かないようだ。。。</del>動かないのは僕のアプリでした(><)直した。<br />
<br />
通信中が分かるようにチャチャッとajaxアイコンを導入した。また通信中は、編集・削除ができないようにロックをかけた。<br />
<br />
wiki一覧⇔wikiの閲覧と編集は、ページを遷移して行い、ブラウザの戻るに以前の状態が記録されるようにする。<br />
<br />
こんな感じで、閲覧と編集用ページを書いていく。<br />
<br />
<content view="wiki"><br />
<![CDATA[<br />
Wikiの閲覧・編集・履歴の確認<br />
]]><br />
</Content><br />
<br />
このページに遷移するにはこんな感じにする。<br />
location.href = baseUrl + '?view=wiki&wikiId=' + wiki.id;<br />
<br />
baseUrlはとりあえずこんな感じでとっている。<br />
baseUrl = (function(){<br />
var path = location.pathname;<br />
path = path.match( /#/) ? path.replace( /#.*/, '') : path;<br />
var ary = path.split( '/');<br />
return ary[ ary.length -1];<br />
})()<br />
<br />
コンテナが&view=を読み取って、意図したページを生成してくれる。3arrowsでは、Opensocialコンテナデフォルトのviewのほかに(home,profile,canvasなど)こんな感じにユーザーが独自に設定した値も使えるということになる。<br />
<br />
次回は、いよいよWikiの閲覧と編集(履歴・エクスポート・インポート、、、できるか??)に入っていく。<br />
<br />
それにしても、ひとつのxmlに設定、言語設定、css、html、jsと埋め込まれていてややこしい。でも、こうして自分でも作ってみると、3arrowsのレギュラーなアプリのコードのつくりの意図が見えてきたりする。<br />
<br />
コードは以下。今回からxmlとjsを分けている。Aptanaがxml+js+html+cssなOpensocialに対応してないので。。。<br />
<a href="http://code.google.com/p/gadget-os/source/detail?r=257&path=/tinywiki/3arrows/tinyWiki.3arrows.xml">http://code.google.com/p/gadget-os/source/detail?r=257&path=/tinywiki/3arrows/tinyWiki.3arrows.xml</a>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-37169232924789940182011-03-07T20:26:00.000+09:002016-08-23T10:57:53.169+09:00液晶TVの修理とジャンクノートの動作確認Download Ontrack Disk Manager 9.43 (IBM OEM) version 9.43 (IBM OEM) :: WinWorld
https://winworldpc.com/download/AC6CD5F3-88C7-11E4-AC5A-5404A6F17893 これ? 2016-08-23
<hr>
少し前に買った¥800の液晶モニタの修理と年末に¥10で買ったノートPCの動作確認をした。<br /><br /><a href="https://lh3.googleusercontent.com/-MEGlrQi1eHs/TXS8751r83I/AAAAAAAAHDA/NaNYxZNNP_8/s1600/iiyamaE430S.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="197" src="https://lh3.googleusercontent.com/-MEGlrQi1eHs/TXS8751r83I/AAAAAAAAHDA/NaNYxZNNP_8/s200/iiyamaE430S.jpg" width="200" /></a>液晶モニタは、未確認ジャンクということで売っていたもの。<a href="http://ascii.jp/elem/000/000/336/336804/">iiyama E430S</a> 1280x1024。その日は迷って結局買わず、試験日の帰りに開放感から購入。<br /><br />家に帰って通電すると画面が乱れていて見れない状態。液晶やバックライトにダメージがないことは分かった。<br /><br />分解して確認すると、電源側の基盤でケミコンが膨れ上がっていた。また、iiyamaのモニタは初めてだけど、分解が容易で好感が持てる。<br /><br />本日、壊れたMBの基盤から同じ容量のケミコンを見つけて付け替えた。16V 1000μFx1と16V 470μFx2それぞれを別のMBからいただく。<br /><br />~で、運よく動いた(^o^)<br /><br /><a href="https://lh5.googleusercontent.com/-RMhY9pdHSpI/TXTAHpQSviI/AAAAAAAAHDE/TIoEI6d-cZg/s1600/v513nax.gif" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="136" src="https://lh5.googleusercontent.com/-RMhY9pdHSpI/TXTAHpQSviI/AAAAAAAAHDE/TIoEI6d-cZg/s200/v513nax.gif" width="200" /></a>続いて¥10のノートPC・<a href="http://www.fmworld.net/biz/fmv/product/former/bi9603/na513.html">FMV-5133NA/W</a>。Pentium 133Mhz、HDDはなく64MB分の拡張メモリカードが刺さっている。CDDなしのFDDモデル。計80MB。800x600。<br /><br />一切通電せず、でもたまにステータス表示用のLEDが点灯するので、電源コネクタの接触不良が酷いみたい。<br /><br />分解というかほとんど壊しながら基盤を取り出し、電源コネクタを外して、以前、Eden500Mhzマザーから交換して取り外していたコネクタをリードを引き出して繋ぐ。<br /><br />はじめCRTに繋ぐと映らないが、ブザーが鳴ってCPUが熱くなる。続いてもともとあったTFT液晶モニタを繋ぐと起動画面を確認。BIOSの設定がCRTへの出力にも成功。<br /><br />無理やり電源コネクタを剥がさなくても接点復活剤を使えなかったか、と後悔する、、、<br /><br />NTLR is missing に対処してFMV-5133にXPを入れている。<br /><a href="http://plaza.rakuten.co.jp/windowsupdate98/diary/200801140000/">http://plaza.rakuten.co.jp/windowsupdate98/diary/200801140000/</a><br /><a href="http://plaza.rakuten.co.jp/windowsupdate98/diary/200801160000/">http://plaza.rakuten.co.jp/windowsupdate98/diary/200801160000/</a><br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://lh6.googleusercontent.com/-9lSN8GJ31Jg/TXTPFnZTZOI/AAAAAAAAHDI/ScMV8TMMXWI/s1600/fmv475.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="https://lh6.googleusercontent.com/-9lSN8GJ31Jg/TXTPFnZTZOI/AAAAAAAAHDI/ScMV8TMMXWI/s200/fmv475.jpg" width="200" /></a></div><a href="http://www.eva.hi-ho.ne.jp/mobile/fmv475nl.html">FMV475NU/T</a>の基盤も通電してみる。<br /><br />こいつは、2003年頃に脚本を書くためにワープロのようなPCを持ちたい、と弟に相談して5000円程度でヤフオクで落札してもらったものだ。<br /><br />当時はまだPCを持っていなかった。職場の同僚はずいぶん進めてくれたのに、、、<br /><br />OSもACアダプタなどの周辺機器がなかったため、結局一度も起動できていない。<br /><br />今回、通電してみるとCPUが熱を持ち、イヤホンからはピコピコ音が聞こえたので生きているのかもしれない。しかし液晶モニタがないためBIOS画面は確認できない。きっとCRTに出すにはBIOSで設定が必要なのだと思う。ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-4928880505759947282011-03-06T23:28:00.003+09:002011-04-01T02:29:34.042+09:00Wiki for 3arrows制作日記 2<div class="separator" style="clear: both; text-align: center;"><a href="https://lh5.googleusercontent.com/-BGFMs4Tpqs0/TXOIqA8xpKI/AAAAAAAAHC8/3dTMGbJJkYo/s1600/tinyWiki.3arrows.120306.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="213" src="https://lh5.googleusercontent.com/-BGFMs4Tpqs0/TXOIqA8xpKI/AAAAAAAAHC8/3dTMGbJJkYo/s320/tinyWiki.3arrows.120306.png" width="320" /></a></div>本日は、ソート・色付け・削除ができるようになった。それぞれ変更がappDataにも保存されます。<br />
<br />
xmlはこんな感じ<br />
<a href="http://code.google.com/p/gadget-os/source/browse/tinywiki/3arrows/tinyWiki.3arrows.xml?r=213">http://code.google.com/p/gadget-os/source/browse/tinywiki/3arrows/tinyWiki.3arrows.xml?r=213</a><br />
<br />
途中thisの挙動がよく分からなかったりして困ったり、そのせいもあってnew ではなく、applyで新しいオブジェクトを作ることになった。<br />
<br />
ここら辺のことはさっぱり分かっていない、、、<br />
<br />
<del>ソート後の配列データの再構成もうまくいかなかったけど、これは別のやり方で回避した。</del><br />
<ins>そもそも.splice( start, n)のパラメータが間違っていた。nを設定してなくて、配列をゴッソリ消してたみたい。。。</ins><br />
<br />
jQuery-uiのソート(sortable)があんまり簡単で驚く。 でも、placeholderプロパティをつけたら、3arrowsのjQuery-ui 1.8.1ではエラーが出た。Google Codeに最新の1.8.10を置いてそちらを読むようにしたところ解決した。<br />
<br />
各Wikiに振られるユニークなIDの割り振りがいい加減なので、消したり追加したりしているうちに変な挙動に遭遇します。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-70911244487137895102011-03-04T23:50:00.002+09:002011-03-09T07:03:56.710+09:00Wiki for3arrows制作日記<div class="separator" style="clear: both; text-align: center;"><a href="https://lh3.googleusercontent.com/-JHwJ33P8Q9M/TXDX7t7AdJI/AAAAAAAAHC0/nykuXwOgW-Q/s1600/tunyWiki_3arrows_110304.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="152" src="https://lh3.googleusercontent.com/-JHwJ33P8Q9M/TXDX7t7AdJI/AAAAAAAAHC0/nykuXwOgW-Q/s320/tunyWiki_3arrows_110304.png" width="320" /></a></div><a href="http://outcloud.blogspot.com/search/label/TinyWiki">自作のローカルWiki</a>を、<a href="http://www.3arrows.jp/">3arrows</a>というOpensocialベースのグループウェアに移植しています。<br />
<br />
ローカルWiki自体は、<a href="http://outcloud.blogspot.com/2011/03/html.html">ちょっと変態的なことをして詰まったり</a>しましたが、僕は元気です。<br />
<br />
以下のURLで見たり触ったりできます。<br />
<a href="http://gadget-os.googlecode.com/svn/tinywiki/wikihelp.html">http://gadget-os.googlecode.com/svn/tinywiki/wikihelp.html</a><br />
<br />
とりあえず、Wikiを作ってみたいという方は以下から。<br />
<a href="http://gadget-os.googlecode.com/svn/tinywiki/tinyWiki_origin.html">http://gadget-os.googlecode.com/svn/tinywiki/tinyWiki_origin.html</a><br />
<br />
動作確認はWindowsのみ、IE6~8、Firefox3、Safari3、Iron8、Opera9~10で動きました。Opera11では動きませんでした。無念っ、、、!<br />
<br />
~で、こいつを3arrowsに移植してみます。<br />
<br />
<b>Opensocialコンテナ3arrowsの所感</b><br />
3arrowsは、Opensocialをベースにしたグループウェアで、情報共有の軸にはTwitterのような<span class="xml-attribute">マイクログログ</span>を据えています。この<span class="xml-attribute">マイクロブログ</span>機能もOpensocial規格のユーザーのアクションを友達に通知する、機能で実現しています。<br />
<br />
また日報や日程表といったサービスも、すべてOpensocialガジェットで提供するパラノイアっぷりで、今後シンプルでパワフルなサービスとして育っていきそうです。<br />
<br />
そういう思い切った感じがいいなと思って、自作Wikiの移植に挑んでみました。<br />
<br />
<b>開発ための情報</b><br />
Opensocial準拠ですのでOpensocialの知識があれば制作できます。<br />
<br />
<a href="http://socialprise-association.blogspot.com/">SocialPrise 広報ブログ</a><br />
<a href="http://nakajiman.blogspot.com/">Nakajiman Software Blog</a><br />
開発のための情報は少ないですが、機能紹介を見ていけばソーシャルガジェット制作のヒントになります。このページで紹介されている<a href="http://socialprise-association.blogspot.com/2011/01/3arrows_5781.html">ツイートイン</a>ガジェットのコードは短いものなのではじめて作るときには参考になると思います。<br />
<br />
<a href="http://twitter.com/#%21/nakajiman/status/39238368726487040">http://twitter.com/#!/nakajiman/status/39238368726487040</a><br />
<blockquote><a class="twitter-timeline-link" href="http://www.3arrows.jp/" rel="nofollow" target="_blank">http://www.3arrows.jp/</a> の AppData は、今のところ 1キーあたり 1MB くらい格納できます。キー数も制限していません。データ量やキー数を大量に使うのは誤用にあたりますが、常識の範囲であればまったく問題ないです!</blockquote><br />
一般的なOpensocialガジェットは10KB程度のアプリケーションデータをOpensocialコンテナに保持できますが、3arrowsはこの部分が拡張されていて、アプリケーションの保存容量に制限はないそうです。ただし1キー辺り(このキーをつけてそのとき必要なデータだけを呼び出す)1MB位にしたほうがいいそうです。<br />
<b><br />
データの持ち方</b><br />
自前のTinyWikiでは、すべてのページをひとつのhtml中に持っています。手元の結構ガッツリ書いたものでも200KB程度のファイルサイズですので、ひとつのWikiをひとつのキーに格納する感じでいいでしょう。<br />
<br />
また、TinyWikiにはなかった、複数のWikiを作れる機能が必要そうですね。<br />
せっかくガジェットをインストールしたのに、Wikiが一つしか作れなかったらシャレになりません。。。<br />
<br />
<b>まずは複数のWikiを管理するマネージャから作る</b><br />
を最初の目標にして、とりあえずここまできたのが一番上の画像になります。<br />
<br />
userのdisplayNameをhtmlに書き込むサンプルは、コントロールパネル>アプリケーション>アプリケーションの追加で、テンプレートというアプリケーションが現れるのでそいつを見てみましょう。または最初から追加されています。<br />
<br />
jQueryやjQuery-uiはあらかじめ3arrowsのサーバにあがっているので、カレンダーなどのコードを覗いてscriptの呼び出しをコピペしておきましょう。<br />
<br />
appDataのgetとupdateを使って、ユーザーのWiki一覧を表示するための情報を取得したり更新しています。(このデータにはWikiの実体は含まなくて、画像のようなWikiのサムネイルを表示するための僅かなデータだけを持っています。)この部分を作るのには、<a href="http://socialprise-association.blogspot.com/2011/01/3arrows_5781.html">ツイートイン</a>ガジェットが参考になりました。ツイートインガジェットはコード量も他のガジェットにくらべ短いので最初に見るにはいいと思います。<br />
<br />
<b>アプリケーションエディターについて</b><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://lh5.googleusercontent.com/-Ih-GMvc7bFY/TXDvFviuU9I/AAAAAAAAHC4/z5kHvQW2c50/s1600/editor_3arrows.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="133" src="https://lh5.googleusercontent.com/-Ih-GMvc7bFY/TXDvFviuU9I/AAAAAAAAHC4/z5kHvQW2c50/s200/editor_3arrows.png" width="200" /></a></div>3arrowsはアプリケーションエディタを持っていて、ガジェットのカスタマイズが行えます。<br />
<br />
ガジェットの設定部分、html部分、js部分、それぞれきちんと色分けされていていいです。僕のAptanaも見習ってほしいです。<br />
<br />
たまに保存に失敗したりするので、今はAptanaで書いてコピペして保存>実行しながら開発しています。<br />
<br />
<b>まだよく把握できていないこと</b><br />
jQuery.historyを使ってブラウザの戻る・進む時にユーザーの予期した画面を提供するようにしている。最終的にこいつも考慮しながら作らなくちゃいけないけど、これはまだやったことがない。<br />
<br />
<span class="xml-attribute">おそらくそれと関連して、gadget.Viewにいろんなものができてる。</span><<span class="xml-punctuation"></span><span class="xml-tagname">Content </span><span class="xml-attname">view</span><span class="xml-punctuation">=</span><span class="xml-attribute">"home,schedule,register,import,profile"></span><span class="xml-attribute">これはガジェット仕様なのかな?3arrowsの拡張なのかな~?<br />
<br />
カレンダーと</span>ツイートインでappDataの呼び方が違う。最初にカレンダーを参考にしたときはデータの保存がうまくいかなかった。Opensocialには、viewerとかuserとかfriendとかいろんなパラメータがあるんだけどこの辺をよく把握してないからかな??<br />
<br />
<br />
カレンダー<span class="whitespace"><br />
</span><span class="js-localvariable"></span><span class="whitespace"></span><span class="js-punctuation">.</span><span class="js-property">add</span><span class="js-punctuation">(</span><span class="js-string">'userAppData'</span><span class="js-punctuation">, </span><span class="js-variable">osapi</span><span class="js-punctuation">.</span><span class="js-property">appdata</span><span class="js-punctuation">.</span><span class="js-property">get</span><span class="js-punctuation">(</span><span class="js-punctuation">{ </span><span class="js-property">userId</span><span class="js-punctuation">: </span><span class="js-string">'@viewer'</span><span class="js-punctuation">, </span><span class="js-property">groupId</span><span class="js-punctuation">: </span><span class="js-string">'@self'</span><span class="js-punctuation">, </span><span class="js-property">appId</span><span class="js-punctuation">: </span><span class="js-string">'@app'</span><span class="js-punctuation">, </span><span class="js-property">keys</span><span class="js-punctuation">: </span><span class="js-punctuation">[ </span><span class="js-string">'calendar'</span><span class="js-punctuation">, </span><span class="js-string">'gcal' </span><span class="js-punctuation">] </span><span class="js-punctuation">}</span><span class="js-punctuation">)</span><span class="js-punctuation">)</span><br />
<br />
ツイートイン<br />
<span class="whitespace"></span><span class="js-keyword"></span><span class="whitespace"> </span><span class="js-punctuation">.</span><span class="js-property">add</span><span class="js-punctuation">(</span><span class="js-string">'viewer'</span><span class="js-punctuation">, </span><span class="js-variable">osapi</span><span class="js-punctuation">.</span><span class="js-property">people</span><span class="js-punctuation">.</span><span class="js-property">getViewer</span><span class="js-punctuation">(</span><span class="js-punctuation">{ </span><span class="js-property">fields</span><span class="js-punctuation">: </span><span class="js-string">'appdata.qs' </span><span class="js-punctuation">}</span><span class="js-punctuation">)</span><span class="js-punctuation">)</span><br />
<br />
この次は、ここまでで何とか表示できたサムネイルに削除や編集ができるようにしていきたいと思います。<br />
<br />
以下がここまでのコードになります(^-^;;<br />
<a href="http://code.google.com/p/gadget-os/source/browse/tinywiki/3arrows/tinyWiki.3arrows.xml?spec=svn210&r=210">http://code.google.com/p/gadget-os/source/browse/tinywiki/3arrows/tinyWiki.3arrows.xml?spec=svn210&r=210</a><br />
<span class="xml-punctuation"></span>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-5115711956749817142011-03-03T04:14:00.000+09:002011-03-03T04:14:57.629+09:00html Editorについてちょっと考え始めるCMSやSNS、ブログについているWYSIWYGエディターは、完成状態のまま書いていけるのがいいのですが、反面、出来上がったhtmlタグがメチェメチャになってしまったりします。<br />
<br />
pタグで囲まないで、brが連続したり。文字の色を変えたりデコレーションしていくと、意味と見栄えの分離からどんどん離れていってしまいます。<br />
<br />
XHTML Basic を対象に、カチっとしたhtmlをそこそこのサポートを受けながら書けるjs製エディターってのを考えてみる。さすがに完成状態を見せながらはできない。<br />
<br />
要素を囲む枠線がいるし、要素名やパラメータも適宜表示する。<br />
<br />
含包要素をチェックする。<br />
<B>太字 や <i>斜線 みたいなタグ付けが無くて、強調<strong>や短い引用<q>を使う。<br />
classやIDの規則は、ユーザー側で設定できる。<br />
<br />
また、おいおい、、、<br />
<br />
http://www.kanzaki.com/docs/html/xbasic.html<br />
http://undine.sakura.ne.jp/uglabo/htmlref/xhtml-basic10/dt.htmlizhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-13085458352510549912011-03-03T03:54:00.000+09:002015-04-25T06:35:30.222+09:00ブラウザ内でローカルのhtmlファイルを更新して保存する<div class="box"><a href="https://lh3.googleusercontent.com/-kTZLf_RGhIY/TW6K6VFrS2I/AAAAAAAAHCw/aLNwT65Fkv4/s1600/tinyWiki0.1.2.png"><img src="https://lh3.googleusercontent.com/-kTZLf_RGhIY/TW6K6VFrS2I/AAAAAAAAHCw/aLNwT65Fkv4/s240/tinyWiki0.1.2.png"/></a>
<p>ちょっと込み入ったhtmlを書く、そんな作業をjsでサポートする。</p>
<p>そんな感じでブラウザ上で更新された Dom は、通常“このページを保存”には反映されない。(多分適当なブラウザ拡張とかはあると思う)そこで Flash で新しいファイルを保存できるようにしてみた。</p>
</div>
<h3>ポイント</h3>
<ol><li>ローカルにあるhtmlもサーバ上のhtmlも保存時には、Web上のFlashを使う。</li>
<li>ローカルファイルからIEでのクロスドメインiframeの注意点</li>
<li>変更前のhtmlの全文はjQuery.getでやる。</li>
</ol><br />
<h3>1. html を作ってくれる Flash は Web に置く</h3>
<p>Flash は、Web 上にある場合とローカルにある場合、当初はその二通りを想定していた。</p>
<p>しかし、Flash ファイルがローカルにあってそのパスに日本語が入ると場合にセキュリティサンドボックス障害のエラーがでる。(多分日本語が入るのが障害の条件だと思う)</p>
<p>仕方が無いので、ローカルの方はあきらめて Flash はサーバ上に置く。もちろんドメインが異なるので、クロスドメインなテクニックを使う。</p>
<p>ここで厄介なのが、ローカルにある html の iframe に Web 上の html を呼び出す場合(いきなり呼ばずにまずは自分自身の URL を iframe に読んで、window.name に値をセット。その後 Flash のある html に移動する)、IE でうまく動作しなかった。</p>
<h3>2. IE 用の対処</h3>
<p>IE でローカルファイルの場合 iframe を作れない(ie8)。空の iframe を作ってスクリプトを書き込む。そのスクリプトでファイル生成用の url に移動する。</p>
<p>他のブラウザでも結局この方法で動いたので、こちらに一本化した。</p>
<h3>3. 変更前の html 全文の取得</h3>
<p>DOM では html すべての内容を取得することができない。xml 宣言やドキュメントタイプは DOM で取得できないし、head内の内容もIEなど一部のブラウザで取得できない。</p>
<p>そこでアプローチを変えて通信で取得してみる。<code>$.get( 'tinyWiki_Origin.html')</code> を使うと全文が取得できた。</p>
<p>(Firefox3.6, IE678, Safari3, Iron8, Opera9,10,11 と試してみて、Opera11 だけ動かなかった。Opera11.00, 11.01とも動かないので一時の気まぐれではないのかもしれない、、、また、get に指定する url は相対パスでないと取得できないブラウザがあった。確か Opera と Safari、Iron。)</p>
<p>新しい html は以上で取得した html 原文のうち、コメントでマークされている部分を新しいものに置き換えることでデータができあがる。</p>
<h3>4. window.name を使うクロスドメイン通信</h3>
<p>空の iframe を作ってスクリプトを書き込んでやる。スクリプトはその window.name にデータをセットしたのち、Flash を呼び出す html のある url に飛ばしてやる。</p>
<p>window.name はドメインをまたいでデータを渡すことができる。クロスドメイン通信のテクニックはいくつかあるけど window.name は最大で8MBまでのデータを保持してくれるのでおそらく一番扱いやすいし高速だ。</p>
<h3>5. 通信というか行きっぱなし</h3>
<p>これはローカルにあるファイルから Web 上のページに遷移し、その後 <code>history.back()</code> でローカルのページに戻ることができない。</p>
<p>html がファイル保存の終了を知ることができないので、画面デザインもそれを見越したものになるし、所以制約される。</p>
<p>ダウンロードしたいファイルが変わった場合は、iframe を消して作り直す。</p>
<p>変態なことすると疲れる、、、<p>
<a href="http://trac.dojotoolkit.org/browser/branches/1.5/dojox/io/windowName.js" target="_blank">
dojox.io.windowName.js
http://trac.dojotoolkit.org/browser/branches/1.5/dojox/io/windowName.js</a>izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-37497641676070861342011-02-28T17:01:00.000+09:002015-11-17T01:34:54.722+09:00初代iMacの整備ご自由にお持ち帰りください、となっていて貰ったiMacを分解して詳しい状態を確認、OSをインストールした。<br /><br /><ul><li>iMac 233Mhz, 32MB+128MB, HDDなし, CDドライブ故障,ボンダイブルー</li><li>iMacDV 400MHz, メモリx2, HDDなし, CDドライブなし(MBとのコネクタもなし、、)ライム、OS8.6のやつ</li></ul>以下は、iMacのためにヤフオクで仕入れたインストールCD。<br /><ul><li>MacOSX 10.1 インストールCD</li><li>OS8.6 インストールCD(iMacDV用)</li></ul><br />最初に(昨夜)DVの方をばらす。CDドライブが専用コネクタと併せて欠品のため、ヤフオクで入手したOSのインストールができない。USBの外付けドライブからのインストールもできない、、、借り物のiMac G5のOSを再インストールしたことがあるだけなので、MacのOSインストールがさっぱり分からない、、、<br /><br />試行錯誤して、初代でインストールしてからHDDを外して400DVに挿す、という方法で成功した。<br /><br />まず、ずっと以前にもらっていた別の初代iMacのHDD(OS8.6)に10.1をインストールした。先の初代を使い、壊れたCDドライブは壊れたノートPCからはずしたものを使っている。<br /><br />HDDへのファイルのコピーが終わったら、自動で再起動がかかるが先には進まず電源を切る。HDDを外してDVライムに挿したところOSの設定画面に進めた!<br /><br />続いてこのPCを使って、IDE-USB変換ケーブルでHDDをMac用にフォーマット。このとき一番先頭のパーテーションのサイズを8GB以下にする。(デュアルブートにする場合は2つのパーテーションで8GB以下)<br /><br />フォーマットの済んだHDDを外して、CDドライブの使える初代につなぐ。これでWindowsなどで使っていたHDDにもOSXをインストールできた。<br /><br />初代でDV付属のOS8.6のインストールにはできなかった。またドライブの設定はできるけどあらかじめマック用にフォーマットされている必要があるみたいだ。<br /><br />DVはこのまましばらくMacIEの動作確認用に使おうと思う。<br /><br />iMacDV ライム<br /><ol><li> OSX 10.1</li><li>PowerPC G3 400Mhz</li><li>128MB+128MB(¥50x2・チップの小さいタイプ)</li><li>Maxtor20GB(¥20)</li><li>CDドライブなし</li></ol>手元にある256MBメモリは使えず、256x2の512MBにはできなかった、、、ジャンク狼http://www.blogger.com/profile/00783910622435757183noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-50238163661360177862011-02-27T00:16:00.000+09:002011-02-27T00:16:10.687+09:00TinyWikiとりあえずできた年末にほぼ完成までいったTinyWikiの最後の問題がつぶせた。<br />
<br />
Wikiのhtmlファイルがローカルにあって、更新されたhtmlを取得する場合にファイルのパスに日本語が入るとFlashがセキュリティサンドボックス障害を吐いてくれて呼び出しもとのhtmlと交信できない。<br />
クロスドメイン風なiframeを用意して、Flashは常にサーバー上に置いてあるものを利用する感じにする。ネット環境がないとファイルの更新ができない。困った、、、<br />
<br />
まず、TinyWikiはいわゆるローカルWikiというやつだ。多分。いや、ただのアウトラインプロセッサかもしれない。アウトラインプロセッサは使ったことないけど。<br />
<br />
Wikiはテーマに沿ってたくさんページを作りながら情報をまとめていくものだけど(アウトラインプロセッサもそんな感じだと思う)TinyWikiではすべてのページがひとつのhtml中に作られる。<br />
<br />
ローカルにたくさんファイルができてしまうといろいろ不具合が多いけど、TinyWikiではそんなことにならない。またできたWikiを外部に簡単に公開できる。htmlだからだ。<br />
<br />
このように、TinyWikiはローカルWikiの特徴も、通常のWikiの特徴も持っている。二つ合わせて7で割った感じだ。2で割った感じにならないのがなんとも悲しい。<br />
<br />
一応、ローカルにファイルをエクスポートした場合もクリアしたので、このWikiを3arrowsに移植してみようと思う。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-83748811994056108302011-02-22T00:31:00.000+09:002011-02-25T03:11:51.983+09:00制作記録 2011/02/21今日は、ハローワークの求人検索時の付加パラメータをサイトから拾ってくるように、Google Spraed SheetsにGoogle Apps Scriptを書いた。<br />
<br />
とりあえず、セレクトタグを切ってくるところまで。<br />
<br />
2年前、ハローワークの世話になっていたときは、求人地域の詳細設定が面倒で難儀した。土地勘が無かったので特に。<br />
<br />
当時と操作も選択項目も変わっている。選択項目は減っているので、検索部分が賢くなっているのかな?<br />
<br />
自宅と就業場所間のルートを確認するような機能は欲しいな。<br />
<br />
このほかに、地域選択部分のUIライブラリがないか調べたりした。<br />
<br />
昨日は、Finder周りを書き換えていった。ドライバがFinderのビューを提供するようにしていく。また、スクロールバーが出たときにバー幅分のコンテンツがリサイズかかるようにする。<br />
<br />
こうして、デバイスに特有なものはドライバに委託していくと、コードがすっきりしていっていいね。イベントについてはそのイベント名だけを持っているクラスを用意する。Stringだけを定義したクラスがあるわけがようやく分かった。<br />
<br />
外部アプリの読み込み開始が、ズームするエフェクトのあとだったのを、クリック時点にする。これで1秒間のエフェクトが終わったときには小さいアプリならロードが完了できる。LLEvelConsoleは外部アプリ化しようかな。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-73993392985406241442011-02-21T19:39:00.000+09:002016-09-23T20:09:08.865+09:00地域選択UIライブラリ欲しいよ<div class="box"><img src="//1.bp.blogspot.com/-bFdDxfMMWsk/TWI2BzYoz1I/AAAAAAAAHCM/ulXw2SGMoMs/s160/place-select.png">
<p>Actionscript製の地域選択UIライブラリがないかなぁ~と思っている。
<p>日本地図から、県を選んでいって、最終的に市町村をササッと選択できるようなの。
<p>jsで県までということなら、画像のものがある。
<div class="links"><a href="http://jsmap.cognitom.com/" target="_blank">http://jsmap.cognitom.com/</a></div>
</div>
<hr>
<p>さて、以上のライブラリを自作するとしたら、ということで調べてみた。
<p>まずは、市町村の数だけど、1700。2001年には3000あって、ここまで減ったのは平成の大合併のおかげということみたい。3000ではさすがにアレだが、1700なら頑張ればなんとか、という気になってくる。まずい!
<p>データはどういう風に持てばいいかな、と以下のページをざぁっと眺める。
<div class="links"><a href="http://ja.wikipedia.org/wiki/%E5%85%A8%E5%9B%BD%E5%B8%82%E7%94%BA%E6%9D%91%E4%B8%80%E8%A6%A7" target="_blank">日本の地方公共団体一覧</a></div>
<p>北海道は、石狩振興局などまずは局で区分されてその下に市が来る。初めて知った。さらに地名にはアイヌ語を元にしたものがあって、改めてみてみるとなんか楽しい。小学校のとき地図帳を眺めていた気分というか。ヨシ、データには読み仮名も入れよう!(って作るのか、、、)
<p>都道府県の下には(局はとりあえず抜かす)、区(東京23区のみ)・市・郡・部(東京の離島だけみたい)の4種類があり、さらに市の下には区、郡と部の下には町・村がくる場合がある。
<p>続いて、マップデータ。荒めのドットで持とうかと考えています。ベクトルは僕の頭では無理だし。
<p>で、作業を始める前に留意しなくてはいけないのが、その解像度。正確な日本地図である必要はないけど要望として、市町村レベルで隣接関係の整合性をとりたい、と思ってて、そのためあんまり省略もできないかなと思っている。
<p>例えばある市について、その市に隣接する市町村はどんなものがあるだろうか?を知りたいときに地図を略図にしすぎると、その隣接関係が崩れてしまう危険がある。
<p>なので、日本地図に方眼紙をあてて、最低どのくらいのドットの細かさなら大丈夫か、行政区分の密な地域についてチェックしておく必要がある。
<p>さて、行政区分の分かる日本地図をどこから手に入れるか?だけど、まさか中学のときの地図帳を使うわけにはいかない。ありがたいことに丁度いいページがあった。
<div class="links"><a href="http://www.freemap.jp/japan/" target="_blank">http://www.freemap.jp/japan/</a></div>
<p>行政区分が市町村レベルで引かれた最新の白地図が手に入る。さすがに日本全部はないので、自分で合成しなくちゃだけど。
<p>最後に保守。10年間で3000⇒1700ということでしょっちゅう合併しているような感じです。データを最新の状態に保つのは結構めんどそう、、、
<p><a href="http://www.post.japanpost.jp/zipcode/dl/oogaki.html" target="_blank">行政などの信用のおけそうなページ</a>のデータを監視するスクリプトを書いておけば、行政区分に変化があったときにはアラートくらいは貰えそう。
<p>また、単純な合併ならデータをマージすればいいだけなので、簡単かも。
<p>最後に、なんかで負けてよその領土になった、なんか独立宣言した、なんかの実験が失敗して地図から消滅した、などはデータの更新が面倒なのでくれぐれも勘弁してもらいたいところです。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-12064403173432126282011-02-20T02:35:00.000+09:002011-02-25T03:11:51.984+09:00求職アプリ<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-PVo2ehlIryU/TV_-NFu5WMI/AAAAAAAAHCI/Nna-3MUJCoM/s1600/hTunes_110220.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="217" src="http://3.bp.blogspot.com/-PVo2ehlIryU/TV_-NFu5WMI/AAAAAAAAHCI/Nna-3MUJCoM/s320/hTunes_110220.png" width="320" /></a></div>求職アプリの制作をはじめて2日。<br />
<br />
検証用のサンプルまで含めるともっと。<br />
<br />
去年の初めに一度着手して、一番簡単なデータの取得には成功している。その後、ハローワークサイトのシステム変更で動かなくなった。<br />
<br />
ちょっとてこずったけど、最初の20件以降のデータも取得できている。<br />
<br />
久しぶりに、Google以外のサービスを利用しているので、気分的にも新鮮。<br />
<br />
短時間でこのくらいまでチャチャっとできるので、俺ライブラリも順調に成長してきてくれているな、と思う。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-45961989587096768302011-02-20T00:03:00.000+09:002011-02-20T00:03:36.527+09:00制作記録 2011/02/19昨日から新しい求職アプリを作ってみている。<br />
<br />
その前に開発中のアプリがpublicβ版に表示されないように、urlパラメータに指定したcsvのURLからアプリケーションをDockに追加するようにする。<br />
<br />
このほかに、urlパラメータ内にcsv相当のデータを持たせて、ガジェットOS内でカスタムなurlを作れるようにしたい。<br />
<br />
この求職アプリでは、とりあえず求人検索結果の最初の20件は取れるようになった。<br />
で、次の20件以降は、どうもCookieパラメータを返しながら遷移していくみたいだ。<br />
<br />
gadgets.io.makeRequestのレスポンスには、このクッキーの内容もついてきてくれているみたいだ。しかしこれまでの間、このことを想定してないので大きくgOS.io.makeRequestを書き換えた。Opensocial jQueryのajaxを参考にしてみた。まだ、dataTypeとかサポートしてないのもあるけど。<br />
<br />
Flash⇔Javascript間でExternalInterfaceするときに、連想配列の受け渡しで問題がある。連想配列のキーに使えない文字があって、エラーが出たりする。現在のgOS.io.makeRequestの元となるものを書いているときは、この問題をよく把握していなかったのでとにかくtextで結果を取得していた。今なら大丈夫なのでザクっと書き換えよう。<br />
<br />
ところで、Flash内部でOAuthサービスを指すIDとgadget.xmlの<Service name="googledocs">を一致させようとxml側を書き換えたら、エラーが返ってきたり、その後は認可用URLが返ってきた。<br />
<br />
あわてて昔のものに戻して、Flash側のIDをgadget.xmlに倣った。しばらくエラーが帰って、その後は認可済みになった。<br />
<br />
このパラメータは、特に実際の運用に入ってから変えてしまうのはまずいみたいだ。少なくともiGoogleでは。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-25225018256977411032011-02-13T22:45:00.000+09:002011-02-13T22:45:26.006+09:00制作記録 2011/02/13Flashで公開されているゲームをゲームパッドで遊んでみようと思い立って、ゲームパッドを出してきてPCに繋いだ。しかしWindowsXPの「コントロールパネル」に「ゲームオプション」が見つからずパッドの認識が確認できなかった。<br />
<br />
nLiteのせいかと、再インストールまで考えたけど、実はWindowsXP以降はゲームオプションがない、というのが真相みたいだ、、、<br />
<br />
以下のページを参考に「ゲームオプション」を復活させ、ゲームパッドの動作が確認できた。<br />
<a href="http://blog.g-fellows.com/index.php?e=23">XPマシンでジョイスティックの優先順位を変える。</a><br />
<br />
Flashゲームをゲームパッドで遊ぶにはゲームパッドの入力をキーボード入力に切り替えるソフトを使うのがいいみたいだ。残念ながらFlashからゲームパッドに直接アクセスする手段はない。(Unityプラグインの入っているブラウザでは、<a href="http://geoquake.jp/blog/2010/02/10/flashjoystick/">こんな方法</a>でできるそうです。)<br />
<br />
僕はJoyAdapterを利用してゲームパッドにキーボードを割り当てていった。<br />
<br />
で、遊んだのは以下のゲーム。最初のマリオは音が出るので注意。<br />
<br />
<a href="http://space.geocities.jp/flashr0d/mario.html">Infinite Mario Bros</a><br />
<a href="http://aminnes.com/">Amin NES</a><br />
<br />
1番目の人はぱねぇー。このほかにFlashのMSXエミュレータや3D描画エンジンの移植、画像認識なんてことも公開している。<br />
<br />
2番目のものはNESエミュレータで、ROMと併せての公開は多分違法だ。作者は中国の方のようで、さすが、NESハック先進国だけある。音の再現はなくキーレスポンスも実機に及ばず慣れが必要。<a href="http://code.google.com/p/aminnes/downloads/list">ソースコードも公開</a>されている。<br />
<br />
今日は普段触らないゲームパッドを出してきたせいで嵌って、結局ゲームを遊んだまでで終わってしまった。<br />
以上二つとも、少し前から知っていてキーボードでは少しいじってみたけど、こうしてゲームパッドで遊んでみて気持ちを新たにできた。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0tag:blogger.com,1999:blog-5003761485377366537.post-82762258113658091142011-02-12T00:20:00.002+09:002011-02-25T03:12:49.139+09:00制作記録 2011/02/11本日は久しぶりにガジェットOSの最新版をリリースした。<br />
<br />
今回の版で、複数OAuth認可時の処理について、大方の決着がついた。<br />
<br />
OAuth認可後の再リクエストの段階ではユーザーが認可したか?認可しなかったか?(操作をしないで窓を閉じた場合も含む)をガジェットが知ることはできない。<br />
<br />
再リクエストで、データが返ってくれば認可は済んだことに。<br />
<br />
エラーテキストが返ってきた場合は、ClearOAuthState()でOAuthStateというパラメータを削除した後、再度リクエストする。このリクエストによって再度認可用URLと新しいOAuthStateを取得する。こんな感じに再取得しないと、例えばユーザーの誤操作でOAuth認可用ページを削除していた場合に対処できない。<br />
<br />
以前にOpensocial-Japanに報告したときには、サービス毎にOAuthStateをクリアする機能はなかったが、この機能がないと有効なOAuthStateまで削除してしまうのでよろしくない。<br />
<br />
いまだにはGoogleのサービスについてだけしかOAuthを行っていないため、さらに他のOAuthなAPIを加えて検証を行ったうえで、修正申請しようと思う。<br />
<br />
明日以降はそんな他のOAuthなサービスの取り込みとあと、アプリケーションを外部ファイルから設定できるようにしていく。これで開発中のものと公開版で別のアプリケーション一覧を持つようにする。izhttp://www.blogger.com/profile/02506132237229293738noreply@blogger.com0