maoring blog

このブログはセマンティックウェブ関連の技術的なあれこれを綴ったブログです。

直感! microdata!! その1

直感! microdata!!

今回の連載ではmicrodataとはなんぞや,という話から,microdata(をはじめとしたメタデータ)は何故大事なのか,どうやって活用するの?という話をしていきたいとおもいます。
今回はその1回目。直感的にmicrodataを理解しようという回です。

microdataとは?

誤解を恐れずに一言で言うと,(主に検索エンジンのための)世界共通のタグづけ形式です。
あるデータがウェブページ上にあった時に,そこにある情報が何であるのかということを知るためにタグ付けをします。例えば,レシピ。どんな言語であってもmicrodataを使って,所要時間,カロリー,材料,著者,写真をタグ付けすることができます。イメージとしてはこんな感じ。

f:id:maoring:20130702145520p:plain

こうすると,検索結果がこんな感じになります。(画像はイメージです。)

f:id:maoring:20130702151822p:plain

あんまりうれしさが分からないって?

例えば,あなたがメキシコに行って美味しいメキシコ料理に出会ったとします。これ自分でも作れるんじゃないのかな,と思ったとします。その料理のスペルだけメモしていたとする。そうして検索する。 なんと,画像と評判とかかる時間が一度に分かるのです。こんな風に。

f:id:maoring:20130703163826p:plain

そうだそうだアボカドを使った料理だった。10分でできちゃうのか。カロリーは262kcalか。おつまみにはいいかも。

的な感想も一度に得られます!!!
…?
これだけだとあまり良さが分からないかもしれないですが(^_^;),何語であっても,きちんとmicrodataを使ってくれていれば,このような結果を表示することが可能です。逆に言えば,あなたがブログにレシピを日本語で載せてもmicrodataマークアップしていれば,このような検索結果を世界中の皆さんに表示できるのです(≧∇≦)/

ユーザー&ウェブページ管理者にとって嬉しいこと。

検索結果がリッチになって分かりやすくなる。 自分の書いた記事なら,アクセス増加に繋がる。 (とある調査によると5〜30%クリック率が上がるらしい。←ソースが不明瞭なので ちゃんと書けなくてごめんなさい。)

検索エンジンにとって嬉しいこと。

それが何のデータかが明確になる(構造化されている)ので,検索結果に示しやすくなる。情報を整理して提示しやすくなる。クローラーのプログラムが1つですむこと。

将来的に嬉しいこと。

情報が構造化されていると,ウェブアプリケーションが作りやすくなること。 作るためのプログラムが簡潔&汎用性が高まること。 ID等を使用していて,そのものの限定もされていると,グラフとしてのデータの価値も高まること(後述するかもっ)

続くっ!

次回は,じゃあどうやって書くの?ということやどう活用されているの? ということを中心にお話ししたいと思います。 ではではっ☆

javascriptとmicrodata(実装中)その7 -PubMedIDから論文のAbstractを取得して表示させよう。

大体出来てきたのだけど,不具合あったら教えて下さい☆と書いたところご指摘いただきまして,修正することにしました。

@bonohuさんより @maoringo リンクがWindowの右端のほうだと縦長のポップアップウインドウになってしまうのが玉に瑕ですね

玉に瑕ですって,そんな玉なんてそんな(*´ω`*)!と照れている場合じゃなくて(^_^;,修正します。どの方法が良いのかなとちょいと考えたのですが,マウスオーバーした際の座標とその時のウインドウのサイズが近かった場合のみ,修正を入れるという方法にすることにしました。 まずマウスオーバーした時の座標を取得しましょう。
参考・・・[HTML][Javascript] シンプルなポップアップを表示する

  if (!event) var event = window.event;                                                                                           
  if (!event.pageX) px = event.clientX + document.body.scrollLeft; else px = event.pageX;                                                                                                                                                              
 alert(px + "px  " + $(window).width() + "px");  // $(window).width() は表示幅

event.pageXがif elseになっているのはブラウザ対策のようです。
参考・・・ブラウザごとのeventオブジェクトの違いを理解する
さて,位置を調整しましょう。もともとはJavaScript上で以下のようにポップアップの位置を定義しています。

 var defaults = {
      marginTop: 20,
      marginLeft: 20,                                                                                                                   
      className: "popup_help_window",                                                                                                   
      speed:10                                                                                                                          
    }

//中略
  var offsetTop = $(this).offset().top + defaults.marginTop;
  var offsetLeft = $(this).offset().left + defaults.marginLeft;

ここのmarginTopとかmarginleftとかはポップアップが,ポップアップの出現する元の場所からTopはどのくらいか Leftはどのくらいかを決めているみたいです。本当はもっと複雑らしいけど今は必要ないので省略しちゃいます。
さて,これらをもとにして,ウインドウのサイズに対してマウスオーバーした位置が500px未満だったらずらすということを記載していきます。

 $(this).mouseover(function(event) {//引数を入れないとfirefoxでエラーが出た。
        // 表示対象にマウスが重なった時の処理です。                                                                                     
       if (!event) var event = window.event; //イベントの定義                                                                                           
       if (!event.pageX) px = event.clientX + document.body.scrollLeft; else px = event.pageX;                                         
//      alert(px + "px  " + $(window).width() + "px");               ←動作のチェックによく使っちゃいます。                                                                   
        defaults.marginLeft = 20; //戻ってきた時用                                                                                                      
        var subtract = $(window).width() - px;//差分
        if (subtract < 500) defaults.marginLeft = subtract - 500; //いい塩梅の位置に表示させるためにこっちも調節      
        contenttext = '';
        // ウィンドウにメッセージを設定します。
        contenttext = $(this).attr('content');
        //:以後のみを切り出します。
        contenttext = contenttext.split(":")[1];
        var offsetTop = $(this).offset().top + defaults.marginTop;
        var offsetLeft = $(this).offset().left + defaults.marginLeft;
//以下略

余談ですが,途中まで$(this).mouseover(function() { で引数なしで
if (!event) var event = window.event; //イベントの定義
を書いていたらfirefoxで実行できない!となったので調べてたら,
event.pageX not working in firefox, but does in Chrome
あなたのサイトにエラーがあるので動かないのよ,ボケ!みたいな記述をみつけたので,え”,と思って調べてみたら本当でした。 これで端っこでも上手いこと調節して,表示できるようになりました。

f:id:maoring:20130617163133p:plain

javascriptとmicrodata(調査中)その6 -PubMedIDから論文のAbstractを取得して表示させよう。

ここから前回までの話からぴょっと飛ぶのだけど,NCBIではPubMedIDからその論文に関するデータをxml形式で取得できるサービスを行っている。ありがとう牧場。ありがとう@i_87さん!!
PubMedのアブストラクトの取得
そしてリンク先はちょっと古くなっているのでここで更新させていただくと,説明書きは以下のリンク先からご覧ください。
EFetch
ここでは詳しい説明は省略しますが,
http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&id=22674858&retmode=xml
のようにid=の後にPubMed IDを入れるとxml形式でデータが得られます。ここでabstractを入手してtextにして表示させようというわけです。

xmlの入手にはjQuery.ajax()を使います。ajax部分だけ抜粋して書いてみると

$.ajax({ 
    url:'http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&retmode=xml&id='+ contenttext,//読み込むURL
    dataType:'xml',//受信するデータの種類                                                                                               
    async:true,//非同期通信を有効にするか
    success:function(xml){                                                                                                              
        html='';                                                                                                                        
            title = $(xml).find("ArticleTitle").text();//titleの読み込み
            abstract = $(xml).find("AbstractText").text();//abstractの読み込み
            popuptext = title + "\n\n" + abstract ;//popup用の文章
   },   
    error: function(html){                                                                                                              
        alert('Fell the data loading, Please access later'); //失敗したら                                                                           
    }   
});       

こんな感じでデータを入手出来ます。今回はタグが<ArticleTitle><AbstractText>と取りたいものそのものになっていたのであっさり取り出せて便利でした。ここで,そのまま前のjavascriptを使ったら,ajaxが後で読まれて誤ったポップアップが出てしまう事態となってしまったので, $(document).ajaxComplete(function(){ を使ってajaxが終わったらポップアップ出してよ☆的なコードに書き換えました。(あっさり書いたけどここに行きつくのにむっちゃ時間かかった。)
jQueryでajax:非同期通信時、実行順番を保障する方法
ありがたや↑美しや↑(何故誤字が多いのかはよく分からない。きっと疲れていたのだろう。)
あとポップアップウィンドウ内で改行が出来ない!みたいなことがあったのですが,white-space: pre-wrap; で解決しました。(←あっさり書いたけどここに…以下略…!!)
参考:white-space - ソース中の空白・Tab・改行の表示の仕方を指定する さて,以上を踏まえてひと通りコードを掲載しておきましょう。前回も書きましたが,コードはかなり以下のリンク先のコードを利用させていただいています。
[jQuery] ヘルプメッセージをポップアップして表示する方法
下のコードは後でダウンロード出来るように近いうちにどこかに置いておきます。
css

.popup_help {
  padding: 0 3px;
  color: #66f;
  font-weight: bold;
  cursor: pointer;
}
.popup_help_window {
  max-width: 500px;
  position: absolute;
  padding: 6px 15px;
  background-color: #fff;
  border: 5px double #ccc;
  display: none;
  color: #333;
  font-family: 'Helvetica Neue';
  font-size: 12px;
  line-height: 1.5em;
  border-radius: 10px;
  box-shadow: 5px 5px 5px #ccc;
  white-space: pre-wrap;
}

JavaScript

(function($) {
  $.fn.popupHelp=function(config) {
    /**
      * marginTop: 表示対象とウィンドウの高さの差分です。
      *   0を指定すると、上端が揃います。
      * marginLeft: 表示対象とウィンドウの横の差分です。
      *   0を指定すると、左端が揃います。
      * className: ウィンドウに設定するクラス名です。
      * speed: ウィンドウを表示する際の秒数[ms]です。
      */
    var defaults = {
      marginTop: 0,
      marginLeft: 20,
      className: "popup_help_window",
      speed:10
    }

    var options = $.extend(defaults, config);

    // ヘルプウィンドウのオブジェクトを準備します。
    var popupObj = $("<div>").addClass(defaults.className).appendTo($("body"));
    var html='';//グローバル変数
    var title = '';
    var abstract = '';
    var contenttext = '';
    var popuptext = '';
    return this.each(function() {

      $(this).mouseover(function() {
        // 表示対象にマウスが重なった時の処理です。

        contenttext = '';
        // ウィンドウにメッセージを設定します。
        contenttext = $(this).attr('content');
        //:以後のみを切り出します。
        contenttext = contenttext.split(":")[1];
        var offsetTop = $(this).offset().top + defaults.marginTop;
        var offsetLeft = $(this).offset().left + defaults.marginLeft;

$.ajax({
    url:'http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&retmode=xml&id='+ contenttext,//読み込むURL
    dataType:'xml',//受信するデータの種類
    async:true,//非同期通信を有効にするか
    success:function(xml){
        html='';
            title = $(xml).find("ArticleTitle").text();//titleの読み込み
            abstract = $(xml).find("AbstractText").text();//abstractの読み込み
            popuptext = title + "\n\n" + abstract ;//popup用の文章 
   },
    error: function(html){
        alert('Fell the data loading, Please access later');//失敗した場合
    }
});
$(document).ajaxComplete(function(){
      popupObj.text(popuptext);
        // ウィンドウのオフセットを計算します。
       // ウィンドウの位置を整え、表示します。
        popupObj.css({
          "top": offsetTop,
          "left": offsetLeft
        }).show(defaults.speed);
      });
      });
$(this).mouseleave(function() {
        // 表示対象にマウスが重なった時の処理です。
        // ウィンドウを隠しつつ,textを空にします。
        popupObj.hide("slow").text("");
      });
    });
  };
})(jQuery);

html

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title></title>
    <link rel="stylesheet" href="style.css" />
    <link rel="stylesheet" href="popup_help.css" />
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script src="jquery.popup_help.js"></script>
    <script>
      $(function() {
        // ?マークにマウスを載せるとヘルプメッセージを表示させるようにします。
        $("[itemprop=entryID]").popupHelp({"marginTop": 20, "marginLeft": 40});
      });
    </script>
 </head>
  <body>
    <header>
      <h1 id="header_title">論文要旨をポップアップして表示するサンプル<br /></h1>
    </header>
<ul itemscope itemtype="http://schema.org/ScholarlyArticle"><li>Morita M., Igarashi Y., Ito M., Chen YA., Nagao C., Sakaguchi Y., Sakate R., Masui T., Mizuguchi K.,  Sagace: a web-based search engine for biomedical databases in Japan., BMC Res Notes, 2012 Oct 31, 5:604, <span itemprop='entryID' content='pmid:23110816' ><a href="http://www.ncbi.nlm.nih.gov/pubmed/23110816" target="_blank">PubMed:23110816</a></span></li>
<li>Nagao C., Izako N., Soga S., Khan SH., Kawabata S., Shirai H., Mizuguchi K.,  Computational design, construction, and characterization of a set of specificity determining residues in protein-protein interactions., Proteins, 2012 Oct, 80(10):2426-36, <span itemprop='entryID' content='pmid:22674858' \><a href="http://www.ncbi.nlm.nih.gov/pubmed/22674858" target="_blank">PubMed:22674858</a></span></li>
<li>Blower TR., Short FL., Rao F., Mizuguchi K., Pei XY., Fineran PC., Luisi BF., Salmond GP.,  Identification and classification of bacterial Type III toxin-antitoxin systems encoded in chromosomal and plasmid genomes., Nucleic Acids Res, 2012 Jul, 40(13):6158-73, <span itemprop='entryID' content='pmid:22434880' \><a href="http://www.ncbi.nlm.nih.gov/pubmed/22434880" target="_blank">PubMed:22434880</a></span></li>
</ul>
      
  </body>
</html>

以上,これはずっと前からやりたかった実装だから出来てよかった!
結果のイメージはこんな感じ。pubmedIDが入ったmicrodataとちょいとタグをhtmlに入れるとなんとタイトルと要旨を自動で取って来てくれるのだ!!!!

f:id:maoring:20130614185755p:plain

デモでお試しください。不具合等ありましたら教えて下さい。
デモ

javascriptとmicrodata(調査中)その5

前回までで特定のclassであれば,ポップアップで中身を表示できるようになった。
これをmicrodataでやりたいのだけど…と思った時に,classじゃなくてitempropで認識出来れば良いのでは?ということに気がついた。しかし,どうやって?と調べていたら,ここにも神が舞い降りた。紙でも髪でもなければ,女将でもない!って何ダジャレを!←気にしないでください。
jqueryのセレクタで name属性を使う

セレクタが便利そうなので、jqueryを使ってみました。 elementを選択するには、 id : $("#idname") class : $(".classname") tag : $("tagname") なんてのが使える 他にも便利なセレクタがありますが、名前でも選択が可能です。 以下のように書けばいいです。

$("*[name=target]")

これって・・・「name」属性が"target"のものを取得するということになります。 てことは、別に、nameじゃなくても、idでも、classでも、hrefでもlangとかでも出来るらしい。

なんですと!そんな簡単に出来ちゃうの?ってことでものは試し。itempropで出来ないか考えることにした。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title></title>
    <link rel="stylesheet" href="style.css" />
    <link rel="stylesheet" href="popup_help.css" />
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script src="jquery.popup_help.js"></script>
    <script>
      $(function() {
        // ?マークにマウスを載せるとヘルプメッセージを表示させるようにします。
//        $("*[itemprop=entryID].popup_help").popupHelp({"marginTop": 20, "marginLeft": 40});
        $("[itemprop=entryID]").popupHelp({"marginTop": 20, "marginLeft": 40});
      });
    </script>
 </head>
  <body>
    <header>
      <h1 id="header_title">ヘルプメッセージをポップアップして表示するサンプル<br />(プラグイン化)</h1>
    </header>
<div itemscope itemtype="http://schema.org/ScholarlyArticle">
<p> Kanehisa M, et al. Nucleic Acids Res. 40, D109-D114 (2012).</p>
[<span itemprop='entryID' content='pmid:12080510'/ data-message="This is an article">
<a href="http://www.ncbi.nlm.nih.gov/pubmed/22080510">pubmed</a></span> ]
<br>
[<span itemprop='entryID' content='pmid:22080510'/ data-message="This is an article">
<a href="http://www.ncbi.nlm.nih.gov/pubmed/22080510">pubmed</a></span> ]
</div>
  </body>
</html>

↓取得する内容がcontentなので一部 popupObj.text($(this).attr('content')); に変更。

(function($) {                                                                                                                          
  $.fn.popupHelp=function(config) {                                                                                                     
    /**                                                                                                                                 
      * marginTop: 表示対象とウィンドウの高さの差分です。                                                                               
      *   0を指定すると、上端が揃います。                                                                                               
      * marginLeft: 表示対象とウィンドウの横の差分です。                                                                                
      *   0を指定すると、左端が揃います。                                                                                               
      * className: ウィンドウに設定するクラス名です。                                                                                   
      * speed: ウィンドウを表示する際の秒数[ms]です。                                                                                   
      */                                                                                                                                
    var defaults = {                                                                                                                    
      marginTop: 0,                                                                                                                     
      marginLeft: 20,                                                                                                                   
      className: "popup_help_window",                                                                                                   
      speed: 300                                                                                                                        
    }                                                                                                                                   
                                                                                                                                        
    var options = $.extend(defaults, config);                                                                                           
                                                                                                                                        
    // ヘルプウィンドウのオブジェクトを準備します。                                                                                     
    var popupObj = $("<p/>").addClass(defaults.className).appendTo($("body"));                                                          
    // popupObj.appendTo($("body"));                                                                                                    
                                                                                                                                        
    return this.each(function() {                                                                                                       
                                                                                                                                        
      $(this).mouseover(function() {                                                                                                    
        // 表示対象にマウスが重なった時の処理です。                                                                                     
                                                                                                                                        
        // ウィンドウにメッセージを設定します。                                                                                         
        popupObj.text($(this).attr('content'));                                                                                         
                                                                                                                                        
        // ウィンドウのオフセットを計算します。                                                                                         
        var offsetTop = $(this).offset().top + defaults.marginTop;                                                                      
        var offsetLeft = $(this).offset().left + defaults.marginLeft;                                                                   
                                                                                                                                        
        // ウィンドウの位置を整え、表示します。                                                                                         
        popupObj.css({                                                                                                                  
          "top": offsetTop,                                                                                                             
          "left": offsetLeft                                                                                                            
        }).show(defaults.speed);                                                                                                        
                                                                                                                                        
      }).mouseout(function() {                                                                                                          
        // 表示対象にマウスが重なった時の処理です。                                                                                     
        // テキストを空にして、ウィンドウを隠します。                                                                                   
        popupObj.text("").hide("fast");                                                                                                 
      });                                                                                                                               
    });                                                                                                                                 
  };                                                                                                                                    
})(jQuery);                   

これで実行すると,おぬし出来ているではないか!!

f:id:maoring:20130613145516p:plain

ここで疑問が生じる。今回の論文のIDの場合content=pmid:22080510 でどの論文かまで指定してしまっているので,itemtypeは気にしなくて良いのではないだろうか…。邪道だってテンカラ声が聞こえてきそうだが,書き間違える人もいるかもだし,taxon等で必要になったら,
先日調べた"jquery.microdata.js"を使ってitemtypeも取得することにしよう。
悪魔のささやきかも…(苦悩)いやでもBioHackathon中にも取り組めるかもしれないし。

というわけで,取得したcontent内のテキストからPubMed IDを抜き出して要旨を表示するところまで持っていきたい。続く…

javascriptとmicrodata(調査中)その4

前回まででmicrodataのitemtypeとitempropとその中身(itemvalue)を得ることが出来た。
今回はその目的のmicrodataが埋め込まれていた場合に,ポップアップでその中身を表示できるようにすることが目的だ。
まずどのポップアップを使うか。そしてどう認識させるか。
ポップアップも色々なものがあるので,軽量で拡張しやすいものを探すべし。

良さげな例を見つけた。
[jQuery] ヘルプメッセージをポップアップして表示する方法
コードをそのまま引用させて頂きます。(今回はjQuery ver.を使用します。)

(function($) {
  $.fn.popupHelp=function(config) {
    /** 
      * marginTop: 表示対象とウィンドウの高さの差分です。
      *   0を指定すると、上端が揃います。
      * marginLeft: 表示対象とウィンドウの横の差分です。
      *   0を指定すると、左端が揃います。
      * className: ウィンドウに設定するクラス名です。
      * speed: ウィンドウを表示する際の秒数[ms]です。
      */
    var defaults = { 
      marginTop: 0,
      marginLeft: 20, 
      className: "popup_help_window",
      speed: 300 
    }   

    var options = $.extend(defaults, config);

    // ヘルプウィンドウのオブジェクトを準備します。
    var popupObj = $("<p/>").addClass(defaults.className).appendTo($("body"));
    // popupObj.appendTo($("body"));

    return this.each(function() {

      $(this).mouseover(function() {
        // 表示対象にマウスが重なった時の処理です。

        // ウィンドウにメッセージを設定します。
        popupObj.text($(this).attr('data-message'));

        // ウィンドウのオフセットを計算します。
        var offsetTop = $(this).offset().top + defaults.marginTop;
        var offsetLeft = $(this).offset().left + defaults.marginLeft;

        // ウィンドウの位置を整え、表示します。
        popupObj.css({
          "top": offsetTop,
          "left": offsetLeft
        }).show(defaults.speed);

      }).mouseout(function() {
        // 表示対象にマウスが重なった時の処理です。
        // テキストを空にして、ウィンドウを隠します。
        popupObj.text("").hide("fast");
      }); 
    }); 
  };  
})(jQuery);

そしてcssは指定したclassとポップアップwindowについて記述。

.popup_help {
  padding: 0 3px;
  color: #66f;
  font-weight: bold;
  cursor: pointer;
}
.popup_help_window {
  max-width: 300px;
  position: absolute;
  padding: 6px 15px;
  background-color: #fff;
  border: 5px double #ccc;
  display: none;
  color: #63f;
  font-size: 15px;
  font-weight: bold;
  line-height: 1.5em;
  border-radius: 10px;
  box-shadow: 5px 5px 5px #ccc;
}

そしてhtmlでは上部に先ほどのcssjavascriptを挿入して $("span.popup_help").でどのタグとclassを使うかを指定,ついでにwindowの位置等を({"marginTop": 20, "marginLeft": 40});で設定して
(以下部分的に抜粋&一部こちらの環境に変更)body中に,span class="popup_help"を書くとこんな感じ。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title></title>
    <link rel="stylesheet" href="style.css" />
    <link rel="stylesheet" href="popup_help.css" />
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script src="jquery.popup_help.js"></script>
    <script>
      $(function() {
        // ?マークにマウスを載せるとヘルプメッセージを表示させるようにします。
        $("span.popup_help").popupHelp({"marginTop": 20, "marginLeft": 40});
      });
    </script>
 </head>
  <body>
    <header>
      <h1 id="header_title">ヘルプメッセージをポップアップして表示するサンプル<br />(プラグイン化)</h1>
    </header>
<div itemscope itemtype="http://schema.org/ScholarlyArticle">
<p> Kanehisa M, et al. Nucleic Acids Res. 40, D109-D114 (2012).</p>
[<span class="popup_help" itemprop='entryID' content='pmid:22080510'/ data-message="This is an article">
<a href="http://www.ncbi.nlm.nih.gov/pubmed/22080510">pubmed</a></span>]
</div>
  </body>
</html>

タグも"a"に限らないし,良いのではないだろうか。
(ちなみにjQueryプラグインバージョンもあり,ダウンロードも解説ページから出来て至れり尽くせり)
ちなみに実装例は以下の画像のとおりである。マウスでホバーするとにょにょにょーと表示してくれるのだ。

f:id:maoring:20130613121114p:plain

そしてここでは spanというタグとclass="popup_help"を認識しているが,これをmicrodataにしてしまいたいのだけど,んーどういった方法がいいだろうか(続く)

javascriptとmicrodata(調査中)その3

Live Microdataで利用しているJavaScriptを参考に,まずはmicrodataをきちんと切り出したいという要望を満たしたい。 今日は以下の3つのjavascriptをみてみるよん。

<script src="../jquery.microdata.js"></script>
<script src="../jquery.microdata.json.js"></script>
<script src="live.js"></script>

最初からクライマックス!というわけでlive.jsを見てみたけど,このウェブサイト特有の事情で使っているっぽいから とりあえず関係ないのではないかという適当な結論に。

次本題。jquery.microdata.js これが何を認識して何を返しているかということを知りたい。
コードを読んでみて自分が随分JavaScriptを知らないことが分かった…。

もとの呼び出しているhtmlから必要そうな部分だけ抜粋したものを掲載する。 これでも普通に動いてmicrodataから得られたタイプとプロパティを綺麗に構造化してJSONで出力してくれる。

<!doctype html>                                                                                                                         
<html>                                                                                                                                  
<head>                                                                                                                                  
<meta charset="utf-8">                                                                                                                  
<title>Live Microdata</title>                                                                                                           
<link rel="stylesheet" href="css/ui-lightness/jquery-ui-1.7.2.custom.css">                                                              
<link rel="stylesheet" href="live.css">                                                                                                 
<script src="../lib/jquery-1.6.4.min.js"></script>                                                                                      
<script src="../lib/jquery-ui-1.7.2.custom.min.js"></script>                                                                            
<script src="../lib/jquery.textarearesizer.compressed.js"></script>                                                                     
<script src="../lib/json2.js"></script>                                                                                                 
<script src="../jquery.microdata.js"></script>                                                                                          
<script src="../jquery.microdata.json.js"></script>                                                                                     
<script src="live.js"></script>                                                                                                         
<script>document.createElement('footer');</script>                                                                                      
</head>                                                                                                                                 
<body>                                                                                                                                  
                                                                                                                                        
<h1><a href=".">Live Microdata</a></h1>                                                                                                 
                                                                                                                                        
<form class="examples">                                                                                                                 
Examples:                                                                                                                               
<select title="Select an example to load it below...">                                                                                  
<option value=""></option>                                                                                                              
<option value="vcard-jack">vCard: Jack Bauer</option>                                                                                   
</select>                                                                                                                               
</form>                                                                                                                                 
                                                                                                                                        
<div class="warnings"></div>                                                                                                            
                                                                                                                                        
<textarea>Write HTML/Microdata markup here...</textarea>                                                                                
                                                                                                                                        
<div id="tabs">                                                                                                                         
  <ul>                                                                                                                                  
    <li><a href="#preview">Preview</a></li>                                                                                             
    <li><a href="#json" title="Microdata as JSON">JSON</a></li>                                                                         
  </ul>                                                                                                                                 
  <div id="preview"><iframe src="preview.html"></iframe></div>                                                                          
  <div id="json"></div>                                                                                                                 
</div>                                                                                                                                  
</body>                                                                                                                                 
</html> 

困った。何が困ったってエレガントすぎてどう呼び出して値をどう渡しているのか分からない… 部分的にでもjquery.microdata.jsがやっていることを理解したい。

'use strict';

(function(){
  var $ = jQuery;

  $.microdata = {};

  // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#valid-time-string
  function validTimeStringLength(s) {
    var m = /^(\d\d):(\d\d)(:(\d\d)(\.\d+)?)?/.exec(s);
    if (m && m[1]<=23 && m[2]<=59 && (!m[4] || m[4]<=59))
      return m[0].length;
    return 0;
  }
…中略  
 $.fn.extend({
    items: document.getItems && t.itemType && t.itemType.contains ? function(types) {
      var doc = this[0];
      if (doc.getItems)
        return $(types ? doc.getItems(types) : doc.getItems());
      return getItems.call(this, types);
    } : getItems,
    itemScope: t.itemScope ? function() {
      return this[0].itemScope;
    } : function () {
      return this[0].getAttribute('itemscope') != null;
    },
    itemType: t.itemType && t.itemType.contains ? function() {
      return this[0].itemType;
    } : tokenList('itemtype'),
    itemId: t.itemId == 'id' ? function() {
      return this[0].itemId;
    } : function () {
      return resolve(this[0], 'itemid');
    },
    itemProp: t.itemProp && t.itemProp.contains ? function() {
      return this[0].itemProp;
    } : tokenList('itemprop'),
    itemRef: t.itemRef && t.itemRef.contains ? function() {
      return this[0].itemRef;
    } : tokenList('itemref'),
    itemValue: t.itemValue == t && t.value == 'value' ? function() {
      return this[0].itemValue;
    } : itemValue,
    properties: t.properties && t.properties.namedItem ? function(name) {
      return $(name ? this[0].properties.namedItem(name) : this[0].properties);
    } : properties
  });
})();

どうやら全体を即時関数にして,その後色々な読み取るための関数を定義し, $.fn.extendでjqueryを拡張して利用できるようにしているらしい。最後の拡張を上手いこと使えば htmlで埋め込まれているmicrodataを上手く取り出せるのではあるまいか…!?
その前にjQuery.fn.extendとはなんぞや。

jQuery日本語リファレンス jQuery does not mean Japanese Query...

jQuery.fn.extend(object)
jQueryエレメントに独自の新しいメソッドを追加する。(典型的なjQueryプラグインの作成方法)

まじか。サンプルも載っていた。

//jQueryオブジェクトに、新たに「全てチェック状態にする」「全て非チェック状態にする」メソッドを追加  
jQuery.fn.extend({
  check: function() {
    return this.each(function() { this.checked = true; });
  },
  uncheck: function() {
    return this.each(function() { this.checked = false; });
  }
});
$("input[@type=checkbox]").check();
$("input[@type=radio]").uncheck();

さて,本題に戻ろう。最終的なイメージはmicrodataの論文のマークアップがされているものがあったら,それを抽出してその要旨を 表示させること。そのためにまず,microdataの論文のマークアップを正しく抽出する必要がある。当然のことを言い過ぎているきらいがあるのは 気にしないでちょ。なので,jquery.microdata.jsとmicrodataの含まれているページを共存させて,jquery.microdata.jsさんに 以下の様なマークアップがあったら,それを綺麗に取り出してくれるようなものを作って欲しいのだ。

<span itemscope itemtype="http://schema.org/ScholarlyArticle">                                                                         
<p> Kanehisa M, et al. Nucleic Acids Res. 40, D109-D114 (2012).</p>                                                              
[<meta itemprop='entryID' content='pmid:22080510'/>                                                                                  
<a href="http://www.ncbi.nlm.nih.gov/pubmed/22080510">pubmed</a>]                                         
<div itemprop="name">Rojar</div>                                                                                                    
</span>                                                                                                                            

↑ここから itemtype(タイプ,語彙の種類)="http://schema.org/ScholarlyArticle"であり,itemprop(プロパティ,属性)='entryID' の content(中身)='pmid:22080510' をとっておくんなましというわけだ。

ヒントになりそうなhtmlを見つけた。
atoato88 / operate-microdata
ちょっと抜粋。

<head>
   <meta charset="UTF-8">
   <title>携帯電話連動型電子レンジ</title>
   <link rel="stylesheet" href="css/style.css" />
   <script type="text/javascript" src="js/jquery-1.4.4.min.js"></script>
   <script type="text/javascript" src="js/jquery.microdata.js"></script>
   <script type="text/javascript">
       $(function(){
           var r = $('article section section').properties().map(function(i, e){return $(e).itemValue();}).get();
           alert(r);
       });
   </script>
</head>
<body>
    <article itemscope itemtype="http://example.com/Thing">
        <section itemscope itemtype="http://example.com/Brand">
            <div itemprop="name">電話レンジ(仮)</div>
            <div itemprop="name">未来ガジェット8号機</div>
            <section itemscope itemtype="http://example.com/Design">
                <div itemprop="name">サイコロ型電子レンジ</div>
                                <div itemprop="description">
                    <p>斬新なサイコロ型デザイン。</p>
                    <p>レトロ調に仕上げました。</p>
                </div> 
            </section>
               </section>
       </article>
</body>
</html>

article タグの中の section タグの中の sectionタグの中のプロパティの中身をmapを使ってコンマ区切りに全て出力してくれる。

サイコロ型電子レンジ,斬新なサイコロ型デザイン。,レトロ調に仕上げました。

と表示してくれる。んー近い気がしてきた。ただこれだとhtmlタグの指定をしないといけない。
そうではなくて,itemtypeで指定したいのだ。んーどうすれば…!
発想の転換をしよう。今回はクローラーではないので網羅的である必要はない。だから,hoverされたらその時のタグ名を入手して(もしくはaタグにして)
itemtypeとitempropとコンテンツを取得出来れば良いのである。ということで三つ組ゲットだぜ!のコードを書いてみた。コードの下の画像のようにalertで取り出してくれる。
ここではspanタグの中身の最初のmicrodataの情報を取り出してちょというコードになっている。

<!DOCTYPE HTML>
<html lang="ja">
<head>
        <meta charset="UTF-8">                                                                                                          
        <title>Short Sample Code</title>                                                                                                
        <link rel="stylesheet" href="css/style.css" />                                                                                  
        <script type="text/javascript" src="js/jquery-1.6.4.min.js"></script>                                                           
        <script type="text/javascript" src="js/jquery.microdata.js"></script>                                                           
        <script type="text/javascript">                                                                                                 
        $(function(){
                triplearray = new Array(3);     
                triplearray[0] = $("span").itemType().toString();                                                                       
                triplearray[1] = $('span').properties().itemProp().toString();                                                          
                triplearray[2] = $('span').properties().itemValue().toString();                                                         
                alert("itemtype : " + triplearray[0] +"\nitemprop : " + triplearray[1] +"\nitemvalue : " +  triplearray[2]);
        });                                                                                                                             
        </script>
</head>
<body>
<span itemscope="sample" itemtype="http://schema.org/ScholarlyArticle">
<p> Kanehisa M, et al. Nucleic Acids Res. 40, D109-D114 (2012).</p>                                                                     
[<meta itemprop='entryID' content='pmid:22080510'/>
<a href="http://www.ncbi.nlm.nih.gov/pubmed/22080510">pubmed</a>]
</span>
</body>
</html>

f:id:maoring:20130612150901p:plain

ってアップしてみて驚いた。hatenaで写真をアップするとmicrodataを勝手に入れてくれるんだ!

コード起こすとこんな感じ。

<p>
 <span itemscope itemtype="http://schema.org/Photograph">
  <img src="http://cdn-ak.f.st-hatena.com/images/fotolife/m/maoring/20130612/20130612150901.png" alt="f:id:maoring:20130612150901p:plain" title="f:id:maoring:20130612150901p:plain" class="hatena-fotolife" itemprop="image">
</span>
</p>

itemtype="http://schema.org/Photograph"
itemprop="image"
img src="http://cdn-ak.f.st-hatena.com/images/fotolife/m/maoring/20130612/20130612150901.png"

JSONにするとこんな感じ

{ "items": [ { "type": [ "http://schema.org/Photograph" ],
"properties": { "image": [ "http://cdn-ak.f.st-hatena.com/images/fotolife/m/maoring/20130612/20130612150901.png" ] } } ] }

Hatena 素晴らしやー。(長くなったので続く…)

javascriptとmicrodata(調査中)その2

まずJavaScriptでフツーに取り出してくれる,タグの中身だけれども,microdataになるとそうはならないので microdataをうまく抽出してくれるmicrodataを探す。 いくつか候補はあったのだけど,Live microdataの中で使用されているJavaScriptを使用することにした。

Live Microdatamicrodataマークアップされたhtmlを入れるとその出力イメージとJSONを返してくれるステキツールだ。(ちなみにここで書いてあるvCardは共通フォーマットの電子名刺だったり,iCalは共通フォーマットのカレンダーだったりするけど,これがもっと広まると多分幸せになれるという話はいつかするかもしれない。)
ここの下部からコードを入手して https://gitorious.org/microdatajs/
こちらの環境上で動かしてみたらLive Microdataはちゃんと動いてくれたので,どうやらここで使われているjavascriptを見ればいいのではないかという結論に至った。

読み込んでいるJavaScriptで関連ありそうなのは以下のとおり。

<script src="../lib/jquery-1.6.4.min.js"></script>
<script src="../lib/jquery-ui-1.7.2.custom.min.js"></script>
<script src="../lib/jquery.textarearesizer.compressed.js"></script>
<script src="../lib/json2.js"></script>
<script src="../jquery.microdata.js"></script>
<script src="../jquery.microdata.json.js"></script>
<script src="live.js"></script>

面倒だが一個一個関係のある可能性を考えて,調べてみる。
CSSは分かるけど jQuery は苦手 … という人が jQuery に親しんでくれるといいなーと思って書きました

jQuery には、圧縮版の Minified と、非圧縮版の Uncompressed があって、一般的には読み込みの早い圧縮版を使います。圧縮版は改行などが排除されていて、ファイル名が jquery-1.6.4.min.js のように min がついてるのがそうです。数字はバージョンを表しています。

にゃるほど。次っ

http://jqueryui.com/

jQuery UI is a curated set of user interface interactions, effects, widgets, and themes built on top of the jQuery JavaScript Library.

ほむ。 簡単にインタフェースが作れるっぽい。あのニュルニュルした動きはそうなのかな。次っ

jQuery TextArea Resizer ドラッグアンドドロップでテキストエリアのサイズを変更する

テキストエリアを使用する場合だいたいのサイズで指定しますが、そのサイズを ドラッグアンドドロップで大きくする事が可能になるプラグインです。

はいよー。次っ

これでできる! クロスブラウザJavaScript入門 第12回 XMLHttpRequest入門

XMLHttpRequestのレスポンスとしてJSONを受け取った場合,それはresponseTextのデータとして読み取ることになります。つまり,それはJavaScriptのオブジェクトではありません。できれば直接JSONをオブジェクトとして読み取りたいところですが,今のところそういったAPIは用意されていません。従ってJSONをパースしてオブジェクトに変換する必要があります。
…中略
json2.jsは読み込むだけでJSON.parseメソッドが利用可能になります。

多分microdataを含まれているものをjsonで返しているはずなのだけど,それを画面に表示させるために使っているのかな,という印象。

さて次は恐らく本題のjquery.microdata.jsとjquery.microdata.json.jsとlive.jsについて。 jquery.microdata.jsだけで上手く切り出せると良いのだけど…(続く)