// ==UserScript==
// @name          Show Hatena Bookmark Comments
// @namespace     http://www.ne.jp/asahi/nanto/moon/
// @description   Show Hatena Bookmark's comments at the bottom of your browser.
// @include       http://*
// ==/UserScript==

/* Original Script: Hatena Bookmark Comments Viewer
 *   <http://worris.sakura.ne.jp/hbcview.html>
 *
 * Original Author: worris
 */

default xml namespace = "http://www.w3.org/1999/xhtml";

if (document.body && location.href == top.location.href) {
  GM_xmlhttpRequest({
    method: "GET",
    url: "http://b.hatena.ne.jp/entry/json/" +
         location.href.replace(/#/g, "%23"),
    onload: showHBComments
  });
}

function showHBComments(details) {
  document.getElementsByTagName("head")[0].appendChild(xml2dom(style));

  var entry = eval(details.responseText);
  var container =
    <div id="hb-comments-container"
         ondblclick="this.parentNode.removeChild(this);">
      <div class="hb-comments-marker">?B: { entry ? entry.count : 0 }</div>
    </div>;
  if (!entry) {
    container.@class = "hb-no-entry";
    document.body.appendChild(xml2dom(container));
    return;
  }

  var comments = <dl></dl>;
  for each (var bm in entry.bookmarks) {
    if (!bm.comment) continue;
    comments.* +=
      <>
        <dt>
          <a href={
            bm.timestamp.replace(/(\d{4})\/(\d{2})\/(\d{2}).*/,
                                 "http://b.hatena.ne.jp/" + bm.user +
                                 "/$1$2$3#bookmark-" + entry.eid)
          }>{ bm.user }</a>
        </dt>
        <dd>{ bm.comment }</dd>
      </>;
  }

  var commentRate = comments.dt.length() / entry.bookmarks.length;
  var panel =
    <div class="hb-comments-panel">
      <svg xmlns="http://www.w3.org/2000/svg" width="160" height="160">
        <circle cx="80" cy="80" r="70"/>
        <path d={
          "M 80,80 v -70 A 70,70 0 " + ((commentRate > 0.5) ? 1 : 0) + ",1 " +
          (80 + 70 * Math.cos(2 * Math.PI * (commentRate - 0.25))) + "," +
          (80 + 70 * Math.sin(2 * Math.PI * (commentRate - 0.25))) + " z"
        }/>
        <text x="80" y="80">
          &#12467;&#12513;&#12531;&#12488;&#29575;:
          { Math.round(100 * commentRate) }%
        </text>
      </svg>
    </div>;

  if (comments.*.length())
    panel.* += comments;
  container.* += panel;

  document.body.appendChild(xml2dom(container));
}

var style =
  <style type="text/css"><![CDATA[
    @namespace svg url(http://www.w3.org/2000/svg);
    #hb-comments-container {
      color:	#000;
      background:	#cef;
      font-size:	-moz-initial;
      font-family:	-moz-initial;
      line-height:	1.2;
      max-height:	50%;
      overflow:	auto;
      position:	fixed;
      right:	0;
      bottom:	0;
      opacity:	0.85;
    }
    #hb-comments-container:hover {
      width:	100%;
    }
    #hb-comments-container.hb-no-entry:hover {
      width:	auto;
    }
    #hb-comments-container * {
      color:	inherit;
      background:	transparent;
      font:	inherit;
      text-decoration:	none;
      text-align:	left;
      margin:	0;
      padding:	0;
      border:	none;
    }
    #hb-comments-container .hb-comments-marker {
      color:	#025;
      font-size:	0.9em;
      font-weight:	bold;
      padding:	3px 8px;
    }
    #hb-comments-container:hover .hb-comments-marker {
      display:	none;
    }
    #hb-comments-container.hb-no-entry:hover .hb-comments-marker {
      display:	block;
    }
    #hb-comments-container .hb-comments-panel {
      font-size:	0.9em;
      display:	none;
    }
    #hb-comments-container:hover .hb-comments-panel {
      display:	block;
    }
    #hb-comments-container.hb-no-entry:hover .hb-comments-panel {
      display:	none;
    }
    #hb-comments-container svg|svg {
      float:	left;
    }
    #hb-comments-container svg|circle {
      fill:	#dff;
      stroke:	#6cf;
      stroke-width:	2;
    }
    #hb-comments-container svg|path {
      fill:	#6cf;
      stroke:	none;
    }
    #hb-comments-container svg|text {
      text-anchor:	middle;
      dominant-baseline:	central;
    }
    #hb-comments-container .hb-comments-panel::after {
      content:	"";
      display:	block;
      clear:	left;
    }
    #hb-comments-container dl {
      padding:	10px 10px 10px 160px;
    }
    #hb-comments-container dt, #hb-comments-container dd {
      display:	inline;
    }
    #hb-comments-container dt::after {
      content:	": ";
    }
    #hb-comments-container dd::after {
      content:	"\a";
      white-space:	pre;
    }
    #hb-comments-container :link {
      color:	#00f;
      text-decoration:	underline;
    }
    #hb-comments-container :visited {
      color:	#707;
      text-decoration:	underline;
    }
  ]]></style>;

function xml2dom(xml) {
  if (typeof xml != "xml")
    return document.createTextNode(xml);

  var isSingleElement = (xml.length() == 1 && xml.nodeKind() == "element");
  if (!isSingleElement)
    xml = <root/>.appendChild(xml);

  var xmlString = xml.toXMLString();
  var doc = new DOMParser().parseFromString(xmlString, "application/xml");
  var root = document.importNode(doc.documentElement, true);

  if (isSingleElement) return root;

  var range = document.createRange();
  range.selectNodeContents(root);
  return range.cloneContents();
}
