非公開 HatenaDiaryKeywordPopup.js

    
      
  • /*
     * @title HatenaDiaryKeywordPopup.js
     * @description はてダでキーワードポップアップ
     * @include http://*
     * @license NYSL
     * @private
     */
    
    
    (function () {
    	var xmlhttp = new XMLHttpRequest();
    	var popupTimerID = null;
    	var fadeInIntervalID = null;
    	var fadeOutIntervalID = null;
    	var xpos = 0;
    	var ypos = 0;
    	var keywordCache = new Array();
    	
    	function createPopup() {
    		var popup = document.createElement('div');
    		with(popup.style) {
    			visibility = 'hidden';
    			fontSize = '10pt';
    			fontFamily = 'sans-serif';
    			textAlign = 'left';
    			lineHeight = '110%';
    			color = '#333333';
    			paddingLeft = '5px';
    			paddingRight = '5px';
    			backgroundColor = 'cornsilk';
    			border = '1px solid #333333';
    			opacity = '0';
    			
    			position = 'absolute';
    			left = xpos;
    			top = ypos+25;
    			width = '200';
    		}
    		popup.id = "popup";
    		return popup;
    	}
    	function fadeOutPopup() {
    		var popup = document.getElementById('popup');
    		if (popup) {
    			var op = parseFloat(getComputedStyle(popup).opacity);
    			var newop = op-0.1;
    			if (newop<=0) {
    				document.body.removeChild(popup);
    				clearInterval(fadeOutIntervalID);
    			} else
    				popup.style.opacity = newop;
    		} else {
    			clearInterval(fadeOutIntervalID);
    		}
    	}
    	function fadeInPopup() {
    		var popup = document.getElementById('popup');
    		if (popup) {
    			var op = parseFloat(getComputedStyle(popup).opacity);
    			var newop = op+0.1;
    			if (newop>=1) {
    				popup.style.opacity = 0.99;
    				clearInterval(fadeInIntervalID);
    			} else {
    				popup.style.opacity = newop;
    			}
    		} else {
    			clearInterval(fadeInIntervalID);
    		}
    	}
    	
    	function appendPopup(xml) {
    		var popup = document.getElementById('popup');
    		if (popup) {
    			clearInterval(fadeOutIntervalID);
    			document.body.removeChild(popup);
    		}
    		var keywordTitle = "";
    		var popupDiv = createPopup();
    		var items = xml.getElementsByTagName('item');
    		for (var i=0; i<items.length; i++) {
    			var item = items[i];
    			for (var n=item.firstChild; n!=null; n=n.nextSibling) {
    				if(i==0 && n.nodeName == 'title') {
    					var titleDiv = document.createElement('div');
    					keywordTitle = n.firstChild.nodeValue;
    					titleDiv.innerHTML = keywordTitle;
    					with(titleDiv.style) {
    						paddingTop = '5px';
    						fontWeight = 'bold';
    						fontSize = '11pt';
    					}
    					popupDiv.appendChild(titleDiv);
    				}
    				if(n.nodeName == 'description') {
    					var kwdDiv = document.createElement('div');
    					kwdDiv.innerHTML = n.firstChild.nodeValue;
    					with(kwdDiv.style) {
    						marginBottom = '0px';
    						paddingTop = '5px';
    						paddingBottom = '5px';
    						if (i != items.length-1)
    							borderBottom = '1px dashed #333333';
    					}
    					popupDiv.appendChild(kwdDiv);
    				}
    			}
    		}
    		if (! keywordCache[keywordTitle])
    			keywordCache[keywordTitle] = xml;
    		
    		popup = document.body.appendChild(popupDiv);
    		
    		var r = popup.offsetLeft + popup.offsetWidth;
    		if (r > window.scrollX+document.body.clientWidth) {
    			popup.style.left = window.scrollX+document.body.clientWidth - popup.offsetWidth -10;
    		}
    		var b = popup.offsetTop + popup.offsetHeight;
    		if (b > window.scrollY+document.body.clientHeight) {
    			var t = window.scrollY + document.body.clientHeight - popup.offsetHeight - 10;
    			if (t<window.scrollY)
    				t = window.scrollY+10;
    			popup.style.top = t;
    		}
    		popup.style.visibility = 'visible';
    		fadeInIntervalID = setInterval(fadeInPopup, 30);
    	}
    	
    	function onLoadKeyword() {
    		if (xmlhttp.readyState == 4) {
    			var xml = xmlhttp.responseXML;
    			if (xml)
    				appendPopup(xml);
    			
    		}
    	}
    	function loadKeyword(rssurl, word) {
    		for(var i in keywordCache) {
    			if (i == word) {
    				var popup = document.getElementById('popup');
    				if (popup) {
    					clearInterval(fadeOutIntervalID);
    					document.body.removeChild(popup);
    				}
    				appendPopup(keywordCache[i]);
    				return true;
    			}
    		}
    		if (xmlhttp) {
    			var state = xmlhttp.readyState;
    			if (state==1 || state==2 || state==3)
    				xmlhttp.abort();
    			xmlhttp.onreadystatechange = onLoadKeyword;
    			xmlhttp.open("GET", rssurl, true);
    			xmlhttp.send("");
    		}
    	}
    	function showPopup(e) {
    		var aTag = e.target;
    		var rssurl = aTag.href+"?mode=rss";
    		xpos = e.pageX;
    		ypos = e.pageY;
    		document.addEventListener("mousemove", setPos, false);
    		popupTimerID = setTimeout(function(){
    			loadKeyword(rssurl, aTag.innerHTML);
    		}, 600);
    	}
    	function hidePopup(e) {
    		xmlhttp.abort();
    		clearTimeout(popupTimerID);
    		document.removeEventListener("mousemove", setPos, false);
    		var popup = document.getElementById('popup');
    		if (popup) {
    			clearInterval(fadeInIntervalID);
    			clearInterval(fadeOutIntervalID);
    			fadeOutIntervalID = setInterval(fadeOutPopup, 30);
    		}
    	}
    	function addKeywordEvents() {
    		var aTags = document.getElementsByTagName('a');
    		aTags = Array.prototype.slice.call(aTags);
    		for (var i in aTags) {
    			if (aTags[i].className == "keyword") {
    				aTags[i].addEventListener("mouseover", showPopup, false);
    				aTags[i].addEventListener("mouseout",  hidePopup, false);
    			}
    		}
    	}
    	function setPos(e) {
    		xpos = e.pageX;
    		ypos = e.pageY;
    	}
    	addKeywordEvents();
    })();
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。

History

  1. 2013/05/08 23:23:38 - 2013-05-08
  2. 2013/05/03 05:48:20 - 2013-05-03
  3. 2013/05/03 05:47:12 - 2013-05-03