social-bookmark-counter-on-google-search

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

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 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);
  }
});


})();