サイトマップ

JavaScriptコードスニペット:移動・リサイズ可能なミニウインドウを表示する

ダイアログ風のウインドウを表示する」のゴールはここにありました。画面内で自由に移動・リサイズ可能なミニウインドウが実現できれば、WebOSみたいなことが可能です。まずは中身の無い空のウインドウを生成し、他のプログラムから利用できるようにします。このプログラムの機能は

  • ウインドウは生成されると画面中央に配置される。
  • ウインドウのタイトルバーを掴んで画面内を自由に移動できる。
  • ウインドウの隅を掴んで画面内で自由にリサイズできる。
  • タイトルバー右端のwindow-closeアイコンをクリックするとウインドウは消滅する。
  • 引数で指定されたオブジェクトから初期サイズやタイトルなどのプロパティを読み込み、コンテンツを表示する。

といったところです。利用例については、また別の機会に。

[サンプルの実行]←クリックすると画面中央に小さなウインドウが表示されます。
var win = new @INCLUDE(window.js)({ title:'空のウインドウ' });

window.js本体

window.js
/*
 * window.js - ミニwindowを生成する
 * 依存するライブラリ:geometry.js, style.js, event.js, pngdecode.js
 * 影響を受けるプロパティ:
 *	- document.onmousemoveその他
 *	- window移動中にGoogleツールバーがエラーを吐く
 */
function(object) {
	var ICONS = {
		'window-close' :
		'data:image/png;base64,' +
		'iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAAAAABzHgM7AAAAAXNSR0IArs4c6QAA' +
		'AAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sHFgQsNRv0lU4AAACnSURBVAgd' +
		'AZwAY/8BWjoACPgACPgACPi+BDpj3ykAAAAAAOgQAAIA8Hy+AAAAAMdj8AAAlP/W' +
		'Ur3//8ZKzv+UAJT//9ZKxr1Kzv//lAQAAAApjHQAjCkAAAACAAAAAOcIAPAAAAAA' +
		'AJT//71K1s5Kxv//lACU/71K1v//zkrO/5QAlNZS1v/////OUv+UAJT37///////' +
		'////lAS+AAAAAAAAAAAAAL4Dt0hRWmfrigAAAABJRU5ErkJggg=='
	};
	var self = this;
	if (!object['width']) object['width'] = 400;
	if (!object['height']) object['height'] = 300;
	var bind = function(obj, fn) {
		return function() { return fn.apply(obj, arguments); }
	};
	var fixEvent = @INCLUDE(event.js);
	var geom = self.geom = new @INCLUDE(geometry.js);
	var pngdecode = @INCLUDE(pngdecode.js);
 
	self.style = (@INCLUDE(style.js))(
		"div.window-frame {" +
		"	border:1px solid gray;" +
		"	position:absolute;" +
		"	font-size:10pt;" +
		"	color:black;" +
		"	text-align:left;" +
		"	line-height:1em;" +
		"	z-index:9999;" +
		"}" +
		"div.window-head {" +
		"	color:white;" +
		"	background-color:gray;" +
		"	height:1em;" +
		"	padding: 3px 3px;" +
		"	cursor:move;" +
		"}" +
		"div.window-body {" +
		"	clear:both;" +
		"	background-color:white;" +
		"	padding:0;" +
		"	margin:0;" +
		"	overflow:auto;" +
		"}" +
		"img.close-icon," +
		"div.close-icon {" +
		"	float:right;" +
		"	vertical-align:baseline;" +
		"	width:12px; height:12px;" +
		"	cursor:default;" +
		"}"
	);
 
	self.frame = document.body.appendChild(document.createElement('div'));
	self.frame.className = self.frame.styleClass = 'window-frame';
	self.frame.style.width = object['width'] + 'px';
	self.frame.style.height = object['height'] + 'px';
	self.frame.onclick = function(evt) {
		if (typeof object.onfocus == 'function') object.onfocus();
	};
	self.head = self.frame.appendChild(document.createElement('div'));
	self.head.className = self.frame.styleClass = 'window-head';
	var closeIcon = self.head.appendChild(document.createElement('img'));
	closeIcon.className = closeIcon.styleClass = 'close-icon';
	closeIcon.onmousedown = function(evt) {
		evt = fixEvent(evt).stop();
	};
	closeIcon.onclick = bind(self, function(evt) {
		fixEvent(evt).stop();
		this.exit();
	});
	closeIcon.onerror = function(evt) { //for data scheme unsupported browser
		evt = fixEvent(evt);
		var img = evt.target;
		var png = new pngdecode(img.src.replace(/^.*,(.*)$/, "$1"));
		var newimg = png.toDOM();
		newimg.className = newimg.styleClass = 'close-icon';
		newimg.onmousedown = img.onmousedown;
		newimg.onclick = img.onclick;
		newimg.style.cssFloat = newimg.style.styleFloat = 'right';
		img.parentNode.insertBefore(newimg, img);
		img.style.display = 'none';
	};
	closeIcon.src = ICONS['window-close'];
	self.head.appendChild(document.createTextNode(object['title']));
 
	self.body = self.frame.appendChild(document.createElement('div'));
	self.body.className = self.frame.styleClass = 'window-body';
	self.body.style.height = (self.frame.offsetHeight - self.body.offsetTop - self.frame.clientTop * 2) + 'px';
	if (object.content) self.body.appendChild(object.content);
 
	var size = geom.getWindowSize();
	self.frame.style.left = ((size.width - self.frame.offsetWidth) / 2
		+ document.documentElement.scrollLeft + document.body.scrollLeft) + 'px';
	self.frame.style.top = ((size.height - self.frame.offsetHeight) / 2
		+ document.documentElement.scrollTop + document.body.scrollTop) + 'px';
 
	self.frame.onfit = function() {
		var fg = geom.getGeometry(self.frame);
		if (self.head.style.display)
			self.head.style.display = '';
		var hg = geom.getGeometry(self.head);
		self.body.style.height = (fg.height - hg.height - fg.borderTop - fg.borderBottom) + 'px';
		self.body.style.display = '';
		return false;
	};
 
	self.head.onmousedown = bind(self, function(evt) {
		evt = fixEvent(evt).stop();
		document.onmousemove = this.move;
		document.onmouseup = this.moveend;
		document.onselectstart = function(evt){ evt = fixEvent(evt); evt.stop(); }
		this.offset = { x:evt.offsetX, y:evt.offsetY };
	});
 
	self.move = bind(self, function(evt) {
		evt = fixEvent(evt).stop();
		self.frame.style.left = (evt.pageX - this.offset.x) + 'px';
		self.frame.style.top = (evt.pageY - this.offset.y) + 'px';
	});
 
	self.moveend = function(evt) {
		document.onmousemove = null;
		document.onmouseup = null;
		document.onselectstart = null;
	};
 
	self.exit = function(evt) {
		self.frame.parentNode.removeChild(self.frame);
		self.style.parentNode.removeChild(self.style);
		geom.finalize();
		if (typeof object.onunload == 'function') object.onunload();
	};
 
	//resizable
	geom.resizable(self.frame);
}

関連コンテンツ

 
research/1311816478.txt · 最終更新: 2011/07/28 10:54 by Kazuyuki Matsuda
特に明示されていない限り、本サイトの内容は次のライセンスに従います:Copyright(C) 2011 Shorindo, Inc. All Rights Reserved
Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki