2016年10月13日木曜日

メニューを階層構造にする第二弾 ~Blogger テンプレートを作るよ! (21)~

こんにちはー!

前回、ページリストを階層構造に見えるようにする css を作りました。

ですが、ページリストのクラスに [level〇] をつける必要があり、階層に見えるようにするには沢山のページリストを使わなくてはいけません。

必須ではないですが、運用時にテンプレートを直接変更したくない人のために、ウィジェットの名前の先頭に [level〇] と書くと勝手に level〇 のクラス名を追加してくれる javascript も考えました。

「どうせ javascript を使うならもうちょっと便利にしてブログ制作者の負担を減らしてしまえ」

悪魔のような天使のささやきが聞こえてきました。

今回は、天使にそそのかされた哀れな子羊の舞をご堪能ください。




リストの統合ができるまで

サクッと作ろうぜ

私は最初、こんなものは簡単に作れるだろうと思っていました。

<h2> 要素の中身と <li> 要素の中身を比較して、一致したら <li> 要素の後ろに移動させればいいのです。



ジャンルは違えど私はプログラミングの(元)プロ、この程度の簡単なアルゴリズムなら、朝飯前だ!

そう易々と行かせるものか!

navigation セクションの上から順にウィジェットを確認し、ウィジェットの中の <ul> 要素を移動させ、もぬけの殻になったウィジェットを非表示にするという javascript を完成させました。それはきちんと動作しました。

前回と同様に css を使って外見もきれいに直し、ぱっと見は完璧に思えました。

しかし、問題が一つあったのです。保存して、実際に確認してみたときにそれは起こりました。

編集者のアカウントでブログを見ると、ウィジェットの隣に工具のマークが表示されます。これはウィジェットの設定をするためのボタンで、これのおかげでわざわざ設定画面を開かずに変更できます。

これは <ul> だけを移動させたものには表示されませんので、これでは Blogger の機能を損なってしまいます!

そう考えると、このボタンも一緒に動かす必要があるのですが、ええい面倒臭い! ウィジェットごと移動させちゃえば万事解決じゃないか!

しかし動かない

ウィジェットごと移動させることで、設定ボタンが表示されるようになりました。ウィジェットのマージンやらなんやらを無効化する css を追加して、これで完璧だろう! そう思いました。

しかし困ったことに、設定ボタンを押すとエラーになるのです。

なんで? 私の頭の中には疑問符がぴょんぴょんと跳ねていました。

理由判明

しばらくの時間がかかり、理由が判明しました。

セクションの直下にウィジェットがない場合、エラーになるのです。今回の場合であれば、<div id="navigation"> の直下に <div id="PageList2"> がなければいけません。

でも、私は移動させたい。親と兄弟のいるあの場所へ、 PageList2 を連れて行ってあげたいんだ!

(※階層構造において、自分の上位の階層にいる要素を「parent(親)」、自分と同列にいる要素を「sibling(兄弟姉妹)」と呼びます)

どうしたものか……私の心は憔悴し、3時のおやつが喉を通りませんでした。

解決策の浮上

おやつに食べようとしたオレオでむせたところで、一つ閃きました。ダミーで、<div id="PageList2"> を作ってセクションに置いてみよう! Blogger はこれを本物と誤解して設定ボタンが使えるようになるかもしれない!

思いつけば即行動。プログラムをちょちょいと修正し、 id が重複してはいけないので、移動させた方からは id を削除します。

緊張の瞬間。果たしてこれで上手くいくのでしょうか上手くいきました!(食い気味に)

これで万事解決です。さあ、深夜3時だ。寝るよー!

しかし、もう一つ注意する点がありました。

設定ボタンが被る

たとえば、PageList2 は一人っ子の PageList3 がいたとします。PageList2 は PageList3 を含んでいるので、PageList3 の下端は PageList2 の下端でもあります。

そして、ウィジェットの設定ボタンは、そのウィジェットの右下に設置されます。

ということは、PageList2 の右下と PageList3 の右下は同じ位置にありますので、PageList2 の設定ボタンと PageList3 の設定ボタンは同じ位置に表示されます。

せっかく設定ボタンが使えるようにという配慮をしようとしたのに、どちらかのボタンは被っているために押すことができません。とっても中途半端な結果になってしまいました。

それをどうしたらいいかを考えたところ、思いついたのは 「右上に移動させよう」 という事でした。

少なくとも、今回の階層構造の仕組では、右上に設定ボタンを置いて他と被るという可能性はありません。大丈夫。まだ迷走していませんよ。

結局、<ul> と設定ボタンだけ移動させることに

どうせ設定ボタンを移動させるなら、もうウィジェットごと移動させる必要はなくなりました。というか、最初から設定ボタンも移動させる方針でやっていれば、ダミーを用意するプログラムとかを書く必要はありませんでしたね。

セクションの直下にウィジェットがないといけないというルールを知らなかったのでしょうがないですが、なるべく簡単にしようとした結果、より手間がかかっちゃいました。でもルールを知れたので良かったです。

ダミーを追加する方法から <ul> 要素を移動させる方法に戻し、その <ul> 要素の中に設定ボタンを追加することにします。

二転三転したこの子羊の旅路ももうすぐゴールが見えてきた……と思ったのも束の間、そのゴールの手前には大きく迂回を必要とする壁が待ち受けています。

重複や統合させたくない時の問題

この時点で作っていた javascript では、レイアウト設定画面で並べたリストの順番で処理していくので、上位のリストを先に、下位のリストを後にと並べないといけません。

ここからが悩みどころです。

自分はこれで十分使いやすいけど、他の人にとってはどうだろう? そう考え始めるとなかなか結論には行けません。自分の感覚だけで判断のしようがないからです。

「こうした方が便利かも」 を片っ端から詰め込んでいけばいいじゃない、と思うかもしれません。しかし、「制限が緩いこと」 が必ずしも使い勝手がいいとは言えないのです。逆に、「制限が厳しいこと」 が使い勝手がいいのかというとそうでもないんですが。

大抵のものは、制限を緩くしようとすればするほど、プログラムは複雑になります。プログラムが複雑になるということは、ルールも難しくなっていきます。

  • 「ルールを知らないと使えない」 でも 「ルール自体は単純」 
  • 「ルールを知らなくても使いやすい」 でも 「いざという時、ルールを知ろうとすると分かりにくい」 

どちらの方がユーザーに喜ばれるか。これは人それぞれで、明確な答えばありません。

例えば、 「上位の階層になるリストから順に連続して並んでいると、統合します」 というルールは、知らなければ使いこなせませんが、ルール自体は明確で比較的使いやすく、統合させたくない場合は連続して置かなければいいということも分かります。

でも、「どんな順に並んでいようと離れていようと統合します。同じ名前の項目が複数並んだときは、移動するウィジェットより前にある一番近いリストに統合します。統合させたくない場合はウィジェットのタイトルを変えるか、別のセクションに移動させてください」 というルールだったらどうでしょう。

統合する制限が緩いため、ルールを知らなくても統合するのが簡単であるというメリットがありますが、上位の階層になるリストから順に並べるという決まりがないため、優先される順序について別途記載が必要になり、また制限が緩すぎて統合させたくない人は割と困ったことになります。

しかも、複数の項目がある場合は結局 「上位の階層になるリストから順に並べる」 事となり、たとえルールが緩くても厳しいほうのルールに合わせたほうが無難だという結論に至ります。

悩むこと2日

おはようございますー! 悩んでいるうちに日付が経ちまして、ようやく結論が出ました。

  • 移動させるリストの名前は 「@移動先の項目名」 
  • リストの順序は問わないが、優先順位は一番上にあるもの

結論に至るために定めた方針は、以下のとおりです。

  • 今まで通りの使い方をなるべく邪魔しないこと
    • 普通にリストを使う分には統合しない
    • リスト名の先頭に「@」を付けることは滅多にないだろうと推測
  • 利用するまでの敷居をとことん低くすること
    • 順序は気にすることなく、リストの名前を変更するだけで統合される
    • 優先順位も一言で言い表せるくらい単純にする

というわけで、もうその通りに実装しちゃいます。

ちらつきを抑えたい

何度も何度もテストをしているときに、ずっと気になっていたことがありました。

ページを表示した時、一瞬だけ階層になる前のメニューが見えてしまうことです。ちらついて見えるだけでも、視覚的にはかなり目立つんですよね。画像では表現のしようがないのが悔しいところです。

ということで、 javascript が実行されるまで navigation は非表示にすることにしたい。そんな思いを css と javascript に込めることにしました。

navigation セクションのクラスに unprocessed (未処理)を追加し、javascript 処理後に unprocessed を削除するようにしました。これにより、 css で unprocessed クラスを非表示にしておくことでこの現象を抑制できます。

過去の経験から、 navigation のデフォルトで非表示にした場合はレイアウト設定画面でも表示されなくなってしまうことは分かっているので、そうならないように 「body:not(#layout) .navigation.unprocessed」 という風にしました。これで、レイアウト設定画面では今まで通り表示してくれるはずです。

最終結果

ようやく、納得のいくメニューになったと思います。これならメンテナンス性も損なわず、階層表示が楽にできるようになりました。



……見た目が全然変わってないって? 機能の修正っていうのは、ユーザーの目には見えないけど、使いやすさに大きく貢献しているんです。それはこれくらい大変で、でも大切なことなんですよ。

地味かもしれないけど、しなくてもいい修正なんかじゃない。そういう自信をもって報告を済ませ、次の仕事に取り掛かるところまでがプログラマーの仕事です。

もう少し続くよ

あとは、色とかをテンプレートデザイナーで変更できるように css の調整等を行えば、メニューに関してはほぼ完ぺきです。ということで、次回はこのブログにもメニューを反映させようと思います。

0 件のコメント :

コメントを投稿