social-bookmark-counter-on-google-search

Script Summary: Supporting Delicious, Facebook, Twitter, Hatena, Digg and StumbleUpon.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name          social-bookmark-counter-on-google-search
// @namespace     https://github.com/ikeikeikeike
// @include       *.google.*
// @include       http://www.google.*/search*
// @include       http://www.google.*/custom*
// @include       https://www.google.*/search*
// @include       https://www.google.*/custom*
// @require       http://code.jquery.com/jquery-2.0.3.min.js
// @grant         GM_addStyle
// @grant         GM_xmlhttpRequest
// @description   Script Summary: Supporting Delicious, Facebook, Twitter, Hatena, Digg and StumbleUpon.
// @author        Tatsuo Ikeda <jp.ne.co.jp at gmail> http://about.me/ikeikeikeike
// @homepage      https://userscripts.org/scripts/show/115527
// @supportURL    https://github.com/ikeikeikeike/social-bookmark-counter-on-google-search/issues
// @version       0.9.1
// @license       Creative Commons
// ==/UserScript==
/*
@include       http://search.yahoo.co.jp/search?*
@include       https://search.yahoo.co.jp/search?*
@include       http://www.bing.com/search*
@include       https://www.bing.com/search*
@include       http://userscripts.org/scripts/search?*
@include       https://userscripts.org/scripts/search?*
*/
(function(){

/**
 * CSS
 */
GM_addStyle([
".__GMsavers a\
  {\
    background: #3274D0 none repeat scroll 0 0;\
    color: #FFFFFF;\
    font-weight: bold;\
    font-size: 12px;\
    padding: 1px 5px;\
    margin-left: 5px;\
    text-decoration: none;\
  }",
".__GMsavers a:hover\
  {\
    background: #7CBA0F none repeat scroll 0 0;\
    color: #FFFFFF;\
    font-weight: bold;\
    padding: 1px 5px;\
    margin-left: 5px;\
    text-decoration: none;\
  }",
".__GMtwisavers a\
  {\
    background: rgba(51,204,255,0.9) none repeat scroll 0 0;\
    color: #FFFFFF;\
    font-weight: bold;\
    font-size: 12px;\
    padding: 1px 5px;\
    margin-left: 5px;\
    text-decoration: none;\
  }",
".__GMtwisavers a:hover\
  {\
    background: #7CBA0F none repeat scroll 0 0;\
    color: #FFFFFF;\
    font-weight: bold;\
    padding: 1px 5px;\
    margin-left: 5px;\
    text-decoration: none;\
  }",
".__GMdiggsavers a\
  {\
    background: rgba(31,100,105,0.9) none repeat scroll 0 0;\
    color: #FFFFFF;\
    font-weight: bold;\
    font-size: 12px;\
    padding: 1px 5px;\
    margin-left: 5px;\
    text-decoration: none;\
  }",
".__GMdiggsavers a:hover\
  {\
    background: #7CBA0F none repeat scroll 0 0;\
    color: #FFFFFF;\
    font-weight: bold;\
    padding: 1px 5px;\
    margin-left: 5px;\
    text-decoration: none;\
  }",
".__GMstumbleuponsavers a\
  {\
    background: rgba(255, 112, 0, 0.9) none repeat scroll 0 0;\
    color: #FFFFFF;\
    font-weight: bold;\
    font-size: 12px;\
    padding: 1px 5px;\
    margin-left: 5px;\
    text-decoration: none;\
  }",
".__GMstumbleuponsavers a:hover\
  {\
    background: #7CBA0F none repeat scroll 0 0;\
    color: #FFFFFF;\
    font-weight: bold;\
    padding: 1px 5px;\
    margin-left: 5px;\
    text-decoration: none;\
  }",
".__GMredditsavers a\
  {\
    background-color: #4FA7FF;\
    color: #FFFFFF;\
    font-weight: bold;\
    font-size: 12px;\
    padding: 1px 5px;\
    margin-left: 5px;\
    text-decoration: none;\
  }",
".__GMredditsavers a:hover\
  {\
    background: #7CBA0F none repeat scroll 0 0;\
    color: #FFFFFF;\
    font-weight: bold;\
    padding: 1px 5px;\
    margin-left: 5px;\
    text-decoration: none;\
  }",
".__GMhatebusavers a\
  {\
    background: rgba(255,99,71,0.9) none repeat scroll 0 0;\
    color: #FFFFFF;\
    font-weight: bold;\
    font-size: 12px;\
    padding: 1px 5px;\
    margin-left: 5px;\
    text-decoration: none;\
  }",
".__GMhatebusavers a:hover\
  {\
    background: #7CBA0F none repeat scroll 0 0;\
    color: #FFFFFF;\
    font-weight: bold;\
    padding: 1px 5px;\
    margin-left: 5px;\
    text-decoration: none;\
  }",
".__GMfacebooksavers a\
  {\
    background: rgba(0,0,128,0.9) none repeat scroll 0 0;\
    color: #FFFFFF;\
    font-weight: bold;\
    font-size: 12px;\
    padding: 1px 5px;\
    margin-left: 5px;\
    text-decoration: none;\
  }",
".__GMfacebooksavers a:hover\
  {\
    background: #7CBA0F none repeat scroll 0 0;\
    color: #FFFFFF;\
    font-weight: bold;\
    padding: 1px 5px;\
    margin-left: 5px;\
    text-decoration: none;\
  }"
].join(''));
// GM_addStyle(<><![CDATA[
// .__GMsavers a
// {
// background: #3274D0 none repeat scroll 0 0;
// color: #FFFFFF;
// font-weight: bold;
// padding: 1px 5px;
// margin-left: 5px;
// text-decoration: none;
// }
// .__GMsavers a:hover
// {
// background: #7CBA0F none repeat scroll 0 0;
// color: #FFFFFF;
// font-weight: bold;
// padding: 1px 5px;
// margin-left: 5px;
// text-decoration: none;
// }
// .__GMtwisavers a
// {
// background: rgba(51,204,255,0.9) none repeat scroll 0 0;
// color: #FFFFFF;
// font-weight: bold;
// padding: 1px 5px;
// margin-left: 5px;
// text-decoration: none;
// }
// .__GMtwisavers a:hover
// {
// background: #7CBA0F none repeat scroll 0 0;
// color: #FFFFFF;
// font-weight: bold;
// padding: 1px 5px;
// margin-left: 5px;
// text-decoration: none;
// }
// ]]></>);

var USER_AGENT = "Mozilla/5.0 (compatible; Social bookmark Counter/0.9.1; +https://github.com/ikeikeikeike/social-bookmark-counter-on-google-search)"

// Monkey patch
Bookmarkhub['requester'] = function(options, callback) {
  GM_xmlhttpRequest({
    method: "GET",
    url: options.url,
    headers: {
      "User-Agent": USER_AGENT,
      "Accept": "text/xml"
    },
    onload: function(data) {
      try {
        callback($.parseJSON(data.responseText));
      } catch(e) {
        var receiveCount = function(o) {return o;},
            IN = {Tags: {Share: {handleCount: function(o) {return o;}}}};
        callback(eval(data.responseText));
      }
    }
  });
};


/**
 * Api requester.
 */
function requestApi(url, func) {
  GM_xmlhttpRequest({
    method: "GET",
    url: url,
    headers: {
      "User-Agent": USER_AGENT,
      "Accept": "text/xml"
    },
    onload: func
  });
}


/**
 * Render Html
 */
function renderHtml(link, total, url, className) {
  var span = document.createElement('span'),
      a = document.createElement('a');

  a.setAttribute('style', 'color: #FFF;');
  a.href = url;
  a.textContent = total;

  span.className = className;
  span.appendChild(a);

  try {
    // normal
    var s = link.parentNode.parentNode.getElementsByClassName('s')[0];
    var ss = link.parentNode.parentNode.parentNode.getElementsByClassName('s')[0];
    if (s) {
      var tonode = s.childNodes[0];
      tonode.parentNode.insertBefore(span, tonode.parentNode.firstChild);
    }
    else if (ss) {
      var tonode = ss.childNodes[0];
      tonode.parentNode.insertBefore(span, tonode.parentNode.firstChild);
    }
    else {
      link.parentNode.insertBefore(span, link.nextSibling);
    }
  } catch(e) {
    // console.log(e);
  }
}


/**
 * Delicious
 */
function deliCountView(link) {
  var bookmarker = new Bookmarkhub.Bookmarker(link.href);

  bookmarker.delicious()
    .done(function(data) {
      if (Number(data.count) > 0) {
        renderHtml(link, data.count, data.link, "__GMsavers");
      }
    })
    .fail(function(data) {
      // console.log(data);
    });
}


/**
 * 1. Tweetmeme is over. Thanks!!
 * #. Change Topsy API.
 * #. Change to native twitter API.  # Note: Exists, count bug.
 */
function twitterCountView(link) {
  var bookmarker = new Bookmarkhub.Bookmarker(link.href);

  bookmarker.twitter()
    .done(function(data) {
      if (Number(data.count) > 0) {
        renderHtml(link, data.count, data.link, "__GMtwisavers");
      }
    })
    .fail(function(data) {
      // console.log(data);
    });
}


/**
 * digg
 */
function diggCountView(link) {
  var url = "http://services.digg.com/1.0/endpoint?method=story.getAll&link=" + link.href + '&type=javascript&callback=crossdomain_res';

  requestApi(url, function(res) {
    var json,
        total;

    try {
      json = eval(res.responseText.replace('crossdomain_res', ''));
      total = json.stories[0].diggs;
      if (!json || !total) {
        return;
      }
    } catch (e) {
      // console.log(e);
      return;
    }

    renderHtml(link, total, json.stories[0].href, "__GMdiggsavers");
  });
}


/**
 * hatena bookmark
 */
function hatebuCountView(link) {
  var bookmarker = new Bookmarkhub.Bookmarker(link.href);

  bookmarker.hatena()
    .done(function(data) {
      if (Number(data.count) > 0) {
        renderHtml(link, data.count, data.link, "__GMhatebusavers");
      }
    })
    .fail(function(data) {
      // console.log(data);
    });
}


/**
 * facebook like button
 */
function facebookCountView(link) {
  var bookmarker = new Bookmarkhub.Bookmarker(link.href);

  bookmarker.facebook()
    .done(function(data) {
      if (Number(data.count) > 0) {
        renderHtml(link, data.count, 'https://developers.facebook.com/docs/reference/plugins/like/', "__GMfacebooksavers");
      }
    })
    .fail(function(data) {
      // console.log(data);
    });
}


/**
 * StumbleUpon
 */
function stumbleuponCountView(link) {
  var bookmarker = new Bookmarkhub.Bookmarker(link.href);

  bookmarker.stumbleupon()
    .done(function(data) {
      if (Number(data.count) > 0) {
        renderHtml(link, data.count, data.link, "__GMstumbleuponsavers");
      }
    })
    .fail(function(data) {
      // console.log(data);
    });
}

/**
 * reddit
 */
function redditCountView(link) {
  var bookmarker = new Bookmarkhub.Bookmarker(link.href);

  bookmarker.reddit()
    .done(function(data) {
      if (Number(data.count) > 0) {
        renderHtml(link, data.count, data.link, "__GMredditsavers");
      }
    })
    .fail(function(data) {
      // console.log(data);
    });
}

/**
 * http://nanoappli.com/blog/archives/768
 */
function asyncProcArray(params, onProcess, onFinish) {
  var paramList = params.concat();

  (function() {
    var slipNo = paramList.shift();

    onProcess( slipNo );
    if ( paramList.length <= 0 ) {
      onFinish();
      return;
    }

    setTimeout( arguments.callee, 100);
  })();
}


/**
 * http://nanoappli.com/blog/archives/768
 */
function runAcyncArray(params, onProcess, onFinish) {
  var paramList = params.concat();

  (function() {
    var startTime = new Date();

    while ( 1 ) {
      var curParam = paramList.shift();

      onProcess( curParam );

      if ( paramList.length <= 0 ) {
        onFinish( params );
        return;
      }

      if ( (new Date()) - startTime > 100 ) {
        break;
      }
    }
    setTimeout( arguments.callee, 40 );
  })();
}



// https://gist.github.com/BrockA/2625891/raw/waitForKeyElements.js
/*--- waitForKeyElements():  A utility function, for Greasemonkey scripts,
 that detects and handles AJAXed content.

 Usage example:

 waitForKeyElements (
   "div.comments"
   , commentCallbackFunction
 );

 //--- Page-specific function to do what we want when the node is found.
 function commentCallbackFunction (jNode) {
   jNode.text ("This comment changed by waitForKeyElements().");
 }

 IMPORTANT: This function requires your script to have loaded jQuery.
 */
function waitForKeyElements (
  selectorTxt,    /* Required: The jQuery selector string that
   specifies the desired element(s).
   */
  actionFunction, /* Required: The code to run when elements are
   found. It is passed a jNode to the matched
   element.
   */
  bWaitOnce,      /* Optional: If false, will continue to scan for
   new elements even after the first match is
   found.
   */
  iframeSelector  /* Optional: If set, identifies the iframe to
   search.
   */
) {
  var targetNodes, btargetsFound;

  if (typeof iframeSelector == "undefined")
    targetNodes     = $(selectorTxt);
  else
    targetNodes     = $(iframeSelector).contents ()
  .find (selectorTxt);

  if (targetNodes  &&  targetNodes.length > 0) {
    btargetsFound   = true;
    /*--- Found target node(s).  Go through each and act if they
     are new.
     */
    targetNodes.each ( function () {
      var jThis        = $(this);
      var alreadyFound = jThis.data ('alreadyFound')  ||  false;

      if (!alreadyFound) {
        //--- Call the payload function.
        var cancelFound     = actionFunction (jThis);
        if (cancelFound)
          btargetsFound   = false;
        else
          jThis.data ('alreadyFound', true);
      }
    } );
  }
  else {
    btargetsFound   = false;
  }

  //--- Get the timer-control variable for this selector.
  var controlObj      = waitForKeyElements.controlObj  ||  {};
  var controlKey      = selectorTxt.replace (/[^\w]/g, "_");
  var timeControl     = controlObj [controlKey];

  //--- Now set or clear the timer as appropriate.
  if (btargetsFound  &&  bWaitOnce  &&  timeControl) {
    //--- The only condition where we need to clear the timer.
    clearInterval (timeControl);
    delete controlObj [controlKey]
  }
  else {
    //--- Set a timer, if needed.
    if ( ! timeControl) {
      timeControl = setInterval ( function () {
        waitForKeyElements (    selectorTxt,
          actionFunction,
          bWaitOnce,
          iframeSelector
        );
      },
      300
    );
    controlObj [controlKey] = timeControl;
  }
}
waitForKeyElements.controlObj   = controlObj;
}


function main(doc) {
  // bookmarkcounter code below.
  var params = [];
  var n, l = doc.getElementsByClassName("r");
  var fin = function(params) {
    // console.log('finish: ' + params);
  }

  for(var i=0; i<l.length; i++) {
    n = l[i].childNodes.item(0);

    //hatebuCountView(n);
    // diggCountView(n);

    params.push(n);
  }

  asyncProcArray(params, hatebuCountView, fin);
  asyncProcArray(params, deliCountView, fin);
  asyncProcArray(params, facebookCountView, fin);
  asyncProcArray(params, twitterCountView, fin);
  asyncProcArray(params, stumbleuponCountView, fin);
  asyncProcArray(params, redditCountView, fin);
  // asyncProcArray(params, diggCountView, fin);
}


// For AutoPagerize
document.body.addEventListener('AutoPagerize_DOMNodeInserted', function(evt) {
  // console.log('AutoPagerize_DOMNodeInserted')
  main(evt.target);
});


///// Main

// For instant search result.
waitForKeyElements("#rso", function(jNode) {
  try{
    main(jNode[0]);
  } catch(e) {
    // console.log(e);
  }
});


})();