// ==UserScript==
// @name          SBM Comments Viewer And Access-log x SBM
// @namespace     http://libelabo.jp/greasemonkey
// @description	  Show social bookmark's comments at the bottom of your browser. And Your Access-log meets Social Bookmarkers. (Thanks to http://white.s151.xrea.com/wiki/index.php?script/SBMCommentsViewer )
// @include       http://*
// @exclude       *.js
// @exclude       *.txt
// @exclude       *.css
// @exclude       *.py
// @exclude       *.rb
// @exclude       *.pl
// @exclude       *.el
// @exclude       *.l
// @version       0.11
// ==/UserScript==

(function() {
    // Shortcut key
    // C -- control
    // S -- shift
    // A -- alt
    var BIND_KEY = 'A-c';

    // true  : JSONP
    // false : RSS
    var hatena_use_jsonp = true;

    // --------------------------------------------------------------
    // ignore user
    // --------------------------------------------------------------
    var ignore_hatena = [];
    var ignore_delicious = [];
    var ignore_livedoor = [];
    var ignore_ecnavi = [];
    var ignore_pookmark = [];

    // --------------------------------------------------------------
    // CSS
    // --------------------------------------------------------------
    var font_css = "font-size:100%; color:#333333;";
    var back_css = "background-image:none; background-color:white; opacity:0.90;";
    var comment_height = 250;
    var option_height = 80;
    // for comment area
    var comment_area_css = "left:20px; right:0px; bottom:0px; text-align:left; position:fixed; z-index:100;"
      +"height:" + comment_height + "px;"
        + "margin:0px; padding:0px;"
          + back_css + font_css;

    // for comment
    var comment_css = "position:relative; bottom:0px; border: 1px solid #999999; overflow:auto; margin:0px;"
      +"height:" + comment_height + "px;"
        + back_css + font_css;

    // for count
    var count_css = "position:absolute; text-align:right; right:0px; position:absolute; border:1px solid #999999;"
      +"top:-" + (option_height-2) + "px;"
        + back_css + font_css
          + "opacity:0.6";

    // for count(number)
    var number_css = "font-weight:bold;";

    // for options
    var option_css = "left:0px; right:0px; position:absolute; border:1px solid #999999; margin:0px; border-bottom:0; line-height:110%;"
      +"height:" + option_height + "px;"
        +"top:-" + option_height + "px;"
          + back_css + font_css;

    // for stress text of option
    var option_text_css = "font-weight:bold; text-decoration:underline;";

    // for anchor
    var anchor_css = "font-size:100%; color:blue; text-decoration:none;";
    + back_css;

    // for mini mode
    var mini_css = "right:0px; bottom:0px; text-align:right; position:fixed; overflow:auto; z-index:100;"
      + back_css + font_css
        + "padding-left:10px; padding-right:10px; border-top: 1px solid #666666; border-left: 1px solid #666666;";

    // tag cloud
    var tag_cloud_min_size = 15;
    var tag_cloud_max_size = 50;

    if (self.location.href!=top.location.href) return;
    var uri = top.location.href.replace(/#/g, '%23');
    var firefox;
    var w;
    if(typeof unsafeWindow != 'undefined'){
        // firefox
        firefox = true;
        w = unsafeWindow;
    }else {
        // not firefox
        firefox = false;
        w = window;
    }
    var option = new Option();
    var comment_area = new CommentArea();
    var is_load = false;

    // --------------------------------------------------------------
    // Comment Area
    // --------------------------------------------------------------
    function CommentArea (show) {
        this.comments = [];
        this.comments_no_dup = false;
        var counts = [];
        this.id = 'SBMCommentsViewerArea';
        this.div = document.createElement('div');
        this.div.setAttribute('id', this.id);
        this.div.setAttribute('style', comment_area_css + 'display:none;');
        this.div.addEventListener("dblclick", function(){comment_area.hide()}, false);
        document.body.appendChild(this.div);

        this.id_option = 'SBMoptionsViewerOptionArea';
        this.option = document.createElement('div');
        this.option.setAttribute('id', this.id_option);
        this.option.setAttribute('style', option_css);
        this.div.appendChild(this.option);

        this.id_panel = 'SBMCommentsViewerCommentArea';
        this.comment = document.createElement('ol');
        this.panel = document.createElement('div');
        this.panel.setAttribute('style', comment_css);
        this.panel.setAttribute('id', this.id_panel);
        this.div.appendChild(this.panel);

        this.id_count = 'SBMCommentsViewerCountArea';
        this.count = document.createElement('div');
        this.count.setAttribute('id', this.id_count);
        this.count.setAttribute('style', count_css);
        this.count_opacity = this.count.style.opacity;
        this.count.addEventListener("mouseover", function(){
            this.style.opacity = '1.0';
        }, false);
        this.count.addEventListener("mouseout", function(){
            this.style.opacity = comment_area.count_opacity;
        }, false);
        this.div.appendChild(this.count);

        this.id_mini = 'SBMCommentsViewerMini';
        this.mini = document.createElement('div');
        this.mini.setAttribute('id', this.id_mini);
        this.mini.setAttribute('style', mini_css + 'display:none');
        this.mini.addEventListener("mouseover", function(){comment_area.show()}, false);
        document.body.appendChild(this.mini);

        CommentArea.prototype.show = function (reset) {
            loadSBM();
            this.getOption();
            if(reset) this.init(false);
            if(this.mini.style.display != 'none')
              this.mini.style.display = 'none';
            if(this.div.style.display != 'block')
              this.div.style.display = 'block';
        }
        CommentArea.prototype.hide = function () {
            if(this.mini.style.display != 'block')
              this.mini.style.display = 'block';
            if(this.div.style.display != 'none')
              this.div.style.display = 'none';
        }
        CommentArea.prototype.toggle = function () {
            if(this.div.style.display == 'none'){
                this.show();
            }else{
                this.hide();
            }
        }
        CommentArea.prototype.init = function (_type) {
            var types = [];
            for(var property in this.comments) {
                types.push(property);
            }
            if(option.show_type == "Comment"){
                this.initComment(_type, types);
            }else if(option.show_type == "TagCloud"){
                this.initTagCloud(_type, types);
            }else {
				this.initHistory(_type, types);
			}
        }
        CommentArea.prototype.initTagCloud = function (_type, types) {
            var tagcloud;
            if(!_type && this.tagcloud){
                tagcloud = this.tagcloud;
            }else{
                var tags = [];
                var min;
                var max;
                var cmts = this.getUniqueUser(_type, types);
                for(var i=0; i<cmts.length; i++){
                    var comment = cmts[i];
                    if(comment){
                        for(var k=0; k<comment.tags.length; k++){
                            if(tags[comment.tags[k].toLowerCase()]){
                                tags[comment.tags[k].toLowerCase()]++;
                            }else{
                                tags[comment.tags[k].toLowerCase()] = 1;
                            }
                        }
                    }
                }
                for(var tag in tags){
                    var count = tags[tag];
                    if(!min && !max){
                        min = count;
                        max = count;
                    }
                    if(count != 0 && min>count){
                        min = count;
                    }
                    if(count !=0 && max<count){
                        max = count;
                    }
                }
                tagcloud = new TagCloud(tags, min, max);
                if(!_type){
                    this.tagcloud = tagcloud;
                }
            }
            this.panel.innerHTML = '';
            this.panel.appendChild(tagcloud.getHTML());
        }
        CommentArea.prototype.initComment = function (_type, types) {
            this.panel.innerHTML = '';
            this.comment.innerHTML = '';
            var text = "";
            var cmts = [];
            if(option.remove_multipost) {
                cmts = this.getUniqueUser(_type, types);
            }else{
                for(var i=0; i<types.length; i++){
                    cmts = cmts.concat(this.comments[types[i]].filter(function(c){
                        return c.isNotIgnore();
                    }));
                }
            }
            switch(option.sort_type) {
              case "SBMAsc":
                cmts.sort(function(a,b){return (a.href > b.href) ? 1 : -1;});
                break;
              case "SBMDesc":
                cmts.sort(function(a,b){return (a.href > b.href) ? -1 : 1;});
                break;
              case "DateAsc":
                cmts.sort(function(a,b){return a.date-b.date;});
                break;
              case "DateDesc":
                cmts.sort(function(a,b){return b.date-a.date;});
                break;
              case "UserAsc":
                cmts.sort(function(a,b){return (a.user > b.user) ? 1 : -1;});
                break;
              case "UserDesc":
                cmts.sort(function(a,b){return (a.user > b.user) ? -1 : 1;});
                break;
            }
            for(var a=0; a<cmts.length; a++){
                text += cmts[a].getHTML();
            }
            this.comment.innerHTML += text;
            this.panel.appendChild(this.comment);
        }
        CommentArea.prototype.getUniqueUser = function(_type, types){
            var cmts = [];
            if(!_type && this.comments_no_dup){
                cmts = this.comments_no_dup;
            }else{
                while(types.length > 0) {
                    var type = types.shift();
                    for(var i=0; i<this.comments[type].length; i++) {
                        var flag = true;
                        var comment1 = this.comments[type][i];
                        if(comment1 && comment1.isNotIgnore()) {
                            var user = comment1.user.toLowerCase();
                            var cmnt = comment1.comment;
                            var y = comment1.date.getFullYear();
                            var m = comment1.date.getMonth();
                            var d = comment1.date.getDate();
                            for(var j=0; j<types.length; j++) {
                                for(var k=0; k<this.comments[types[j]].length; k++){
                                    var comment2 = this.comments[types[j]][k];
                                    if(comment2){
                                        var date = comment2.date;
                                        if(user == comment2.user.toLowerCase() && cmnt == comment2.comment){
                                            if(y == date.getFullYear() && m == date.getMonth() && d == date.getDate()) {
                                                flag = false;
                                                k = this.comments[types[j]].length;
                                                j = types.length;
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                            if(flag){
                                cmts.push(comment1);
                            }
                        }
                    }
                }
                if(!_type){
                    this.comments_no_dup = cmts;
                }
            }
            return cmts;
        }
        CommentArea.prototype.getOption = function() {
            this.option.innerHTML = ''
              this.option.appendChild(option.getHTML());
        }
        CommentArea.prototype.addCount = function (count, image, link) {
            var c = new Count(count, image, link);
            counts.push(c);
            this.count.innerHTML += c.getHTML();
            this.mini.innerHTML += c.getMiniHTML();
        }
        CommentArea.prototype.addComments = function (type ,comments) {
            this.comments[type] = comments;
        }
        CommentArea.prototype.hist_user_key = "histusers";
        CommentArea.prototype.hist_tag_key = "histtags";
        CommentArea.prototype.initHistory = function (_type, types) {
			var historycloud;
			if(!_type && this.historycloud && this.historycloud.history_type && this.historycloud.history_type == option.history_type ){
				historycloud = this.historycloud;
			} else {
				var tags = {};
				var decodedtags = {};
				var min;
				var max;
				
				switch(option.history_type) {
					case "User" :
						tags = eval("("+GM_getValue(this.hist_user_key)+")") || {};
						break;
					case "Tag" :
						tags = eval("("+GM_getValue(this.hist_tag_key)+")") || {};
						break;
				}
				for(var tag in tags){
					decodedtags[decodeURIComponent(tag)] = tags[tag];
				}
				tags = decodedtags;
				for(var tag in tags){
					var count = tags[tag];
					if(!min && !max){
						min = count;
						max = count;
					}
					if(count != 0 && min>count){
						min = count;
					}
					if(count !=0 && max<count){
						max = count;
					}
					var decodedtag = decodeURIComponent(tag);
					tag = decodedtag;
				}
				historycloud = new TagCloud(tags, min, max);
				historycloud.history_type = option.history_type;
				if(!_type){
					this.historycloud = historycloud;
				}
			}
			this.panel.innerHTML = '';
			this.panel.appendChild(historycloud.getHTML());
		}
		CommentArea.prototype.setHistory = function (comments) {
			var histusers = eval("("+GM_getValue("histusers")+")") || {};
			var histtags = eval("("+GM_getValue(this.hist_tag_key)+")") || {};
			
			for(var i=0; i<comments.length; i++ ){
				comment = comments[i];
				user = comment.user;
				switch (comment.sbm) {   // "hatena" "delicious" "livedoor" "ecnavi" "pookmark"
					case "hatena" :
						user = "h:"+user;
						break;
					case "delicious" :
						user = "d:"+user;
						break;
					case "livedoor" :
						user = "l:"+user;
						break;
					case  "ecnavi" :
						user = "e:"+user;
						break;
					case "pookmark" :
						user = "p:"+user;
						break;
				}
				tags = comment.tags;
				
				( histusers[user] ) ? histusers[user]++ : histusers[user] = 1;
				for(var j=0; j<tags.length; j++ ){
					var encodedTag = encodeURIComponent(tags[j]);
					( histtags[encodedTag] ) ? histtags[encodedTag]++ : histtags[encodedTag] = 1;
				}
			}
			GM_setValue(this.hist_user_key, histusers.toSource());
			GM_setValue(this.hist_tag_key, histtags.toSource());
			GM_setValue("clear_history", false);
		}
        return this;
    }
    // --------------------------------------------------------------
    // Option
    // --------------------------------------------------------------
    function Option() {
        // "Comment" or "TagCloud"
        this.show_type = (typeof GM_getValue("show_type") != 'undefined') ? GM_getValue("show_type"): "Comment";
        this.show_types = ["Comment", "TagCloud", "History"];
        this.remove_multipost = (typeof GM_getValue("remove_multipost") != 'undefined') ? GM_getValue("remove_multipost"): true;
        this.sort_type = (typeof GM_getValue("sort_type") != 'undefined') ? GM_getValue("sort_type"): 'SBMAsc';
        this.sort_types = ['SBMAsc', 'SBMDesc', 'DateAsc', 'DateDesc', 'UserAsc', 'UserDesc'];
        this.tag_sort_type = (typeof GM_getValue("tag_sort_type") != 'undefined') ? GM_getValue("tag_sort_type"): 'NumberDesc';
        this.tag_sort_types = ['NumberAsc', 'NumberDesc', 'NameAsc', 'NameDesc'];
        this.history_type = (typeof GM_getValue("history_type") != 'undefined') ? GM_getValue("history_type"): 'NumberDesc';
        this.history_types = ['User', 'Tag'];
        this.show_tag = (typeof GM_getValue("show_tag") != 'undefined') ? GM_getValue("show_tag"): true;
        this.show_nocomment = (typeof GM_getValue("show_nocomment") != 'undefined') ? GM_getValue("show_nocomment"): true;
        this.auto_start = (typeof GM_getValue("auto_start") != 'undefined') ? GM_getValue("auto_start"): true;
        this.auto_start_open = (typeof GM_getValue("auto_start_open") != 'undefined') ? GM_getValue("auto_start_open"): false;

        Option.prototype.setShowType = function(arg){
            this.show_type = arg;
            GM_setValue("show_type", this.show_type);
            comment_area.show(true);
        }
        Option.prototype.setShowTag = function(arg){
            this.show_tag = arg;
            GM_setValue("show_tag", this.show_tag);
            comment_area.show(true);
        }
        Option.prototype.setShowNoComment = function(arg){
            this.show_nocomment = arg;
            GM_setValue("show_nocomment", this.show_nocomment);
            comment_area.show(true);
        }
        Option.prototype.setSort = function(arg){
            this.sort_type = arg;
            GM_setValue("sort_type", this.sort_type);
            comment_area.show(true);
        }
        Option.prototype.setRemoveMultipost = function(arg){
            this.remove_multipost = arg;
            GM_setValue("remove_multipost", this.sort_type);
            comment_area.show(true);
        }
        Option.prototype.setAutoStart = function(arg){
            this.auto_start = arg;
            GM_setValue("auto_start", this.auto_start);
            comment_area.show(true);
        }
        Option.prototype.setAutoStartOpen = function(arg){
            this.auto_start_open = arg;
            GM_setValue("auto_start_open", this.auto_start_open);
            comment_area.show(true);
        }
        Option.prototype.setTagSort = function(arg){
            this.tag_sort_type = arg;
            GM_setValue("tag_sort_type", this.tag_sort_type);
            comment_area.show(true);
        }
		Option.prototype.setHistory = function(arg){
			this.history_type = arg;
			GM_setValue("history_type", this.history_type);
			comment_area.show(true);
		}
		Option.prototype.setClearHistory = function(arg){
			this.clear_history = arg;
			GM_setValue("clear_history", this.clear_history);
			var emptytags = {};
			GM_setValue(comment_area.hist_user_key, emptytags.toSource());
			GM_setValue(comment_area.hist_tag_key, emptytags.toSource());
			comment_area.show(true);
		}
        Option.prototype.getHTML = function() {
            var ul = document.createElement('ul');
            ul.setAttribute('style', 'list-style: none; margin: 10px;');

            var li_option = document.createElement('li');
            ul.appendChild(li_option);
            // Comment , TagCloud or History
            var a_type = document.createElement('a');
            for(var i=0; i<this.show_types.length; i++){
                if(this.show_types[i] == this.show_type) {
                    var span_type = document.createElement('span');
                    span_type.innerHTML = this.show_types[i];
                    span_type.setAttribute('style', option_text_css);
                    li_option.appendChild(span_type);
                }else{
                    var a_type = document.createElement('a');
                    a_type.setAttribute('href', "javascript:void(0)");
                    a_type.setAttribute('style', anchor_css);
                    a_type.innerHTML = this.show_types[i];
                    a_type.addEventListener("click", function(){option.setShowType(this.innerHTML)}, false);
                    li_option.appendChild(a_type);
                }
                li_option.appendChild(document.createTextNode(" / "));
            }
            // auto start
            var a_as = document.createElement('a');
            a_as.setAttribute('href', "javascript:void(0)");
            a_as.setAttribute('style', anchor_css + ((this.auto_start) ? option_text_css : ''));
            a_as.innerHTML = "Auto start";
            if(this.auto_start){
                a_as.addEventListener("click", function(){option.setAutoStart(false)}, false);
            }else{
                a_as.addEventListener("click", function(){option.setAutoStart(true)}, false);
            }
            li_option.appendChild(a_as);
            li_option.appendChild(document.createTextNode(" "));
            if(this.auto_start){
                // auto start open
                var a_aso = document.createElement('a');
                a_aso.setAttribute('href', "javascript:void(0)");
                a_aso.setAttribute('style', anchor_css + ((this.auto_start_open) ? option_text_css : ''));
                a_aso.innerHTML = "(Open)";
                if(this.auto_start_open){
                    a_aso.addEventListener("click", function(){option.setAutoStartOpen(false)}, false);
                }else{
                    a_aso.addEventListener("click", function(){option.setAutoStartOpen(true)}, false);
                }
                li_option.appendChild(a_aso);
                li_option.appendChild(document.createTextNode(" "));
            }
            li_option.appendChild(document.createTextNode("/ "));
            if(this.show_type == "Comment") {
                // sort
                var li_sort = document.createElement('li');
                for(var i=0; i<this.sort_types.length; i++){
                    if(this.sort_types[i] == this.sort_type) {
                        var span_sort = document.createElement('span');
                        span_sort.innerHTML = this.sort_types[i];
                        span_sort.setAttribute('style', option_text_css);
                        li_sort.appendChild(span_sort);
                    }else{
                        var a_sort = document.createElement('a');
                        a_sort.setAttribute('href', "javascript:void(0)");
                        a_sort.setAttribute('style', anchor_css);
                        a_sort.innerHTML = this.sort_types[i];
                        a_sort.addEventListener("click", function(){option.setSort(this.innerHTML)}, false);
                        li_sort.appendChild(a_sort);
                    }
                    if(i+1<this.sort_types.length) {
                        li_sort.appendChild(document.createTextNode(" / "));
                    }
                }
                ul.appendChild(li_sort);
                var li_comment_option = document.createElement('li');
                ul.appendChild(li_comment_option);
                // multiposter
                var a_multi = document.createElement('a');
                a_multi.setAttribute('href', "javascript:void(0)");
                a_multi.setAttribute('style', anchor_css + ((!this.remove_multipost) ? option_text_css : ''));
                a_multi.innerHTML = "Multi poster" ;
                if(this.remove_multipost){
                    a_multi.addEventListener("click", function(){option.setRemoveMultipost(false)}, false);
                }else{
                    a_multi.addEventListener("click", function(){option.setRemoveMultipost(true)}, false);
                }
                li_comment_option.appendChild(a_multi);
                li_comment_option.appendChild(document.createTextNode(" / "));
                // tag
                var a_tag = document.createElement('a');
                a_tag.setAttribute('href', "javascript:void(0)");
                a_tag.setAttribute('style', anchor_css + ((this.show_tag) ? option_text_css : ''));
                a_tag.innerHTML = "Tag";
                if(this.show_tag){
                    a_tag.addEventListener("click", function(){option.setShowTag(false)}, false);
                }else{
                    a_tag.addEventListener("click", function(){option.setShowTag(true)}, false);
                }
                li_comment_option.appendChild(a_tag);
                li_comment_option.appendChild(document.createTextNode(" / "));
                // no commenter
                var a_com = document.createElement('a');
                a_com.setAttribute('href', "javascript:void(0)");
                a_com.setAttribute('style', anchor_css + ((this.show_nocomment) ? option_text_css : ''));
                a_com.innerHTML = "No commenter";
                if(this.show_nocomment){
                    a_com.addEventListener("click", function(){option.setShowNoComment(false)}, false);
                }else{
                    a_com.addEventListener("click", function(){option.setShowNoComment(true)}, false);
                }
                li_comment_option.appendChild(a_com);
            }else if(this.show_type == "TagCloud"){
                // sort
                var li_tag_sort = document.createElement('li');
                for(var i=0; i<this.tag_sort_types.length; i++){
                    if(this.tag_sort_types[i] == this.tag_sort_type) {
                        var span_tag_sort = document.createElement('span');
                        span_tag_sort.innerHTML = this.tag_sort_types[i];
                        span_tag_sort.setAttribute('style', option_text_css);
                        li_tag_sort.appendChild(span_tag_sort);
                    }else{
                        var a_tag_sort = document.createElement('a');
                        a_tag_sort.setAttribute('href', "javascript:void(0)");
                        a_tag_sort.setAttribute('style', anchor_css);
                        a_tag_sort.innerHTML = this.tag_sort_types[i];
                        a_tag_sort.addEventListener("click", function(){option.setTagSort(this.innerHTML)}, false);
                        li_tag_sort.appendChild(a_tag_sort);
                    }
                    if(i+1<this.tag_sort_types.length){
                        li_tag_sort.appendChild(document.createTextNode(" / "));
                    }
                }
                ul.appendChild(li_tag_sort);
            }else if(this.show_type == "History"){
				var li_history = document.createElement('li');
				for(var i=0; i<this.history_types.length; i++){
					if(this.history_types[i] == this.history_type) {
						var span_history = document.createElement('span');
						span_history.innerHTML = this.history_types[i];
						span_history.setAttribute('style', option_text_css);
						li_history.appendChild(span_history);
					} else{
						var a_history = document.createElement('a');
						a_history.setAttribute('href', "javascript:void(0)");
						a_history.setAttribute('style', anchor_css);
						a_history.innerHTML = this.history_types[i];
						a_history.addEventListener("click", function(){option.setHistory(this.innerHTML)}, false);
						li_history.appendChild(a_history);
					}
					if(i+1<this.history_types.length){
						li_history.appendChild(document.createTextNode(" / "));
					}
				}
				li_history.appendChild(document.createTextNode(" / "));
				var a_ch = document.createElement('a');
				a_ch.setAttribute('href', "javascript:void(0)");
				a_ch.setAttribute('style', anchor_css );
				a_ch.innerHTML = "Clear History";
				if(!this.clear_history){
					a_ch.addEventListener("click", function(){option.setClearHistory(true)}, false);
					li_history.appendChild(a_ch);
					li_history.appendChild(document.createTextNode(" "));
					li_history.appendChild(document.createTextNode("/ "));
				}
				ul.appendChild(li_history);
                var li_tag_sort = document.createElement('li');
                for(var i=0; i<this.tag_sort_types.length; i++){
                    if(this.tag_sort_types[i] == this.tag_sort_type) {
                        var span_tag_sort = document.createElement('span');
                        span_tag_sort.innerHTML = this.tag_sort_types[i];
                        span_tag_sort.setAttribute('style', option_text_css);
                        li_tag_sort.appendChild(span_tag_sort);
                    }else{
                        var a_tag_sort = document.createElement('a');
                        a_tag_sort.setAttribute('href', "javascript:void(0)");
                        a_tag_sort.setAttribute('style', anchor_css);
                        a_tag_sort.innerHTML = this.tag_sort_types[i];
                        a_tag_sort.addEventListener("click", function(){option.setTagSort(this.innerHTML)}, false);
                        li_tag_sort.appendChild(a_tag_sort);
                    }
                    if(i+1<this.tag_sort_types.length){
                        li_tag_sort.appendChild(document.createTextNode(" / "));
                    }
                }
                ul.appendChild(li_tag_sort);
			}
            return ul;
        }
        return this;
    }
    // --------------------------------------------------------------
    // Count
    // --------------------------------------------------------------
    function Count(count, image, link) {
        this.count = count;
        this.image = image;
        this.link  = link;
        Count.prototype.getHTML = function(){
            var s = (this.count>1) ? "s" : " ";
            return '<a href="' + this.link + '" style="' + anchor_css + '"><span style="'
              + number_css + '">' + this.count + '</span> user' + s +'</a> <img src="' + this.image + '"/><br/>';
        }
        Count.prototype.getMiniHTML = function(){
            return '<img src="' + this.image + '"/>:<span style="' + number_css + '">' + this.count + '</span> ';
        }
        return this;
    }

    // --------------------------------------------------------------
    // Tag Cloud
    // --------------------------------------------------------------
    function TagCloud(_tags, _min, _max){
        this.tags = _tags;
        this.count_min = _min;
        this.count_max = _max;
        this.size_min = tag_cloud_min_size;
        this.size_max = tag_cloud_max_size;
        this.keys = [];
        for(var tag in this.tags){
            this.keys.push(tag);
        }
        TagCloud.prototype.calc = function(count) {
            return (this.size_max - this.size_min) * (count - this.count_min) /
              (this.count_max - this.count_min) + this.size_min;
        }
        TagCloud.prototype.getHTML = function(){
            var div = document.createElement('div');
            var tags = this.tags;
            switch(option.tag_sort_type) {
              case "NumberAsc":
                this.keys.sort(function(a,b){return tags[a]-tags[b]});
                break;
              case "NumberDesc":
                this.keys.sort(function(a,b){return tags[b]-tags[a]});
                break;
              case "NameAsc":
                this.keys.sort(function(a,b){return (a > b) ? 1 : -1;});
                break;
              case "NameDesc":
                this.keys.sort(function(a,b){return (a > b) ? -1 : 1;});
                break;
            }
            for(var i=0; i<this.keys.length; i++){
                tag = this.keys[i];
                var span = document.createElement('span');
                span.setAttribute('style', "font-size:" + this.calc(this.tags[tag]) + "px;");
				if( option.show_type == "History" && option.history_type == "User" ){
					sbm = tag.split(":")[0];
					user = tag.split(":")[1];
					var url;
					var image;
					switch (sbm) {
						case "h" :
							url = "http://b.hatena.ne.jp/"+user+"/";
							image = 'http://www.hatena.ne.jp/users/' + user.substring(0, 2) + '/' + user + '/profile_s.gif';
							break;
						case "d" :
							url = "http://del.icio.us/"+user+"/";
							image = "http://del.icio.us/favicon.ico";
							break;
						case "l" :
							url = "http://clip.livedoor.com/clips/"+user+"/";
							image = "http://clip.livedoor.com/favicon.ico"
							break;
						case "e" :
							url = "http://news.ecnavi.jp/user/"+user+"/";
							image = 'http://cdn.news.ecnavi.jp/user/' + user + '/photo';
							break;
						case "p" :
							url = "http://pookmark.jp/user/"+user+"/";
							image = "http://pookmark.jp/images/profileicon/16/1.gif";
							break;
					}
					
					span.innerHTML = '<a href="'+ url + '" target="_blank" style="text-decoration: none; "><img src="'+ image +'" width="12px" heigth="12px" border="0"/> ' + user +'</a>';
				} else {
	                span.innerHTML = tag;
				}
                div.appendChild(span);
                div.appendChild(document.createTextNode("(" + this.tags[tag] + ") "));
            }
            return div;
        }
    }

    // --------------------------------------------------------------
    // MD5
    // http://www.onicos.com/staff/iz/amuse/javascript/expert/md5.txt
    // --------------------------------------------------------------
    /* md5.js - MD5 Message-Digest
     * Copyright (C) 1999,2002 Masanao Izumo <iz@onicos.co.jp>
     * Version: 2.0.0
     * LastModified: May 13 2002
     *
     * This program is free software.  You can redistribute it and/or modify
     * it without any warranty.  This library calculates the MD5 based on RFC1321.
     * See RFC1321 for more information and algorism.
     */
    var MD5_T = new Array(0x00000000, 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391);
    var MD5_round1 = new Array(new Array( 0, 7, 1), new Array( 1,12, 2), new Array( 2,17, 3), new Array( 3,22, 4), new Array( 4, 7, 5), new Array( 5,12, 6), new Array( 6,17, 7), new Array( 7,22, 8), new Array( 8, 7, 9), new Array( 9,12,10), new Array(10,17,11), new Array(11,22,12), new Array(12, 7,13), new Array(13,12,14), new Array(14,17,15), new Array(15,22,16));
    var MD5_round2 = new Array(new Array( 1, 5,17), new Array( 6, 9,18), new Array(11,14,19), new Array( 0,20,20), new Array( 5, 5,21), new Array(10, 9,22), new Array(15,14,23), new Array( 4,20,24), new Array( 9, 5,25), new Array(14, 9,26), new Array( 3,14,27), new Array( 8,20,28), new Array(13, 5,29), new Array( 2, 9,30), new Array( 7,14,31), new Array(12,20,32));
    var MD5_round3 = new Array(new Array( 5, 4,33), new Array( 8,11,34), new Array(11,16,35), new Array(14,23,36), new Array( 1, 4,37), new Array( 4,11,38), new Array( 7,16,39), new Array(10,23,40), new Array(13, 4,41), new Array( 0,11,42), new Array( 3,16,43), new Array( 6,23,44), new Array( 9, 4,45), new Array(12,11,46), new Array(15,16,47), new Array( 2,23,48));
    var MD5_round4 = new Array(new Array( 0, 6,49), new Array( 7,10,50), new Array(14,15,51), new Array( 5,21,52), new Array(12, 6,53), new Array( 3,10,54), new Array(10,15,55), new Array( 1,21,56), new Array( 8, 6,57), new Array(15,10,58), new Array( 6,15,59), new Array(13,21,60), new Array( 4, 6,61), new Array(11,10,62), new Array( 2,15,63), new Array( 9,21,64));
    function MD5_F(x,y,z){return (x&y)|(~x&z);}
    function MD5_G(x,y,z){return (x&z)|(y&~z);}
    function MD5_H(x,y,z){return x^y^z;}
    function MD5_I(x,y,z){return y^(x|~z);}
    var MD5_round=new Array(new Array(MD5_F, MD5_round1), new Array(MD5_G, MD5_round2), new Array(MD5_H, MD5_round3), new Array(MD5_I, MD5_round4));
    function MD5_pack(n32){return String.fromCharCode(n32 & 0xff)+String.fromCharCode((n32>>>8)&0xff)+String.fromCharCode((n32>>>16)&0xff)+String.fromCharCode((n32>>>24)&0xff);}
    function MD5_unpack(s4){return s4.charCodeAt(0)|(s4.charCodeAt(1)<<8)|(s4.charCodeAt(2)<<16)|(s4.charCodeAt(3)<<24);}
    function MD5_number(n){while(n<0)n+=4294967296;while(n>4294967295)n-=4294967296;return n;}
    function MD5_apply_round(x,s,f,abcd,r){var a,b,c,d;var kk,ss,ii;var t,u;a=abcd[0];b=abcd[1];c=abcd[2];d=abcd[3];kk=r[0];ss=r[1];ii=r[2];u=f(s[b],s[c],s[d]);t=s[a]+u+x[kk]+MD5_T[ii];t=MD5_number(t);t=((t<<ss)|(t>>>(32-ss)));t+=s[b];s[a]=MD5_number(t);}
    function MD5_hash(data){var abcd,x,state,s;var len,index,padLen,f,r;var i,j,k;var tmp;state = new Array(0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476);len=data.length;index=len&0x3f;padLen=(index<56)?(56-index):(120-index);if(padLen>0){data+="\x80";for(i=0;i<padLen-1;i++)data+="\x00";}data+=MD5_pack(len*8);data+=MD5_pack(0);len+=padLen+8;abcd=new Array(0,1,2,3);x=new Array(16);s=new Array(4);for(k=0;k<len;k+=64){for(i=0,j=k;i<16;i++,j+=4){x[i] = data.charCodeAt(j)|(data.charCodeAt(j+1)<<8)|(data.charCodeAt(j+2)<<16)|(data.charCodeAt(j+3)<<24);}for(i=0;i<4;i++)s[i]=state[i];for(i=0;i<4;i++){f=MD5_round[i][0];r=MD5_round[i][1];for(j=0;j<16;j++){MD5_apply_round(x,s,f,abcd,r[j]);tmp=abcd[0];abcd[0]=abcd[3];abcd[3]=abcd[2];abcd[2]=abcd[1];abcd[1]=tmp;}}for(i=0;i<4;i++){state[i]+=s[i];state[i]=MD5_number(state[i]);}}return MD5_pack(state[0])+MD5_pack(state[1])+MD5_pack(state[2])+MD5_pack(state[3]);}
    function MD5_hexhash(data){var i,out,c;var bit128;bit128=MD5_hash(data);out="";for(i=0;i<16;i++){c=bit128.charCodeAt(i);out+="0123456789abcdef".charAt((c>>4) & 0xf);out+="0123456789abcdef".charAt(c & 0xf);}return out;}

    // --------------------------------------------------------------
    // Comment
    // --------------------------------------------------------------
    function Comment (user, image, href, tags, comment, date, tag_base, sbm) {
        this.user     = user;
        this.image    = image;
        this.href     = href;
        this.tags     = tags;
        this.comment  = comment;
        this.date     = date;
        this.tag_base = tag_base;
        this.sbm      = sbm;// "hatena" "delicious" "livedoor" "ecnavi" "pookmark"
        this.ignore   = [];
        this.ignore["hatena"] = ignore_hatena;
        this.ignore["delicious"] = ignore_delicious;
        this.ignore["livedoor"] = ignore_livedoor;
        this.ignore["ecnavi"] = ignore_ecnavi;
        this.ignore["pookmark"] = ignore_pookmark;
        Comment.prototype.isNotIgnore = function(){
            var res = true;
            for(var i=0; i<this.ignore[this.sbm].length; i++){
                if(this.ignore[this.sbm][i].toLowerCase() == this.user.toLowerCase()){
                    res = false;
                    break;
                }
            }
            return res;
        }
        Comment.prototype.getHTML = function() {
            this.HTML = '';
            if(option.show_nocomment || this.comment != '') {
                var m = String(this.date.getMonth()+1);
                if(m.length == 1){
                    m = "0" + m;
                }
                var d = String(this.date.getDate());
                if(d.length == 1){
                    d = "0" + d;
                }
                this.HTML = '<li>' + this.date.getFullYear() + "/" + m + "/" + d
                  + ' <a href="'+ this.href + '" style="' + anchor_css + '"><img src="'
                    + this.image +'" width="12px" heigth="12px" border="0"/> ' + this.user +'</a>: ';
                if(option.show_tag) {
                    for(var i=0; i<this.tags.length; i++) {
                        this.HTML+='<a href="' + this.tag_base + encodeURIComponent(this.tags[i]) + '" style="' + anchor_css + '">' + this.tags[i] + '</a>';
                        if(i+1<this.tags.length){
                            this.HTML+=', ';
                        }else{
                            this.HTML+=' ';
                        }
                    }
                }
                this.HTML+= this.comment + "</li>";
            }
            return this.HTML;
        }
        return this;
    }

    // --------------------------------------------------------------
    // hatena (jsonp)
    // --------------------------------------------------------------
    var hb_jsonp = "http://b.hatena.ne.jp/entry/json/";
    var hb_favicon = "http://b.hatena.ne.jp/favicon.ico";
    var hb_page = "http://b.hatena.ne.jp/entry/" + uri;
    if(hatena_use_jsonp){
        w.hbCallback = function(json) {
            var comments = [];
            if(json){
                comment_area.addCount(json.count, hb_favicon, hb_page);
                var comment = "";
                var count = json.bookmarks.length;
                for(var i=0; i<count; i++) {
                    var bm = json.bookmarks[i];
                    var user = bm.user;
                    var date = new Date(bm.timestamp.slice(0,4), Number(bm.timestamp.slice(5,7))-1,
                                        bm.timestamp.slice(8,10), bm.timestamp.slice(11,13),
                                        bm.timestamp.slice(14,16), bm.timestamp.slice(17,19));
                    var tag_base = 'http://b.hatena.ne.jp/' + user + '/';
                    var href = tag_base + bm.timestamp.slice(0,4) + bm.timestamp.slice(5,7) + bm.timestamp.slice(8,10) + '#bookmark-' + json.eid;
                    var image = 'http://www.hatena.ne.jp/users/' + user.substring(0, 2) + '/' + user + '/profile_s.gif';
                    var tags = bm.tags;
                    var comment = bm.comment.replace(/^\s+|\s+$/g, "");
                    comments.push(new Comment(user, image, href, tags, comment, date, tag_base, "hatena"));
                }
                comment_area.addComments('hatena', comments);
                comment_area.init('hatena');
				comment_area.setHistory(comments);
            }else{
                comment_area.addCount(0, hb_favicon, hb_page);
            }
        }
    }
    function hbLoadJSONP() {
        var json = document.createElement('script');
        json.src = hb_jsonp + "?url=" + encodeURIComponent(uri.replace(/%23/g, '#')) + "&callback=hbCallback";
        json.type = 'text/javascript';
        json.charset = 'utf-8';
        comment_area.div.appendChild(json);
    }

    // --------------------------------------------------------------
    // hatena (rss)
    // --------------------------------------------------------------
    var hatena_rss = "http://b.hatena.ne.jp/entry/rss/";
    function hbLoadRSS(){
        GM_xmlhttpRequest({
          method:"GET",
          url: hatena_rss + uri,
          onload:function(response) {
              var r;
              var comments = [];
              if (r=response.responseText.match(/<item rdf:about(\s|.)+?<\/item>/mg)){
                  var r1;
                  comment_area.addCount(r.length, hb_favicon, hb_page);
                  for (i=0; i<r.length; i++) {
                      r[i].match(/<title>([^<]+)<\/title>/);
                      var user = RegExp.$1;
                      r[i].match(/<link>([^<]+)<\/link>/);
                      var href = RegExp.$1;
                      var comment = '';
                      if(r[i].match(/<description>([^<]*[^\s<]+[^<]*)<\/description>/))
                        comment = RegExp.$1;
                      r[i].match(/<dc:date>([^<]+)<\/dc:date>/);
                      var date = RegExp.$1;
                      date = new Date(date.slice(0,4), Number(date.slice(5,7))-1,
                                      date.slice(8,10), date.slice(11,13),
                                      date.slice(14,16), date.slice(17,19) );
                      var tags = [];
                      if(r1 = r[i].match(/<dc:subject>([^<]+)<\/dc:subject>/mg)) {
                          for(var j=0; j<r1.length; j++) {
                              r1[j].match(/<dc:subject>([^<]+)<\/dc:subject>/);
                              tags.push(RegExp.$1);
                          }
                      }
                      var tag_base = 'http://b.hatena.ne.jp/' + user + '/';
                      var image = 'http://www.hatena.ne.jp/users/' + user.slice(0, 2) + '/' + user + '/profile_s.gif';
                      comments.push(new Comment(user, image, href, tags, comment, date, tag_base, "hatena"));
                  }
                  comment_area.addComments('hatena', comments);
                  comment_area.init('hatena');
					comment_area.setHistory(comments);
              }else{
                  comment_area.addCount(0, hb_favicon, hb_page);
              }
          }
        });
    }
    function hbLoad(){
        if(hatena_use_jsonp){
            hbLoadJSONP();
        }else{
            hbLoadRSS();
        }
    }

    // --------------------------------------------------------------
    // del.icio.us (rss)
    // --------------------------------------------------------------
    var delicious_rss = "http://del.icio.us/rss/url/";
    var delicious_url = "http://del.icio.us/";
    var delicious_favicon = "http://del.icio.us/favicon.ico";
    var delicious_page = "http://del.icio.us/url/" + MD5_hexhash(uri.replace(/%23/g, '#'));
    function dlLoadRSS() {
        GM_xmlhttpRequest({
          method: "GET",
          url: delicious_rss + MD5_hexhash(uri.replace(/%23/g, '#')),
          onload: function(response) {
              var r;
              var comment ="";
              var comments = [];
              var tags = [];
              if (r=response.responseText.match(/<item rdf:about(\s|.)+?<\/item>/mg)) {
                  comment_area.addCount(r.length, delicious_favicon, delicious_page);
                  for (var i=0; i<r.length; i++){
                      r[i].match(/<item rdf:about=".*">\s*<title>[^<]+<\/title>\s*<link>[^<]+<\/link>\s*(<description>([^<]*[^\s<]+[^<]*)<\/description>\s*)?<dc:creator>([^<]+)<\/dc:creator>\s*<dc:date>([^<]*)<\/dc:date>(\s*<dc:subject>([^<]*)<\/dc:subject>)?/);
                      var user = RegExp.$3;
                      if(RegExp.$6){
                          tags = RegExp.$6.split(" ");
                      }
                      var date = RegExp.$4;
                      var comment = RegExp.$2;
                      comment = comment.replace(/^\s+|\s+$/g, "");
                      var date = new Date(date.slice(0,4), Number(date.slice(5,7))-1, date.slice(8,10), Number(date.slice(11,13))+9, date.slice(14,16), date.slice(17,19) );
                      comments.push(new Comment(user, delicious_favicon, delicious_url+user, tags, comment, date ,"http://del.icio.us/" + user + "/", "delicious"));
                  }
                  comment_area.addComments('del.icio.us', comments);
                  comment_area.init('del.icio.us');
					comment_area.setHistory(comments);
              }else if(response.responseText.match(/<title>Yahoo! - 503 Service Temporarily Unavailable<\/title>/)){
                  comment_area.addCount("503error", delicious_favicon, delicious_page);
              }else{
                  comment_area.addCount(0, delicious_favicon, delicious_page);
              }
          }
        });
    }

    // --------------------------------------------------------------
    // del.icio.us (html)
    // --------------------------------------------------------------
    var delicious_html = "http://del.icio.us/url/";
    function dlLoadHTML(){
        GM_xmlhttpRequest({
          method: "GET",
          url: delicious_html + MD5_hexhash(uri.replace(/%23/g, '#')),
          onload: function(response) {
              var num = 0;
              var r1,r2,r3;
              var comment_hash = [];
              var comments = [];
              if(r1 = response.responseText.match(/<ul class="notelist">(\s|.)+?<\/ul>/mg)) {
                  for(var h=0; h<r1.length; h++){
                      if(r2 = r1[h].match(/<li>(\s|.)+?<\/li>/mg)) {
                          for(var i=0; i<r2.length; i++){
                              r2[i].match(/<p>([^<]+)<\/p>/);
                              var c = RegExp.$1;
                              r2[i].match(/<a href=".*">([^<]+)<\/a>/);
                              var u = RegExp.$1;
                              comment_hash[u] = c;
                          }
                      }
                  }
              }
              var r4,r5,r6,r7;
              if(r4 = response.responseText.match(/<ul class="historylist">(\s|.)+?<\/ul>/mg)){
                  for(var h=0; h<r4.length; h++) {
                      if(r5 = r4[h].match(/<p>.+<\/p>/mg)) {
                          for(var i=0; i<r5.length; i++) {
                              if(r6 = r5[i].match(/<a.+?<\/a>/mg)) {
                                  var user;
                                  var tags = [];
                                  for(var j=0; j<r6.length; j++) {
                                      r6[j].match(/<a.+?>(.+?)<\/a>/);
                                      if(j==0){
                                          user = RegExp.$1;
                                      }else{
                                          tags.push(RegExp.$1);
                                      }
                                  }
                                  var comment = "";
                                  if(comment_hash[user]){
                                      comment = comment_hash[user];
                                  }
                                  comments.push(new Comment(user, delicious_favicon, delicious_url+user, tags, comment, new Date(0,0,0,0,0,0) ,"http://del.icio.us/" + user + "/", "delicious"));
                                  num++;
                              }
                          }
                      }
                  }
              }
              comment_area.addCount(num, delicious_favicon, delicious_page);
              comment_area.addComments('del.icio.us', comments);
              comment_area.init('del.icio.us');
				comment_area.setHistory(comments);
          }
        });
    }
    function dlLoad(){
        if(firefox){
            dlLoadRSS();
        }else{
            dlLoadHTML();
        }
    }
    // --------------------------------------------------------------
    // Livedoor Clip(html)
    // --------------------------------------------------------------
    var livedoor_url = "http://clip.livedoor.com/page/";
    var livedoor = "http://clip.livedoor.com/clips/";
    var livedoor_favicon = "http://clip.livedoor.com/favicon.ico";
    var livedoor_page = livedoor_url + uri;
    function ldLoad() {
        GM_xmlhttpRequest({
          method: "GET",
          url: livedoor_url + uri ,
          onload: function(response) {
              var r1 = null;
              var r_table = null;
              var r_tr = null;
              var r_element = null;
              var comments = [];
              if(r_table = response.responseText.match(/<table(\s|.)*?<\/table>/g)[5]) {
                  if(r_tr = r_table.match(/<tr>(\s|.)*?<\/tr>/g)) {
                      comment_area.addCount(r_tr.length, livedoor_favicon, livedoor_page);
                      for(var i=0; i<r_tr.length; i++) {
                          r_tr[i].match(/<td class="tkcliptime color1">([^<]+)<\/td>/);
                          var date = RegExp.$1;
                          date = new Date(date.slice(0,4), Number(date.slice(5,7))-1, date.slice(8,10), 0, 0 ,0);
                          r_tr[i].match(/<span(\s|.)*?<\/span>([^<]*)/);
                          var comment = RegExp.$2;
                          r_element = r_tr[i].match(/<a[^>]*>[^<]*?<\/a>/g);
                          r_element[0].match(/<a[^>]*>([^<]*?)<\/a>/);
                          var user = RegExp.$1;
                          var tags = [];
                          if(r_element.length>0){
                              for(var j=1; j<r_element.length; j++){
                                  r_element[j].match(/<a[^>]*>([^<]*?)<\/a>/);
                                  tags.push(RegExp.$1);
                              }
                          }
                          comments.push(new Comment(user, "http://clip.livedoor.com/favicon.ico", livedoor + user, tags, comment, date, livedoor + user + "/tag/", "livedoor"));
                      }
                      comment_area.addComments('livedoor', comments);
                      comment_area.init('livedoor');
						comment_area.setHistory(comments);
                  }else{
                      comment_area.addCount(0, livedoor_favicon, livedoor_page);
                  }
              }else{
                  comment_area.addCount(0, livedoor_favicon, livedoor_page);
              }
          }
        })
      }

    // --------------------------------------------------------------
    // EC Navi (rss)
    // --------------------------------------------------------------
    var ec_navi_rss  = 'http://news.ecnavi.jp/entry/comment/rss/';
    var ec_navi = 'http://news.ecnavi.jp/user/';
    var ec_navi_favicon = "http://news.ecnavi.jp/favicon.ico";
    var ec_navi_page = "http://news.ecnavi.jp/entry/" + uri;
    function ecLoadRSS() {
        GM_xmlhttpRequest({
          method: "GET",
          url: ec_navi_rss + uri,
          onload: function(response) {
              var r1 = null;
              var r2 = null;
              var html = "";
              var comments = [];
              if (r1=response.responseText.match(/<item rdf:about=".*">(\s|.)+?<\/item>/mg)){
                  comment_area.addCount(r1.length, ec_navi_favicon, ec_navi_page);
                  for(var i=0; i<r1.length; i++) {
                      r1[i].match(/<title>([^<]*)<\/title>(\s|.)+?(<description>([^<]*)<\/description>|<description\/>)/);
                      var user = RegExp.$1.slice(0,-2);
                      var comment = RegExp.$4;
                      var tags = [];
                      if(r2 = r1[i].match(/<dc:subject>[^<]*<\/dc:subject>/g)) {
                          for(var j=0; j<r2.length; j++){
                              r2[j].match(/<dc:subject>([^<]*)<\/dc:subject>/);
                              tags.push(RegExp.$1);
                          }
                      }
                      var image = 'http://cdn.news.ecnavi.jp/user/' + user + '/photo';
                      var tag_base = ec_navi + user + '/keyword/';
                      comments.push(new Comment(user, image, ec_navi + user, tags, comment, new Date(0,0,0,0,0,0), tag_base, "ecnavi"));
                  }
                  comment_area.addComments('ec_navi', comments);
                  comment_area.init('ec_navi');
					comment_area.setHistory(comments);
              }else{
                  comment_area.addCount(0, ec_navi_favicon, ec_navi_page);
              }
          }
        });
    }
    // --------------------------------------------------------------
    // EC Navi (html)
    // --------------------------------------------------------------
    var ec_navi_html  = 'http://news.ecnavi.jp/entry/';
    function ecLoadHTML(){
        GM_xmlhttpRequest({
          method: "GET",
          url: ec_navi_html + uri,
          onload: function(response) {
              var r1,r2,r3,r4;
              var comments = [];
              if (r1=response.responseText.match(/<ul id="user_list">(\s|.)+?<\/ul>/)){
                  if(r2=r1[0].match(/<li>(\s|.)+?<\/li>/mg)){
                      comment_area.addCount(r2.length, ec_navi_favicon, ec_navi_page);
                      for(var i=0; i<r2.length; i++){
                          r3=r2[i].match(/<a[^>]*>.*?<\/a>/mg);
                          r3[0].match(/<a[^>]*>(.*)<\/a>/);
                          var user = RegExp.$1.slice(0,-2);
                          var image = 'http://cdn.news.ecnavi.jp/user/' + user + '/photo';
                          var tag_base = ec_navi + user + '/keyword/';
                          var tags = [];
                          var comment = "";
                          for(var j=2; j<r3.length; j++){
                              r3[j].match(/<a[^>]*>(.*)<\/a>/);
                              tags.push(RegExp.$1.replace(/^\[|\]$/g, ""));
                          }
                          r2[i].match(/(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)/);
                          var date = new Date(RegExp.$1, Number(RegExp.$2)-1, RegExp.$3,
                                              RegExp.$4, RegExp.$5, RegExp.$6);
                          if(r4=r2[i].match(/<div class='bg_body'>\s*<p>(.|\s)*?<\/p>/)){
                              if(r4[0].match(/<a[^>]*?>.*<\/a>((.|\s)*)<\/p>/)){
                                  comment = RegExp.$1.replace(/^\s+|\s+$/g, "");
                              }else{
                                  r4[0].match(/<p>((.|\s)*)<\/p>/);
                                  comment = RegExp.$1.replace(/^\s+|\s+$/g, "");
                              }
                          }
                          comments.push(new Comment(user, image, ec_navi + user, tags, comment, date, tag_base, "ecnavi"));
                      }
                      comment_area.addComments('ec_navi', comments);
                      comment_area.init('ec_navi');
						comment_area.setHistory(comments);
                  }
                  var image = 'http://cdn.news.ecnavi.jp/user/' + user + '/photo';
              }else{
                  comment_area.addCount(0, ec_navi_favicon, ec_navi_page);
              }
          }
        });
    }
    function ecLoad(){
        ecLoadHTML();
    }
    // --------------------------------------------------------------
    // Pookmark (html)
    // --------------------------------------------------------------
    var pookmark_base  = 'http://pookmark.jp/';
    var pookmark_html  = pookmark_base + 'url';
    var pookmark_favicon = pookmark_base + 'favicon.ico';
    var pookmark_page = pookmark_html + '/'+ MD5_hexhash(uri.replace(/%23/g, '#'));
    function pmLoadHTML(){
        GM_xmlhttpRequest({
          method: "GET",
          url: pookmark_page,
          onload: function(response){
              var r1,r2,r3;
              var comments=[];
              if(r1 = response.responseText.match(/<div class="subsection" id="passenger-list">(\s|.)+?<\/div>/)){
                  r2 = r1[0].match(/<li class="pt pt_s">(\s|.)+?<\/li>/mg);
                  comment_area.addCount(r2.length, pookmark_favicon, pookmark_page);
                  for(var i=0; i<r2.length; i++){
                      r2[i].match(/<span class="datetime">(\d\d\d\d)\/(\d\d)\/(\d\d)<\/span>/);
                      var date = new Date(RegExp.$1, Number(RegExp.$2)-1, RegExp.$3,0,0,0);
                      r2[i].match(/<img src="(.+?)"/);
                      var image = pookmark_base + RegExp.$1;
                      var comment ='';
                      if(r2[i].match(/<span>(.+?)<\/span>/)){
                          comment = RegExp.$1;
                      }
                      r2[i].match(/<a href="\/user\/(.+?)">/);
                      var user = RegExp.$1;
                      var href = pookmark_base + "user/" + user + "/";
                      var tags = [];
                      if(r3 = r2[i].match(/<a href="\/user\/.+?" class="tag">.+?<\/a>/mg)){
                          for(var j=0; j<r3.length; j++){
                              r3[j].match(/<a href="\/user\/.+?" class="tag">(.+?)<\/a>/);
                              tags.push(RegExp.$1);
                          }
                        }
                      comments.push(new Comment(user, image, href, tags, comment, date, href, "pookmark"));
                  }
                  comment_area.addComments('pookmark', comments);
                  comment_area.init('pookmark');
					comment_area.setHistory(comments);
              }else{
                  comment_area.addCount(0, pookmark_favicon, pookmark_page);
              }
          }
        });
    }
    function pmLoad(){
        pmLoadHTML();
    }

    function loadSBM() {
        if(is_load == false){
            dlLoad();
            ldLoad();
            hbLoad();
            ecLoad();
            pmLoad();
            is_load = true;
        }
    }
    var skipEl = {'input': true, 'button': true, 'select': true, 'textarea': true, 'password': true};
    window.addEventListener('keypress', function(e) {
        if (skipEl[e.target.tagName.toLowerCase()]) {return;}
        var key = ''
          + ((e.ctrlKey)  ? 'C' : '')
            + ((e.shiftKey) ? 'S' : '')
              + ((e.altKey || e.metaKey)   ? 'A' : '')
                + '-';
        if(firefox){
            key += String.fromCharCode(e.charCode).toLowerCase();
        }else{
            key += String.fromCharCode(e.keyCode).toLowerCase();
        }
        if (key == BIND_KEY){
            comment_area.toggle();
        }
    }, false);

    if(option.auto_start){
        comment_area.show();
        if(option.auto_start_open == false){
            comment_area.hide();
        }
    }
    
})();
