Re: twitterに張られたニコニコのリンクをサムネ(というかiframe)展開するぐりもん

書いた人: noriaki 2008,01月29日(火) 02:30

ジェバンニが一晩でやってくれました.

ぐりもんは初めて書いたんで無駄・無理な所があるやもしれません。ツッコミ・添削などお待ちしております。

久々のコッチ - console

というわけで,@Noboruhi(id:noboruhi)さんのぐりもんをもとに,私の環境では動かなかったXPath周りの修正とAutoPagerize対応を加えて作ってみました.

追記(2008/02/24 18:30): ニコニコ動画のサムネイルWebAPIの公開に合わせて,iframe ではなくAPIを利用する形式に書き直しました.その結果,iframe 展開時にはブラウザ履歴にサムネイルURLが残っていましたが,APIを利用することによって履歴にサムネイルURLが残らないようになりました.
また,サムネイルAPIにタグ情報が含まれるようになりましたので,それも併せて表示するようにしています.

インストール

インストールはこちらからどうぞ.

matasamune.user.js

追記: CodeRepos上にスクリプトを置き,インストールURIもそちらになりました.

以下にはソースコードを載せておきます.

ソースコード

@Noboruhiさんさえよければ,CodeReposにソースコードをコミットして,みんなで作っていければいいなと思ってますがいかがでしょう.Noburuhiさんもこの機会にCodeReposのコミッタに!

追記: ここに載っているソースコードは公開時点のものです.最新のものはCodeRepos上のソースコードをご覧ください.

// ==UserScript==
// @name          mata samune
// @namespace     http://d.hatena.ne.jp/noboruhi
// @description   matemiteru samuneiru
// @include       http://twitter.com/*
// @author        noboruhi
// @author        noriaki
// @version       0.2
// ==/UserScript==

const hasNicoLinkExp = [
  'descendant::*[(local-name() = "a" or local-name() = "A") and ',
  'starts-with(@href, "http://www.nicovideo.jp/watch/")]'
].join('');
const hasNicoEntriesExp = [
  'self::node()/descendant::*[local-name() = "td" or local-name() = "TD"]',
  '[contains(concat(" ",@class," "), " content ")', ' and ',
  'count(', hasNicoLinkExp, ')>0]'
].join('');
const NicoLinkExp = 'self::node()/' + hasNicoLinkExp;

function insertThumbnail(context) {
  context = context.length ? context[0] : context;
  var entries = $x(hasNicoEntriesExp, context);
  entries.forEach(function (entry) {
    var link = $x(NicoLinkExp, entry)[0];
    if(link.getAttribute('href').match(/http:\/\/www\.nicovideo\.jp\/watch\/(sm\d+)/)) var id = RegExp.$1;
    else return;
    var iframe = $N('iframe',{
      src: 'http://www.nicovideo.jp/thumb/' + id,
      scrolling: 'no',
      frameborder: '0',
      style: {
        border: 'solid 1px #CCC',
        marginTop: '4px',
        width: entry.clientWidth - 10 + 'px'
      }
    },'');
    entry.appendChild($N('br',{},''));
    entry.appendChild(iframe);
  });
};

var i=4;
function addFilter() {
  if(window.AutoPagerize && window.AutoPagerize.addFilter) {
    window.AutoPagerize.addFilter(insertThumbnail);
  } else if(i-- > 0) {
    setTimeout(arguments.callee, 500);
  }
}
insertThumbnail(document);
addFilter();

// Utility
function $x(xpath, context) {
  context = context || document;
  var res = document.evaluate(xpath, context, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);
  for(var i, nodes = [] ; i=res.iterateNext() ; nodes.push(i));
  return nodes;
}

function $N(name, attr, childs) {
  var ret = document.createElement(name);
  for(k in attr) {
    if(!attr.hasOwnProperty(k)) continue;
    if(k == "class") {
      ret.className = attr[k];
    } else if(k == "style" && typeof(attr[k]) == "object") {
      for(j in attr[k]) ret.style[j] = attr[k][j];
    } else {
      ret.setAttribute(k, attr[k]);
    }
  }
  switch(typeof childs) {
  case "string": {
    ret.appendChild(document.createTextNode(childs));
    break;
  }
  case "object": {
    for(var i=0,len=childs.length; i<len; i++) {
      var child = childs[i];
      if(typeof child == "string") {
        ret.appendChild(document.createTextNode(child));
      } else {
        ret.appendChild(child);
      }
    }
    break;
  }
  }
  return ret;
}

このエントリをdel.icio.usにブックマークしているユーザ数このエントリをdel.icio.usに追加する
このエントリをはてなブックマークしているユーザ数このエントリをはてなブックマークに追加する
 | Tags , ,

このエントリはアーカイブされています。
コメントする場合は、お手数ですが「このページのURL」を記載した上で、新しいエントリにお願いします。