うぃろぅです。
納期1に追われてしばらく死んでいました。多分今月は状況が変わりそうにありません。
上司に「これ修正したんですけど反映していいですかー」と訊くたびに「ちょっと待ってね」と返ってきて下手に動けないため今回遭遇した事象を書きます。
若干長くなったので目次置いときます。
今日のお題
久しぶりにとんでもないHTMLを見た
何があったの
今何をやっているかというお話。とあるandroid / iOS向けの交通系アプリを改修しているのですが、このアプリの追加機能として、「お知らせ
タブを選択したらWebView
でサーバに置いてあるHTMLを表示」というものがあります。
アプリの中でサイトのお知らせがみられる、みたいなあれですな。
アプリ側の開発は私のチームが対応していて、表示するHTMLは別チームのおじさんが作成している、という体制です。
このおじさんがまぁ仕事ができないらしく、お客様からもクレームが来るという方なのですが、詳細は置いておきましょう。
で、先日「android6.0だとHTML内のリンク(target="_blank"
)を叩いてもブラウザ起動してくれない、WebView
内で開いてしまうから前の画面に戻れない」という報告を受けたので解析をしました。
最終的に「アプリ側でブラウザを起動して対応」という形にしたのですが、これが最適解ではない気がするので答えを探したいところ(手が回ってない)。
この修正をする過程で上記のおじさんが作成したHTMLを見てみたわけなのですが、ついつい笑ってしまったためここで供養しておきます。
件のHTML
※ 名前等いろいろ伏せていますが構造的にはほとんど変えていません
<html lang="ja">
<head>
<meta charset="UTF-8">
<head>
<title>HogeView</title>
<meta name="viewport"
content="initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<style type="text/css">
.fsize {
font-size: 75%;
}
</style>
<link rel="stylesheet" href="Hoge_sample.css" type="text/css">
</link>
<script type="text/javascript">
var agent = navigator.userAgent;
function setTitle(_title) {
if (agent.search(/Mac OS/) != -1) {
document.location="iphone://setTitle?title=" + _title;
} else if (agent.search(/Android/) != -1) {
android.setTitle(_title);
}
}
function reloadWebView() {
if (agent.search(/Mac OS/) != -1) {
document.location="iphone://reloadWebView";
} else if (agent.search(/Android/) != -1) {
android.reloadWebView();
}
}
function startApp() {
if (agent.search(/Mac OS/) != -1) {
document.location="iphone://startApp?&siteUrl=hoge://&storeUrl=https://example.com";
} else if (agent.search(/Android/) != -1) {
android.startApp("hoge://","https://example.com")
} else {
window.open('https://example.com', '_blank');
}
}
</script>
</head>
<body class="fsize">
<table width="100%" border="0">
<caption></caption>
<thead></thead>
<colgroup col span="2">
<col width="200">
<col width="200">
</colgroup>
<tbody>
<tr>
<td valign="top">
<figure style="text-align:center;"id="HgHgInf">
<a href="https://example.com" target="_blank">
<img src="images/hoge_logo.png" alt="Hoge Hoge Information" width="60" height="60" hspace="0" valign="top">
</a>
<figcaption>Hoge Hoge Information</figcaption>
</figure>
</td>
<td valign="top">
<figure style="text-align:center;"id="FugaInf">
<a href="https://example.net" target="_blank">
<img src="images/fuga_logo.png" alt="Fuga Info" width="60" height="60" hspace="0" align="top">
</a>
<figcaption>Fuga Info</figcaption>
</figure>
</td>
</tr>
<tr>
<td valign="top">
<figure style="text-align:center;"id="HogeFuga">
<a href="javascript:void(0)" onclick="startApp();">
<img src="images/hogefuga_ico.png" alt="HogeFuga" width="60" height="60" hspace="0" valign="top">
</a><br>
<img src="images/hogefuga_logo.png" alt="HogeFuga" width="87" height="20" hspace="0" valign="top">
</figure>
</td>
<td valign="top">
<figure style="text-align:center;"id="fooBar">
<a href="https://example.org" target="_blank">
<img src="images/foobar_logo.jpg" alt="Foo Bar Organization" width="90" height="40" hspace="0" valign="top">
</a>
<figcaption>Foo Bar Organization</figcaption>
</figure>
</td>
</body>
</html>
賢明なる皆様は普段こんなHTMLを読むことはないでしょうが、本当にこんな感じでした。
ブラウザで表示するとこんな感じ。画像ファイルは置いてません。
さて、順番に見ていきましょう。
問題点を見てみよう
タグの重複
5行目あたりなんですが、
<html lang="ja">
<head>
<meta charset="UTF-8">
<head>
head
タグが重複しています。なぜ。
このhead
タグ、ここで閉じるべきなのかというとそうではなく、54行目でちゃんと閉じタグがあるんですよね。
なので単純ミスなのかな、という気がします。なぜ。
謎のCSSファイル読み込み
17行目に<link rel="stylesheet" href="Hoge_sample.css" type="text/css">
とありますね。
どうやらHoge_sample.css
というCSSファイルを読み込んでいるようです。なのでファイルサーバを確認してみました。
そんなファイルは存在しませんでした。まぁそんなこったろうと思ったよ。_sample
の箇所は名称変更してないし。
おそらくその辺に転がっていたHTMLサンプルをコピペしてきたのでしょう。よくある話ですね。
タグが閉じていない
そもそもこのファイルをIDEで開いたらエラーが出たんですよ。「エレメントが閉じられていない」みたいなエラー文言。
そうなんです。</body>
の周辺を見ていただけたらなんとなくわかるかもしれません2が、tr
タグとtbody
タグとtable
タグが閉じられていません。
根本原因が見えてきましたね。
※ 調べてみたらtbody
の閉じタグは省略可能のようです。
詳しくは後述。
valign間違い探し
CSSを読み込んでいないのでHTML内にstyle
要素を直書きしているため、割と多くの箇所にvalign="top"
が記載されているのですが、84行目に注目すると、<img src="images/fuga_logo.png" alt="Fuga Info" width="60" height="60" hspace="0" align="top">
となっており、ここだけvalign
がalign
になっています。サイゼリヤかよ。
コピペ漏れでしょうか。もしかしたら意図してこうしているのかもしれませんが、その場合top
は指定しても意味がないんですよね。
ここまでは「絶対おかしい」と指摘できるポイント。ここからは「いやまぁいいけどさぁ」なポイントです。
※ 個人の感想です。
インデント
一番気になるのはここですよね。head
とbody
がインデントなしなのは人によりけりなので気になりませんが、せめてtable
配下は字下げしたいですね。左の壁に粘着テープでも貼ってあるんか???
大方ページのソースを表示
でHTMLが自動生成されているサイトをコピペしたのではなかろうかと推測されますが、試しにはてなブログ(この画面)のソースを表示してみても
<div class="curation-header header">
<h2>
編集サイドバー
</h2>
<p>よく使う機能は、ショートカットとしてタブに追加できます。</p>
</div>
ちゃんとインデントされているんですよね。うーん。
空のタグ
58行目あたりなのですが、
<caption></caption>
<thead></thead>
中身がないタグがあるんですよね。これは省略可能な気がしますが、どうなんでしょうか。
試しに省略してみても問題なく表示はできましたが記載するお作法なのでしょうか…?
コメント内に謎の例示
43行目あたりに// 外部アプリ起動(例:Hogeアプリ)
とあります。
この例は何なんでしょうか。HTML内にはこのメソッドを呼び出している箇所が1か所しかないんですよね。追加する方針でもあるのかしら…?
大きさの単位が不明
結構いろいろな箇所にwidth="60" height="60"
という表記があります。きっと単位はpx
なのでしょう。em
だと大変なことになりそうですし。でも単位を書かないってどうなのでしょうね。line-height
に記載しないのはよく見るのですが。
ちなみに私は中学生くらいの頃に図形の問題で単位が書かれていないのにcm
だったかを入れて不正解をもらったことがあります。許せん(自業自得)。
列のグループ化の意図が不明
60行目あたりの
<colgroup col span="2">
<col width="200">
<col width="200">
</colgroup>
ここなんですが、これを記載する意図が分からないんですよね。これって
ID |
名前 |
生年月日 |
1 |
花澤香菜 |
1989年2月25日 |
2 |
小倉唯 |
1995年8月15日 |
3 |
豊崎愛生 |
1986年10月28日 |
こんな感じで列の幅が違うことを明示的に示すために利用すると考えています。
でも上記のソースだとこの幅が同じなんですよね。明示的に同じ幅にしたかったのかもしれない。なあにこれえ。
謎のID付与
随所に見られるid="HgHgInf"
のようなIDはいつ使うのでしょうか。CSSでもJavaScriptでも使用している形跡がみられないんですよね。必要性が気になるところ。
もっというとC言語の変数名のような謎の省略がされていたり、1文字目が大文字になっていたり小文字になっていたりと統一性もない。CSSで指定するならclass
指定がよく見るのですがなんなんでしょうか。私今日ずっと混乱してるな。
こんなところでしょうか…?探せばもっとあるかも??私には何もわからないよ。
どうしたか
上記2点を修正してそのファイルを使ってくれないかと懇願しました。
現在は「ちょっと待ってね」状態なので通るといいなあ、といったところ。
修正後を貼っておきます。多分これでもまだまだだと思うのでマサカリ大歓迎。
CodePenは会社のWebフィルターでブロックされてしまうので貼れませんでした。かなしい。
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>HogeView</title>
<meta name="viewport" content="initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
var agent = navigator.userAgent;
function setTitle(_title) {
if (agent.search(/Mac OS/) != -1) {
document.location="iphone://setTitle?title=" + _title;
} else if (agent.search(/Android/) != -1) {
android.setTitle(_title);
}
}
function reloadWebView() {
if (agent.search(/Mac OS/) != -1) {
document.location="iphone://reloadWebView";
} else if (agent.search(/Android/) != -1) {
android.reloadWebView();
}
}
function startApp() {
if (agent.search(/Mac OS/) != -1) {
document.location="iphone://startApp?&siteUrl=hoge://&storeUrl=https://example.com";
} else if (agent.search(/Android/) != -1) {
android.startApp("hoge://","https://example.com")
} else {
window.open('https://example.com', '_blank');
}
}
</script>
<link href="https://unpkg.com/sanitize.css" rel="stylesheet" />
<link rel="stylesheet" href="links.css" type="text/css" />
</head>
<body>
<table>
<tbody>
<tr>
<td>
<figure>
<a href="https://example.com" target="_blank" >
<img class="hoge-info" src="images/hoge_logo.png" alt="Hoge Hoge Information">
</a>
<figcaption>Hoge Hoge Information</figcaption>
</figure>
</td>
<td>
<figure>
<a href="https://example.net" target="_blank" >
<img class="fuga-info" src="images/fuga_logo.png" alt="Fuga Info">
</a>
<figcaption>Fuga Info</figcaption>
</figure>
</td>
</tr>
<tr>
<td>
<figure>
<a href="javascript:void(0)" onclick="startApp();">
<img class="hogefuga-icon" src="images/hogefuga_ico.png" alt="HogeFuga">
</a><br>
<img class="hogefuga-logo" src="images/hogefuga_logo.png" alt="HogeFuga">
</figure>
</td>
<td>
<figure>
<a href="https://example.org" target="_blank">
<img class="foobar" src="images/foobar_logo.jpg" alt="Foo Bar Organization">
</a>
<figcaption>Foo Bar Organization</figcaption>
</figure>
</td>
</tr>
</tbody>
</table>
</body>
</html>
body {
font-size: 75%;
}
td {
valign: top;
}
table {
width: 100%;
border: 0;
}
figure {
text-align: center;
}
img {
hspace: 0;
valign: top;
}
img.hoge-info {
width: 60px;
height: 60px;
}
img.fuga-info {
width: 60px;
height: 60px;
}
img.hogefuga-icon {
width: 60px;
height: 60px;
}
img.hogefuga-logo {
width: 87px;
height: 20px;
}
img.foobar {
width: 90px;
height: 40px;
}
できるだけ元ソースを維持したまま修正してこんな感じに。
これが正しいかもわからない。私は今霧の中にいる。
どうしてこうなったか
原因は…何なんでしょうね。
割とおじさん自身にある気がしていて、
- そもそもの知識不足
- コピペでこれまで何とかなってきた謎の自信
- 人に訊けないプライドと年齢
あたりは大きい気がしています。
防ぐ方法としては
- レビューをする
- もう少し何とかなりそうなひな型を作っておいて参考にしてもらう
あたりですかね。
あとさっきCSSのタグについて見つけたサイトがあります。
html-coding.co.jp
こちらのサイトの例えばtable
タグのページ。
実に「それっぽく」ないですか…?
ちなみに少し下にスクロールするとちゃんとインデントされているサンプルが掲載されています。
サイトは悪くない。
気になるのはこのサイトがHTML5とCSS3に対応していないことですが、それはサイト運営側の話なので私が何か言える立場ではないですね。
今日の教訓
クソコードに気をつけて
結局修正するのは私のような末端になるんですよね。うまいこと受け流して生きていきましょう。
私はこれから別のバグ修正が入ったので終電の心配をしながら作業を続けます。
ではまた。