飴屋

開発日記/2016年の日記

2016/12/28

Wordpressで管理するサイトの制作をよくお引き受けするのですが、タイトルや本文以外にお客さんが独自に入力したい項目を更新画面に追加する際、よくカスタムフィールドテンプレートというプラグインを導入させてもらってもらす。数ある似たようなプラグインの中からこれを選択した理由は、ググるとよくみかける、という理由なのですが、たくさんの人に使われているだけあって、機能が充実しています。

ただ、ちょっとバグっぽい挙動が現在の最新バージョンに残っていて、お客さんから何とかならないかと相談されました。

相談1

フィールドセット(特定の入力欄のセット)をmultiple指定(セットの追加・削除ができるように)した際に、セットの中の複数行入力欄(textarea)にtinyMCE(リッチエディタな拡張)をつけると、フィールドセットを「追加」した際に追加されたtextareaのtinyMCEが操作を受け付けなくなる。

どうも調べた感じだと「追加」されるフィールドセットは一つ前のフィールドセットを複製し、入力値をリセットした上で下に追加されているっぽかったです。その複製の際にtinyMCE化されているtextareaがそのまま複製され、その上さらにtinyMCE化を重ねて行うおうとしているのが問題になっているようでした。

そこで「追加」の際にtinyMCE化を一度解除して、追加後に再度tinyMCE化を行うことでなんとなく誤魔化せるようになりました。具体的には「textarea_tmce_ids」というローカル変数にtextareaのidが集められているところで「tinyMCE.execCommand('mceRemoveEditor')」を呼び出すように変えたのと、「textarea_tmce_ids」で集めたidに対してtinyMCE化している箇所があるのでそれが終わった後に同様にそのidに対して「switchMode(id)」を呼び出してあげました。

相談2

tinyMCE化されたtextareaの内容を編集してから、別の入力欄でメディアピッカーを使って画像を選択すると先に編集したtextareaの編集内容がリセットされている

これはメディアピッカーで画像を選択した際の挙動が

  1. 選択した内容を入力欄(input[type~"hidden"])に反映させる
  2. カスタムフィールドテンプレートの入力欄の内容をサーバーに送って、更新する
  3. 更新された内容を読み込みなおして入力欄を更新する

    という流れになっているのと関係がありそうでした。2番と3番の挙動はajax的にサーバーと通信をして行われるので、ページの遷移は伴いません。

ここでtinyMCEの挙動について説明をしておくと、textareaをtinyMCE化した場合、textareaは非表示となり、DOM的にtextareaの直前にリッチエディタが作成されます。リッチエディタ上で編集された情報は随時非表示のtextareaに反映されるというわけではなく、どうもフォームのsubmitをきっかけに自動的に内容が同期されるっぽいです。

メディアピッカーが画像を選択し終わったあとの処理はajax的に処理をされるので、カスタムフィールドテンプレートの入力欄の中でtinyMCE化されたtextareaだけは編集内容が同期される前の状態でサーバーに送信されてしまうというのが、問題の原因だったと思われます。

メディアピッカーで画像を選択した際に「cft_use_this」という関数が呼び出されるので、前述の2番の挙動の前に何かtextareaに編集内容を同期する方法がないかと考えていたのですが、時間がなかったので

win.jQuery("#cft textarea:hidden").each(function(){
switchMode(win.jQuery(this).attr("id"));
switchMode(win.jQuery(this).attr("id"));
});

↑こんな感じのコードを追加してお茶を濁しました。tinyMCE化を一度オフにしてからオンにしなおすと同期されるというのを利用しました。多分、もっといい方法があると思いますが、tinyMCEのAPIリファレンスを眺めていてもすぐに見つけることができなかったのでした。

早くプラグインの開発者の人が直してくれるといいなと思っています。
もしかしたらWordpress(の同梱tinyMCE)とカスタムフィールドテンプレートの相性が悪いだけなのかもしれません。そうだとしたら、導入タイミングがよくなかったという感じですね。

2016/9/12

WEBサイトを彩るパーツにSVGが使われることも増えてきた昨今に出くわした問題のメモです。とあるレスポンシブWEBデザインなページの内のとあるボタンをSVGにし、PCのブラウザでボタンをクリックできることを確認し、Android端末のブラウザ(Chrome)でも同様にボタンがクリックでき、問題なく動作することを確認し、続いてiOS端末のブラウザ(Safari)で同様の確認作業を行った際、ボタンをタップしても想定した動作が起こりませんでした。
タップ時にiOSでだけ何かしらのJavaScriptのバグが発生しているのかと思い、タップ時にalertを出すように処理を変更し、再度タップしてもうんともすんともいいませんでした。

どうやらiOSのSafariでは要素でonclickイベントが発火しないっぽいので、要素ででも囲ってみようかと思いましたが、試しに

svg {cursor:pointer;}

↑このように要素に対して、マウスカーソルを指型にするCSSをあててみたところ、要素のボタンもonclickを発火するようになりました。「なんでだよ!?」と内心思いましたが、動いたのでとりあえずよしとしたのでした。

2016/8/22

不可解な現象が起こったとの連絡をお客さんからもらったので調査したときのお話です。いわゆるお問い合わせフォームを設置したら、お問い合わせ完了時の通知メールが二通届き、しかも片方は入力内容が空になっているとのことでした。

お客さん内製のPHPのフォームだったのですが、PHPの記述には問題がなく、サーバー側の問題かメールサーバーかスパムフィルターの問題を疑ったのですが、どうも関係なさそうでした。

悩んだ末、たどり着いた問題の原因は、完了ページに二度アクセスが飛んでいるということでした。

<link rel="shortcut icon" href="" />

お客さんがページのアイコンの設定を空にしていたのを発見しました。アイコン画像のファイルはユーザの操作とは関係なくブラウザが自動的に取得するようになっていることが多いと思います。その際href属性が空文字だと、リンクは現在表示中のURLに向かっていることになるので、完了画面を表示すると同時に自身へのアクセスがもう一度発生するということになります。その二度目のアクセスが入力内容が空っぽの不要なメールを生んでいたというのが原因でした。未検証ですが、Firefoxで起こるという情報がありました。

これが