﻿// coding: UTF-8
/***************************************
	Main script file for Hekiraku
	Copyright(C) 2000-2008 SGRY
	(last update: 2008-04-05)
***************************************/

//===== Variable =====//

// style definition
//      format: [ <css uri>, <display text>, <custom-script uri> ];
var gStyleInfo = new Array();
gStyleInfo[0] = [ "plain.css"    , "plain"        , ""       ];
gStyleInfo[1] = [ "3rd.css"      , "3rd style"    , ""       ];
gStyleInfo[2] = [ "solitude.css" , "SOLitude"     , ""       ];
gStyleInfo[3] = [ "5th.css"      , "outliner"     , "5th.js" ];

// index of the style user selected.
var gSelectedStyle = 3; // defaulting to 3

// font set definition
var gFontSets = new Array();
gFontSets[0] = [ "fontset_hira36_otf.css", ["ヒラギノ明朝 Pro W3", "ヒラギノ明朝 Pro W6", "ヒラギノ角ゴ Pro W6", "Monaco", "Osaka-等幅"] ];
gFontSets[1] = [ "fontset_hira35_ttf.css", ["ヒラギノ明朝体3", "ヒラギノ明朝体5", "ヒラギノ角ゴ5", "ヒラギノ角ゴ3等幅", "Courier New"] ];
gFontSets[2] = [ "fontset_ipa.css"       , ["IPA P明朝", "IPA Pゴシック"] ];
gFontSets[3] = [ "fontset_ms.css"        , ["ＭＳ 明朝", "Century"] ];
gFontSets[4] = [ "fontset_generic.css"   , ["sans-serif"] ];

// index of the style user selected.
var gSelectedFontSet = 4;


//===== Initialization =====//

// set default OnLoad event handler
window.onload = function() {
	// if a font set was already chosen, do nothing
	var fontSetId = document.cookie.match( "FontSet=([^;]*)" );
	if( fontSetId == null )
	{
		// choose appropriate font set and record it
		gSelectedFontSet = TestFontSets();
		UpdateCookie();
	}
}

// apply style selected by user (or default style)
ApplyUserSelectedStyle();

// redirect to "sgry.jp" without history
if( location.hostname == "www.sgry.jp"
	|| location.hostname == "sgry.sakura.ne.jp" )
{
	if( location.replace != undefined )
	{
		location.replace( location.protocol + "//sgry.jp" + location.pathname );
	}
}



//=========================================================
//
//  General purpose scripts
//
//=========================================================

//-------------------------------------
// function: GetInnerText
// brief: Connect all descendant text nodes and return it
// returns  : (success) ... connected string
//            (failure) ... empty string
//-------------------------------------
function GetInnerText( domNode ) /*string*/
{
	var TEXT_NODE = 3;
	var text = "";
	var node;
	
	node = domNode.firstChild;
	while( node != null )
	{
		if( node.nodeType != TEXT_NODE )
		{
			text += this.GetInnerText( node );
		}
		else
		{
			text += node.nodeValue;
		}
		
		node = node.nextSibling;
	}
	
	return text;
}

//-------------------------------------
// function: GetIEVer
// brief: Get major version of IE (if the browser is IE)
// returns  : (success) ... version number of IE
//            (failure) ... -1
//-------------------------------------
function GetIEVer() /*int*/
{
	var matches;
	
	// parse version string
	matches = /MSIE (\d)/.exec( navigator.appVersion );
	if( matches == null )
	{
		return -1; // not IE
	}
	
	return Number(RegExp.$1);
}

//-------------------------------------
// function: IsIE
// brief: Distiinguish the browser is IE or not.
//-------------------------------------
function IsIE() /*boolean*/
{
	return ( navigator.appName == "Microsoft Internet Explorer" );
}

//-------------------------------------
// function: IsMozilla
// brief: Distiinguish the browser is Mozilla or not.
//-------------------------------------
function IsMozilla() /*boolean*/
{
	return ( navigator.appName == "Netscape" );
}

//-------------------------------------
// function: IsOpera
// brief: Distiinguish the browser is Opera or not.
//-------------------------------------
function IsOpera() /*boolean*/
{
	return ( navigator.appName == "Opera" );
}

//-------------------------------------
// function: CreateXmlHttp
// brief: Create XMLHttp object for each browser
// returns  : (success) ... XMLHttp object
//            (failure) ... null
//-------------------------------------
function CreateXmlHttp() /*XmlHttpRequest*/
{
	var xmlHttp = null;
	
	// Opera / Mozilla
	if( typeof XMLHttpRequest != 'undefined' )
	{
		xmlHttp = new XMLHttpRequest();
	}
	// Internet Explorer 6 or later
	else try
	{
		xmlHttp = new ActiveXObject( "Msxml2.XMLHTTP" );
	}
	catch( ex ) { /* currently do nothing ;P */ }
	
	return xmlHttp;
}

//-----------------------------------------------
// function: ReformatDateString
// brief: Parse yyyy-MM-dd formatted string and return re-formatted string
//-----------------------------------------------
function ReformatDateString( dateString ) /*string*/
{
	var tokens;
	var year, month, date;

	tokens = dateString.split( '-', 3 );
	if( tokens.length < 3 )
	{
		return null;
	}
	
	// generate year
	year = tokens[0];
	
	// generate month (if value is '0x', make it 'x')
	month = tokens[1];
	if( month.charAt(0) == '0' )
	{
		month = month.charAt( 1 );
	}

	// generate date (if value is '0x', make it 'x')
	date = tokens[2];
	if( date.charAt(0) == '0' )
	{
		date = date.charAt( 1 );
	}
	
	// return the value
	return (year + "&#x5E74;" + month + "&#x6708;" + date + "&#x65E5;");
}

//-----------------------------------------------
// function: WriteMetaDate
// brief: Write date information of the document
//-----------------------------------------------
function WriteMetaDate() /*void*/
{
	var dateInfo = GetDocumentDateInfo();
	
	document.write( "<p class='date'>\n" );
	if( dateInfo["DC.Date.Created"] != undefined )
	{
		document.write( "Created: "
			+ ReformatDateString( dateInfo["DC.Date.Created"] )
			+ "<br/>\n" );
	}
	if( dateInfo["DC.Date.Modified"] != undefined )
	{
		document.write( "Last modified: "
			+ ReformatDateString( dateInfo["DC.Date.Modified"] )
			+ "<br/>\n" );
	}
	if( dateInfo["DC.date"] != undefined ) /* #deprecated# */
	{
		document.write( "Date: "
			+ ReformatDateString( dateInfo["DC.date"] )
			+ "<br/>\n" );
	}
	document.write( "</p>\n" );
}

//-----------------------------------------------
// function: GetDocumentDateInfo
// brief: Get date information of the document
// returns  : dictionary object like {"DC.Date.Created" : "2007-05-02"}
//-----------------------------------------------
function GetDocumentDateInfo() /*Dictionary*/
{
	var metaElms;
	var dateInfo = new Array();
	
	// get all meta elements
	metaElms = document.getElementsByTagName( "meta" );

	// find meta data related to the date
	for( var i=0; i<metaElms.length; i++ )
	{
		var elm = metaElms[i];
		
		// DC.date? (#deprecated#)
		if( elm.getAttribute("name") == "DC.date" )
			dateInfo["DC.date"] = elm.getAttribute( "content" );
		// DC.Date.Created?
		else if( elm.getAttribute("name") == "DC.Date.Created" )
			dateInfo["DC.Date.Created"] = elm.getAttribute( "content" );
		// DC.Date.Modified?
		else if( elm.getAttribute("name") == "DC.Date.Modified" )
			dateInfo["DC.Date.Modified"] = elm.getAttribute( "content" );
	}
	
	return dateInfo;
}

//-----------------------------------------------
// function: #deprecated# GetMetaDate
// brief: Get date that are written in meta tag
//-----------------------------------------------
function GetMetaDate() /*string*/
{
	var i;
	var metaElms;
	var fullDate;
	var year;
	var month;
	var date;
	
	// get all meta elements
	metaElms = document.getElementsByTagName( "meta" );

	// find one which name is "DC.date".
	for( i=0; i<metaElms.length; i++ )
	{
		// is this element's name "DC.date"?
		if( metaElms[i].getAttribute("name") == "DC.date" )
		{
			fullDate = metaElms[i].getAttribute( "content" );
		}
	}
	
	// re-format string
	return ReformatDateString( fullDate );
}

//-----------------------------------------------
// function: debug_log
// brief: Create a div element and write text into it.
//-----------------------------------------------
function debug_log( log_content ) /*void*/
{
	var DEBUG_VIEW;
	var view;
	
	// get debug-view element
	body = document.getElementsByTagName( "body" )[0];
	if( body.firstChild.id == "DEBUG_VIEW" )
	{
		// use debug-view element that was already created
		view = body.firstChild;
	}
	else
	{
		// create debug-view element
		view = document.createElement( "div" );
		view.setAttribute( "id", "DEBUG_VIEW" );
		view.style.background = "gray";
		view.style.color = "white";
		body.insertBefore( view, body.firstChild );
	}
	
	view.innerHTML += log_content;
}


//=========================================================
//
//  Hekiraku specific scripts
//
//=========================================================

//-------------------------------------
// function: WriteForm
// brief: Write form tag
//-------------------------------------
function WriteForm() /*void*/
{
	var i;
	
	document.write( "<form>\n" );
	document.write( "<select id=\"style_selector\" onchange=\"" );
	document.write( "gSelectedStyle = this.options[this.selectedIndex].value;" );
	document.write( "UpdateCookie();" );
	document.write( "location.reload();" );
	document.write( "\">\n" );
	for( i=0; i<gStyleInfo.length; i++ )
	{
		if( i == gSelectedStyle )
		{
			document.write( "<option value=\""+i+"\" selected>"+gStyleInfo[i][1]+"</option>\n" );
		}
		else
		{
			document.write( "<option value=\""+i+"\">"+gStyleInfo[i][1]+"</option>\n" );
		}
	}
	
	document.write( "</select>\n" );
	document.write( "</form>\n" );
}

//-------------------------------------
// function: UpdateCookie
// brief: Update cookie
//-------------------------------------
function UpdateCookie()
{
	// remove old cookie
	document.cookie = "HekirakuStyle=0;expires=Fri, 4-Feb-2008 00:00:00 GMT;path=/";
	
	// write style ID and font-set ID
	document.cookie = "Style=" + gSelectedStyle + "; expires=Thu, 1-Jan-2030 00:00:00 GMT; path=/";
	document.cookie = "FontSet=" + gSelectedFontSet + "; expires=Thu, 1-Jan-2030 00:00:00 GMT; path=/";
}


//-------------------------------------
// function: GetRootUri
// brief: Get URI of site root
//-------------------------------------
function GetRootUri() /*string*/ 
{
	var releaseUriPattern = new RegExp( "(http://[^/]*sgry[^/]*)/?" );
	var onWebServer = releaseUriPattern.test( location );
	var hostName;
	
	// on released site (sgry.sakura.ne.jp / sgry.jp)
	if( onWebServer )
	{
		// add '/' to host name and return it
		return RegExp.$1 + '/';
	}
	// un-uploaded local file
	else if( location.href.indexOf("hekiraku") != -1 )
	{
		var dirEndPos = location.href.lastIndexOf( "hekiraku/" ) + 9; // 9 == "hekiraku/".length
		return location.href.substr( 0, dirEndPos );
	}
	
	// error
	return "";
}


//-----------------------------------------------
// function: ShowHint
// brief: Popup hint window
//-----------------------------------------------
function ShowHint( id ) /*void*/
{
	if( gSelectedStyle == 0 )
	{
		return; // スタイルが plain ならば無視
	}
	document.getElementById(id).style.visibility = "visible";
}


//-----------------------------------------------
// function: HideHint
// brief: Popup hint window
//-----------------------------------------------
function HideHint( id ) /*void*/
{
	if( gSelectedStyle == 0 )
	{
		return; // スタイルが plain ならば無視
	}

	document.getElementById(id).style.visibility = "hidden";
}


//-----------------------------------------------
// function: GetAccessCount
// brief: Get counter value
// note: value would be incremented sametime
//-----------------------------------------------
function GetAccessCount() /*int*/
{
	var xmlHttpRequest;
	var countElem;
	var scriptUri;
	
	// create and setup XML HTTP object
	xmlHttpRequest = CreateXmlHttp();
	if( xmlHttpRequest == null )
	{
		return -1;
	}
	
	// make URI to the counter script
	scriptUri = GetRootUri() + "counter.cgi";
	if( scriptUri.indexOf("file://") == 0 )
	{
		return -1; // local file
	}
	
	// kick script and get XML containing access count
	xmlHttpRequest.open( "GET", scriptUri, false );
	xmlHttpRequest.send( null );
	
	// parse XML got
	countElem = xmlHttpRequest.responseXML.getElementsByTagName( "counter" );
	if( countElem.length == 0 )
	{
		return -1;
	}
	countElem = countElem[0];
	
	// return counter
	return Number( GetInnerText(countElem) );
}

//-----------------------------------------------
// function: ApplyUserSelectedStyle
// brief: get user selected style and apply it
//-----------------------------------------------
function ApplyUserSelectedStyle() /*void*/
{
	// try loading cookie
	if( document.cookie != "" )
	{
		// get user selected style ID
		var styleId = document.cookie.match( "Style=([^;]*)" );
		if( styleId != null )
		{
			gSelectedStyle = Number( styleId[1] );
		}
		
		// get user selected font set ID
		var fontSetId = document.cookie.match( "FontSet=([^;]*)" );
		if( fontSetId != null )
		{
			gSelectedFontSet = Number( fontSetId[1] );
		}
	}

	// load style sheet
	document.write(
		"<link " +
			"rel='stylesheet' " +
			"type='text/css' " + 
			"charset='UTF-8' " +
			"href='" + GetRootUri() + "styles/" + gStyleInfo[gSelectedStyle][0] +
			"'>\n" );

	// load style related script
	if( gStyleInfo[gSelectedStyle][2] != "" )
	{
		document.write(
			"<script " +
				"type=\"text/javascript\"" +
				"src=\"" + GetRootUri() + "styles/" + gStyleInfo[gSelectedStyle][2] +
				"\"></script>\n" );
	}
	
	// apply font set
	document.write(
		"<link " +
			"rel='stylesheet' " +
			"type='text/css' " + 
			"charset='UTF-8' " +
			"href='" + GetRootUri() + "styles/" + gFontSets[gSelectedFontSet][0] +
			"'>\n" );
}

//-----------------------------------------------
// function: TestFontSets
// brief: Test all font sets and return index of the available one.
// returns: index of the available font set
//-----------------------------------------------
function TestFontSets() /*int*/
{
	var defaultValue = gFontSets.length - 1;
	var detector;
	var fontSetCssName;
	var neededFonts;
	var fontExists;
	var allFontsExists;
	
	// test all font set
	detector = new FontDetector();
	for( var i=0; i<gFontSets.length; i++ )
	{
		fontSetCssName = gFontSets[i][0];
		neededFonts = gFontSets[i][1];
		
		// check whether the fonts used in this set exist or not
		allFontsExists = true;
		for( var j=0; j<neededFonts.length; j++ )
		{
			fontExists = detector.test( neededFonts[j] )[3];
			if( fontExists != true )
			{
				allFontsExists = false;
				break;
			}
		}
		
		// if all needed fonts exist, use this set
		if( allFontsExists )
		{
			return i;
		}
	}
	
	// use default
	return defaultValue;
}

//==========================================================
// Font Detector written by Lalit Patel
//     Licensed under Apache License 2.0
//     original source --> http://www.lalit.org/lab/fontdetect.php
//==========================================================

/**
 * Acutal Fuction that does all the work. Returns an array with all the info.
 * My Assumption is that most of the browsers will have arial set as their default san-serif font.
 */
var FontDetector = function(){
	var h = document.getElementsByTagName("BODY")[0];
	var d = document.createElement("DIV");
	var s = document.createElement("SPAN");

	d.appendChild(s);
	d.style.fontFamily = "sans-serif";		//font for the parent element DIV.
	s.style.fontFamily = "sans-serif";		//arial font used as a comparator.
	s.style.fontSize   = "72px";			//we test using 72px font size, we may use any size. I guess larger the better.
	s.innerHTML        = "mmmmmmmmmml";		//we use m or w because these two characters take up the maximum width. And we use a L so that the same matching fonts can get separated
	h.appendChild(d);
	var defaultWidth   = s.offsetWidth;		//now we have the defaultWidth
	var defaultHeight  = s.offsetHeight;	//and the defaultHeight, we compare other fonts with these.
	h.removeChild(d);

	/* test
	 * params:
	 * font - name of the font you wish to detect
	 * return: 
	 * f[0] - Input font name.
	 * f[1] - Computed width.
	 * f[2] - Computed height.
	 * f[3] - Detected? (true/false).
	 */
	function test(font) {
		h.appendChild(d);
		var f = [];
		f[0] = s.style.fontFamily = font;	// Name of the font
		f[1] = s.offsetWidth;				// Width
		f[2] = s.offsetHeight;				// Height
		h.removeChild(d);

		font = font.toLowerCase();
		if (font == "arial" || font == "sans-serif") {
			f[3] = true;	// to set arial and sans-serif true
		} else {
			f[3] = (f[1] != defaultWidth || f[2] != defaultHeight);	// Detected?
		}
		return f;
	}
	this.test = test;
}

