2012/12/27

Wordpress3.5(追記:3.5.1も) と HeadSpace2

腰かけSE様よりご指摘をいただき訂正:2013-03-23)

WordPressのプラグインHeadSpace2の設定画面で、「ページモジュール」表示中に、

  • モジュールのドラッグ&ドロップができない。
  • メニューバーの「メニューを閉じる」でメニューは閉じない。
  • モジュールの「編集」ボタンをクリックすると、おそらく表示しているページにappendかprependされるだろう要素が無装飾で表示されてしまう。
という問題に出くわした。


WordPressは最近バージョンが3.5になったらしいのだけれど、そもそも最近になって使い始めたものだから前のバージョンだったら動くのかもわからない。

ただ、なんとなくだけど上記の症状から jQuery か jQuery ui の挙動がおかしい感じがする。。。


GoogleChromeの“要素を検証”で確認

対象のページで
右クリック > “要素を検証(N)” > “Resources”
で load-scripts.php にエラーを発見。

やっぱり jQuery の読込み時にエラーが発生しているみたいだ。


jQuery関連のバージョンダウンでサクッと解決

調べてみるとWordPressが3.5になったときに、jQuery 関連のバージョンも変更されていたので、
とりあえず WordPress3.4.2 に内包されている jQueryフォルダ(/wp-includes/js内) をアップロードしてみたら、上記3つの問題は全て解決。

他のプラグインとかで問題が出てくるかもしれないが、今のところは何も起きていない。


注意

おそらくWordPressのアップグレードに伴うjQueryのバージョン変更により、HeadSpaceが正常に動作しなくなったものと考えていますが、実際はどこがどうエラーを起こしているかまでは検証してはおりません。


追記:WordPress3.5.1でも同じような症状にでくわした。

上記と同様にjQueryフォルダを3.4.2のものと入れ替えても解決しないので、
フォルダ内を覗いてみると3.4.xから3.5.xのときにjsのファイル名が変わってた。

jQuery
[wp3.4]jquery.js(ver.1.7.2) ⇒ [wp3.5]jquery.js(ver.1.8.3)
非圧縮ファイル
[wp3.4]jquery.xxx.dev.js ⇒ [wp3.5]jquery.xxx.js
圧縮ファイル
[wp3.4]jquery.xxx.js ⇒ [wp3.5]jquery.xxx.min.js
追加ファイル
[wp3.5]jquery.masonry.min.js
uiフォルダ内
みてない

つまり、WordPress3.4.2内のjQueryフォルダを読込ませるだけでは、load-script.phpscript-loader.php はちゃんとjsファイルを読込めてないということだから、 WordPress3.5.1の load-script.phpscript-loader.php 内のjQuery関連のjsファイル読込み部分を書き換えることで解決するはず。

でも面倒だったので、機能不全にはなっても致命的エラーはないだろうと高を括って WordPress3.4.2のload-script.phpscript-loader.phpと入れ替えて解決。 ちなみに、WordPress3.4.2のload-script.phpscript-loader.phpだと122行目、3.5.1だと127行目あたりでjQuery関連を読込んでいる。


さらに追記:最終的な解決方法

上記の方法でHeadSpaceは動くようになった。が、管理画面上でフォーム部品(主にボタン)の描写と挙動がおかしくなった。

あるじゃないか、致命的なエラー。描写はともかく挙動がおかしくなるのは困る。


ということで不完全燃焼気味の応急処置の方法は、以下のようになる。

  1. /wp-includes/js/jQuery//wp-includes/load-script.phpscript-loader.phpを3.4.2のものと入れ替える。
  2. HeadSpaceの設定をする(以後、変更しないでいいように入念に)。
  3. /wp-includes/js/jQuery//wp-includes/load-script.phpscript-loader.phpを3.5.xのものに戻す。

jQueryフォルダ交換とload-script.phpscript-loader.php内のjQuery読込み部分のみの書換をした場合については未検証。


2012/07/03

"header"や"footer"を再利用する方法|jQuery Mobile

ヘッダーとかフッターをjQuery Mobile利用のサイト内で再利用する方法。


jQuery Mobile(jqm)ではAjaxを利用したページ遷移が基準となっている。

さらに、スマートフォン向けにUIを最適化までしてくれるため、
単純に外部ページの要素を読込むだけでは表示が上手くいかない。

ページ遷移については初期設定により通常リンクに変更することができるけれど、
UI最適化まで無効にしてしまったらjqmを使う意味がなくなってしまう。


そこでjqmの機能を最大限に活かしつつ部品(フッターなど)を外部ページから取り込む方法を考えてみた。


"部品"を集めたページを用意する|module.html

とりあえず読込まれる側のページを用意する。

このページから必要な部品を取り出して、jQueryのprepend()append()を利用して必要なページに埋め込む。

<!DOCTYPE html>
<html lang="ja">
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <section data-role="page">
   <header data-role="header">
    <h1>module header</h1>
   </header>
   <footer data-role="footer" data-theme="e" class="ui-bar">
    <h3>module footer</h3>
   </footer>
  </section>
 </body>
</html>

上記の例ではリンクを含んでないけれど、メニュー表示などの<a href="***"></a>を含む場合は、絶対URLで指定する。


"部品"を読込むためのスクリプト|module.js

スクリプトでしたいことは3つ。

  • 外部ページから"部品"を読込むこと
  • 読込んだ"部品"を埋め込んだ後にUI最適化すること(ランディング時や更新時用)
  • 最適化された"部品"を次のページに埋め込むこと(ページ遷移時用)
function module() {
 var head = $('#module :jqmData(role="header")').clone();
 var foot = $('#module :jqmData(role="footer")').clone();
 $(':jqmData(role="header"),:jqmData(role="footer")').remove();
 $(':jqmData(role="page")').prepend(head).append(foot).page().trigger('pagecreate');
}

$(function(){
 $('body').append('
'); $('#module').load('module.html div:jqmData(role="page")',function(){ $($(this).html()).replaceAll(this).attr('id','module'); module(); }); $(':jqmData(role="page")').live('pageinit',module); });

jqmは新たなページを読込むときに、だいたい次のようにページ遷移を表現する。

  1. 次のページを読込む(pageloadイベント)
  2. 次のページの表示を最適化する(pagecreatepageinitializeイベント)
  3. 前のページを隠す(pagehideイベント)
  4. 次のページを表示する(pageshowイベント)

例えば、2.の後に"部品"を埋め込んでもキレイには表示されない。

とはいっても、javascriptについてはjQueryとjqmが少し扱える程度の理解しかないので、
試行錯誤を繰り返した結果、たまたま上手くいったスクリプト。

ちゃんと理解している人が作ったらもっとスマートなものになるんだろう。


ちなみに

この方法を使うと、階層化リストの2階層以降で表示されるリストにもヘッダーとフッターを埋め込むことができる。

階層化リストではフッターを表示や指定することが出来ないので、フッターのモジュール化は応用ができそう。

ただ、ヘッダーに関してはモジュール化する必要性はあまり感じない。


あ、ダイアログへの埋め込みはについては考えてなかった。。。
$(':jqmData(role="dialog")')とかを上手に使えば上手くいくのかな?




2012/06/20

"ui-icon-alt"を使う2つの方法|jQuery Mobile

jQuery Mobileのデザインを作ることができるThemeRollerでダウンロードしたCSSの中に .ui-icon-alt というセレクタを見つけた。

/* Alt icon color
-------------------------------------*/
.ui-icon-alt {
 background: #fff;
 background: rgba(255,255,255,.3);
 background-image: url(images/icons-18-black.png);
 background-repeat: no-repeat;
}

どうやら色違いのアイコンを設定できるようだ。

jQuery MobileのDocs内にはアイコンの切替(Alt icon color)についての記述はないようなので、
ThemeRoller独自に拡張されたものなのだろうか。
ui-icon-alt」などで検索してみたけれども、それらしき情報も見つからない。

ということで、実装する方法をいろいろ試してみた結果、応用が効きそうな2つをご紹介。
ただし、一部のフォーム要素には非対応


個別の要素ごとに Alt icon color を設定する方法



アイコンを設定する時は、対象の要素にdata-icon="***"を指定する。
jQuery Mobileはアイコンを描写するために、指定された要素の内部に新たな要素を生成し、
"ui-icon-***"をクラスとして(class="ui-icon-***"を)追加する。

そこでdata-icon="aaa bbb"と半角スペースを挟んで2つの文字列を指定してあげると、
生成される要素にはclass="ui-icon-aaa bbb"が付与され、2つのクラスを追加する事ができる。

つまり、半角スペースの後を ui-icon-alt にしてアイコンを指定すると、
生成される要素に ui-icon-alt のクラスを付与させることができる。

ただ、なんかちょっとずるい感じがするな。。。

sample1:個別の要素ごとにアイコンの色を設定
右側のボタンに『data-icon="*** ui-icon-alt"』を設定

<div class="ui-grid-a">
 <div class="ui-block-a">
  <h3>Normal</h3>
  <a data-role="button" data-icon="check">check</a>
  <a data-role="button" data-icon="gear">grid</a>
  <a data-role="button" data-icon="refresh">refresh</a>
  <a data-role="button" data-icon="grid">grid</a>
  <a data-role="button" data-icon="star">star</a>
 </div>
 <div class="ui-block-b">
  <h3>Icon-Alt</h3>
  <a data-role="button" data-icon="check ui-icon-alt">check</a>
  <a data-role="button" data-icon="gear ui-icon-alt">grid</a>
  <a data-role="button" data-icon="refresh ui-icon-alt">refresh</a>
  <a data-role="button" data-icon="grid ui-icon-alt">grid</a>
  <a data-role="button" data-icon="star ui-icon-alt">star</a>
 </div>
</div>


テーマごとに Alt icon color を設定する方法



アイコンの背景を透明にした場合、テーマによってはアイコンが見えづらくなってしまう。
任意のテーマ内全てのアイコンに対して個別の設定をするのは結構大変。
jQueryを使いテーマを指定して内部のアイコンを一括で設定してしまおう。

sanple2.jsだけでは、Ajaxで読込んだページには適用されないので、
本当は$('div:jqmData(role="page")')の pageinit イベントなんかにバインドしてあげたほうがよい。

sample2:テーマごとにアイコンの色を設定
明度の高いc、d、eのテーマに黒いアイコンを設定

$(function(){
 var $alttheme = new Array( "c", "d", "e" ); //ここでテーマを指定
 var at = new Array();
 for( t in $alttheme ){
  at.push(':jqmData(theme="' + alttheme[t] + '"):jqmData(icon) > span > span');
 }
 $(at.join()).addClass('ui-icon-alt');
});
<div data-role="header" data-theme="a">
 <h1>theme a</h1>
 <a data-icon="arrow-l">button a</a>
 <a data-theme="b" data-icon="arrow-r" data-iconpos="right">button b</a>
</div> 
<div data-role="header" data-theme="b">
 <h1>theme b</h1>
 <a data-icon="arrow-l">button b</a>
 <a data-theme="c" data-icon="arrow-r" data-iconpos="right">button c</a>
</div> 
<div data-role="header" data-theme="c">
 <h1>theme c</h1>
 <a data-icon="arrow-l">button c</a>
 <a data-theme="d" data-icon="arrow-r" data-iconpos="right">button d</a>
</div> 
<div data-role="header" data-theme="d">
 <h1>theme d</h1>
 <a data-icon="arrow-l">button d</a>
 <a data-theme="e" data-icon="arrow-r" data-iconpos="right">button e</a>
</div> 
<div data-role="header" data-theme="e">
 <h1>theme e</h1>
 <a data-icon="arrow-l">button e</a>
 <a data-theme="a" data-icon="arrow-r" data-iconpos="right">button a</a>
</div> 



※ 一部フォーム要素には非対応



jQuery Mobileはsample3-1.htmlのようなマークアップからsample3-2.htmlを生成する。
<a href="#" data-role="button" data-icon="check">sample<a>
<a href="#" data-role="button" data-icon="check" class="ui-btn ui-btn-icon-left">
 <span class="ui-btn-inner ui-btn-corner-all">
  <span class="ui-btn-text">sample</span>
  <span class="ui-icon ui-icon-check ui-icon-shadow"> </span>
 </span>
</a>


上記の2つの方法はこの生成されるマークアップ構造を利用して Alt icon color を実装している。
そのためアイコンを描写するマークアップが異なる次の3つのフォーム要素は非対応となってしまう。

  • <input type="radio" />
  • <input type="checkbox" />
  • <input type="search" /> ※入力内容削除ボタンには有効


ラジオボタン・チェックボックスがON時に表示されるアイコンの色は、ThemeRoller内でも白固定で指定することができない。
全テーマ共通の設定になるので、アクティブカラーをある程度明度の低い色にしておけば特に問題はないだろう。

ただし、検索タイプのインプットに関しては、アイコンの背景を透明にした場合に致命的な問題が起こる。
jQuery Mobileが「ここは検索タイプ」と分かりやすいようにしてくれているのに、
虫眼鏡アイコンが外側の要素の背景に溶け込んでしまいほとんど見えなくなってしまう。

CSSを修正とjavascript追加で解決できなくはないんだけど、
CSSはいじらないで実装したいので、もうちょっと勉強してきます!