素人がプログラミングを勉強していたブログ

プログラミング、セキュリティ、英語、Webなどのブログ since 2008

連絡先: twitter: @javascripter にどうぞ。

Minibufferに依存しないLDRizeクローンを作った

LDRizeは魅力的だけど、僕はMinibufferを使っていない。あとちょっと重い。
それで、軽くてMinibufferに依存しないスクリプトを作った。

問題点:

  1. hAtomにしか対応してないので、LDRizeと比べて動くサイトが少ない。
  2. id:Constellationさんの作ったMicroformatize for Greasemonkeyを使うと動くサイトが増すが、これはMinibuffer依存。駄目。

なんかダメダメ。

// ==UserScript==
// @name           LDLite
// @namespace      http://d.hatena.ne.jp/javascripter/
// @include        http*
// ==/UserScript==
(function(){
  var USE_SMOOTH=true;
  var AUTO_SCROLL=false;

  var entries=document.getElementsByClassName('hentry');
  if(entries.length==0)return;
  GM_addStyle(<><![CDATA[
  ._highlight{
    -moz-outline:rgba(206,225,255,0.8) solid 2px !important;
    -moz-outline-offset:-2px !important;
    -moz-outline-radius:3px !important;
  }
  ._pinned{
    -moz-outline:rgba(204,96,96,0.8) solid 2px !important;
    -moz-outline-offset:-2px !important;
    -moz-outline-radius:3px !important;
  }
  body{
    margin-bottom:500px !important;
  }
  ]]></>);

  document.addEventListener('keypress',
    function(e){
      if(['input','textarea'].indexOf(e.target.tagName.toLowerCase())!=-1)return;
      var flag=false;
      switch(String.fromCharCode(e.which)){
        case 'j':scrollNext();break;
        case 'k':scrollPrev();break;
        case 'o':openPinned();break;
        case 'p':togglePin();break;
        case 'v':openCurrent();break;
        default :flag=true;break;
      }
      if(!flag)e.preventDefault();
    }
  ,false);

  var current=-1;
  if(AUTO_SCROLL)scrollNext();

  function scrollNext(){
   if((current+1)==entries.length){
      current++;
      smoothScroll({ left: window.scrollMaxX-window.scrollX , top: window.scrollMaxY-window.scrollY });
    }else if( (current+1) <entries.length){
      if(current>=0)removeClassName(entries[current],'_highlight');
      var entry=entries[++current];
      addClassName(entry,'_highlight');
      scrollByElement(entry,USE_SMOOTH);
    }
  }

  function scrollPrev(){
    if( (current-1) == -1){
      current--;
      smoothScroll({ left: -window.scrollX , top: -window.scrollY });
    }else if((current-1)>=0){
      if(current<entries.length)removeClassName(entries[current],'_highlight');
      var entry=entries[--current];
      addClassName(entry,'_highlight');
      scrollByElement(entry,USE_SMOOTH);
    }
  }

  function openPinned(){
    Array.slice(document.getElementsByClassName('_pinned')).forEach(
        function(entry){
          var url=getTitleURL(entry);
          if(url){
            GM_openInTab(url);
          }
          removeClassName(entry,'_pinned');
          });
  }

  function togglePin(){
    toggleClassName(entries[current],'_pinned');
    scrollNext();
  }

  function openCurrent(){
    if(isInRange(current)){
      var url=getTitleURL(entries[current]);
        if(url)
          location.href=url;
    }
  }

  function getTitleURL(elem){
  var [bookmark]=getElementsByRelName(elem,'bookmark');
  if(bookmark)
    [bookmark]=elem.getElementsByClassName('entry-title')[0].getElementsByTagName('a');
  return bookmark.href;
  }
  function scrollByElement(elem,isSmooth){
    var pos=elem.getBoundingClientRect();
    if(isSmooth){
      smoothScroll({left:pos.left,top:pos.top});
    }else{
      scrollBy(pos.left,pos.top);
    }
  }
  function smoothScroll(pos){
    var x=pos.left/8;
    var y=pos.top/8;
    (function(i){
     window.scrollBy(x,y);
     if(++i<8)
       setTimeout(arguments.callee,15,i);
     else
       scrollBy(pos.left%8,pos.top%8);
    })(0);
  }

  function hasClassName(elem,className)
    elem.className.split(/\s/).indexOf(className)!=-1;

  function addClassName(elem,className){
    if(hasClassName(elem,className))
      return null;
    else
      elem.className+=' '+className;
    return className;
  }

  function removeClassName(elem,className)
    elem.className=elem.className.split(/\s/).filter(function(str)str!=className).join(' ');

  function toggleClassName(elem,className)
    hasClassName(elem,className)?removeClassName(elem,className):addClassName(elem,className);

  function getElementsByRelName(elem,relName){
    var rels=relName.split(/\s/);
    return Array.filter(elem.getElementsByTagName('*'),
        function(i){
        var relVaue=i.getAttribute('rel');
        return rels.some(
          function(rel)
            RegExp('^|\\s'+rel+'\\s|$','i').test(relVaue)
          );
        });
  }
})()