ons-input について

私のいる地域(岩手沿岸)では台風10号の影響で健康診断が一か月延期になりました。そして今日、待ちに待ってない健康診断に行ってきました。外で順番待ちの間とても寒かったのと、血を抜かれたのとでだるだるです。ということでリハビリがてらブログ更新です。今週のアプリのアップデート作業はほとんど進まず。おもしろいようにハマるので、もう無理せず行くことにしました。転んでただで起きるのは損なので、この一週間でハマったことをネタにします。

HTML/CSS 編

その1

display: black;

正解は「block」。どうやら blackを指定してもディスプレイは黒くならないようです。勉強になりました。

その2

<div style="margin:10px;width:100px;height:100px;" class="..." style="padding:10px">

デバッガで直接要素のスタイルを書き換えてレイアウトやデザインを調整しているとき、style属性に値を設定しても反映されず悩みました。よく見ると前のほうにすでにstyle属性が。これはきっと属性を複数使っちゃダメということですね。上記の例では2つ目の「style=”padding:10px”」が無効になりました。

ons-input type=”radio” 編

その1

これまでラジオボタンは input要素で作成していましたが、今回 Onsen UI v2を使用するにあたり、はじめて ons-input 要素を使ってみました。そこで謎の現象が。マテリアルデザインのラジオボタンをタップすると、checkedが付加されることでCSSのアニメーション処理が発生し、緑の丸がscale(0)からscale(1)に拡大します。心地よいアニメーションです。ところが、IDEのプレビュー動作はスムーズなのですが、Monacaデバッガでは緑の丸が表示される前に四角形が一瞬表示され、ちらついて見えます。私だけ?
ソースを出すほどではありませんが、とりあえず載せてみます。

... 略 ...
  <script src="lib/angular/angular.min.js"></script>
  <script src="lib/onsenui/js/onsenui.min.js"></script>
  <script src="lib/onsenui/js/angular-onsenui.min.js"></script>
... 略 ...
<body>
  <ons-page>
    <ons-toolbar>
      <div class="center">radio button - test</div>
    </ons-toolbar>

    <div style="margin: 10px;">
        <ons-list>
            <ons-list-item tappable>
                <label class="left"><ons-input name="g1" type="radio" input-id="r1" checked></ons-input></label>
                <label for="r1" class="center">radio 1</label>
            </ons-list-item>
            <ons-list-item tappable>
                <label class="left"><ons-input name="g1" type="radio" input-id="r2"></ons-input></label>
                <label for="r2" class="center">radio 2</label>
            </ons-list-item>
            <ons-list-item tappable>
                <label class="left"><ons-input name="g1" type="radio" input-id="r3"></ons-input></label>
                <label for="r3" class="center">radio 3</label>
            </ons-list-item>
        </ons-list>
    </div>
  </ons-page>
</body>
</html>

いろいろ調べたり試しました。ネットで検索していると「:checked擬似クラスの隣接セレクターのWebkit系での挙動とか」や、そこで紹介されている「Chrome/webkit not rendering css display change on input:checked + element + element」という記事を見つけ、これで解決と喜び勇んで隣接セレクタを間接セレクタに変更してみたのですが効果なしでした。
結局、よく分からないながらも以下のようにチェック前の内側(:after)のopacityを1から0に変更することで四角形の表示を抑止できました。

.radio-button--material__input + .radio-button__checkmark:after {
    opacity: 0;
}

これでうまくいってそうに見えますが、ダイアログ上のラジオボタンで試すとアニメーションが発生しないようです。別問題かもしれませんけど。とりあえず、私としては四角形はこれで防いで、アニメーションは最悪なくてもいいかなと思ってます。ほんとは原因・対策がはっきりするのが一番いいのですが、留意事項ということで。

その2

input 要素でラジオボタンを作成していた時は、以下のように document.getElementsByName() で input要素にアクセスしていました。

// チェックしている項目を取得
var radioList = document.getElementsByName("background");
for(var i=0; i<radioList.length; i++){
  if (radioList[i].checked) {
    ...
  }
}
// チェックする
var radioList = document.getElementsByName("background");
radioList[mdt.setting.backgroundType].checked = true;

ここで、ons-inputにname属性を設定し上記と同様にアクセスすると、うまくいきませんでした。
原因は、ons-input に設定した name属性が、ons-input の子要素として生成される input要素にも設定されるため、document.getElementsByName()で取得した配列には input要素と ons-inputコンポーネント両方が格納されるからです。マニュアルの属性欄にはnameの記載がありませんが実例の5ページ目でname属性を使用していますし、name属性はあったほうが自然だと思います。ons-inputの input-id属性と同じように input-name属性を用意してinput要素にだけ name属性を付けるようにするといいような気がします、素人考えですが。
現状でラジオボタンへアクセスするために、ラジオボタンの親要素にidを追加し、document.getElementsByName() を document.querySelectorAll() に変更してアクセスするようにしました。

var radioList = document.querySelectorAll("#background-list input");

なんかほかにもあったような気がしますが今日はここまで。

Meditation Noteアップデート作業中(2)

リリース済みのアプリのアップデート作業ということでサクっと終わると思っていたのですが、ことあるごとにはまってしまい悪戦苦闘しています。さぼってるわけではないんですが、スキル不足というか集中力が続かないというか。。。
アプリを制作する上でAngularJSと英語がわからないことの不便さも痛感します。いまさらですがAngularJSの勉強をしようかと思っています(英語は来世で)。

進捗

とりあえず、このアップデート作業で何をしていたのか、制作日記から抜粋し振り返ってみます。

  • 10/25 アップデート作業を開始する
  • 10/28 v1.0.0のファイルデータの変換関数完成。前機能の削除、管理テーブルの変更
  • 11/3  日付・時間表示形式設定機能完成
  • 11/8  グラフ機能完成。ブログにAdSense広告が表示されるようになってうかれる
  • 11/9  メモ機能完成。アメリカ大統領選挙。アンドロイダーの公認デベロッパー登録が完了してうかれる
  • 11/14 ニフティバックエンドを利用した機能追加
  • 11/15 レイジーリピート導入
  • 11/16 Onsen UI v2に移行

グラフはずっとflotr2を使っているのですが、今回はじめて棒グラフと線グラフを一緒に表示することにしたのでちょっと時間がかかってしまいました。あと、ニフティバックエンドを使ってみたくて、いろいろ調べたりサンプルを作って勉強したりもしてました。
現在Onsen UI v2対応とマテリアルデザイン化を行っているところです。
この作業に意外と手間取っています。

Onsen UI v2への移行

Onsen UI v1からv2への移行自体は割とスムーズにいきました。Onsen UIドキュメント「Onsen UI 1 系からの移行」や、Monaca公式ブログ「Onsen UIをバージョン1から2へ移行するには」にわかりやすい説明があります。ただ私の場合(localkit)、「JS/CSSコンポーネントの設定画面で Onsen UI をいったん削除する」とあったのですが、インストールしたコンポーネントの一覧に Onsen UI がなかったため、そのまま Onsen UI v2.0.3をインストールしました。そうしたところ、アプリの画面がへんてこに。調べてみると、なぜか v1.3.8 の CSS ファイルを参照しているらしく、Onsen UI を削除してから再度インストールをしたら正常に動作するようになりました。

マテリアルデザイン

Onsen UI v2をインストール後アプリを起動すると、自動的にマテリアルデザイン化されるようです(IDEのプレビューは ons.platform.select(‘android’); を実行すると対応します)。最初、マテリアルデザインに違和感があり、元のデザインに戻そうかと考えたのですが、何度も見ているうちに慣れてきたというか逆にシンプルさが気に入り、今回アプリをマテリアルデザインに対応させることにしました。
Onsen UIコンポーネント(ons-xxx)は自動的にマテリアルデザイン化してくれるのですが、それ以外の要素(div, li, …)は手動で対応させる必要があります。今、この作業をOnsen UI Theme Rollerを参考にしながら行っています。例えば、ulリストは以下のような記述になります(Material List引用)。

<ul class="list list--material">
  <li class="list__item list__item--material">
    <div class="list__item__center list__item--material__center">
      <div class="list__item__title list__item--material__title">Orange</div>
      <div class="list__item__subtitle list__item--material__subtitle">Sweet fruit that grows on trees.</div>
    </div>
  </li>
  <li class="list__item list__item--material">
    <div class="list__item__center list__item--material__center">
      <div class="list__item__title list__item--material__title">Pear</div>
      <div class="list__item__subtitle list__item--material__subtitle">Funny-shaped fruit.</div>
    </div>
  </li>
</ul>

クラス名はBEM(Block Element Modifier)を適用しているので慣れてない私にはどこで切れてるか見分けるのが大変。目がしょぼしょぼしてきますが、これを自分で作成するのはもっと大変なわけで、こういうサンプルは非常にありがたいです。

なお、マテリアルデザインについてはグーグルがガイドラインを公開しています。
・公式サイト: Material design
・日本語のドキュメントはこちらからダウンロードできます。

おわり

来週リリースを目標に明日から本気出します。

リリースしたアプリの起動がある日突然遅くなった話

昨日 11/2 お昼前、いっぷくしようと思い、自作アプリ Smoking Note を立ち上げようとしたときのことです。
… アプリの起動が妙に遅い
スプラッシュスクリーンが消えた後も、時刻などの動的に描画する要素がなかなか表示されない。ちょっと許容できない遅さで、たまたまかなと思い何度か立ち上げなおしても状況は変わらず。アプリの起動後の動作には問題がなく、広告自体もちゃんと表示されるのですが、ただただ遅い。

アプリのキャッシュをクリアしても、スマホを再起動してもだめ。
「いやいや、今日ついさっきまで普通に起動してたのに、冗談でしょう?」と軽く現実逃避しながら昼食をとり、気を取り直して再度アプリを立ち上げてみても、やっぱり起動が異常に遅い。

このとき、めっちゃ焦りました。さーっと血の気が引く感じ。

突然動作が変わる原因として、広告配信かファイル関連くらいしか思いつかなくて、私が使用している広告 admob について現在なにか起こっていないか、ネットでずっと調べてました。admob の表示には cordova プライグインの cordova-admob-pro を使っているので、これについても調べたのですが、それらしい情報はどこにもなく、admob への問い合わせ先も見つからない。

で、デバッグ開始です。
実機での起動時の動作確認のため、ちょっとめんどいけど仕方なし。
まず、ソースを変更せず(アプリ名だけ変更)デバッグビルドで構築して実機にインストールし、現象が再現するかを確認。
うん、再現します。間違いなく。
この時点でファイルなしでも発生することが確認できました。
また、広告をテスト広告に変更しても同様に発生しました。
次に、ブレークポイントは貼れないのでコンソール文とアラート関数を埋め込み、ビルド・インストールし動作確認。
これを繰り返してやっとのことで発生個所を特定しました。

/*** test 2016/11/02 ***/
window.alert("init_ad in");
  if(window.AdMob) AdMob.prepareInterstitial({
                     adId: admobid.interstitial,
//                     isTesting: true,
                     autoShow: false
                   });
window.alert("init_ad out");  // 上記の alert 表示後の
                              // この alert 表示が異常に遅い!

上記のインタースティシャル広告作成関数でプログラムがしばらく止まるんです
この関数自体は非同期関数のようにすぐに返ってくるはずなんですが、この日このとき、なぜかすぐに返ってこない。

で、特定はできたけどこれからどうしようと考えながらいっぷくしようと Smoking Note を立ち上げたら …
なおってる!
なんかしらないけど、普通に起動しました!
このとき、午後 18:16 。
まるで夢のような出来事でした。
こうゆうケースが現実にありましたということで、ご参考まで。