//===========================================================================================================================
//
// notebook_common.js
//
// 最終更新履歴	2007/09/26
// 作成者	二宮
//
// 2007/09/26 FlashクラスにgetVisibleメソッドの追加
// 2007/09/19 段落のデフォルト画像を指定できるメソッド(Paragraph.setDefaultImage)を追加
//            また、それに伴いデフォルト画像のデータを取得できるメソッド(Paragraph.getDefaultImage)を追加
//            画像のサイズを指定できるメソッドの追加(Paragraph.setImageSize, ExpansionImage.setSize)
// 2007/09/13 動画読み込み関係の修正
//
//===========================================================================================================================

//===========================================================================================================================
/**
 * Flash extends Column
 *
 * @param id		:String id名
 * @param maxPages	:Number 最大ページ数
 * @param maxParagraphs	:Number 最大段落数
 */
function Flash(id, maxPages, maxParagraphs)
{
	var element = new Column(id, maxPages, maxParagraphs);
	
	element.maxPages	= maxPages;
	element.maxParagraphs	= maxParagraphs;
	
	//=======================================================================================================================
	
	//onmousemoveイベントの定義
	Event.observe(window.document, MouseEvent.MOUSE_MOVE, function(e)
	{
		var element = document.clickElement;
		if (element == null) {
			return;
		}
		element.mouseMove(e);
	});
	
	//onmouseupイベントの定義
	Event.observe(window.document, MouseEvent.MOUSE_UP, function(e)
	{
		var element = document.clickElement;
		if (element == null) {
			return;
		}
		
		element.mouseUp(e);
	});
	
	//onkeydownイベントの定義
	Event.observe(window.document, KeyboardEvent.KEY_DOWN, function(e)
	{
		var element = document.clickElement;
		if (element == null) {
			return;
		}
		
		element.keyDown(e);
	});
	
	/**
	 * エレメントの表示、非表示を指定する。
	 * ただし、エレメントをドキュメントに配置していない状態で
	 * このメソッドを実行するとエラーが発生してしまうので注意が必要
	 */
	element.setVisible = function(b) {
		document.layers ? (this.style.visibility = b ? 'show' : 'hide')
			: (this.style.visibility = b ? 'visible' : 'hidden');
	}
	
	element.getVisible = function() {
		if (document.layers) {
			return this.style.visibility == 'show' ? true : false;
		}
		return this.style.visibility == 'visible' ? true : false;
	}
	
	//=======================================================================================================================
	
	return element;
}

//===========================================================================================================================
/**
 * ExpansionImageクラス
 *
 * 拡張イメージクラス
 * イメージのリサイズを行う事ができる
 *
 * @param id		:String  id名
 * @param src		:String  画像のパス
 * @param minWidth	:Number  リサイズの最小幅
 * @param minHeight	:Number  リサイズの最小高
 * @param maxWidth	:Number  リサイズの最大幅
 * @param maxHeight	:Number  リサイズの最大高
 * @param resizeEnable	:Boolean リサイズ許可
 */
function ExpansionImage(id, src, alt, minWidth, minHeight, maxWidth, maxHeight, resizeEnable)
{
	var element = new Element(id);
	
	//変数===================================================================================================================
	
	element._image = new Image();
	element._image.src = src;
	element._image.alt = alt;
	
	element._direction	= Direction.RIGHT | Direction.BOTTOM;
	element._borderColor	= "#000000";
	element._firstWidth	= element._image.width;
	element._firstHeight	= element._image.height;
	element._minWidth	= minWidth  == null ? undefined : minWidth;
	element._minHeight	= minHeight == null ? undefined : minHeight;
	element._maxWidth	= maxWidth  == null ? undefined : maxWidth;
	element._maxHeight	= maxHeight == null ? undefined : maxHeight;
	element._resizeEnable	= resizeEnable == undefined ? true : resizeEnable;
	
	element._border = new Element(id + "_border");
	
	element._border.className = " " + ExpansionImage.CLASSNAME;
	element._border._firstMarginLeft	= 0;
	element._border._firstMarginTop		= 0;
	element._border._firstMarginRight	= 0;
	element._border._firstMarginBottom	= 0;
	
	element._border.style.borderWidth 	= "1px";
	element._border.style.borderStyle	= "solid";
	element._border.style.borderColor	= "#000000";
	element._border.style.color		= "#ffffff";	//ie transparent color
	element._border.style.position		= "relative";
	
	element._border.setFloat("left");
	element._border.add(element._image);
	
	element._resize = {
		n  : null, s  : null,
		w  : null, e  : null,
		ne : null, nw : null,
		se : null, sw : null
	}
	
	//addメソッドを書き換える前に一度実行する
	element.add(element._border);
	
	//イベントハンドラ=======================================================================================================
	
	element.onmouseover = function() {
		if (!ExpansionImage.resizable && this._resizeEnable) {
			this.setBorderVisible(true);
		}
	}
	
	element.onmouseout = function() {
		if (!ExpansionImage.resizable && this._resizeEnable) {
			this.setBorderVisible(false);
		}
	}
	
	/**
	 * イメージがリサイズされた時に実行されるイベントハンドラ
	 */
	element.onResize = function() {}
	
	//メソッド===============================================================================================================
	
	/**
	 * オブジェクトを追加する
	 *
	 * @param element:Element 追加オブジェクト
	 */
	element.add = function(element) {
		this._border.add(element);
	}
	
	/**
	 * マージンを指定する
	 *
	 * @param left	:Number	左マージン
	 * @param right	:Number	右マージン
	 * @param top	:Number	上マージン
	 * @param bottom:Number	下マージン
	 */
	element.setMargin = function(top, right, bottom, left)
	{
		this._border.style.marginTop	= top    + "px";
		this._border._firstMarginTop	= top;
		this._border.style.marginRight	= right  + "px";
		this._border._firstMarginRight	= right;
		this._border.style.marginBottom	= bottom + "px";
		this._border._firstMarginBottom	= bottom;
		this._border.style.marginLeft	= left   + "px";
		this._border._firstMarginLeft	= left;
	}
	
	/**
	 * リサイズする方向を指定する
	 *
	 * @param direction:Number リサイズ方向
	 */
	element.setDirection = function(direction)
	{
		var nEnable = (direction & Direction.TOP  ) == Direction.TOP;
		var wEnable = (direction & Direction.LEFT ) == Direction.LEFT;
		var eEnable = (direction & Direction.RIGHT) == Direction.RIGHT;
		
		if ((wEnable && eEnable) || nEnable)
		{
			this.style.position = "absolute";
		}
		
		if (this.style.position != "absolute") {
			if (eEnable)
			{
				this._border.setFloat("left");
				this._border.style.marginLeft = 0;
				this._border.style.marginRight = this._border._firstMarginRight;
			}
			else if (wEnable)
			{
				this._border.setFloat("right");
				this._border.style.marginLeft = this._border._firstMarginLeft;
				this._border.style.marginRight = 0;
			}
		}
		
		this._direction = direction;
	}
	
	/**
	 * ボーダーの色を指定する
	 *
	 * @param clr:String ボーダーの色（#rrggbb）
	 */
	element.setBorderColor = function(clr) {
		this._borderColor = clr;
	}
	
	/**
	 * ボーダーの表示、非表示を指定する
	 *
	 * @param b:Boolean ボーダーを表示表示するかどうか
	 */
	element.setBorderVisible = function(b) {
		this._border.style.borderColor = b
			? this._borderColor : "transparent";
			
		if (b) {
			this._appearResizeBlock();
			return;
		}
		
		for(var key in this._resize) {
			this._resize[key].setVisible(false);
		}
	}
	
	/**
	 * リサイズブロックを表示する
	 */
	element._appearResizeBlock = function()
	{
		var wEnable = (this._direction & Direction.LEFT  ) == Direction.LEFT;
		var nEnable = (this._direction & Direction.TOP   ) == Direction.TOP;
		var eEnable = (this._direction & Direction.RIGHT ) == Direction.RIGHT;
		var sEnable = (this._direction & Direction.BOTTOM) == Direction.BOTTOM;
		
		var r = element._resize;
		r.n.setVisible(nEnable);
		r.s.setVisible(sEnable);
		r.w.setVisible(wEnable);
		r.e.setVisible(eEnable);
		r.ne.setVisible(nEnable && eEnable);
		r.nw.setVisible(nEnable && wEnable);
		r.se.setVisible(sEnable && eEnable);
		r.sw.setVisible(sEnable && wEnable);
	}
	
	/**
	 * 画像を読み込む
	 *
	 * @param url	:String	読み込み先画像パス
	 * @param width	:Number 値がある場合、その値を基にリサイズを行う。無い場合は変更しない
	 * @param height:Number	値がある場合、その値を基にリサイズを行う。無い場合は変更しない
	 */
	element.load = function(url, width, height) {
		this._image.src = url;
		this.setSize(width, height);
	}
	
	/**
	 * 画像の情報を取得する
	 *
	 * @return Object
	 */
	element.getData = function() {
		return {
			src	: this._image.src,
			width	: this._image.width,
			height	: this._image.height
		}
	}
	
	/**
	 * イメージのサイズを指定する
	 *
	 * @param width :Number 幅
	 * @param height:Number 高さ
	 */
	element.setSize = function(width, height) {
		if (width) {
			this._image.width = width;
		}
		if (height) {
			this._image.height = height;
		}
	}
	
	/**
	 * リサイズを許可するか
	 *
	 * @param b:Boolean
	 */
	element.resizeEnable = function(b) {
		this._resizeEnable = b;
	}
	
	/**
	 * リサイズ範囲を設定する
	 *
	 * @param minWidth	:Number 最小幅
	 * @param minHeight	:Number 最小高
	 * @param maxWidth	:Number 最大幅
	 * @param maxHeight	:Number 最大高
	 */
	element.setResizeArea = function(minWidth, minHeight, maxWidth, maxHeight)
	{
		this._minWidth	= minWidth  == null ? undefined : minWidth;
		this._minHeight	= minHeight == null ? undefined : minHeight;
		this._maxWidth	= maxWidth  == null ? undefined : maxWidth;
		this._maxHeight	= maxHeight == null ? undefined : maxHeight;
	}
	
	//=======================================================================================================================
	
	for(var key in element._resize)
	{
		element._resize[key] = new _ResizeBlock(id + "_" + key + "Resize");
		
		var resize = element._resize[key];
		
		resize.keyDown = function(e) {
			this.onmouseup(e);
		}
		
		resize.mouseMove = function(e)
		{
			if (!element._resizeEnable) {
				return;
			}
			
			if (window.getSelection) {	//DOM
				window.getSelection().removeAllRanges();
			}
			
			//以下のメソッドの実行順が重要になる
			//this._resizeTop(e);
			this._resizeBottom(e);
			this._resizeLeft(e);
			this._resizeRight(e);
		}
		
		resize.mouseUp = function(e) {
			if (!element._resizeEnable) {
				return;
			}
			this.onmouseup(e);
			element.setBorderVisible(false);
		}
		
		resize.onmouseover = function() {
			if (!element._resizeEnable) {
				return;
			}
			if (!ExpansionImage.resizable) {
				document.body.style.cursor = this._direction + "-resize";
				return;
			}
		}
		
		/**
		 * リサイズ（左方向）
		 *
		 * @param e:Event イベントオブジェクト
		 */
		resize._resizeLeft = function(e) {
			if ((element._direction & Direction.LEFT) == Direction.LEFT
				 && this._direction.indexOf('w') != -1)
			{
				var difW = Event.pointerX(e) - this._oldPX;
				var width = element._image.width - difW;
				
				var tmpWidth = 0;	//臨時保存用
				if (width <= element._minWidth) {
					tmpWidth = element._minWidth;
				} else if (element._maxWidth <= width) {
					tmpWidth = element._maxWidth;
				} else {
					tmpWidth = width;
					this._oldPX = Event.pointerX(e);
				}
				
				//等幅で拡大縮小
				if (this._direction.indexOf('s') != -1)
				{
					var nRatio = tmpWidth / element._image.width;
					//小数点による誤差をなくす
					element._image.height = Math.round(element._image.height * nRatio);
				}
				element._image.width = tmpWidth;
				
				var mw = element._maxWidth - width;
				if (mw <= element._border._firstMarginLeft)
				{
					element.style.height = "1%";
					element._border.style.marginLeft = (element._maxWidth - element._image.width) + "px";
				}
				else if (element._border._firstMarginLeft < mw
					&& parseInt(element._border.style.marginLeft) != element._border_firstMarginLeft)
				{
					element.style.height = "auto";
					element._border.style.marginLeft = element._border._firstMarginLeft + "px";
				}
			}
		}
		
		/**
		 * リサイズ（右方向）
		 *
		 * @param e:Event イベントオブジェクト
		 */
		resize._resizeRight = function(e) {
			if ((element._direction & Direction.RIGHT) == Direction.RIGHT
				 && this._direction.indexOf('e') != -1)
			{
				var difW = Event.pointerX(e) - this._oldPX;
				var width = element._image.width + difW;
				
				var tmpWidth = 0;	//臨時保存用
				if (width <= element._minWidth) {
					tmpWidth = element._minWidth;
				} else if (element._maxWidth <= width) {
					tmpWidth = element._maxWidth;
				} else {
					tmpWidth = width;
					this._oldPX = Event.pointerX(e);
				}
				
				//等幅で拡大縮小
				if (this._direction.indexOf('s') != -1)
				{
					var nRatio = tmpWidth / element._image.width;
					//小数点による誤差をなくす
					element._image.height = Math.round(element._image.height * nRatio);
				}
				element._image.width = tmpWidth;
				
				var mw = element._maxWidth - element._image.width;
				if (mw <= element._border._firstMarginRight)
				{
					element.style.height = "1%";
					element._border.style.marginRight = (element._maxWidth - element._image.width) + "px";
				}
				else if (element._border._firstMarginRight < mw
					&& parseInt(element._border.style.marginRight) != element._border_firstMarginRight)
				{
					element.style.height = "auto";
					element._border.style.marginRight = element._border._firstMarginRight + "px";
				}
			} else {
				element._image.width = element._image.width;
			}
		}
		
		/**
		 * リサイズ（上方向）
		 *
		 * @param e:Event イベントオブジェクト
		 */
		resize._resizeTop = function(e) {
			/*今回使用しない
			if ((element._direction & Direction.TOP) == Direction.TOP
				 && this._direction.indexOf('n') != -1)
			{
				
			}
			*/
		}
		
		/**
		 * リサイズ（下方向）
		 *
		 * @param e:Event イベントオブジェクト
		 */
		resize._resizeBottom = function(e) {
			if ((element._direction & Direction.BOTTOM) == Direction.BOTTOM
				 && this._direction.indexOf('s') != -1)
			{
				var height = element._image.height + (Event.pointerY(e) - this._oldPY);
				
				if (this._direction.indexOf('e') != -1
					|| this._direction.indexOf('w') != -1)
				{
					return;
				} else {
					if (height < element._minHeight) {
						element._image.height = element._minHeight;
					} else if (element._maxHeight < height) {
						element._image.height = element._maxHeight;
					} else {
						element._image.height = height;
						this._oldPY = Event.pointerY(e);
					}
				}
			} else {
				element._image.height = element._image.height;
			}
		}
		
		element._border.add(resize);
	}
	
	element.setBorderVisible(false);
	return element;
}
//定数
ExpansionImage.CLASSNAME = "ExpansionImage";
ExpansionImage.resizable = false;


//===========================================================================================================================
/**
 * _ResizeBlockクラス
 *
 * @param id:String id名
 */
function _ResizeBlock(id)
{
	var element = new Element(id);
	
	//変数===================================================================================================================
	
	element._direction = "";
	element._oldPX = 0;
	element._oldPY = 0;
	
	element.style.position		= "absolute";
	element.style.width		= "6px";
	element.style.height		= "6px";
	element.style.fontSize		= "6px";
	element.style.backgroundColor	= "#000000";
	element.setVisible(false);
	
	var posX = -(parseInt(element.style.width ) / 2) + "px";
	var posY = -(parseInt(element.style.height) / 2) + "px";
	
	//メソッド===============================================================================================================
	
	element.getDirectionString = function() {
		return this.id.substring(this.id.lastIndexOf('_') + 1, this.id.lastIndexOf('Resize'));
	}
	
	element.onmouseout = function(e) {
		if (!ExpansionImage.resizable) {
			document.body.style.cursor = "default";
			document.clickElement = null;
		}
	}
	
	element.onmousedown = function(e) {
		ExpansionImage.resizable = true;
		this._oldPX = Event.pointerX(e);
		this._oldPY = Event.pointerY(e);
		
		document.clickElement = this;
		
		//ie only
		document.onselectstart = function() { return false; }
	}
	
	element.onmouseup = function(e) {
		document.body.style.cursor = "default";
		ExpansionImage.resizable = false;
		document.clickElement = null;
		
		//ie only
		document.onselectstart = null;
		
		this.parentNode.parentNode.onResize();
	}
	
	var nm = element.getDirectionString();
	if (nm.indexOf("n") != -1) {
		element._direction += "n";
		element.style.top = posY;
		if (nm.length == 1) {
			element.style.left = "50%";
		}
	}
	
	if (nm.indexOf("s") != -1) {
		element._direction += "s";
		element.style.bottom = posY;
		if (nm.length == 1) {
			element.style.left = "50%";
		}
	}
	
	if (nm.indexOf("w") != -1) {
		element._direction += "w";
		element.style.left = posX;
		if (nm.length == 1) {
			element.style.top = "50%";
		}
	}
	
	if (nm.indexOf("e") != -1) {
		element._direction += "e";
		element.style.right = posX;
		if (nm.length == 1) {
			element.style.top = "50%";
		}
	}
	
	return element;
}


//===========================================================================================================================
/**
 * Columnクラス
 *
 * @param id		:String id名
 * @param maxPages	:Number 最大ページ数
 * @param maxParagraphs	:Number	最大段落数
 */
function Column(id, maxPages, maxParagraphs)
{
	var element = $(id);
	
	//変数===================================================================================================================
	
	element.className	= Column.CLASSNAME;
	element.maxPages	= maxPages ? maxPages : 1;
	element.maxParagraphs	= maxParagraphs ? maxParagraphs : 1;
	element.totalPages	= 0;	//現在コラム内に存在するページ数
	element.currentPage	= 1;
	element._pages		= new Array(maxPages);
	element._pageId		= 0;
	
	//メソッド===============================================================================================================
	
	/**
	 * コラムを初期化する
	 */
	element.init = function() {
		for(var i = 0; i < this.maxPages; i++) {
			if (this._pages[i]) {
				this.removeChild(this._pages[i]);
				delete this._pages[i];
			}
		}
		
		this.totalPages  = 0;
		this.currentPage = 1;
		this._pageId     = 0;
		
		this.createPage(1);
	}
	 
	/**
	 * ページを作成する
	 *
	 * @param n:Number 作成するページ
	 *
	 * @return Element ページが無事作成できれば作成したオブジェクト そうでなければnull
	 */
	element.createPage = function(n, pageTitle) {
		if (n <= 0 || this.maxPages < n) {
			return null;
		}
		
		var tmp	 	= this._pages;
		//引数を省略するとopera等で不具合が出る
		var pull1	= tmp.splice(n - 1, tmp.length - (n - 1));
		var page	= null;
		for(var i = 0; i < pull1.length; i++)
		{
			if (pull1[i] == undefined)
			{
				var pull2 = pull1.splice(0, i + 1);
				pull2.pop();
				
				page		= new Page("page_" + (++this._pageId), this.maxParagraphs, pageTitle);
				if (page.getTitle().indexOf("undefined") == -1) {
					page.setTitle(page.getTitle() + " " + this._pageId);
				}
				this._pages	= tmp.concat([page].concat(pull2, pull1));
				this.appendChild(page);
				
				this.totalPages++;
				break;
			}
		}
		
		this.onCreated(page);
		return page;
	}
	
	/**
	 * ページの削除
	 *
	 * @param n:Number 指定ページ
	 *
	 * @return Boolean 指定したページが存在し、削除が成功したら 正 そうでなければ 負
	 */
	element.deletePage = function(n) {
		if (!this.existPage(n)) {
			return false;
		}
		
		var num = n - 1;
		this.removeChild(this._pages[num]);
		delete this._pages[num];
		
		for(var i = 0; i < this._pages.length - num; i++)
		{
			this._pages[num + i] = this._pages[num + i + 1];
		}
		
		this.totalPages--;
		
		return true;
	}
	
	/**
	 * 表示しているページを指定ページに切り替える
	 *
	 * @param n:Number 指定ページ
	 *
	 * @return Boolean 指定したページが存在し、切り替えが完了したら 正 そうでなければ 負
	 */
	element.changeDisplayPage = function(n) {
		if (!this.existPage(n)) {
			return false;
		}
		
		this._pages[this.currentPage - 1].style.display = "none";
		this._pages[n - 1].style.display = "block";
		this.currentPage = n;
		
		return true;
	}
	
	/**
	 * 指定ページを次ページへ移動させる
	 *
	 * @param n:Number 指定ページ
	 *
	 * @return Boolean 指定ページよりも先にページが存在し、移動が成功すれば 正 そうでなければ 負
	 */
	element.gotoNextPage = function(n) {
		if (!this.existPage(n + 1)) {
			return false;
		}
		
		var num = n - 1;
		var tmp = this._pages[num + 1];
		this._pages[num + 1] = this._pages[num];
		this._pages[num] = tmp;
		
		return true;
	}
	
	/**
	 * 指定ページを前ページへ移動させる
	 *
	 * @param n:Number 指定ページ
	 *
	 * @return Boolean 指定ページよりも前にページが存在し、移動が成功すれば 正 そうでなければ 負
	 */
	element.gotoPrevPage = function(n) {
		if (!this.existPage(n - 1)) {
			return false;
		}
		
		var num = n - 1;
		var tmp = this._pages[num - 1];
		this._pages[num - 1] = this._pages[num];
		this._pages[num] = tmp;
		
		return true;
	}
	
	/**
	 * データの読み込み
	 *
	 * xmlデータ例：
	 * <column>
	 *   
	 *   <!--
	 *     page
	 *     
	 *     string id ページ数
	 *   -->
	 *   <page id="1">
	 *     <!--
	 *       title
	 *     -->
	 *     <title>タイトル</title>
	 *     
	 *     <!--
	 *       paragraph
	 *       
	 *       string id           段落数
	 *       int    templateType レイアウト（０＝画像左側、１＝画像右側、２＝画像なし）
	 *     -->
	 *     <paragraph id="1" templateType="0">
	 *       <!--
	 *         img
	 *         
	 *         string src    画像パス	（パスが存在しない場合、デフォルトの画像パスが代入される）
	 *         int    width  幅			（値がない場合、デフォルトの値が代入される）
	 *         int    height 高さ		（値がない場合、デフォルトの値が代入される）
	 *
	 *         paragraphのtemplateType要素に２が代入されている場合、無視される
	 *         また、movieタグが段落タグ内に存在する場合、imgタグは無視される
	 *       -->
	 *       <img src="#" width="n" height="n" />
	 *
	 *       <!--
	 *         content
	 *         
	 *         中には入力された内容をドバッと書いてください。
	 *       -->
	 *       <content>本文</content>
	 *     </paragraph>
	 *     
	 *   </page>
	 *   
	 * </column>
	 */
	element.load = function(xml) {
		this.init();
		
		if (!xml) {
			return false;
		}
		
		var date = (new Date()).getMilliseconds();
		
		var root = xml.childNodes[xml.childNodes.length - 1];
		for(var i = 0; i < root.childNodes.length; i++)
		{
			var xn1 = root.childNodes[i];
			if (xn1.nodeName == "page")
			{
				var pageNum = getAttributeValue(xn1, "id");
				var page;
				
				if (pageNum == 1) {
					page = this.getPage(pageNum);
				} else if (pageNum) {
					page = this.createPage(pageNum);
					page.style.display = "none";
				} else {
					continue;
				}
				
				for(var j = 0; j < xn1.childNodes.length; j++)
				{
					var xn2 = xn1.childNodes[j];
					
					switch(xn2.nodeName) {
						case "title":
							if (xn2.firstChild) {
								page.setTitle(xn2.firstChild.nodeValue);
							}
							break;
							
						case "paragraph":
							var pgNum = getAttributeValue(xn2, "id");
							var templateType = getAttributeValue(xn2, "templateType");
							var paragraph;
							
							if (pgNum == 1) {
								paragraph = page.getParagraph(pgNum);
								paragraph.setTemplateType(templateType);
							} else if (pgNum) {
								paragraph = page.createParagraph(templateType);
							} else {
								continue;
							}
							
							for(var k = 0; k < xn2.childNodes.length; k++)
							{
								var xn3 = xn2.childNodes[k];
								
								switch(xn3.nodeName)
								{
									case "img":
										var imgSrc       = getAttributeValue(xn3, "src"   );
										var imgWidth     = getAttributeValue(xn3, "width" );
										var imgHeight    = getAttributeValue(xn3, "height");
										var isMovie      = imgSrc.indexOf('.flv') != -1;
										var defaultImage = Paragraph.getDefaultImage();
										
										imgWidth  = imgWidth  == "" ? defaultImage.width  : imgWidth;
										imgHeight = imgHeight == "" ? defaultImage.height : imgHeight;
										
										//拡張子.flvがあれば、movie用のメソッドを実行する
										if (isMovie) {
											paragraph.setImageSize(imgWidth, imgHeight);
											paragraph.loadMovie(imgSrc, imgWidth, imgHeight);
										} else {
											paragraph.loadImage(
												(imgSrc   == "" ? defaultImage.src : imgSrc) + "?date=" + date,
												imgWidth, imgHeight);
										}
										break;
										
									case "content":
										paragraph.setContent(xn3.firstChild ? xn3.firstChild.nodeValue : "");
										break;
								}
							}
							break;
							
						default:
							break;
					}
				}
			}
		}
		
		this.onLoaded();
		
		return true;
	}
	
	/**
	 * データを送信
	 *
	 * @param data:Object 送信するデータ
	 */
	element.send = function(data, filename) {
		var sendData = [];
		for(var key in data) {
			sendData[key] = data[key];
			//alert(key + " = " + sendData[key]);
		}
		
		//ローカルで作業できる様に分けておく
		if (window.requestFile)
		{
			requestFile(sendData, "post", filename, true);
		}
	}
	
	/**
	 * 指定したページが存在するかどうか
	 *
	 * @param n:Number 指定ページ
	 */
	element.existPage = function(n) {
		return this._pages[n - 1] != undefined;
	}
	
	/**
	 * 指定したページを取得する
	 *
	 * @param n:Number 指定ページ
	 */
	element.getPage = function(n) {
		return this._pages[n - 1];
	}
	
	//イベントハンドラ=======================================================================================================
	
	/**
	 * 段落作成時に実行するイベントハンドラ
	 *
	 * @param page:Page 作成したページ
	 */
	element.onCreated = function(page) {}
	
	/**
	 * 読み込み完了時のイベントハンドラ
	 *
	 * @param xhr:XML 読み込んだXML
	 */
	element.onLoaded = function(xhr) {}
	
	return element;
}
Column.CLASSNAME = "Column";

//===========================================================================================================================
/**
 * Pageクラス
 *
 * @param id		:String id名
 * @param maxParagraphs	:Number 最大段落数
 * @param title		:String ページタイトル
 */
function Page(id, maxParagraphs, pageTitle)
{
	var element = new Element(id);
	
	//変数===================================================================================================================
	
	element.className	+= " " + Page.CLASSNAME;
	element.maxParagraphs	= maxParagraphs;
	element.totalParagraphs = 0;
	element.editable	= true;	//編集許可
	element._editable	= element.editable;
	element._paragraphs	= new Array(maxParagraphs);
	element._tmpTitle	= "";
	
	//メソッド===============================================================================================================
	
	/**
	 * タイトル編集部分のエレメントの作成
	 */
	element._makeTitleEditElements = function()
	{
		this._title._edit		= new Element(id + "_title_edit", 'span');
		this._title._edit.style.display	= "none";
		this._title._edit._text		= new Element(id + "_title_edit_text", 'input');
		this._title._edit._text.type	= "text";
		this._title._edit._text.value	= this._title._default._value.innerHTML;
		this._title._edit._saveBtn	= new Button(id + "_title_edit_saveBtn",
			'保存', function() {
				element.setTitle(element._title._edit._text.value);
				changeDisplay(id + "_title_default", id + "_title_edit");
				element.onSave();
			});
		this._title._edit._cancelBtn	= new Button(id + "_title_edit_cancelBtn",
			'キャンセル', function() {
				element._title._edit._text.value = element._tmpTitle;
				changeDisplay(id + "_title_default", id + "_title_edit");
			});
		
		this._title._edit.add(this._title._edit._text);
		this._title._edit.add(this._title._edit._saveBtn);
		this._title._edit.add(this._title._edit._cancelBtn);
	}
	
	/**
	 * タイトルエレメントの作成
	 */
	element._makeTitleElements = function()
	{
		this._title			= new Element(id + "_title", 'h5');
		this._title.style.marginBottom	= "10px";
		this._title._default		= new Element(id + "_title_default", 'span');
		this._title._default._value	= new Element(id + "_title_default_value", 'b');
		this._title._default._value.innerHTML = pageTitle;
		this._title._default._editBtn	= new Button(id + "_title_default_editBtn",
			'編集する', function() { changeDisplay(id + "_title_default", id + "_title_edit"); });
		
		this._title._default.add(this._title._default._value);
		this._title._default.add(this._title._default._editBtn);
		
		this._makeTitleEditElements();
		
		this._title.add(this._title._default);
		this._title.add(this._title._edit);
		
		this.add(this._title);
		if (!pageTitle) {
			this._title.style.display = "none";
		}
	}
	
	/**
	 * 段落を作成する
	 *
	 * @param templateType	:Number レイアウト
	 * @param minWidth	:Number 画像リサイズ（最小幅）
	 * @param minHeight	:Number 画像リサイズ（最小高）
	 * @param maxWidth	:Number 画像リサイズ（最大幅）
	 * @param maxHeight	:Number 画像リサイズ（最大高）
	 * 
	 * @return Paragraph 作成した段落オブジェクト
	 */
	element.createParagraph = function(templateType, minWidth, minHeight, maxWidth, maxHeight)
	{
		if (this.maxParagraphs < this.totalParagraphs) {
			return null;
		}
		
		var paragraph = new Paragraph(id + "_paragraph_"
			+ (this.totalParagraphs + 1), templateType, minWidth, minHeight, maxWidth, maxHeight, this._editable);
		this._paragraphs[this.totalParagraphs++] = paragraph;
		this.add(paragraph);
		
		this.onCreated(paragraph);
		
		return paragraph;
	}
	
	/**
	 * ページタイトルを設定する
	 *
	 * @param str:String タイトル名
	 */
	element.setTitle = function(str) {
		if (str && this._title.style.display == "none") {
			this._title.style.display = "";
		}
		
		this._tmpTitle = this._title._edit._text.value;
		this._title._edit._text.value = str;
		
		this._title._default._value.innerHTML = replaceTag(str);
	}
	
	/**
	 * ページタイトルの取得
	 *
	 * @return String 現在アクティブになっているページタイトル（タグは無視される）
	 */
	element.getTitle = function() {
		return replaceTag(this._title._edit._text.value);
	}
	
	/**
	 * 指定した段落が存在するか
	 *
	 * @param n:Number 段落数
	 *
	 * @return Boolean 存在していれば 正 そうでなければ 負
	 */
	element.existParagraph = function(n) {
		return this._paragraphs[n - 1] != undefined;
	}
	
	/**
	 * 指定した段落を取得する
	 *
	 * @param n:Number 段落数
	 *
	 * @return Paragraph 指定した段落（存在してなければ未定義が返る）
	 */
	element.getParagraph = function(n) {
		return this._paragraphs[n - 1];
	}
	
	/**
	 * 指定した段落が何番目かを取得する
	 *
	 * @return Number 何番目
	 */
	element.getParagraphNum = function(paragraph)
	{
		for(var i = 0; i < this._paragraphs.length; i++)
		{
			if (this._paragraphs[i] == paragraph) {
				return i + 1;
			}
		}
		return null;
	}
	
	/**
	 * 編集許可
	 *
	 * @param arguments:Array
	 */
	element.setEnable = function() {
		if (arguments.length == 1) {
			for(var i = 0; i < this.totalParagraphs; i++)
			{
				this._paragraphs[i].setEnable(arguments[0]);
			}
			
			arguments[0] == false ? this._title._default._editBtn.style.display = "none"
				: this._title._default._editBtn.style.display = "";
			
			this._editable = arguments[0];
			this.editable = this._editable;
		}
		else {
			switch(arguments[0]) {
				default:
					break;
			}
		}
	}
	
	//イベントハンドラ=======================================================================================================
	
	/**
	 * 『保存』を押した時のイベントハンドラ
	 */
	element.onSave = function() {}
	
	/**
	 * 段落作成時に実行するイベントハンドラ
	 *
	 * @param paragraph:Paragraph 作成した段落オブジェクト
	 */
	element.onCreated = function(paragraph) {}
	
	//=======================================================================================================================
	
	element._makeTitleElements();
	
	return element;
}
Page.CLASSNAME = "Page";

//===========================================================================================================================
/**
 * Paragraphクラス
 *
 * 段落
 *
 * @param id		:String	 id名
 * @param templateType	:Number	 段落の表示タイプ（３タイプ）
 * @param minWidth	:Number  画像リサイズ（最小幅）
 * @param minHeight	:Number  画像リサイズ（最小高）
 * @patam maxWidth	:Number  画像リサイズ（最大幅）
 * @param maxHeight	:Number  画像リサイズ（最大高）
 * @param editable	:Boolean 編集許可かどうか
 */
function Paragraph(id, templateType, minWidth, minHeight, maxWidth, maxHeight, editable)
{
	var element = new Element(id);
	var initialContent = "ここに文章を入力してください。";
	
	//変数===================================================================================================================
	
	element.className	+= " " + Paragraph.CLASSNAME;
	element.reference	= "";		//参照ファイルのパス
	element._init		= false;	//初期化が完了したか
	element._timerId;
	element._templateType	= templateType == undefined ? Paragraph.TEMPALTE_LEFT : templateType;
	element._tmpValue	= "";
	element._tmpImage	= null;		//動画がアップロード完了したか確認する際に使用
	element._tagEnable	= true;
	element._lpCount	= 0;
	element._lpMax		= 4;
	element._loadSpd	= 500;
	
	//メソッド===============================================================================================================
	
	/**
	 * 動画を読み込む
	 *
	 * @param url	:String 動画パス
	 * @param width	:Number 幅
	 * @param height:Number 高さ
	 */
	element.loadMovie = function(url, width, height)
	{
		if (url.search(/.flv/i) == -1) {
			return;
		}
		
		this.reference = url;
		
		this._tmpImage = new Image();
		this._tmpImage.onload = function() {
			clearTimeout(element._timerId);
			
			//ファイル名だけ抜き出す
			var fname = Paragraph.FLV_UPLOAD_IMAGE.substring(
				Paragraph.FLV_UPLOAD_IMAGE.lastIndexOf('/') + 1);
			
			!element.parentNode.editable && this.src.indexOf(fname) == -1
				? element._loadMovie(url, width, height)
				: element.loadImage(this.src, width, height);
			element._lpCount  = 0;		//ループ回数を初期化
			element.reference = url;
		}
		
		var date = (new Date()).getMilliseconds();
		this._timerId = setTimeout("$('" + this.id + "')._loadCaptureImage("
			+ "'" + url + "', " + width + ", " + height + ")", this._loadSpd);
		
		this._tmpImage.src = url.substring(0, url.search(/.flv/i)) + ".jpg?date=" + date;
	}
	
	/**
	 * 動画読み込み部分の本体
	 *
	 * @param url    :String 動画パス
	 * @param width  :Number 幅
	 * @param height :Number 高さ
	 */
	element._loadMovie = function(url, width, height)
	{
		if (this._p._image.style.display != "none")
		{
			this._p._image.style.display = "none";
		}
		
		var so = new SWFObject(Paragraph.FLASH_PLAYER, this._p._movie.id + "_player", width, height, 9, "#ffffff");
		so.addParam("allowfullscreen","true");
		so.addParam("wmode", "transparent");
		so.addVariable("file", url);
		so.addVariable("usefullscreen", false);
		so.write(this._p._movie.id);
		
		var direction = "";
		switch(parseInt(this._templateType))
		{
			case Paragraph.TEMPLATE_LEFT:
				direction = "left";
				break;
				
			case Paragraph.TEMPLATE_RIGHT:
				direction = "right";
				break;
				
			case Paragraph.TEMPLATE_NOIMAGE:
				this._p._movie.style.display = "none";
				break;
				
			default:
				break;
		}
		
		this._p._movie.setFloat(direction);
		this._p._movie.style.display = "block";
	}
	
	/**
	 * 
	 * @param url    :String 画像パス
	 * @param width  :Number 幅
	 * @param height :Number 高さ
	 */
	element._loadCaptureImage = function(url, width, height)
	{
		clearTimeout(this._timerId);
		
		if (this._lpMax < this._lpCount) {
			this._tmpImage.src = Paragraph.FLV_UPLOAD_IMAGE;
		} else {
			this._timerId = setTimeout("$('" + this.id + "')._loadCaptureImage("
				+ "'" + url + "', " + width + ", " + height + ")", this._loadSpd);
			this._lpCount++;
		}
	}
	
	/**
	 * イメージを読み込む
	 *
	 * @param url	:String 画像パス
	 * @param width	:Number 幅
	 * @param height:Number 高さ
	 */
	element.loadImage = function(url, width, height)
	{
		if (this._p._image) {
			this._p._image.load(url, width, height);
			this.reference = url;
		}
	}
	
	/**
	 * 段落内に存在するイメージ情報を取得する
	 *
	 * @return Object
	 */
	element.getImageData = function() {
		var img = this._p._image;
		return img != undefined ? img.getData() : nulll;
	}
	
	/**
	 * イメージのサイズを指定する
	 *
	 * @param width :Number 幅
	 * @param height:Number 高さ
	 */
	element.setImageSize = function(width, height) {
		this._p._image.setSize(width, height);
	}
	
	/**
	 * レイアウトを設定する
	 *
	 * @param templateType:Number テンプレートタイプ
	 */
	element.setTemplateType = function(templateType)
	{
		if (templateType == Paragraph.TEMPLATE_NOIMAGE)
		{
			this._p.style.display = "none";
		}
		else {
			this._p._image.setDirection((templateType == Paragraph.TEMPLATE_LEFT
				? Direction.RIGHT : Direction.LEFT) | Direction.BOTTOM);
			this._p.style.display = "inline";
		}
		
		this._templateType = templateType;
	}
	
	/**
	 * 現在のレイアウトを取得する
	 *
	 * @return Number テンプレートタイプ
	 */
	element.getTemplateType = function() {
		return this._templateType;
	}
	
	/**
	 * 画像のリサイズ範囲を設定する
	 *
	 * @param minWidth	:Number 最小幅
	 * @param minHeight	:Number 最小高
	 * @param maxWidth	:Number 最大幅
	 * @param maxHeight	:Number 最大高
	 */
	element.setImageResizeArea = function(minWidth, minHeight, maxWidth, maxHeight)
	{
		element._p._image.setResizeArea(minWidth, minHeight, maxWidth, maxHeight);
	}
	
	/**
	 * 本文の内容を設定する
	 *
	 * @param content:String 内容
	 */
	element.setContent = function(content) {
		this._article._editSpace._textField.value = content;
		this._tmpValue = content;
		
		var str	 = !this._tagEnable ? replaceTag(this._tmpValue) : this._tmpValue;
		var str2 = "";
		
		//自動改行
		var tmp = str.split('\n');
		for(var i = 0; i < tmp.length; i++) {
			str2 += tmp[i];
			if (i != tmp.length - 1) {
				str2 += "<br />";
			}
		}
		
		this._article._content.innerHTML = str2;
	}
	
	/**
	 * 本文の内容を取得する
	 *
	 * @return String 本文の内容
	 */
	element.getContent = function() {
		return this._tmpValue;
	}
	
	/**
	 * アイテムの使用許可
	 *
	 * @param arguments:Array
	 * 引数が一つの場合で、booleanを代入した場合、全てのアイテムの許可、不許可を指定できる。
	 * また、引数が二つの場合、個別に許可、不許可が指定できる。
	 * その際、第１引数はアイテム名（String型）、第２引数は使用許可を書く
	 * 
	 * 指定できるアイテムは３つ
	 * 　・editImage　　画像の上に置かれている『編集する』ボタン
	 * 　・editArticle　記事に置かれている『編集』ボタン
	 * 　・resizeImage　画像のリサイズ
	 */
	element.setEnable = function()
	{
		//親要素にあたるページのeditableプロパティがfalseの場合処理を抜ける
		if (this._init && !this.parentNode.editable) {
			return;
		}
		
		if (arguments.length == 1) {
			this._p._image._editBtn.style.display	= arguments[0] ? "inline" : "none";
			this._article._editBtn.style.display	= arguments[0] ? "inline" : "none";
			this._p._image.resizeEnable(arguments[0]);
		} else {
			switch(arguments[0]) {
				case "editImage":
					this._p._image._editBtn.style.display = arguments[1] ? "inline" : "none";
					break;
					
				case "editArticle":
					this._article._editBtn.style.display = arguments[1] ? "inline" : "none";
					break;
					
				case "resizeImage":
					this._p._image.resizeEnable(arguments[1]);
					break;
					
				case "tag":
					this._tagEnable = arguments[1];
					break;
			}
		}
	}
	
	/**
	 * イベントを設定する
	 *
	 * @param listenerObject:Object リスナーオブジェクト
	 */
	element.addListener = function(listenerObject)
	{
		for(var key in listenerObject) {
			if (key == "onResize") {
				this._p._image.onResize = listenerObject[key];
			} else {
				this[key] = listenerObject[key];
			}
		}
	}
	
	//イベントハンドラ=======================================================================================================
	
	/**
	 * イメージ上の『編集する』ボタンを押した際に実行されるイベントハンドラ
	 */
	element.onEdit = function() {}
	
	/**
	 * 記事上の『保存』ボタンを押した際に実行されるイベントハンドラ
	 */
	element.onSave = function() {}
	
	//以下画面の作成=========================================================================================================
	
	element._p = new Element(id + "_p", 'p');
	element._p.className = "image";
	
	//画像
	element._p._image = new ExpansionImage(id + "_image", Paragraph._defaultImage, "");
	element._p._image.setSize(Paragraph._defaultImageWidth, Paragraph._defaultImageHeight);
	element._p._image._editBtn = new Button(id + "_image_editBtn",
		"編集する", function() { element.onEdit(); });
	element._p._image._editBtn.className = "edit";
	element._p._image.add(element._p._image._editBtn);
	element._p.add(element._p._image);
	
	//動画
	element._p._movie = new Element(id + "_movie", 'span');
	element._p._movie.style.display = "none";
	element._p.add(element._p._movie);
	
	element.setTemplateType(templateType);
	element.add(element._p);
	
	element._article = new Element(id + "_article", 'span');
	element._article._content = new Element(id + "_article_content", 'font');
	element._article._content.innerHTML = initialContent;
	element._article.add(element._article._content);
	
	//記事内の『編集』ボタンの作成
	element._article._editBtn = new Button(id + "_article_editBtn",
		"編集", function() { changeDisplay(element._article._editBtn.id, element._article._editSpace.id); });
	element._article.add(element._article._editBtn);
	
	element._article._editSpace = new Element(id + "_article_editSpace");
	element._article._editSpace.style.display = "none";
	element._article._editSpace._textField = new TextField(id + "_article_editSpace_textField");
	element._article._editSpace._textField.value = initialContent;
	element._article._editSpace._textField.style.width = "100%";
	element._article._editSpace._textField.rows = 5;
	
	element._tmpValue = element._article._editSpace._textField.value;
	
	element._article._editSpace._span = new Element(id + "_article_editSpace_p", 'p');
	element._article._editSpace._span.style.textAlign = "center";
	element._article._editSpace._span.style.marginTop = "10px";
	element._article._editSpace._span.style.marginBottom = "0px";
	
	element._article._editSpace._saveBtn = new Button(id + "_article_editSpace_p_saveBtn",
		"保存", function() {
			element.setContent(element._article._editSpace._textField.value);
			changeDisplay(element._article._editSpace.id, element._article._editBtn.id);
			element._article._editBtn.style.display = "inline";
			
			element.onSave();
		});
	element._article._editSpace._saveBtn.style.marginRight = "5px";
	element._article._editSpace._cancelBtn = new Button(id + "_article_editSpace_p_cancelBtn",
		"キャンセル", function() {
			changeDisplay(element._article._editSpace.id, element._article._editBtn.id);
			element._article._editBtn.style.display = "inline";
			element._article._editSpace._textField.value = element._tmpValue;
		});
	element._article._editSpace._span.add(element._article._editSpace._saveBtn);
	element._article._editSpace._span.add(element._article._editSpace._cancelBtn);
	element._article._editSpace.add(element._article._editSpace._textField);
	element._article._editSpace.add(element._article._editSpace._span);
	
	element._article.add(element._article._editSpace);
	element.add(element._article);
	
	element._br = new Element(id + "_clear", 'br');
	element._br.clear = "all";
	element.add(element._br);
	
	element.setEnable(editable ? true : false);
	element._init = true;
	
	return element;
}

//静的定数
Paragraph.CLASSNAME		= "Paragraph";
Paragraph.TEMPLATE_LEFT		= 0;
Paragraph.TEMPLATE_RIGHT	= 1;
Paragraph.TEMPLATE_NOIMAGE	= 2;
Paragraph.FLASH_PLAYER		= "/elements/flash/flvplayer.swf";
Paragraph.FLV_UPLOAD_IMAGE	= "/image/flv_upload.gif";	//flvがまだアップロードされてない場合に使用する画像パス
Paragraph._DEFAULT_IMAGE	= "/elements/image/noimage.gif";
Paragraph._DEFAULT_IMAGE_WIDTH	= 245;
Paragraph._DEFAULT_IMAGE_HEIGHT	= 190;

Paragraph._defaultImage		= Paragraph._DEFAULT_IMAGE;
Paragraph._defaultImageWidth	= Paragraph._DEFAULT_IMAGE_WIDTH;
Paragraph._defaultImageHeight	= Paragraph._DEFAULT_IMAGE_HEIGHT;

/**
 * デフォルトのイメージを設定する
 *
 * @param src    :String イメージリソース
 * @param width  :Number 幅
 * @param height :Number 高さ
 */
Paragraph.setDefaultImage = function(src, width, height)
{
	Paragraph._defaultImage = src ? src : Paragraph._DEFAULT_IMAGE;
	if (width != undefined) {
		Paragraph._defaultImageWidth  = width != null ? width : Paragraph._DEFAULT_IMAGE_WIDTH;
	}
	if (height != undefined) {
		Paragraph._defaultImageHeight = height != null ? height : Paragraph._DEFAULT_IMAGE_HEIGHT;
	}
}

/**
 * デフォルトのイメージを取得する
 *
 * @return Object
 */
Paragraph.getDefaultImage = function() {
	return {src    :Paragraph._defaultImage,
		width  :Paragraph._defaultImageWidth,
		height :Paragraph._defaultImageHeight};
}


//===========================================================================================================================

document.clickElement = null;	//クリックしたエレメントが代入される
document.observeElements = [];	//監視するエレメント達

function getAttributeValue(node, attr) {
	return node.attributes[attr] != undefined ? node.attributes[attr].value : node.getAttributeNode(attr).value;
}

function getLayOj(layName){  
	if(document.getElementById) {           //e5,e6,n6,n7,m1,o6,o7,s1用
		return document.getElementById(layName);
	} else if(document.all) {               //e4用
		return document.all(layName);
	} else if(document.layers) {            //n4用
		return document.layers[layName];
	}
}

function getLayStyleOj(layName){  
	if(document.getElementById) {           //e5,e6,n6,n7,m1,o6,o7,s1用
		return document.getElementById(layName).style;
	} else if(document.all) {               //e4用
		return document.all(layName).style;
	} else if(document.layers) {            //n4用
		return document.layers[layName];
	}
}

//document.getElementByIdの略
function $() {
	var elements = [];
	if (arguments.length <= 1) {
		return getLayOj(arguments[0]);
	}
	
	for(var i = 0; i < arguments.length; i++) {
		elements[i] = getLayOj(arguments[i]);
	}
	
	return elements;
}

//スタイルオブジェクトを返す
function $s() {
	var elements = [];
	if (arguments.length <= 1) {
		return getLayStyleOj(arguments[0]);
	}
	
	for(var i = 0; i < arguments.length; i++) {
		elements[i] = getLayStyleOj(arguments[i]);
	}
	
	return elements;
}

//タグを特殊文字に置き換える;
function replaceTag(str) {
	var tmp = "";
	
	for(var i = 0; i < str.length; i++)
	{
		var chr = str.charAt(i);
		if (chr == "<") {
			chr = "&lt;";
		} else if (chr == ">") {
			chr = "&gt;";
		}
		tmp += chr;
	}
	
	return tmp;
}

//既存のObject.watchメソッドとは少し内部が違う。
Object.WATCH_TIME    = 1;
Object._watchObjects = [];
Object._watchId      = 0;

Object.watch = function(propname, handler, userData)
{
	if (!propname || !handler) {
		return false;
	}
	
	Object._watchObjects[Object._watchObjects.length] = {
		_propname : propname,
		_oldValue : eval(propname),
		_handler  : handler
	};
	
	if (!Object._watchId) {
		Object._watchId = setInterval(function()
		{
			var objects = Object._watchObjects;
			for(var i in objects) {
				if (objects[i]._oldValue != eval(objects[i]._propname))
				{
					eval(objects[i]._handler)(objects[i]._propname,
						objects[i]._oldValue, eval(objects[i]._propname), userData);
					objects[i]._oldValue = eval(objects[i]._propname);
				}
			}
		},
		Object.WATCH_TIME);
	}
	
	return true;
}

Object.unwatch = function(propname) {
	var b = false;
	var objects = Object._watchObjects;
	for(var i in objects) {
		if (objects[i]._propname == propname) {
			objects.splice(i, 1);
			b = true;
		}
	}
	
	if (objects.length == 0) {
		clearInterval(Object._watchId);
	}
	
	return b;
}


//クラス群=========================================================================================================================================

/**
 * Elementクラス
 *
 * @param id	:String id名
 * @param tag	:String tag名
 *
 * @return Element
 */
function Element(id, tag) {
	var element = !tag ? document.createElement('div') : document.createElement(tag);
	element.id = id;
	if (document.layers) {
		element.style = document.layers[id];
	}
	
	/**
	 * エレメントに子エレメントを追加する
	 *
	 * @param element:Element 子エレメント
	 *
	 * @return Object
	 */
	element.add = function(element) {
		if (typeof element != "object") {
			var span = document.createElement('span');
			span.innerHTML = element;
			element = span;
		}
		
		try {
			this.appendChild(element);
			return element;
		} catch(e) {
			return null;
		}
	}
	
	/**
	 * イベントにリスナーを追加する
	 * また、ieの場合、リスナーに渡す引数にDOM Eventに模したオブジェクトを与えてやる
	 *
	 * @param type		:String		イベント名
	 * @param listener	:Function	イベントハンドラ
	 */
	element.addEvent = function(type, listener)
	{
		if (this.addEventListener) {		//Standard DOM Events
			this.addEventListener(type, listener, false);
		} else if (this.attachEvent) {	//ie
			this.attachEvent('on' + type,
				function() { listener({
					type		: window.event.type,
					target		: window.event.srcElement,
					currentTarget	: this,
					clientX		: window.event.clientX,
					clientY		: window.event.clientY,
					pageX		: document.body.scrollLeft + window.event.clientX,
					pageY		: document.body.scrollTop  + window.event.clientY,
					shiftKey	: window.event.shiftKey,
					stopPropagation	: function() { window.event.cancelBubble = true }
				} ) }
			);
		}
	}
	
	/**
	 * イベントを解除する
	 */
	element.removeEvent = function(type, listener)
	{
		if (this.removeEventListener) {
			this.removeEventListener(type, listener, false);
		} else if (this.detachEvent) {
			try {
				this.detachEvent('on' + type, listener);
			} catch (e) {}
		}
	}
  	
	element.resizeToLayer = function(width, height) {
		if (navigator.userAgent.search(
			"Opera(\ |\/)6") != -1) {			//o6用
			this.style.pixelWidth  = width;
			this.style.pixelHeight = height;
		} else if (document.getElementById) {	//e5, e6, n6, n7, m1, o7, s1用
			this.style.width  = width  + 'px';
			this.style.height = height + 'px';
		} else if (document.all) {				//e4用
			this.style.pixelWidth  = width;
			this.style.pixelHeight = height;
		} else if (document.layers) {			//n4用
			this.style.resizeTo(width, height);
		}
	}
	
	element.resizeByLayer = function(offsetX, offsetY) {
		if (navigator.userAgent.search(
			"Opera(\ |\/)6") != -1) {			//o6用
			this.style.pixelWidth  = this.style.pixelWidth  + offsetX;
			this.style.pixelHeight = this.style.pixelHeight + offsetY;
		} else if (document.getElementById) {	//e5, e6, n6, n7, m1, o7, s1用
			this.style.width  = (parseInt(this.style.width ) + offsetX) + 'px';
			this.style.height = (parseInt(this.style.height) + offsetY) + 'px';
		} else if (document.all) {				//e4用
			this.style.pixelWidth  = this.style.pixelWidth  + offsetX;
			this.style.pixelHeight = this.style.pixelHeight + offsetY;
		} else if (document.layers) {			//n4用
			this.style.resizeBy(offsetX, offsetY);
		}
	}
	
	/**
	 * エレメントの表示、非表示を指定する。
	 * ただし、エレメントをドキュメントに配置していない状態で
	 * このメソッドを実行するとエラーが発生してしまうので注意が必要
	 */
	element.setVisible = function(b) {
		document.layers ? (this.style.visibility = b ? 'show' : 'hide')
			: (this.style.visibility = b ? 'visible' : 'hidden');
	}
	
	element.getVisible = function() {
		if (document.layers) {
			return this.style.visibility == 'show' ? true : false;
		}
		return this.style.visibility == 'visible' ? true : false;
	}
	
	element.setFloat = function(direction) {
		this.style.cssFloat != undefined ? this.style.cssFloat = direction
			: this.style.styleFloat = direction;
	}
	
	element.getFloat = function() {
		return this.style.cssFloat != undefined ? this.style.cssFloat
			: this.style.styleFloat;
	}
	
	//レイヤー左辺X座標get
	element.getLeft = function() {
		if (document.all) {						//e4,e5,e6,o6,o7用
			return document.all(this.id).style.pixelLeft;
		} else if (document.getElementById) {	//n6,n7,m1,s1用
			return (document.getElementById(this.id).style.left != "")
				? parseInt(document.getElementById(this.id).style.left) : "";
		} else if (document.layers) {			//n4用
			return document.layers[this.id].left;
		}
	}
	
	//レイヤー上辺Y座標get
	element.getTop = function() {
		if (document.all) {						//e4,e5,e6,o6,o7用
			return document.all(this.id).style.pixelTop;
		} else if (document.getElementById) {	//n6,n7,m1,s1用
			return (document.getElementById(this.id).style.top != "")
				? parseInt(document.getElementById(this.id).style.top) : "";
		} else if (document.layers) {			//n4用
			return document.layers[this.id].top;
		}
	}
	
	//レイヤー右辺X座標get
	element.getRight = function() {
		if (document.all) {						//e4,e5,e6,o6,o7用
			return document.all(this.id).style.pixelLeft
				+ document.all(this.id).style.pixelWidth;
		} else if (document.getElementById) {	//n6,n7,m1,s1用
			var l = document.getElementById(this.id).style.left;
			var w = document.getElementById(this.id).style.width;
			return (l != "" && w != "") ? parseInt(l) + parseInt(w) : "";
		} else if (document.layers) {			//n4用
			return document.layers[this.id].left + document.layers[this.id].clip.right;
		}
	}
	
	//レイヤー下辺Y座標get
	element.getBottom = function() {
		if (document.all) {						//e4,e5,e6,o6,o7用
			return  document.all(this.id).style.pixelTop
				+ document.all(this.id).style.pixelHeight;
		} else if (document.getElementById) {	//n6,n7,m1,s1用
			var t = document.getElementById(this.id).style.top;
			var h = document.getElementById(this.id).style.height;
			return (t != "" && h != "" ) ? parseInt(t) + parseInt(h) : "";
		} else if (document.layers) {			//n4用
			return document.layers[this.id].top
				+ document.layers[this.id].clip.height;
		}
	}
	
	return element;
}

//========================================================================================================================================
/**
 * TextFieldクラス
 *
 * @param id:String id名
 * 
 * @return Element
 */
function TextField(id) {
	var element = document.createElement('textarea');
	element.id = id;
	
	element.connect = function(layName) {
		var e = "$('" + this.id + "')";
		Object.watch(e + ".value", e + ".onChange", layName);
	}
	
	element.onChange = function(propname, oldVal, newVal, userData) {}
	
	return element;
}

//========================================================================================================================================
/**
 * Buttonクラス
 *
 * ボタンを生成する
 *
 * @param id		:String		id名
 * @param value		:String		ラベル
 * @param handler	:Function	ボタンが押された際、呼び出される関数
 *
 * @return Element
 */
function Button(id, value, handler) {
	var element = new Element(id, "input");
	
	element.className	+= " " + Button.CLASSNAME;
	element.type		= "button";
	element.value		= value;
	element.onclick		= handler;
	
	return element;
}
Button.CLASSNAME = "Button";

//========================================================================================================================================
/**
 * Eventクラス
 *
 * イベントハンドラ等を管理する
 */
if (!window.Event) {
	Event = new Object();
}
Event.LOAD	= "load";
Event.UNLOAD	= "unload";
Event.FOCUS	= "focus";
Event.BLUR	= "blur";
Event.SUBMIT	= "submit";
Event.RESET	= "reset";
Event.CHANGE	= "change";
Event.RESIZE	= "resize";
Event.MOVE	= "move";	//n4
Event.DRAGDROP	= "dragdrop";	//n4
Event.ABORT	= "abort";
Event.ERROR	= "error";
Event.SELECT	= "select";

/**
 * マウスＸ座標を取得する
 *
 * @param e:Event イベントオブジェクト
 *
 * @return Number マウスＸ座標
 */
Event.pointerX = function(e) {
	if (navigator.userAgent.search("Opera(\ |\/)6") != -1)	//o6用
	{
		return e.clientX;
	}
	else if (document.all)					//e4,e5,e6用
	{
		return document.body.scrollLeft + event.clientX;
	}
	else if (document.layers || document.getElementById)	//n4,n6,n7,m1,o7,s1用
	{
		return e.pageX;
	}
}

/**
 * マウスＹ座標を取得する
 *
 * @param e:Event イベントオブジェクト
 *
 * @return Number マウスＹ座標
 */
Event.pointerY = function(e) {
	if (navigator.userAgent.search("Opera(\ |\/)6") != -1)	//o6用
	{
		return e.clientY;
	}
	else if (document.all)					//e4,e5,e6用
	{
		return document.body.scrollLeft + event.clientY;
	}
	else if (document.layers || document.getElementById)	//n4,n6,n7,m1,o7,s1用
	{
		return e.pageY;
	}
}

Event.observe = function(element, type, observer)
{
	if (element.addEventListener) {		//Standard DOM Events
		element.addEventListener(type, observer, false);
	} else if (element.attachEvent) {	//ie
		element.attachEvent('on' + type,
			function() { observer({
				type		: window.event.type,
				target		: window.event.srcElement,
				currentTarget	: this,
				clientX		: window.event.clientX,
				clientY		: window.event.clientY,
				pageX		: document.body.scrollLeft + window.event.clientX,
				pageY		: document.body.scrollTop  + window.event.clientY,
				shiftKey	: window.event.shiftKey,
				stopPropagation	: function() { window.event.cancelBubble = true }
			})}
		);
	}
}

Event.stopObserving = function(element, type, observer)
{
	if (element.removeEventListener) {	//Standard DOM Events
		element.removeEventListener(type, observer, false);
	} else if (element.detachEvent) {	//ie
		try {
			element.detachEvent('on' + type, observer);
		} catch (e) {}
	}
}

//========================================================================================================================================
/**
 * KeyboardEventクラス
 * 
 * キーイベントを示す定数群
 */
var KeyboardEvent = {
	KEY_DOWN 	: "keydown",
	KEY_PRESS	: "keypress",
	KEY_UP		: "keyup"
}

//========================================================================================================================================
/**
 * MouseEventクラス
 *
 * マウスイベントを示す定数群
 */
var MouseEvent = {
	CLICK		: "click",
	DOUBLE_CLICK	: "dblclick",	
	MOUSE_DOWN	: "mousedown",
	MOUSE_UP	: "mouseup",
	MOUSE_OVER	: "mouseover",
	MOUSE_OUT	: "mouseout",
	MOUSE_MOVE	: "mousemove"
}

//========================================================================================================================================
/**
 * Directionクラス
 *
 * 方向を示す定数群
 */
var Direction = {
	LEFT	: 0x01,
	TOP	: 0x02,
	RIGHT	: 0x04,
	BOTTOM	: 0x08,
	ALL	: 0x15
};