skyblues のすべての投稿

アジアカップ2015 日本代表QF敗退 と アギーレ監督解任

アジアカップはコメントする前に敗退してしまいました。生、録画なりでTV観戦しましたが、W杯と違い勝って当たり前のアジアの争い。現地参戦組はさぞかし悔しかったことでしょう!お察しします。

個人的にベストゲームはイランvイラク戦ですかね。技術とかフォーメーションとか云々は度外視した本当に意地(メンタル)の戦いでした。

これは全く外野の私的意見ですが、今の日本代表には、なにか良い意味でのピリピリとした緊張感が足りないように見えてしまうんですよね。チームやプロジェクト(組織)で成功を収めた方なら経験則からわかるかと思いますが、よいチームって、全員が同じ方向を向いていて同じ目標を共有し、そこに流れる空気ってある意味心地よい緊張感があるものなのですが、今の代表には感じられないんですよね。仲良しクラブじゃないですが、仲が良すぎるというのも緊張感が鈍る原因にもなりますしね。選手からしたら大きなお世話でしょうが、善し悪しは別にして今のミランやドルトの方がよっぽどピリピリ感があったりして(笑)
また外野も生卵投げたり、水浴びせたりもなくなってしまったのもどこか心寂しい。

先日、プロフェッショナル・仕事の流儀というエディー・ジョーンズ ラグビー日本代表監督のNHK番組がありました。エディー監督いわく以下の点について説いてました。

  • 強みを知り、強みを伸ばす
    日本人の強み。それは、どんな過酷な練習にも耐え、向上心を持ち続ける”勤勉(タフ)さ”。真面目で忍耐力があること。それは間違いなく世界一です。他の国の選手なら、とっくに逃げ出しているでしょう。
    (AM6~PM7までの過酷な練習って高校野球じゃないんだから。でも映像からは相当な過酷さが垣間見えました。)

  • ハッピーにしない
    選手を成長させるために必要なのは、選手を正しく理解し、それに合った方法で“少しの不安”や“緊張感”を与えること。居心地がいいと能力は発揮できないからです。ときには少し突き放すことで、選手が100%安心しないようにしています。

  • どんどんミスさせる
    日本の練習で一番間違っているのはミスをしないように練習すること。ノーミス、ノーミスと言うが、ミスするから上達する。失敗から学ぶということが重要。

  • 責任感を持たせる
    各ポジションのリーダー(サブリーダー)が責任感を持つ必要がある。責任とは各ポジションのメンバーによいパフォーマンスをさせること。

  • 感情の波を小さく
    指導者として、誰にでも感情に起伏があることを理解した上で、そうした波を最小限にとどめさせることが大切。

やはり、ビジネス界からも注目されているだけのことはありますね。このうち、「ハッピーにしない」が足りないように思うんですよね、今のサッカー日本代表。「ハッピーにしない」という独特の言い回しで理解しにくいですが、要するに常に緊張感を持たせ戦う集団を持続すること。競争を促すこと。モチベーションを維持するということ。メンタル的な部分ですね。一般的にビジネスシーンでいちばん難しい部分でもあります(汗)。人を動かすという肝でもあります。「日本人観察が趣味」というエディー監督。人観察ができないと的確な言葉はかけられませんからね。TV会議って難しい~(汗)

それにしてもエディー監督の通訳の女性スタッフと発する言葉のギャップが凄かった(笑)私は、通訳とは監督の言葉をそのまま正確に訳すほうがよいダバディ派です。ことスポーツに関して、なんでそしゃくする必要があるのか疑問です。そんなこと直訳したら日本人にはきつすぎると言う理由で直訳しない、、、それこそが問題(相当の違和感)で、その言葉にこそ監督の(メンタル的)想い、狙いがあるのではないかって思いますけどね。監督通訳は決して緩衝材になってはいけないということです。

アギーレ監督は選手とコミュニケーションを取られる監督であっただけに、もう少しその手腕というか哲学を見たかったという想いのほうが強いですが、こればかりは仕方ないですね。

次期監督、今シーズンのマインツはイマイチですが、個人的には昨シーズンのトゥヘル・マインツの全員がハードワークするチーム、全員サッカーが好みでしたから、トゥヘルJAPANっていうのも期待してみたいものです。

また次期監督には4年任期ではなく、賃貸住宅同様2年更新にすべきだと思います(笑)。監督にも協会にも緊張感を促すということ。トルシエの時って予選免除だったとはいえ協会と戦っていたり、監督とマスコミと協会とのかけ引きがあったりと、そういう緊張感が必要だということです。

そういえば、これが今年最初の記事でしたね(汗)今年もどうぞよろしくお願い致します。

2014年締め

今年はなんと言ってもブラジルワールドカップにつきますね!年初から行こうか行くまいか3月末あたりまで迷っていましたが、行ってよかった。惨敗を現地でこの目で生で観れたのも貴重な財産になりました。

  1. FIFA World Cup 2014 ブラジル入国もレシフェ便に乗り遅れる
    今年の一番はやはりサンパウロでレシフェ行き国内線に乗り遅れたことですね。今年はあれ以上の凹凸はなかったです。
  2. FIFA World Cup 2014 R16 コロンビア v ウルグアイ をマラカナンにて観戦!!
    次点はマラカナンでコロンビアサポとウルグアイサポのケンカに巻き込まれてウルグアイサポから頭突きを食らったことですね。フェリョ・ダ・Pータ(イホ・デ・Pータ)連発!!
  3. FIFA World Cup 2014 MLB ヤンキース vs レイズ 黒田先発試合を現地観戦!!
    来年はヤンキース黒田、イチロー、それにジーター3人とも観られないという。現地観戦できてよかった。黒田は男の中の男ですね。広島で200勝ですね!来年の広島は楽しみです。

W杯は予算内で収まりましたし想定内ではあったのですが、それにしても今年は少々お金を使い過ぎましたね。クレカ年総額は200万円オーバーかと。来年は少し大人しくしようかと(汗)。また4年後の貯金もですね!

年明けのアジアカップは断念しました。毎度のことですが、職業病につきこの時期はどーしてもスケジュールを確保出来ませんでした。仕方ないですね、おとなしくTV観戦します。

年初に立てた目標ラン1000km/年には若干届きませんでしたが、昨年1月末からの総ラン距離は2,015kmになりました。今月はかなりの追い込みをかけ134kmを走破、なんとか最後に帳尻を合わせることができました(笑)今年はブラジルやタイ、シンガポール渡航のおおよそ1.5ヶ月間は上積みできませんでしたので、意外やがんばったほうかなと思います。

では、みなさんよいお年を!

gmaps.js ライブラリを使用した地図表示 – Google Maps

  1. Simple Map で簡単に地図表示 WordPressプラグイン – Google Maps
  2. gmaps.js ライブラリを使用した地図表示 – Google Maps
  3. Google Maps JavaScript API v3 を直接使用した地図表示- Google Maps (作成中)

Google Maps を表示するには、Google Maps API v3 を使用するのが基本ですが、なかでもインタラクティブな Google MapsをWebページに埋め込むには Google Maps JavaScript API v3ですね。この Google Maps JavaScript API v3 でも、十分簡単に地図を表示できるのですが、それをより簡単にjQueryライクに表示できるようにしたのが、今回ご紹介する gmaps.js ライブラリになります。

Google Maps JavaScript API v3 の基本機能はほぼカバーしているので、マニアックな使い方でなければgmaps.js ライブラリでこと足りると思います。まあJavaのGoFな観点からするとFacade パターンといったところですかね!

ということで、多機能につき詳細はgmaps.jsをご覧いただき、ここでは主にルート機能に絞ってみたいと思います。

コントロール

Google Mapsはいくつかのコントロールのカスタマイズが可能で、地図の動作や外見を変更できます。
サンプルを変更しますと、実際に上記地図のコントロールを変更できます。
コントロール 説明 初期値 サンプル
div マップを表示するHTMLの<div>エレメントタグを設定します。一意な指定が必要なため通常はID属性となります。マップサイズはCSSにて縦横幅を設定します。
lat マップ中心の緯度を設定します。
lng マップ中心の経度を設定します。
mapTypeControl マップ タイプ(地図や航空写真など)を切り替えるマップ タイプ コントロールを有効または無効にします。このコントロールは、デフォルトでは地図の右上隅に表示されます。 有効 :有効 :無効
mapTypeId
マップ タイプを設定します。
  • ROADMAP: デフォルトの道路地図を表示します。
  • SATELLITE: Google Earth の航空写真を表示します。
  • HYBRID: 通常のビューと航空写真を混合して表示します。
  • TERRAIN: 地形情報に基づいて物理的なマップ タイルを表示します。
ROADMAP
  •  
  • :ROADMAP
  • :HYBRID
  • :SATELLITE
  • :TERRAIN
overviewMapControl 概観マップを有効または無効にします。概観マップ コントロールは、完全に表示(サムネイル概観マップを表示)するか、折りたたんで最小化した状態で表示することができます。 有効 有効 無効
panControl 移動コントロールの有効/無効を設定します。このコントロールは、デフォルトでは地図の左上隅に表示されます。 有効 有効 無効
scaleControl シンプルな地図縮尺を表示するスケール コントロールの有効/無効を設定します。このコントロールは、デフォルトでは表示されません。 無効 有効 無効
streetViewControl ここに含まれるペグマン アイコンを地図上にドラッグして、ストリートビューを有効にすることができます。このコントロールは、デフォルトでは地図の左上隅に表示されます。 有効 有効 無効
scrollwheel マップ上のスクロールホイールの有効/無効を設定します。 有効 有効 無効
zoom ズーム倍率を設定します。0~21の数字を設定します。 15
zoomControl 地図のズーム レベルをコントロールするために、スライダ(大きな地図の場合)または小さな「+」ボタン(小さな地図の場合)が表示されます。デフォルトではこのコントロールは、タッチ パネル端末以外では地図の左上隅に、タッチ パネル端末では左下隅に表示されます。 有効 有効 無効
<style type="text/css">.gmaps img{ max-width: none !important; padding: 0 !important; margin: 0 !important; }</style>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="//maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="https://hpneo.github.io/gmaps/gmaps.js"></script>
<script type="text/javascript">
var map;
$(document).ready(function(){
    map = new GMaps({
        div: "#map-01",
        lat: 35.7105617,  // Map Center lat.
        lng: 139.8042225, // Map Center lng. 
        mapTypeControl: true,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        overviewMapControl: true,
        panControl: true,
        scaleControl: false,
        streetViewControl: true,
        scrollwheel: true,
        zoom: 15,
        zoomControl: true
    });
});
</script>
<div class="gmaps">
    <div id="map-01" style="width: 100%; height: 300px"></div>
</div>

マーカー

デフォルトアイコン

表示する地図の中心位置をGMaps()クラスに設定し、浅草駅・東京スカイツリーのマーカーを追加します。マーカーはいくつでも追加可能です。位置データをJSONやXMLからロードし追加する等も可能ですね。
<style type="text/css">.gmaps img{ max-width: none !important; padding: 0 !important; margin: 0 !important; }</style>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="//maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="https://hpneo.github.io/gmaps/gmaps.js"></script>
<script type="text/javascript">
var map;
$(document).ready(function(){
    map = new GMaps({
        div: "#map-02",
        lat: 35.7105617,  // Map Center lat.
        lng: 139.8042225  // Map Center lng.
    });
    map.addMarker({
        lat: 35.710540,
        lng: 139.797874,
        title: "浅草駅",
        infoWindow: {
            content: "浅草駅"
        }
    });
    map.addMarker({
        lat: 35.710063,
        lng: 139.8107,
        title: "東京スカイツリー",
        infoWindow: {
            content: "東京スカイツリー"
        }
    });
});
</script>
<div class="gmaps">
    <div id="map-02" style="height: 300px"></div>
</div>

カスタムアイコン

アイコン画像の変更も可能です。但しアイコンサイズは指定不可のようで、予め画像をリサイズしておく必要がありそうです。gmaps.jsソースコードを斜め読みする限り、どうもマーカーのオプション指定はパイプで指定する旧APIのGoogle maps API v2の指定方法になっているっぽいです。うーむ、いまいちです。これならv3を直接弄ったほうがサイズ指定など細かな設定ができ、使い勝手がよさそうな気がします。
<style type="text/css">.gmaps img{ max-width: none !important; padding: 0 !important; margin: 0 !important; }</style>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="//maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="https://hpneo.github.io/gmaps/gmaps.js"></script>
<script type="text/javascript">
var map;
$(document).ready(function(){
    map = new GMaps({
        div: "#map-03",
        lat: 35.7105617,  // Map Center lat.
        lng: 139.8042225  // Map Center lng. 
    });
    map.addMarker({
        lat: 35.710540,
        lng: 139.797874,
        title: "浅草駅",
        infoWindow: {
            content: "浅草駅"
        },
        icon: "http://maps.google.com/mapfiles/ms/micons/subway.png"
    });
    map.addMarker({
        lat: 35.710063,
        lng: 139.8107,
        title: "東京スカイツリー",
        infoWindow: {
            content: "東京スカイツリー"
        },
        icon: "http://www.tokyo-skytree.jp/img/mod/mod_indexlist_img_02.gif"
    });
});
</script>
<div class="gmaps">
    <div id="map-03" style="height: 300px"></div>
</div>

オーバーレイ

drawPolyline

GMaps()クラスに、浅草駅-東京スカイツリー間を直線で結ぶdrawPolyline()を追加します。
<style type="text/css">.gmaps img{ max-width: none !important; padding: 0 !important; margin: 0 !important; }</style>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="//maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="https://hpneo.github.io/gmaps/gmaps.js"></script>
<script type="text/javascript">
var map;
$(document).ready(function(){
    map = new GMaps({
        div: "#map-04",
        lat: 35.7105617,  // Map Center lat.
        lng: 139.8042225  // Map Center lng.
    });
    map.addMarker({
        lat: 35.710540,
        lng: 139.797874,
        title: "浅草駅",
        infoWindow: {
            content: "浅草駅"
        }
    });
    map.addMarker({
        lat: 35.710063,
        lng: 139.8107,
        title: "東京スカイツリー",
        infoWindow: {
            content: "東京スカイツリー"
        }
    });
    map.drawPolyline({
        path: [[35.710540,139.797874], [35.710063,139.8107]],
        strokeColor: '#01b1ff',
        strokeOpacity: 0.8,
        strokeWeight: 6
    });
});
</script>
<div class="gmaps">
    <div id="map-04" style="height: 300px"></div>
</div>

ルート

drawRoute

GMaps()クラスに、浅草駅から東京スカイツリーまでのルート(徒歩)表示するdrawRoute()を追加します。
<style type="text/css">.gmaps img{ max-width: none !important; padding: 0 !important; margin: 0 !important; }</style>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="//maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="https://hpneo.github.io/gmaps/gmaps.js"></script>
<script type="text/javascript">
var map;
$(document).ready(function(){
    map = new GMaps({
        div: "#map-05",
        lat: 35.7105617,  // Map Center lat.
        lng: 139.8042225  // Map Center lng.
    });
    map.addMarker({
        lat: 35.710540,
        lng: 139.797874,
        title: "浅草駅",
        infoWindow: {
            content: "浅草駅"
        }
    });
    map.addMarker({
        lat: 35.710063,
        lng: 139.8107,
        title: "東京スカイツリー",
        infoWindow: {
            content: "東京スカイツリー"
        }
    });
    map.drawRoute({
        origin: [35.710540,139.797874],
        destination: [35.710063,139.8107],
        travelMode: 'walking',
        strokeColor: '#01b1ff',
        strokeOpacity: 0.8,
        strokeWeight: 6
    });
});
</script>
<div class="gmaps">
    <div id="map-05" style="height: 300px"></div>
</div>

drawRoute(Geocode)

GMaps()クラスに、ジオコーディング(住所やランドマーク名から経度、緯度を取得)を使い、浅草駅から東京スカイツリーまでルート(徒歩)表示するdrawRoute()を追加します。
<style type="text/css">.gmaps img{ max-width: none !important; padding: 0 !important; margin: 0 !important; }</style>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="//maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="https://hpneo.github.io/gmaps/gmaps.js"></script>
<script type="text/javascript">
var map;
$(document).ready(function(){
    map = new GMaps({
        div: "#map-06",
        lat: 35.7105617,  // Map Center lat.
        lng: 139.8042225  // Map Center lng.
    });
    GMaps.geocode({
        address: "MRT浅草駅",
        callback: function(results, status) {
            if (status == 'OK') {
                var sl = results[0].geometry.location;
                map.addMarker({
                    lat: sl.lat(),
                    lng: sl.lng(),
                    title: "浅草駅",
                    infoWindow: {
                        content: "浅草駅"
                    }
                });
                GMaps.geocode({
                    address: "東京スカイツリー",
                    callback: function(results, status) {
                        if (status == 'OK') {
                            var el = results[0].geometry.location;
                            map.addMarker({
                                lat: dl.lat(),
                                lng: dl.lng(),
                                title: "東京スカイツリー",
                                infoWindow: {
                                    content: "東京スカイツリー"
                                }
                            });
                            map.drawRoute({
                                origin: [sl.lat(), sl.lng()],
                                destination: [dl.lat(), dl.lng()],
                                travelMode: 'walking',
                                strokeColor: '#01b1ff',
                                strokeOpacity: 0.8,
                                strokeWeight: 6
                            });
                        }
                    }
                });
            }
        }
    });
});
</script>
<div class="gmaps">
    <div id="map-06" style="height: 300px"></div>
</div>

「浅草駅」でジオコーディング検索しますと、なぜか「TX浅草駅」になってしまうので(笑)、「MRT浅草駅」としています。下のGoogle Maps Embed APIも「浅草駅」とすると「TX浅草駅」になってしまうため「MRT浅草駅」とすると今度はなぜか「浅草寺」なってしまいます。仕方なく「銀座線浅草駅」としていますが、この座標も若干違う気がします。どうもジオコーディングで検索される浅草駅の座標が違っているようです。実際のルートは浅草駅を出て吾妻橋を渡ったほうが近い気がします。日によってTX浅草駅なったり浅草駅になったりと、「浅草駅」のジオコーディングは鬼門ですね(笑)

おまけ

本当は以下のGoogle Maps Embed APIのようなルート表示が理想なのですが、 gmaps.js ライブラリや Google Maps API v3 ではなかなか難しいようです。

Simple Map で簡単に地図表示 WordPressプラグイン – Google Maps

  1. Simple Map で簡単に地図表示 WordPressプラグイン – Google Maps
  2. gmaps.js ライブラリを使用した地図表示 – Google Maps
  3. Google Maps JavaScript API V3 を使用した地図表示- Google Maps (作成中)

WordPress記事に地図を表示するには、いろいろな方法がありますが、まずは一番お手軽な「Simple Map」というWordPressプラグインを使ってみました。作者は日本の方で、名前がシンプルが付くだけに非常に簡単に地図を表示できます。地図表示できるのは1地点のみになりますが、普通は1地点を表示できれば大概は問題ないですね!また地図表示にはgmaps.jsライブラリを使用しています。

インストールはいつもの通り管理画面のプラグイン画面から「Simple Map」で検索しインストールします。バージョンは2.2.0(2014/12/13時点)です。インストール手順は割愛します。またシンプルなだけに設定画面もありません。

このプラグインの面白いところは、端末のブラウザの横幅(breakpoint)が480px以下の場合、地図画像に切り替りリンクがGoogle Mapsへの遷移となることです。5インチ以下のスマホなどでは、なかなかよい機能だと思います。

まずは Simple Map プラグインのショートコードから。

ショートコード

[cc lang=”bash” theme=”blackboard” width=”99%”] [/cc]

位置情報

地図の位置情報は、url, lat&lng, addr, content のどれか一つを指定します。
属性名 必須/任意 初期値 説明
url 一つが必須 URL
lat,lng 緯度、経度
addr 住所・地名
content 住所・地名 or 吹き出しテキスト(マーカーをクリックすると表示)

オプション

属性名 必須/任意 初期値 説明
width 任意 100% 横幅
height 任意 200px 縦幅
zoom 任意 16 ズーム倍率 0~21(0が最小、21が最大)
breakpoint 任意 480 地図埋め込みか、地図画像リンクにするかのブラウザ横幅のしきい値。最大640。
infowindow 任意 close 吹き出しテキストのデフォルト開閉。<open|close>

サンプル

位置情報

url (URL)

[cc lang=”bash” theme=”blackboard” width=”99%”] [/cc]
属性名 width height zoom breakpoint infowindow ○:設定可、-:設定不可
url

lat,lng (緯度,経度)

[cc lang=”bash” theme=”blackboard” width=”99%”]
東京スカイツリー
[/cc]
属性名 width height zoom breakpoint infowindow ○:設定可、-:設定不可
lat,lng
東京スカイツリー

addr (住所・地名)

[cc lang=”bash” theme=”blackboard” width=”99%”]
東京スカイツリー
[/cc]
属性名 width height zoom breakpoint infowindow ○:設定可、-:設定不可
addr
東京スカイツリー

content (住所・地名)

[cc lang=”bash” theme=”blackboard” width=”99%”]
東京スカイツリー
[/cc]
属性名 width height zoom breakpoint infowindow ○:設定可、-:設定不可
content
東京スカイツリー

オプション

[cc lang=”bash” theme=”blackboard” width=”99%”]
東京スカイツリー
[/cc]
属性名 width height zoom breakpoint infowindow
属性値 90% 240px 17 400 open

width, height, zoom, infowindow

東京スカイツリー

breakpoint

「breakpoint=”400″」ですと、ブラウザの横幅が400px以下にならないとbreakpointが有効にならないため、便宜的に以下のような地図画像のリンクで再現してみました。クリックするとGoogle Mapsへ遷移します。スマホであればGoogle Mapsアプリが起動します。(iOSはGoogle Mapsアプリのリンクページへ遷移)
東京スカイツリー

カスタマイズ

ストリートビューコントロールの追加

ストリートビューのペグマン(人型のアイコン)を表示したく、コントロールをtrueに設定しました。以下はコードを解りやすくするため、 simple-map.js を記載していますが、実際には simple-map.min.js を変更する必要があります。
    if ($('html').width() > breakpoint) {
        var map = new GMaps({
            div: element,
            lat: pos.lat(),
            lng: pos.lng(),
            mapTypeControl: false,
            zoom: parseFloat(zoom),
            streetViewControl: true,
            scrollwheel: false,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        });
diffは以下の通りです。
% diff -u simple-map.js.org simple-map.js
--- simple-map.js.org   2014-11-16 18:05:32.000000000 +0900
+++ simple-map.js       2014-11-19 22:26:59.000000000 +0900
@@ -20,3 +20,3 @@
             zoom: parseFloat(zoom),
-            streetViewControl: false,
+            streetViewControl: true,
             scrollwheel: false,

IEのデザイン(Copyrights)崩れの修正

テーマがTwenty Fourteenの場合、IEで地図を表示しますと右下のCopyrights「地図データ(c)2014 Google, ZENRIN」のwidthが狭まり、縦に表示されてしまうため、以下のCSSを追加しました。これは Simple Map プラグインが原因ではなくGoogle Mapsの問題ですね。
(以下の地図はIEで表示しないと違いがわかりません)

2015/09/16
Google の新ロゴが 2015/09/01 に発表されたのを機に、Google Map の CSS もアップデートされたようで(Fixed issue with overly broad CSS classes)当修正は不要になりました。

東京スカイツリー
.gmnoprint { 
	word-wrap: normal !important;
}
東京スカイツリー

jQuery コロン付きセレクタの指定方法

先日 Nike+ Running アプリが改悪になった記事で、このアプリの カスタマーレビューをRSS feedで表示してみました。その際に「<im:rating/>」という5段階評価のXML要素を取得し、五つ星で表示する処理を実装したのですが、iPhoneで表示したらなぜか星が表示されず、気持ち悪いので調査してみました。どうもXMLのコロン付きセレクタの場合、ブラウザによりjQueryの挙動が違うようです。

HTML

$(“コロン付きidセレクタ”)

  • コロン付きidセレクタの場合
    [cc lang=”php” width=”99%”]
    hogehoge1
    [/cc]

    以下の記述ではコロンがfilterと判断され、セレクタを識別できません。
    [cc lang=”javascript” theme=”blackboard” width=”99%”] $(“#im:rating”)
    [/cc]

    以下のようにバックスラッシュでエスケープする必要があります。
    [cc lang=”javascript” theme=”blackboard” width=”99%”] $(“#im\\:rating”)
    [/cc]

    基本ですね。idセレクタに関してはブラウザによる差異はありません。

$(“コロン付き要素名”)

  • コロン付き要素名の場合
    [cc lang=”php” width=”99%”] hogehoge2
    [/cc]

    以下の記述ではコロンがfilterと判断され、セレクタを識別できません。
    [cc lang=”javascript” theme=”blackboard” width=”99%”] $(“im:rating”)
    [/cc]

    以下のようにバックスラッシュでエスケープする必要があります。
    [cc lang=”javascript” theme=”blackboard” width=”99%”] $(“im\\:rating”)
    [/cc] こちらもブラウザによる差異はありません。

XML

ご存じのようにXMLには名前空間という仕組みがあり、名前空間は接頭辞とローカル名をコロンで区切ります。こちらのIBM記事を見ますと、jQueryはこのXML名前空間を全く処理することができないようです。したがって要素名は完全修飾子名(接頭辞:ローカル名(<im:rating/>))でアクセスする必要があるかと思います。

XML名前空間なしの場合

.find(“コロン付き属性値”)

  • コロン付き属性値の場合
    [cc lang=”xml” width=”99%”]
    hogehoge1

    [/cc]

    属性値であればエスケープ不要で以下の記述で動作します。
    [cc lang=”javascript” theme=”blackboard” width=”99%”] .find(“content[id=’im:rating’]”)
    [/cc]

    こちらもブラウザによる差異はありません。

XML名前空間ありの場合

.find(“コロン付き属性名”)

  • コロン付き属性名の場合
    [cc lang=”xml” width=”99%”]
    hogehoge2

    [/cc]

    以下の記述ではコロンは構文エラーとなります。
    [cc lang=”javascript” theme=”blackboard” width=”99%”] .find(“content[im:rating]”)
    [/cc]

    以下のようにバックスラッシュでエスケープする必要があります。
    [cc lang=”javascript” theme=”blackboard” width=”99%”] .find(“content[im\\:rating]”)
    [/cc]

    こちらもブラウザによる差異はありません。

.find(“コロン付き要素名”)

  • コロン付き要素名の場合
    [cc lang=”xml” width=”99%”]
    hogehoge3

    [/cc]

    以下のようにエスケープするとIE,FireFoxでは動作しましたが、Chrome,Safariでは動作しませんでした。
    [cc lang=”javascript” theme=”blackboard” width=”99%”] .find(“im\\:rating”)
    [/cc]

    一方以下のようにローカル名「rating」のみで指定ですと、今度はChrome,Safariでは動作しましたが、IE,FireFoxでは動作しませんでした。
    [cc lang=”javascript” theme=”blackboard” width=”99%”] .find(“rating”)
    [/cc]

    ■ブラウザによる差異

    jQuery IE10 FireFox33 Chrome39 Safari7
    .find(“im\\:rating”) × ×
    .find(“rating”) × ×

    以下のように両方をカンマ区切りで指定すればブラウザによる差異を吸収できます。カンマは論理和「OR」と等価です。
    [cc lang=”javascript” theme=”blackboard” width=”99%”] .find(“im\\:rating, rating”)
    [/cc]

XML名前空間あり要素名、もといコロン付き要素名の場合のみ、なぜかブラウザにより差異がありました。バグかもしれませんね。またエスケープにバックスラッシュ2個というのもミソですが、JAVAの正規表現置換などですと、バクスラ8個(円マーク)なんて言う場合もありますからね!(笑)でもまあスッキリしてよかったです。

以下のサンプルをIE/FireFoxとChrome/Safariとで見比べてみれば違いがわかると思います。


カスタマーレビューに関しては、ローカル名が一意(ユニーク)であったため上記方法で解決しましたが、一般的には、名前空間が複数あり接頭辞が別でローカル名が同じという場合も多々あります。そのための名前空間なのですからね。この場合、今回の方法ではIE,FireFoxでは完全修飾子名で指定しますので識別できますが、Chrome,Safariはローカル名のみのため識別できず破綻します。find()メソッドの限界ですかね。ということで別の方法を探りました。

.children(“コロン付き要素名”)

  • コロン付き要素名の場合
    [cc lang=”xml” width=”99%”]
    hogehoge1
    hogehoge2

    [/cc]

    親要素<feed>の直下の子要素をターゲットにして指定
    [cc lang=”javascript” theme=”blackboard” width=”99%”] .find(“feed”).children(“im\\:rating”)
    .find(“feed”).children(“jn\\:rating”)
    [/cc]

    この指定方法であればブラウザによる差異はありません。子要素というピンポイントでの指定が必要ですが、jQueryであれば、この方法が一番かと思います。

getElementsByTagNameNS(“名前空間”, “ローカル名”)

  • コロン付き要素名の場合
    [cc lang=”xml” width=”99%”]
    hogehoge1
    hogehoge2

    [/cc]

    DOM操作による名前空間とローカル名を指定
    [cc lang=”javascript” theme=”blackboard” width=”99%”] getElementsByTagNameNS(“http://itunes.apple.com/rss/im”, “rating”)[0].childNodes[0].nodeValue
    getElementsByTagNameNS(“http://itunes.apple.com/rss/jn”, “rating”)[0].childNodes[0].nodeValue
    [/cc]

  • jQueryにこだわらなければ、IE9以降の条件付きですが、DOMによるgetElementsByTagNameNS(ns, name)メソッドでの取得も可能です。サレオツではないですが、この方法こそが名前空間を解決する一番ベタ(基本)なメソッドなんでしょうね!この指定方法もブラウザによる差異はありません。

    蛇足ですが、getElementsByTagName(name)で指定しますと、上記のようなブラウザによる差異がありました。ソースを見ないとなんともですが、おそらくjQueryのfind()メソッドの実装がgetElementsByTagName(name)なのではないかと思います。

jQueryはXMLをあまり得意としていないということがわかりました。このIBM記事での指摘でもありましたが、IE(Internet Explorer)がgetElementsByTagNameNS()をサポートしていないのが原因のようですが、これは5年前の記事の話で、確かにIE8まではサポート外でしたが、IE9でサポートされています。実際IE10では問題なく動作しています。レガシーが足を引っ張っている感じですね!
2014/11時点でIE8のブラウザシェアが15.11%(当サイトはIE7,8が12%)ほどですから、まだまだですかね。またOSシェアを見る限り、Windows XPが13.57%とそのままIE8のシェアになってる感じですかね。Safari以下にならないと斬り捨てるのはまだまだ躊躇しますね。
jQuery2.x系はIE9以降のサポート(IE <9 not supported)のはずなので、ぜひ対応して欲しいですね!