<!DOCTYPE html>
<html>
<!-- { //# emir__INFO__
	git clone git@github.com:EnDe/EMiR.git

	WARNING: The code here is a mix of HTML, CSS and JavaScript. There is
	no proper design/architecture like MVC,  everything is implemented as
	simple as possible.  The intention is to define "things" once and use
	them multiple times.
	Most runtime-configuration can be done in the "Config" section of the
	Webpage, except configuration for debugging (see "var debug" below).
	There are also some comments "emir__*__" used as marker for tags.pl .
} //# emir__INFO__ -->
<head> <!-- //# emir__HEAD__ -->
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>EMiR - Event Mappings in Reality (emir.html 1.73)</title> <!-- //# emir__TITLE__ -->
	<meta name="dummy"          content=""> <!-- //# emir__META__ -->
	<meta name="Author"         content="Achim Hoffmann">
	<meta name="Generator"      content="me using vi ;-)">
	<meta name="DC.Creator"     content="emir @at@ my -dash- stp .dot. net">
	<meta name="DC.Date"        content="2009-08-02">
	<meta name="DC.Source"      content="@(#) emir.html 1.73 20/08/05 00:28:04">
	<meta name="DC.Identifier"  content="git://github .dot. com/EnDe/EMiR/">
	<meta name="DC.Title"       content="EMiR">
	<meta name="DC.Description" content="EMiR - Event Mappings in Reality, strange Browser behaviours">
	<meta name="DC.Language"    content="en">
	<meta name="DC.Rights"      content="Creative Commons 3.0, http://creativecommons.org/licenses/by-sa/3.0/">
	<style  type="text/css">
/*# { emir__CSS__ */
body, h1        { font-weight:normal; font-family:monospace; font-size:10pt; }
h2              { font-weight:bold;   font-size:150%; }
.chck { }
.c1 { float:left; background:#fafafa; width:1em; max-width:1em; position:fixed;top:0px;left:0px;margin:0px;padding:0px; height:100%; border-right:1px solid #000000; padding-left:0.3em; }
.c2             { margin-left:2em; }
.c2 > div       { padding:0.5em;   }
.c2 > div:hover { border-radius:8px; box-shadow:0px 5px 5px #666; }
.c2 > div button { width:7em; height:1.6em; }
.c2 li > b:before , .testme:before { content:"- test me -"; }
.c2 li > b      { background:#00ffff; border:1px solid #000000; }
.testme         { background:#00ffff; border:1px solid #000000; }
.c1 ul          { display:none; background:#fafafa; position:fixed; top:0.5em; left:1em; z-index:1; border-top:1px solid #000000;border-right:1px solid #000000;  border-bottom:1px solid #000000; padding:0.5em; }
.c1 li:hover ul { display:block; }
.c1    li       { list-style:none; margin-left:0px; }
.c1 ul li       { list-style:none; margin-left:0px; }
.nav a          { color:#000000; text-decoration:none; background:#f0f0f0; border:1px outset #f6f6f6; padding-left:0.5em; padding-right:0.5em; width:100%; font-weight:bold; }
.nav            { border-radius:8px; box-shadow:0px 5px 5px #666; }
.nav a:hover    { color:#0000ff; text-decoration:none; }
.nav a:active   { color:#000000; text-decoration:none; }
ul.conf { padding: 0px; }
ul.conf li {
	display:        none;
	list-style:     none;
	list-style-type:none;
}
ul.conf:hover li {
	display:        block;
	position:       absolute;
	margin-top:     -0.9em;
	margin-right:   1.0em;
	z-index:        1;
	background:     #ffffff;
}
.otab ul {
	padding-top:    1.0ex;
	padding-right:  1.0em;
	padding-bottom: 1px;
	margin-bottom:  0px;
	border-bottom:  1px solid #a0a0a0;;
}
.otab ul li {
	display:        inline;
	list-style:     none;
	list-style-type:none;
}
.otab ul li a {
	margin:         0px;
	padding-top:    0.3ex;
	padding-bottom: 0.3ex;
	padding-right:  0.5em;
	padding-left:   0.5em;
	border-right:   1px solid #a0a0a0;;
	border-top:     1px solid #a0a0a0;;
	border-left:    1px solid #a0a0a0;;
/*	border-bottom:  1px solid #a0a0a0; / * don't define here!  */
	-moz-border-radius-topleft:      5px;
	-moz-border-radius-topright:     5px;
	-khtml-border-radius-topleft:    5px;
	-khtml-border-radius-topright:   5px;
	-webkit-border-top-left-radius:  5px;
	-webkit-border-top-right-radius: 5px;
	text-decoration: none;
	color:          #000000;
}
.otab ul li a:hover { background:#a0a0a0; color:#000000; text-decoration:none; }
.otab ul li a:focus { outline-style:none; }
.otab_bg            { background:#d8d8d8; border-bottom:1px solid #a0a0a0; }
.otab_fg            { background:#ffffff; border-bottom:1px solid #ffffff; }
.utab ul {
	padding-right:  1.0em;
	padding-top:    1px;
	border-top:     1px solid #a0a0a0;;
}
.utab ul li {
	display:        inline;
	list-style:     none;
	list-style-type:none;
}
.utab ul li a {
	padding-top:    0.3ex;
	padding-bottom: 0.3ex;
	padding-right:  0.5em;
	padding-left:   0.5em;
	border-left:    1px solid #a0a0a0;
/*	border-top:     1px solid #a0a0a0; / * don't define here!  */
	border-right:   1px solid #a0a0a0;
	border-bottom:  1px solid #a0a0a0;
	-moz-border-radius-bottomleft:   5px;
	-moz-border-radius-bottomright:  5px;
	-khtml-border-radius-bottomleft: 5px;
	-khtml-border-radius-bottomright:5px;
	-webkit-border-bottom-left-radius: 5px;
	-webkit-border-bottom-right-radius:5px;
	text-decoration: none;
	color:          #000000;
	min-width:      8.0em;
}
.utab ul li a:hover         { background:#a0a0a0; color:#000000; text-decoration:none; }
.utab ul li a:focus         { outline-style:none; }
.utab_bg                    { background:#d8d8d8; border-top:1px solid #a0a0a0; }
.utab_fg                    { background:#ffffff; border-top:1px solid #ffffff; }
.text label                 { word-break:keep-all; } /* not yet working */
.text label input           { word-break:keep-all; } /* not yet working */
.c                          { width:20em; text-align:right; display:inline; }
p > i                       { background:#d0d0d0; font-family:monospace; font-size:16px; font-style:normal; }
span.tag                    { background:#c0c0f0; padding:3px 5px 3px 5px; font-weight:bold; min-width:8em; display:inline-block; }
span.tag_file               { background:#c0c0c0; font-weight:normal; }
span.tag:before             { content:"<"; }
span.tag:after              { content:">"; }
fieldset                    { background:#f0f0f0; padding:0px; }
fieldset:first-child        { background:#ffffff; }
fieldset:first-child:hover  { background:#00ffff; }
fieldset:first-child:focus  { background:#ff00ff; }
fieldset.e:first-child:hover{ background:#ffffff; }
.err                        { background:#ffff00; }
.err:first-child            { background:#ffff00; }
.err:hover                  { background:#ff0000; }
.err:first-child:hover      { background:#ff0000; }
.table  { border:1px solid #000000; border-collapse:separate; border-spacing:1px 1px; }
.status { border:1px solid #808080; color:#808080; background:#ffffcf; position:fixed; width:99.9%; height:3em; margin:0px; left:0px; bottom:0px; }
.status:before      { content: "Status: "; }
label               { border:1px solid #ffffff; padding:2px; margin:2px; }
.c2 > div label     { border:1px solid #00b0ff; padding:0px; margin:0px; }
#events, #tags, #config      { border-radius:8px; box-shadow:0px 5px 5px #666;
			padding-left:1em;
			padding-bottom:0.5em;
			border-right:1px solid #000000;
			border-bottom:1px solid #000000;
}
#events label:hover { border:1px solid #00b0ff; }
#tags   label:hover { border:1px solid #00b0ff; }
#config             { padding:0em; }
#config label       { width:20em; }
#config label:hover { border:1px solid #00b0ff; }
#config fieldset    { padding:1em; border:2px outset #f6f6f6; }
/*# } emir__CSS__ */
	</style>
<!--[if IE]><style  type="text/css">ul.conf li {display:block;}</style> <![endif] -->
	<script type="text/javascript">
//# { emir__JS__ 
// JavaScript used also in files generated by tags.pl
function $l$(typ)       {//#? called when "get list of .." clicked
	var o = [];
	switch (typ) {
	  case 'events': o = emir.get_events('all').sort(); break;
	  case 'html':   // no break;
	  case 'tags':   o = emir.get_tags('all').sort();   break;
	}
	var win = null;
	try {
		win = window.open('', typ,
				'resizable=yes,scrollbars=yes,dependent=yes'
				+',status=no,menubar=no,toolbar=no,location=no'
				+',innerHeight=400,innerWidth=400,width=450,height=500'
			);
	} catch (e) { alert('window.open: ',e); }
	try {
		// if (isKonqueror===true) { // some browsers behave strange ..
			//win.document.body.innerHTML = '<textarea rows="28" cols="99" id="scratch"></textarea>';
		//} else {
			var area = null;
			if (typ === 'html') {
				var obj  = null;
				area  = document.createElement('DIV');
				for (var a=0; a<o.length; a++) {
					obj  = document.createElement('SPAN');
					obj.innerHTML = ' ' + o[a] + ': &lt;' + o[a] + '&gt;&lt;/' + o[a] + '&gt;';
					area.appendChild(obj);
				}
			} else {
				area  = document.createElement('TEXTAREA');
				area.setAttribute('rows',25);
				area.setAttribute('cols',40);
				area.id   = typ;
				area.innerHTML = o.join('\n');
			}
			win.document.body.appendChild(area);
		//}
	} catch (e) { alert('create area',e); }
    // TODO: IE 10 throws exception but without any text
	return false;
}; // $l$
function $c$(obj,typ)   {//#? called when checkbox in "Show Events" clicked
	var val = (obj.checked===true) ? 'inline' : 'none';
	emir.status('checkbox: ' + typ);
	emir.find.checked({type:typ});
	emir.find.show(val);
	return true; // must return true, otherwise checkbox will not be activated
}; // $c$
function $e$(tag,evt)   {//#? called for events of tag; sets corresponding checkbox
	if (tag.id===undefined) { return true; } // take care for event bubbling
	if (tag.id==='')        { return true; } // ..
	if (emir.cfg.e_show===true) {
		if (tag.id==='marquee') { return true; } // marquee.onStart is too noisy
		emir.status('event: ' + tag.id + '.' + evt + '()');   // does not show text in all browsers
	}
	var o = document.getElementById(tag.id + '-' + evt);
	if (o===null)           { return false; }
	if (!o.emirsend) {
		// only send for first occurance
		// otherwise huge amount of onMouse* events may flood the server
		// and slow down the browser
		if (emir.cfg.e_send===true) {
			emir.http.post_event(tag.tagName, evt);
			o.emirsend = true;
		}
	}
	o.disabled = false; // tweak some browsers to display new text
	o.checked  = true;
	o.disabled = true;
	return false;
}; // $e$
function $s$(obj,typ)   {//#? called when highlight (un)check in "Show Events" clicked
	if (emir.selected.event===undefined) { return false; }
	emir.status('highlight: ' + typ);
	var c = null;
	var e = emir.get_events(emir.selected.event);
	for (var i=0; i<e.length; i++) {
		c = document.getElementById('use-event-' + e[i] + '-' + e[i]);
		if (typ==='check')   { c.checked = true; }
		if (typ==='uncheck') { c.checked = false; }
		$c$(c, e[i]);
	}
	return false;
}; // $s$
function $t$(obj,cls)   {//#? called when tab in "Show Events", "Show Tags" clicked
	emir.status('tab: ' + obj.id);
	var c   = '';
	var arr = obj.id.split('-'); // we get: use-event-* or use-tag-*
	var typ = arr[1];
	var tab = arr[2];
	arr = document.getElementsByTagName('A');
	for (var a=0; a<arr.length; a++) {
		if (arr[a].id===undefined)         { continue };  // unknown object
		if (arr[a].id.split('-')[1]!==typ) { continue };  // skip tabs in other list
		c = arr[a].getAttribute('class');
		if (c.match(new RegExp('^'+cls+'tab_fg$'))!==null) {
			arr[a].setAttribute('class',c.replace('fg','bg'));
			break;
		}
		
	}
	switch (typ) {
	  case 'event': emir.selected.event = tab; break;
	  case 'tag':   emir.selected.tag   = tab; break;
	}
	emir.find.mark(obj);  //
	obj.setAttribute('class',c);
	c = null; try { delete this.arr; } catch(e) { /* some browsers crash */ }
   	return false;
}; // $t$
function dumm(tag)      { alert('Tag <'+tag+'> clicked');return false; }; //#? called when no click expected

function dbx_tree(obj,i) {//#? print functions tree from object
	var txt = '';
	var ident   = '';
	for (var a=0; a<i; a++) { ident += '    '; }
	for(var property in obj) { 
		var type  = typeof(obj[property]);
		switch (type) {
		  case 'function': break;
		  case 'object':   break;
		  case 'undefined': txt += ident + property + ':\tUNDEF;\n'; break;
		  default: // boolean, number, string
			if (type === 'string') { type = '"' + obj[property].valueOf() + '"'; }
			txt  += ident + property + ':\t' + type + ';\n';
			break;
		}
		continue;
	} 
	for(var property in obj) { 
		var type  = typeof(obj[property]);
		switch (type) {
		  case 'function':
			f    = obj[property] + "";
			f    = f.replace(/(\r\n|\r|\n[\s\S]*)/gm, ' }\n'); // line with "function" only
			f    = f.replace(/([{]\s*[\r\n])/, '{}');// pretty print
			f    = f.replace(/([)]\s*)/, ')\t');     // pretty print
			txt += ident + property + ':\t' + f;
			break;
		  case 'object':
			txt += ident + property + ':\t{\n' + dbx_tree(obj[property], i+1) + ident + '};\n';
			break;
		  case 'boolean':
		  case 'number':
		  case 'string':
			break;
		  default: // boolean, number, string
			txt += ident + property + ':\t' + type + '?;\n';
			break;
		}
		continue;
	} 
	return txt;
}; // dbx_tree

// JavaScript used in this file only
window.EMiR = function() {  //#? EMiR object
	function $(id)  { return document.getElementById(id); }
	var debug      = {
        // debugging is enabled if max_tags or max_events > 0
		'max_tags':     0,  // set >0 to use tags.debug
		'max_events':   0,  // set >0 to use events.debug
	}; // debug

	var events     = {
		/*
		 * for a description of the sub-hashes used here, see below in
		 * w3c, categories
		 */
		'w3c': { // well known categories
			// hash labels here must be the same as hash labels following categories{}
			'HTML 4':       {desc:'w3c events: HTML 4',
							 url:'http://www.w3.org/TR/html4/interact/scripts.html#adef-'},
			'HTML 5':       {desc:'w3c events: HTML 5',
							 url:'http://www.w3.org/TR/html5/browsers.html#events-handler-attributes-on-elements-document-objects-and-window-objects'},
							//see also:  url:'http://dev.w3.org/html5/spec/Overview.html',
			'&nbsp;':       {desc:'reset all highlights', url:''},
			'DOM Level 2':  {desc:'w3c events: DOM Level 2',
							 url:'http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-eventgroupings'},
							//see also:  url:'http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html',
			'DOM Level 3':  {desc:'w3c events: DOM Level 3',
							 url:'http://www.w3.org/TR/DOM-Level-3-Events/events.html#Events-EventTypes-complete'}
		}, // w3c
		'categories': {
			'debug':    {desc:'events used for debugging',                   url:''},
			'all':      {desc:'all category, standard w3c and proprietary',  url:''},
			'Form':     {desc:'common w3c events: category HTML form',       url:''},
			'Keys':     {desc:'common w3c events: category Keyboard',        url:''},
			'Mouse':    {desc:'common w3c events: category Mouse',           url:''},
			'Mutation': {desc:'common w3c events: category Mutation',        url:''},
			'Object':   {desc:'common w3c events: category HTML frame/object',url:''},
			'Pointer':  {desc:'common w3c events: category Pointer',         url:'https://en.wikipedia.org/wiki/DOM_events'},
			'Progress': {desc:'common w3c events: category Progress',        url:'https://en.wikipedia.org/wiki/DOM_events'},
			'Touch':    {desc:'common w3c events: category Touch',           url:'https://en.wikipedia.org/wiki/DOM_events'},
			'User':     {desc:'common w3c events: category User Interface',  url:''},
			'Indie':    {desc:'see https://en.wikipedia.org/wiki/DOM_events',url:'https://en.wikipedia.org/wiki/DOM_events'},
			'&nbsp;':   {desc:'reset all highlights',    url:''},
				/* reset is a empty tab used as separartor
				 * it serves as "reset" automatically ;-)  */
		//'browsers':
			'Opera':    {desc:'spezial Opera events',            url:''},
			'Safari':   {desc:'spezial Safari events',           url:''},
			'Firefox3': {desc:'spezial Firfox 3 events',         url:''},
			'Firefox4': {desc:'spezial Firfox 4 events',         url:''},
			'IE':       {desc:'spezial IE events',               url:'https://en.wikipedia.org/wiki/DOM_events'},
			'Webkit':   {desc:'spezial Webkit events',           url:''},
			'&#160;':   {desc:'(spacer, no content)',            url:''},
			'iOS':      {desc:'spezial iOS (Safari) events',     url:''},
			'Android':  {desc:'spezial Android events',          url:''},
			'XUL':      {desc:'spezial Mozilla XUL elements events', url:'https://en.wikipedia.org/wiki/DOM_events'},
			'unsorted': {desc:'spezial events (mainly Mozilla)', url:'https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/  https://developer.mozilla.org/en-US/docs/Web/API/Element/'}
		}, // categories
		/*
		 * # TODO: move some texts here to the public description in HTML
		 * Some notes on names of hashes:
		 *    - Each of following hashes should be described above in:
		 *      w3c or categories.
		 *    - Sequence of following hashes is important for display.
		 * Some notes on names of events:
		 *    - Spelling must be identical in all hashes.
		 *    - Case-sensitive events are marked with "case-sensitive!".
		 *    - Some events are marked with "typo?", because unsure if
		 *      they are used in that spelling.
		 *    - Some events in following categories are defined twice:
		 *      with and without * prefix "on", for example in 'User'.
		 *    - Some events are not intended to be used as attribute in
		 *      HTML tags, but solely exist in the HavaScript implemen-
		 *      tation of a browser, they are marked "native JavaScript"
		 *      and listed here,  because they are sometimes accessable
		 *      with the attribute too.
		 */
		'debug': {    // only used if debug.max_events > 0
			'onClick':           null,
			'onKeyUp':           null,
			'onMouseOut':        null,
			'onKeyDown':         null,
			'onKeyPress':        null,
			'onMouseEnter':      null,
			'onMouseLeave':      null
		}, // debug
/*
		'todo-2020': {
			'altKey':            null,   // 
			'animationName':     null,   // 
			'bubbles':           null,   // 
			'button':            null,   // 
			'buttons':           null,   // 
			'cancelable':        null,   // 
			'charCode':          null,   // 
			'changeTouches':     null,   // 
			'clientX':           null,   // 
			'clientY':           null,   // 
			'clipboardData':     null,   // 
			'code':              null,   // 
			'composed':          null,   // 
			'createEvent':       null,   // 
			'ctrlKey':           null,   // 
			'currentTarget':     null,   // 
			'data':              null,   // 
			'dataTdefaultPrevented':   null,   // 
			'deltaX':            null,   // 
			'deltaY':            null,   // 
			'deltaZ':            null,   // 
			'deltaMode':         null,   // 
			'detail':            null,   // 
			'elapsedTime':       null,   // 
			'elapsedTime':       null,   // 
			'eventPhase':        null,   // 
			'getTargetRanges':   null,   // 
			'getModifierState':  null,   // 
			'inputType':         null,   // 
			'isComposing':       null,   // 
			'isTrusted':         null,   // 
			'key':               null,   // 
			'keyCode':           null,   // 
			'location':          null,   // 
			'lengthComputable':  null,   // 
			'loaded':            null,   // 
			'metaKey':           null,   // 
			'MovementX':         null,   // 
			'MovementY':         null,   // 
			'newValue':          null,   // 
			'newURL':            null,   // 
			'offsetX':           null,   // 
			'offsetY':           null,   // 
			'oldValue':          null,   // 
			'oldURL':            null,   // 
			'pageX':             null,   // 
			'pageY':             null,   // 
			'persisted':         null,   // 
			'preventDefault':    null,   // 
			'propertyName':      null,   // 
			'pseudoElement':     null,   // 
			'region':            null,   // 
			'relatedTarget':     null,   // 
			'repeat':            null,   // 
			'screenX':           null,   // 
			'screenY':           null,   // 
			'shiftKey':          null,   // 
			'state':             null,   // 
			'stopImmediatePropagation':   null,   // 
			'stopPropagation':   null,   // 
			'storageArea':       null,   // 
			'target':            null,   // 
			'targetTouches':     null,   // 
			'timeStamp':         null,   // 
			'total':             null,   // 
			'touches':           null,   // 
			'type':              null,   // 
			'url':               null,   // 
			'which':             null,   // 
			'view':              null    // 
		}, // todo-2020
*/
		'all': {    //# emir__EVENTS__
			// only events not specifid elsewhere # TODO
			'FSCommand':         null,   // SWF only
			'onBegin':           null,
			'onControlSelect':   null,
			'onEnd':             null,
			'onExit':            null,
			'onMediaComplete':   null,
			'onMediaError':      null,
			'onRepeat':          null,
			'onResume':          null,
			'onReverse':         null,
			'onRowDelete':       null,   // typo?
			'onRowInserted':     null,   // typo?
			'onSeek':            null,
			'onSyncRestored':    null,
			'onSynchRestored':   null,   // typo?
			'onTimeError':       null,
			'onTimeuout':        null,   // typo?
			'onTimeUpdate':      null,
			'onTrackChange':     null,
			'onURLFlip':         null,
			'seekSegmentTime':   null
			// ...
			// all others will be added dynamically in init()
		}, // all
		'HTML 4': {
			'onBlur':            null,
			'onChange':          null,
			'onClick':           null,
			'onDblClick':        null,
			'onFocus':           null,
			'onKeyDown':         null,
			'onKeyPress':        null,
			'onKeyUp':           null,
			'onLoad':            null,
			'onMouseDown':       null,
			'onMouseMove':       null,
			'onMouseOut':        null,
			'onMouseOver':       null,
			'onMouseUp':         null,
			'onReset':           null,
			'onSelect':          null,
			'onSubmit':          null,
			'onUnload':          null
		}, // HTML 4
		'HTML 5': {
			//objects: {'document':null, 'window':null },
			'onAuxClick':        null,   //# unknown ??
			'onAbort':           null,
			'onAfterPrint':      null,
			'onBeforePrint':     null,
			'onBeforeUnload':    null,
			'onBlur':            null,
			'onCanPlay':         null,
			'onCanPlayThrough':  null,
			'onChange':          null,
			'onClick':           null,
			'onCompositionEnd':  null,   //# unknown ??
			'onCompositionStart':null,   //# unknown ??
			'onCompositionUpdate':   null,   //# unknown ??
			'onContextMenu':     null,
			'onCueChange':       null,   //# unknown ??
			'onDblClick':        null,
			'onDrag':            null,
			'onDragEnd':         null,
			'onDragEnter':       null,
			'onDragLeave':       null,
			'onDragOver':        null,
			'onDragStart':       null,
			'onDrop':            null,
			'onDurationChange':  null,
			'onEmtied':          null,
			'onEnded':           null,
			'onError':           null,
			'onFocus':           null,
			'onFormChange':      null,
			'onFormData':        null,   //# unknown ??
			'onFormInput':       null,
			'onHashChange':      null,
			'onInvalid':         null,
			'onLoad':            null,
			'onLoadedData':      null,
			'onLoadedMetaData':  null,
			'onLoadStart':       null,
			'onKeyDown':         null,
			'onKeyPress':        null,
			'onKeyUp':           null,
			'onMessage':         null,
			'onMouseDown':       null,
			'onMouseMove':       null,
			'onMouseOut':        null,
			'onMouseOver':       null,
			'onMouseUp':         null,
			'onMouseWheel':      null,
			'onOffline':         null,
			'onOnline':          null,
			'onPause':           null,
			'onPlay':            null,
			'onPlaying':         null,
			'onGotPointerCapture': null, //# unknown ??
			'onLostPointerCapture':null, //# unknown ??
			'onPointerCancel':   null,   //# unknown ??
			'onPointerCenter':   null,   //# unknown ??
			'onPointerDown':     null,   //# unknown ??
			'onPointerEnter':    null,   //# unknown ??
			'onPointerLeave':    null,   //# unknown ??
			'onPointerMove':     null,   //# unknown ??
			'onPointerOut':      null,   //# unknown ??
			'onPointerOver':     null,   //# unknown ??
			'onPointerRawUpdate':null,   //# unknown ??
			'onPointerUp':       null,   //# unknown ??
			'onPopState':        null,
			'onProgress':        null,
			'onRateChange':      null,
			'onReadyStateChange':null,
			'onRedo':            null,
			'onReset':           null,   // missing?
			'onResize':          null,
			'onScroll':          null,
			'onSeeked':          null,
			'onSeeking':         null,
			'onSelect':          null,
			'onShow':            null,
			'onStalled':         null,
			'onStorage':         null,
			'onSubmit':          null,
			'onSuspend':         null,
			'onTimeupdate':      null,
			'onVolumeChange':    null,
			'onWaiting':         null,
			'onUndo':            null,
			'onUnload':          null    // missing?
		}, // HTML 5
		'DOM Level 2': {
			'onAbort':           null,
			'onBlur':            null,
			'onChange':          null,
			'onClick':           null,
			'onDOMActivate':     null,
			'onDOMAttrModified': null,
			'onDOMCharacterDataModified':    null,
			'onDOMFocusIn':      null,
			'onDOMFocusOut':     null,
			'onDOMNodeInserted': null,
			'onDOMNodeInsertedIntoDocument': null,
			'onDOMNodeRemoved':  null,
			'onDOMNodeRemovedFromDocument':  null,
			'onDOMSubTreeModified':          null,
			'onError':           null,
			'onFocus':           null,
			'onLoad':            null,
			'onMouseDown':       null,
			'onMouseMove':       null,
			'onMouseOut':        null,
			'onMouseOver':       null,
			'onMouseUp':         null,
			'onReset':           null,
			'onResize':          null,
			'onScroll':          null,
			'onSelect':          null,
			'onSubmit':          null,
			'onUnload':          null
		}, // DOM Level 2
		'DOM Level 3': {
			'onAuxClick':        null,   //# unknown ??
			'onAbort':           null,
			'onBlur':            null,
			'onChange':          null,
			'onClick':           null,
			'onCompositionEnd':  null,   //# unknown ??
			'onCompositionStart':null,   //# unknown ??
			'onCompositionUpdate': null, //# unknown ??
			'onCueChange':       null,   //# unknown ??
			'onDblClick':        null,
			'onDOMActivate':     null,
			'onDOMAttrModified': null,
			'onDOMAttributeNameChanged':     null,
			'onDOMCharacterDataModified':    null,
			'onDOMElementNameChanged':       null,
			'onDOMFocusIn':      null,
			'onDOMFocusOut':     null,
			'onDOMNodeInserted': null,
			'onDOMNodeInsertedIntoDocument': null,
			'onDOMNodeRemoved':  null,
			'onDOMNodeRemovedFromDocument':  null,
			'onDOMSubTreeModified':null,
			'onError':           null,
			'onFocus':           null,
			'onFormData':        null,
			'onKeyDown':         null,
			'onKeyUp':           null,
			'onLoad':            null,
			'onMouseDown':       null,
			'onMouseMove':       null,
			'onMouseMultiWheel': null,
			'onMouseOut':        null,
			'onMouseOver':       null,
			'onMouseUp':         null,
			'onMouseWheel':      null,
			'onGotPointerCapture': null,
			'onLostPointerCapture':null,
			'onPointerCancel':   null,
			'onPointerCenter':   null,
			'onPointerDown':     null,
			'onPointerEnter':    null,
			'onPointerLeave':    null,
			'onPointerMove':     null,
			'onPointerOut':      null,
			'onPointerOver':     null,
			'onPointerRawUpdate':null,
			'onPointerUp':       null,
			'onReset':           null,
			'onResize':          null,
			'onScroll':          null,
			'onSelect':          null,
			'onSubmit':          null,
			'onTextInput':       null,
			'onUnload':          null
		}, // DOM Level 3
		'Object': {
			'onAbort':           null,
			'onError':           null,
			'onChange':          null,
			'onLoad':            null,
			'onReset':           null,
			'onResize':          null,   // or User Interface?
			'onSave':            null,
			'onScroll':          null,   // or User Interface?
			'onSelect':          null,
			'onSubmit':          null,
			'onUnload':          null
		}, // Object
		'Keys': {
			'onKeyDown':         null,
			'onKeyPress':        null,
			'onKeyUp':           null
		}, // Keys
		'Form': {
			'onBlur':            null,
			'onChange':          null,
			'onFocus':           null,
			'onReset':           null,
			'onSelect':          null,
			'onSubmit':          null
		}, // Form
		'Mouse': {
			'onClick':           null,
			'onDblClick':        null,
			'onMouseDown':       null,
			'onMouseMove':       null,
			'onMouseOut':        null,
			'onMouseOver':       null,
			'onMouseUp':         null,
			'onMouseMultiWheel': null,
			'onMouseWheel':      null
		}, // Mouse
		'Mutation': {
			'DOMAttrModified':   null,
			'DOMCharacterDataModified':    null,
			'DOMNodeInsertedIntoDocument': null,
			'DOMNodeRemovedFromDocument':  null,
			'DOMSubtreeModified':null,
			'onSubTreeModified': null,       // typo?
			'SubTreeModified':   null,       // typo?
			'onAttrModified':    null,       // typo?
			'onCharacterDataModified': null, // typo?
			'onNodeInserted':    null,       // typo?
			'onNodeRemoved':     null,       // typo?
			'onDOMAttrModified': null,
			'onDOMCharacterDataModified':    null,
			'onDOMNodeInsertedIntoDocument': null,
			'onDOMNodeRemovedFromDocument':  null,
			'onDOMSubTreeModified':null,
		}, // Mutation
		'Pointer': {
			'onGotPointerCapture':   null,
			'onLostPointerCapture':  null,
			'onPointerCancel':   null,
			'onPointerCenter':   null,
			'onPointerDown':     null,
			'onPointerEnter':    null,
			'onPointerLeave':    null,
			'onPointerMove':     null,
			'onPointerOut':      null,
			'onPointerOver':     null,
			'onPointerRawUpdate':null,
			'onPointerUp':       null,
		}, // Pointer
		'Progress': {
			'Abort':             null,
			'error':             null,
			'load':              null,
			'loadend':           null,
			'loadstart':         null,
			'progress':          null,
			'onAbort':           null,
			'onError':           null,
			'onLoad':            null,
			'onLoadEnd':         null,
			'onLoadStart':       null,
			'onProgress':        null,
		}, // Progress
		'Touch': {
			'ontouchcancel':     null,
			'ontouchend':        null,
			'ontouchenter':      null,
			'ontouchmove':       null,
			'ontouchleave':      null,
			'ontouchstart':      null
		}, // Touch
		'User': {
			'focusin':           null,
			'focusout':          null,
			'DOMActivate':       null,
			'ongesturechange':   null,
			'ongestureend':      null,
			'ongesturestart':    null,
			'onDOMFocusIn':      null,
			'onDOMFocusOut':     null,
			'onDOMActivate':     null,
			'onBlur':            null,
			'onFocus':           null,
			'onResize':          null,   // or Object?
			'onScroll':          null,   // or Object?
			'onTextInput':       null    // also Text Event
			}, // User
		'Indie': {
			'collapserequest':   null,
			'deleterequest':     null,
			'dismissrequest':    null,
			'expandrequest':     null,
			'redorequest':       null,
			'undorequest':       null,
			'directionalfocusrequest':   null,
			'linearfocusrequest':null,
			'palettefocusrequest':   null,
			'toolbarfocusrequest':   null,
			'moverequest':       null,
			'panrequest':        null,
			'rotationrequest':   null,
			'zoomrequest':       null,
			'scrollrequest':     null,
			'valuechangerequest':null,
		}, // Indie
		'&nbsp;': {},
		'Safari': { // 11/2009
			'onBeforeCopy':      null,
			'onBeforeCut':       null,
			'onBeforePaste':     null,
			'onBlur':            null,
			'onClick':           null,
			'onContextMenu':     null,
			'onCopy':            null,
			'onCut':             null,
			'onDblClick':        null,
			'onDrag':            null,
			'onDragDrop':        null,
			'onDragEnd':         null,
			'onDragEnter':       null,
			'onDragLeave':       null,
			'onDragOver':        null,
			'onDragStart':       null,
			'onDrop':            null,
			'onError':           null,
			'onFocus':           null,
			'onKeyDown':         null,
			'onKeyPress':        null,
			'onKeyUp':           null,
			'onLoad':            null,
			'onMouseDown':       null,
			'onMouseMove':       null,
			'onMouseOut':        null,
			'onMouseOver':       null,
			'onMouseUp':         null,
			'onMove':            null,
			'onOffline':         null,
			'onOnline':          null,
			'onOutOfSync':       null,
			'onSelectStart':     null,
			'onSubmit':          null,
			'onUnload':          null
		}, // Safari
		'Firefox3': { // 11/2009
			'onBack':            null,
			'onForward':         null,
			'onLocate':          null,
			'onMouseDrag':       null,
			'onText':            null,
			'onXfer_Done':       null
		}, // Firefox3
		'Firefox4': { // 11/2009
			'onAfterScriptExecute':  null,
			'onBeforeScriptExecute': null,
			'onWheel':               null
		}, // Firefox4
		'IE': { // 11/2009
			'msVisibilityChange':null,   // IE9 ??
			'onActivate':        null,
			'onAfterPrint':      null,   // Misc.
			'onAfterUpdate':     null,   // Data Binding
			'onBeforeActivate':  null,
			'onBeforeCopy':      null,   // Clipboard
			'onBeforeCut':       null,   // Clipboard
			'onBeforeDeactivate':null,
			'onBeforeEditFocus': null,   // Form
			'onBeforePaste':     null,   // Clipboard
			'onBeforePrint':     null,   // Misc.
			'onBeforeUnload':    null,   // Object
			'onBeforeUpdate':    null,   // Data Binding
			'onBlur':            null,
			'onBounce':          null,   // Marquee
			'onCellChange':      null,   // Data Binding
			'onChange':          null,
			'onClick':           null,
			'oncontentsave':     null,   // HTC Context; case sensitive
			'oncontentready':    null,   // HTC Context; case sensitive
			'onContextMenu':     null,   // Mouse
			'onCopy':            null,   // Clipboard
			'onCut':             null,   // Clipboard
			'onDataAvailable':   null,   // Data Binding
			'onDataSetChanged':  null,   // Data Binding
			'onDataSetComplete': null,   // Data Binding
			'onDblClick':        null,
			'onDeactivate':      null,
			'ondetach':          null,   // HTC Context; case sensitive
			'ondocumentready':   null,   // HTC Context; case sensitive
			'onDrag':            null,   // Mouse
			'onDragDrop':        null,   // Mouse ??
			'onDragEnd':         null,   // Mouse
			'onDragEnter':       null,   // Mouse
			'onDragLeave':       null,   // Mouse
			'onDragOver':        null,   // Mouse
			'onDragStart':       null,   // Mouse
			'onDrop':            null,   // Mouse
			'onError':           null,
			'onErrorUpdate':     null,   // Data Binding
			'onFilterChange':    null,   // Misc.
			'onFinish':          null,   // Marquee
			'onFocus':           null,
			'onFocusIn':         null,
			'onFocusOut':        null,
			'onHelp':            null,   // Keyboard
			'onhide':            null,   // case-sensitive! (IE)
			'onKeyDown':         null,
			'onKeyPress':        null,
			'onKeyUp':           null,
			'onLayoutComplete':  null,
			'onLoad':            null,
			'onLoseCapture':     null,   // Misc.
			'onMouseDown':       null,
			'onMouseEnter':      null,
			'onMouseLeave':      null,
			'onMouseMove':       null,
			'onMouseOut':        null,
			'onMouseOver':       null,
			'onMouseUp':         null,
			'onMouseWheel':      null,
			'onmove':            null,   // case-sensitive!
			'onMoveEnd':         null,
			'onMoveStart':       null,
			'onmsGestureChange': null,   // IE9 ??
			'onmsGestureDoubleTap':null, // IE9 ??
			'onmsGestureEnd':    null,   // IE9 ??
			'onmsGestureHold':   null,   // IE9 ??
			'onmsGestureStart':  null,   // IE9 ??
			'onmsGestureTap':    null,   // IE9 ??
			'onmsSiteModeJumpListitemRemoved': null,  // IE9 ??
			'onmsSiteModeShowJumpList':        null,  // IE9 ??
			'onmsThumbnailClick':null,   // IE9 ??
			'onOffline':         null,   // IE9 ??
			'onopenstatechanged':null,   // case-sensitive! (IE)
			'onOnline':          null,   // IE9 ??
			'onPage':            null,   // IE9 ??
			'onPaste':           null,   // IE9 ??
			'onPause':           null,   // IE9 ??
			'onPlay':            null,   // IE9 ??
			'onPlaying':         null,   // IE9 ??
			'onplaystatechange': null,   // case-sensitive! (IE)
			'onPopState':        null,   // IE9 ??
			'onProgress':        null,   // IE9 ??
			'onPropertyChange':  null,   // Misc.
			'onRateChange':      null,   // IE9 ??
			'onReadyStateChange':null,   // Misc.
			'onReset':           null,
			'onResize':          null,
			'onResizeEnd':       null,   // IE9 ??
			'onResizeStart':     null,   // IE9 ??
			'onRowEnter':        null,   // Data Binding
			'onRowExit':         null,   // Data Binding
			'onRowsDelete':      null,   // Data Binding
			'onRowsInserted':    null,   // Data Binding
			'onsave':            null,   // case-sensitive?
			'onScroll':          null,
			'onSeeked':          null,   // IE9 ??
			'onSeeking':         null,   // IE9 ??
			'onSelect':          null,   // IE9 ??
			'onSelectionChange': null,   // IE9 ??
			'onSelectStart':     null,   // Mouse
			'onshow':            null,   // case-sensitive?
			'onStalled':         null,   // IE9 ??
			'onStart':           null,   // Marquee
			'onStop':            null,   // Object
			'onStorage':         null,   // IE9 ??
			'onStorageCommit':   null,   // IE9 ??
			'onSubmit':          null,   // IE9 ??
			'onSuspend':         null,   // IE9 ??
			'ontimeout':         null,   // IE9 ?? XHR Context; case sensitive
			'onTimeupdate':      null,   // IE9 ??
			'onUnload':          null,
			'onVolumeChange':    null,   // IE9 ??
			'onWaiting':         null,   // IE9 ??
			'anchorClick':       null,   // IE behavior
			'saveFavorite':      null,   // IE behavior
			'saveHistory':       null,   // IE behavior
			'saveSnapshot':      null    // IE behavior
		}, // IE
		'Opera': { // 11/2009
			'DOMContentLoaded':  null,   // ?
			'DOMFrameContentLoaded':null,// ?
			'DOMMouseScroll':    null,   // ?
			'formchange':        null,   // ?
			'forminput':         null,   // ?
			'invalid':           null,   // ?
			'onBeforeUnload':    null,
			'onDragStart':       null,
			'onResize':          null,
			'onScroll':          null,
			'onSelectStart':     null
		}, // Opera
		'Webkit': { // all Events as seen in r51708
/*
 * only unique ones for Webkit (compared to HTML 4/5 or DOM Level 2/3) are enabled
			'onAbort':           null,
			'onBeforeUnload':    null,
			'onBlur':            null,
			'onCanPlay':         null,
			'onCanPlayThrough':  null,
			'onChange':          null,
			'onClick':           null,
			'onContextMenu':     null,
			'onDblClick':        null,
			'onDrag':            null,
			'onDragEnd':         null,
			'onDragEnter':       null,
			'onDragLeave':       null,
			'onDragOver':        null,
			'onDragStart':       null,
			'onDrop':            null,
			'onDurationChange':  null,
			'onEmtied':          null,
			'onEnded':           null,
			'onError':           null,
			'onFocus':           null,
			'onHashChange':      null,
			'onInput':           null,
			'onInvalid':         null,
			'onKeyDown':         null,
			'onKeyPress':        null,
			'onKeyUp':           null,
			'onLoad':            null,
			'onLoadedData':      null,
			'onLoadedMetaData':  null,
			'onLoadStart':       null,
			'onMessage':         null,
			'onMouseDown':       null,
			'onMouseMove':       null,
			'onMouseOut':        null,
			'onMouseOver':       null,
			'onMouseUp':         null,
			'onMouseWheel':      null,
			'onOffline':         null,
			'onOnline':          null,
*/
			'onPageHide':        null,
			'onPageShow':        null,
/*
			'onPause':           null,
			'onPlay':            null,
			'onPlaying':         null,
			'onPopState':        null,
			'onProgress':        null,
			'onRateChange':      null,
			'onReset':           null,
			'onResize':          null,
			'onScroll':          null,
*/
			'onSearch':          null,
/*
			'onSeeked':          null,
			'onSeeking':         null,
			'onSelect':          null,
			'onStalled':         null,
			'onStorage':         null,
			'onSubmit':          null,
			'onSuspend':         null,
			'onTimeupdate':      null,
			'onUnload':          null,
			'onVolumeChange':    null,
			'onWaiting':         null,
*/
			'onwebkitanimationend':      null,
			'onwebkitanimationiteration':null,
			'onwebkitanimationstart':    null,
			'onwebkittransitionend':     null,
			'onwebkitmouseforcechanged': null,
			'onwebkitmouseforcedown':    null,
			'onwebkitmouseforceup':      null,
			'onwebkitmouseforcewillbegin':   null
		}, // Webkit
		'&#160;': {},
		'iOS': {
			// see http://developer.apple.com/library/ios/#DOCUMENTATION/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html#//apple_ref/doc/uid/TP40006511-SW5
			// not sure if these names are case sensitive
			'ondrop':            null,
			'ongesturechange':   null,
			'ongestureend':      null,
			'ongesturestart':    null,
			'onorientationchange':   null,
			'onPageHide':        null,
			'onPageShow':        null,
			'onPaste':           null,
			'onReset':           null,
			'onSelection':       null,
			'ontouchcancel':     null,
			'ontouchend':        null,
			'ontouchmove':       null,
			'ontouchstart':      null
		}, // iOS
		'Android': {
			// not sure if these names are case sensitive
			'onDOMActivate':     null,
			'onDOMFocusIn':      null,
			'onDOMFocusOut':     null,
			'ontouchcancel':     null,
			'ontouchend':        null,
			'ontouchmove':       null,
			'ontouchstart':      null
		}, // Android
		'XUL': {
			'CheckboxStateChange':null,
			'RadioStateChange':  null,
			'DOMContentLoaded':  null,   // ?
			'DOMFrameContentLoaded': null,// ?
			'DOMMouseScroll':    null,   // Mouse
			'DOMMenuItemActive': null,   // User
			'DOMMenuItemInactive':null,  // User
			'onBroadcast':       null,   // User
			'onClose':           null,   // Input
			'onCommand':         null,   // Input
			'onCommandUpdate':   null,   // User
			'onContextMenu':     null,   // User
			'onCheckboxStateChange':null,// Input
			'onDragDrop':        null,   // Mouse
			'onDragEnter':       null,   // Mouse
			'onDragExit':        null,   // Mouse
			'onDragGesture':     null,   // Mouse
			'onDragOver':        null,   // Mouse
			'onInput':           null,   // Input
			'onOverFlow':        null,   // User
			'onOverFlowChanged': null,   // User
			'onPopupHidden':     null,   // User
			'onPopupHiding':     null,   // User
			'onPopupShowing':    null,   // User
			'onPopupShown':      null,   // User
			'onRadioStateChange':null,   // Input
			'onUnderflow':       null
		}, // XUL
		'unsorted': {
			'afterscriptexecute':null,   // Mozilla native JavaScript
			'beforeinput':       null,   // Mozilla native JavaScript
			'fullscreenchange':  null,   // Mozilla native JavaScript
			'fullscreenerror':   null,   // Mozilla native JavaScript
			'mousewheel':        null,   // ?? native JavaScript
			'MozMousePixelScroll': null, // Mozilla native JavaScript
			'msContentZoom':     null,   // IE native JavaScript
			'MSGestureChange':   null,   // IE native JavaScript
			'MSGestureEnd':      null,   // IE native JavaScript
			'MSGestureHold':     null,   // IE native JavaScript
			'MSGestureStart':    null,   // IE native JavaScript
			'MSGestureTap':      null,   // IE native JavaScript
			'MSInertiaStart':    null,   // IE native JavaScript
			'MSManipulationStateChanged':  null, // IE native JavaScript
			'onabsolutedeviceorientation': null, // Firefox 68 ?
			'onanimationcancel': null,   // Mozilla native JavaScript
			'onanimationend':    null,   // Mozilla native JavaScript
			'onanimationiteration':null, // Mozilla native JavaScript
			'onanimationstart':  null,   // Mozilla native JavaScript
			'onBeforeInput':     null,   // beforeinput in react ??
			'ondevicelight':     null,   // Firefox 68 ?
			'ondevicemotion':    null,   // Firefox 68 ?
			'ondeviceorientation': null, // Firefox 68 ?
			'ondeviceproximity': null,   // Firefox 68 ?
			'onfullscreenchange':null,   // Mozilla native JavaScript
			'onfullscreenerror': null,   // Mozilla native JavaScript
			'ontransitioncancel':null,   // ?? native JavaScript
			'ontransitionend':   null,   // ?? native JavaScript
			'ontransitionrun':   null,   // ?? native JavaScript
			'ontransitionstart': null,   // ?? native JavaScript
			'ontoggle':          null,   // Firefox 68 ?
			'onuserproximity':   null,   // Firefox 68 ?
			'seek':              null,   // ?? native JavaScript
			'transitioncancel':  null,   // ?? native JavaScript
			'transitionend':     null,   // ?? native JavaScript
			'transitionrun':     null,   // ?? native JavaScript
			'transitionstart':   null,   // ?? native JavaScript
			'wwebkitmouseforcechanged':  null, // Safari native JavaScript
			'wwebkitmouseforcedown':     null, // Safari native JavaScript
			'wwebkitmouseforceup':       null, // Safari native JavaScript
			'wwebkitmouseforcewillbegin':null, // Safari native JavaScript
		} // unsorted //# emir__EVENTS__
	}; // events

// TODO: behavior not yet implemented (05-may-13)
	var behavior   = {
		'IE': {
		} // IE
	}; // behavior

	var tags       = {
		/*
		 * this hash has following sub-hashes:
		 *  tags_file:  list of tags using their own file (generated)
		 *  w3c:        description
		 *  debug:      list of tags used for debugging
		 *  HTML 4:     list of HTML 4 tags
		 *  HTML 5:     list of HTML 5 tags
		 *
		 * values in each hash are used as follows:
		 *  file:   should be used in its own file also, provide a link for it
		 *  meta:   tags for meta data, should appear in HEAD container only
		 *  use:    don't generate, causes JavaScript DOM error
		 *  attr:   all listes attributes are set in the generated tag
		 *  empty:  element does not have content, hence closing tag forbidden
		 *          (aka standalone tag, see https://www.w3.org/TR/xhtml1/ )
		 *  notext: do not generate text node, causes JavaScript DOM error
		 *          (except the script tag, this should occour for tags marked
		 *           empty:true only)
		 *  action: generate an action= attribute
		 *  input:  special behaviour for INPUT tag
		 *  table:  special behaviour for TABLE, TR, TD, etc. tags
		 *  select: special behaviour for SELECT, OPTION, etc. tags
		 * # TODO:
		 *  parent: list of parent the tag is allowed in (special cases only)
		 *          example: video>source  map>area
		 *  notchild: list of parent the tag is not allowed in (special cases only)
		 *          example: main not in nav, header, footer, ...
		 *  html5:  false if tag is not supported in HTML 5; i.g. all HTML 4
		 *          tags are also supported in HTML 5, hence some must be marked
		 */
		'tags_file': [],  // will be generated from file: in init()
		'w3c': {
			// hash labels here must be the same as hash labels following categories{}
			'HTML 4':       {desc:'w3c tags: HTML 4',    url:'http://www.w3.org/TR/html4/'},
			'HTML 5':       {desc:'w3c tags: HTML 5',    url:'http://dev.w3.org/html5/spec/Overview.html'},
			'&nbsp;':       {desc:'reset all highlights',url:''}
		}, // w3c
		'debug': {    // only used if debug.max_tags > 0
			'egal':       {file:true,attr:{width:'240px',height:'20px',src:'#'}},
			'b':            {attr:{tst:'tst'}},
//			'a':            {href:'return dumm("A");'},
//			'div':          null,
//			'input':        {input:{'text':true},empty:true},
			//'input':        {input:{'button':true,'hidden':true,'text':true,'password':true,'reset':true,'submit':true,'file':true,'checkbox':true,'radio':true,'image':true},empty:true},
//			'h1':           null
		}, // debug
		'HTML 4': {   //# emir__TAGS__
			'a':            {href:'return dumm("A");'},  //# does not work 'cause onClick returns false
			'abbr':          null,
			'acronym':      {html5:false},
			'address':       null,
			'applet':       {html5:false,use:false,file:true,attr:{width:'240px',height:'20px',src:'#'}},
			'area':         {empty:true},                //# must be child of map
			'audioscope':    null,
			'b':             null,
			'base':         {file:true,empty:true,meta:true},
			'basefont':     {empty:true,html5:false},
			'bdo':           null,
			'bgsound':       null,
			'big':          {html5:false},
			'blackface':     null,
			'blink':         null,
			'blockquote':    null,
			'body':         {file:true,use:false},
	/*
			'body':         {file:true},
	*/
			'bq':            null,
			'br':           {empty:true},
			'button':        null,
			'caption':      {table:true},
			'center':       {html5:false},
			'cite':          null,
			'code':          null,
			'col':          {table:true,empty:true},
			'colgroup':     {table:true},
			'comment':       null,
			'dd':            null,
			'del':           null,
			'dfn':           null,
			'dir':          {html5:false},
			'div':           null,
			'dl':            null,
			'dt':            null,
			'em':            null,
			'elements':     {use:false},                 //# must be last tag
			'fieldset':      null,
			'fn':            null,
			'font':         {html5:false},
			'form':         {file:true,action:true},
			'frame':        {file:true,empty:true},      //# must be child of frameset
			'frameset':     {file:true},
			'h1':            null,
			'head':         {file:true,meta:true},
			'hr':           {empty:true,notext:true},
			'html':         {file:true},                 //# seems to work proper in Mozilla
			'i':             null,
			'iframe':       {empty:true,attr:{width:'240px',height:'40px',border:'0px',src:'data:text/html,ein <b>fetter text</b> im iframe'}},
			'ilayer':        null,
			'img':          {empty:true,attr:{width:'240px',height:'20px'}},
			'input':        {empty:true,input:{'button':true,'hidden':true,'text':true,'password':true,'reset':true,'submit':true,'file':true,'checkbox':true,'radio':true,'image':true}},
	//HTML5	'input':        {empty:true,input:{'search':true,'tel':true,'url':true,'email':true,'datetime':true,'date':true,'month':true,'week':true,'time':true,'datetime-local':true,'number':true,'range':true,'color':true}},
			'ins':           null,
			'isindex':      {empty:true,meta:true,action:true},
			'kbd':           null,
			'label':         null,
			'layer':         null,
			'legend':        null,
			'li':            null,
			'limittext':     null,
			'link':         {file:true,empty:true,meta:true},
			'listing':       null,
			'map':           null,
			'marquee':       null,
			'meta':         {file:true,empty:true,meta:true},
			'multicol':     {select:true},
			'nextid':        null,
			'nobr':          null,
			'noframes':     {file:true},
			'noscript':     {file:true},
			'object':        null,
			'ol':            null,
			'optgroup':     {select:true},
			'option':       {select:true},
			'p':             null,
			'param':        {empty:true},
			'plaintext':    {attr:{width:'240px',height:'20px'}}, //# for mozilla 1.7.x
			'pre':           null,
			'q':             null,
			's':             null,
			'samp':          null,
			'script':       {notext:true},
			'select':       {select:true},
			'server':        null,
			'shadow':        null,
			'sidebar':       null,
			'small':         null,
			'spacer':       {empty:true},
			'span':          null,
			'strike':       {html5:false},
			'strong':        null,
			'style':        {file:true,meta:true},
			'sub':           null,
			'sup':           null,
			'table':        {table:true},
			'tbody':        {table:true},
			'td':           {table:true},
			'textarea':     {attr:{width:'240px',height:'20px'}},
			'tfoot':        {table:true},
			'th':           {table:true},
			'thead':        {table:true},
			'title':        {file:true,meta:true},       //# produces strange tags inside body in Mozilla
			'tr':           {table:true},
			'tt':           {html5:false},
			'u':             null,
			'ul':            null,
			'var':           null,
			'wbr':          {empty:true},
			'xml':           null,
			'xmp':           null
		}, // HTML 4  //# emir__TAGS__
		'HTML 5': {   //# emir__TAGS__
			'article':       null,
			'aside':         null,
			'audio':         null,
	//HTML5	'button':       {input:{'button':true,'submit':true,'reset':true}},
			'bdi':           null,
			'bdo':           null,
			'canvas':       {attr:{height:'20px'}},
			'command':       null,
			'datalist':      null,
			'dialog':        null,
			'details':       null,
			'embed':        {attr:{width:'240px',height:'60px',src:''},empty:true},
				// NOTE: embed must use src='' here, otherwise page is loaded again
			'figcaption':    null,
			'figure':        null,
			'footer':        null,
			'header':        null,
			'hgroup':        null,
			'ins':           null,
	//HTML5	'input':        {input:{'search':true,'tel':true,'url':true,'email':true,'datetime':true,'date':true,'month':true,'week':true,'time':true,'datetime-local':true,'number':true,'range':true,'color':true},empty:true},
			'keygen':       {empty:true},
			'main':          null,
			'mark':          null,
			'math':          null,
			'menu':          null,
			'meter':         null,
			'nav':           null,
			'noembed':      {file:true},
			'nosmartquotes': null, // ?
			'picture':       null,
			'progress':      null,
			'output':        null,
			'rp':            null,
			'rt':            null,
			'ruby':          null,
			'section':       null,
			'small':         null,
			'source':       {empty:true},                //# must be child of video
			'summary':       null,
			'svg':           null,
			'template':     {file:true,meta:true},
			'time':          null,
			'track':        {empty:true},                //# must be child of video
			'video':        {attr:{height:'20px'}}
		} // HTML 5   //# emir__TAGS__
	}; // tags
	var objects = [];   // temp. array for sections

	obj = function(){ this.init(); },

	obj.prototype = {
		'cfg':{ // runtime configurations
			'sortkey':   'tags',
			'e_empty':   true,
			'e_send':    false,
			'e_show':    true
		}, // cfg
		//'objects':[],   // temp. array for sections
		'selected': {  // contains current selected tab (Show Events, Tags)
			'event':     'all',
			'tags':      'HTML 4'
		}, // selected
		'html':   '-test me-',

		//#? get array items functions ########################################
		'get_objects':function()      {//#? get array of all objects[]
			return objects;
		}, // get_objects

		'get_events': function(typ)   {//#? get array of all events[typ]
			var t = [];
			for (var e in events[typ]) { t.push(e); }
			return t;
		}, // get_events

		'get_tags':   function(typ)   {//#? get array of all tags[typ]
			var t = [];
			var e = null;
			if (typ==='all') {
				for (e in tags['HTML 4']) { t.push(e); }
				for (e in tags['HTML 5']) { t.push(e); }
			} else {
				for (e in tags[typ])      { t.push(e); }
			}
			return t;
		}, // get_events

		//#? XMLHttpRequest functions #########################################
		'http': {
			/*
			 * NOTE that most modern browsers will not allow to use XMLHttpRequest
			 * to other domains due to the Same Origin Policy
			 */
			// variables set in GUI
			'ua':       navigator.userAgent,
			'host':     location.host,
			'result':   '/emir_result.cgi',
			'gettoken': '/emir_token.cgi',
			'mail':     'some@where',    // not really 'http:', but we don't have 'mail:'
			// following variables are used internal only
			'url':      null,
			'schema':   'http://',
			'token':    '',
			'ctype':    'application/x-www-form-urlencoded',

			'xmlhttp':   new function()              {//#? get XMLHttpRequest object
				if (window.XMLHttpRequest) {
					return new XMLHttpRequest();
				} else {
					if (window.ActiveXObject){
                        try {      return new ActiveXObject("Msxml2.XMLHTTP"); }
                        catch(e) { return new ActiveXObject("Microsoft.XMLHTTP"); }
					}
				}
				return null;
			}, // xmlhttp

			'prepare':   function(url)               {//#? prepare URL to be used in XMLHttpRequest
				if (this.url!==null) { return; }
				if (this.host!=='') { // take care for same origin policy
					this.url = (this.host===location.host) ?  '' : this.schema + this.host;
					this.url += url;
				}
				return;
			}, // prepare

			'post_event':function(tag, evt)          {//#? send tag and event type to remote server
				if (this.xmlhttp) {
					this.prepare(this.result);
					this.xmlhttp.open('POST', this.url, false);
					this.xmlhttp.setRequestHeader('Content-Type', this.ctype);
					try { // as http://www.w3.org/TR/XMLHttpRequest/ does not allow it
					this.xmlhttp.setRequestHeader('User-Agent',   this.ua);
					this.xmlhttp.setRequestHeader('Connection',   'close');
					} catch(e) { alert('**ERROR setting request headers: '+e); }
					this.xmlhttp.onreadystatechange=function(){
						// need absolute variable names for async mode
						if (emir.http.xmlhttp.readyState===4) {
							if (emir.http.xmlhttp.status==="200"){ return true; }
						}
					}
					this.xmlhttp.send('&event='+evt+'&tag='+tag+'&type='+'1'+'&token='+this.token);
				}
				return true;
			}, // post_event

			'get_token': function()                  {//#? get token from remote server
				if (this.xmlhttp) {
					this.url = null; // reset to force correct url
					this.prepare(this.gettoken);
					this.xmlhttp.open('POST', this.url, false);
					this.xmlhttp.setRequestHeader('Content-Type', this.ctype);
					try { // as http://www.w3.org/TR/XMLHttpRequest/ does not allow it
					this.xmlhttp.setRequestHeader('User-Agent',   this.ua);
					this.xmlhttp.setRequestHeader('Connection',   'close');
					} catch(e) { alert('**ERROR setting request headers: '+e); }
					this.xmlhttp.send('foo=1');
					this.url = null;
					return this.xmlhttp.getResponseHeader('Token');
				}
			} // get_token;
		}, // http

		//#? configuration setting functions ###################################
		'set_config': function(src)   {//#? set configuration data for tool itself and AJAX requests;
			// updates internal data structure and display
			if (!src) { return false; }
			if (src.id===undefined) { return false; }
			switch (src.id) {
			  case 'emir.e.stag':     this.cfg.sortkey   = 'tags';   return true; break;
			  case 'emir.e.sevent':   this.cfg.sortkey   = 'events'; return true; break;
			  case 'emir.e.empty':
				this.cfg.e_empty = src.checked;
				document.getElementById(src.id).checked  = src.checked;
				break;
			  case 'emir.e.show':
				this.cfg.e_show = src.checked;
				document.getElementById(src.id).checked  = src.checked;
				break;
			  case 'emir.e.send':
				this.cfg.e_send = src.checked;
				document.getElementById(src.id).checked  = src.checked;
				break;
			  case 'emir.e.get':
				this.http.token = this.http.get_token();
				document.getElementById('emir.e.token').value = this.http.token;
				break;
			  case 'emir.e.ua':       this.http.ua       = src.value; break;
			  case 'emir.e.host':     this.http.host     = src.value; break;
			  case 'emir.e.result':   this.http.result   = src.value; break;
			  case 'emir.e.gettoken': this.http.gettoken = src.value; break;
			  case 'emir.e.mail':     this.http.mail     = src.value;
				document.getElementById('mailto').value.replace(/:([^?]*)/, src.value);
				break;
			}
			return false;
		}, // set_config

		//#? create tags functions ############################################
		'create':   {
			// TODO 'self': this,
			'html': '-test me-', // TODO: should be this.html;
			'inputID':   function(id,txt)            {//#? create special id for INPUT tags
				return id += '\ttype=' + txt;
			},
			'innerHTML': function(parent,html)       {//#? set innerHTML attribute
				if (html !== '') {
					try{ parent.innerHTML = html; }
					catch(e){}; // contribution to w3c-conform browsers
				}
				return;
			}, // innerHTML
			'onEvent':   function(parent,typ)        {//#? set all events[typ] attributes
				var err = '';
				for (var x in events[typ]) {
					try { parent.setAttribute(x, "return $e$(this,'"+ x +"');"); }
					catch(e) { err += '\n** ' + x + '\t"' + e + '"'; }
				}
				return err;
			}, // onEvent

			'on_body':   function(parent,typ)        {//#? set all events[typ] attributes for <body> (excluding 'onload')
				var err = '';
				for (var x in events[typ]) {
					if (x.match(/^onLoad/i)!==null)        {   alert('onload');continue; }
					if (x.match(/^onContextMenu/i)!==null) {   alert('onContextMenu');continue; }
					//if (x.match(/^onFocus/i)!==null)     {   alert('onFocus');continue; }
					//if (x.match(/^onActivate/i)!==null)  {   alert('onActivate');continue; }
					try { parent.setAttribute(x, "return $e$(this,'"+ x +"');"); }
					catch(e) { err += '\n** ' + x + '\t"' + e + '"'; }
				}
				return err;
			}, // on_body

			'checkboxes':function(tag,id,parent,err) {//#? create checkboxes for all events
				var t = null;
				var i = id;
				//parent.appendChild(document.createElement('BR')); // nur bei inline Elementen
				if (err !== '') {
					t = document.createElement('DIV');
					t.innerHTML = err;
					parent.setAttribute('class', 'err');
					parent.appendChild(t);
					delete this.t;
					return;
				}
				for (var e in ((0 < debug.max_events) ? events.debug : events.all)) {
					parent.appendChild(this.CHECKBOX( 'LABEL INPUT checkbox',
					   {'id':       id,
						'type':     'checkbox',
						'event':    e,
						'html':     '|\xa0' + e + ':',
						'display':  false,
						'disable':  true
					   }
					));
				}
				return;
			}, // checkboxes

			'tag':      function(tag,arg_hash,html)  {//#? return specified tag with given attributes
				var args= arg_hash;
				var t   = null;
				var div = false;
				/*
				 * tags which could not be used normally within HTML's BODY
				 * have the file: attribute, then a DIV tag will be generated
				 * instead of the given tag
				 * the passed tag may be defined in any type of the tags hash,
				 * hence we search the given tag in any (HTML 4, HTML 5, etc.)
				 */
//if (tag !='A') { alert("tag  : "+tag+" , attr: "+args.file); }
				for (typ in tags) {
					// check if given tag has file: attribute
					if (typ==='w3c')       { continue; }
					if (typ==='debug')     { continue; }
					if (! tags[typ][tag])  { continue; }
					if (tags[typ][tag].file!==undefined) { div = true; }
				}
				if (div===true) {
					t = document.createElement('DIV');
					t.title = "DIV instead " + tag + " tag";
t.setAttribute('style', 'background:red');
// alert(t.title); // TODO: does not show title
				} else {
					t   = document.createElement(tag);
				}
				this.innerHTML(t,html);
				for (var arg in args)     { t.setAttribute(arg,     args[arg]); }
				if (args.cls!==undefined) { t.setAttribute('class', args.cls);  }
				if (args.id !==undefined) { t.setAttribute('name',  args.id);   }
					// we need a name attrinute if we want to make a request
				return t;
			}, // tag

			'tags':     function(parent,typ)         {//#? create all tags of given typ (returns void)
				var i   = 0;
				var obj = null;
				var tag = null;
				var html= this.html;
				var has_events = true;
				if (typ==='SELECT') {
					parent.appendChild(this.SELECT('SELECT',   {}, html));
					parent.appendChild(this.SELECT('OPTGROUP', {}, html));
					parent.appendChild(this.SELECT('OPTION',   {}, html));
					return;
				}
				if (typ==='TABLE') {
					parent.appendChild(this.TABLE('TABLE',     {}, html));
					parent.appendChild(this.TABLE('THEAD',     {}, html));
					parent.appendChild(this.TABLE('TBODY',     {}, html));
					parent.appendChild(this.TABLE('TFOOT',     {}, html));
					parent.appendChild(this.TABLE('CAPTION',   {}, html));
					parent.appendChild(this.TABLE('TR',        {}, html));
					parent.appendChild(this.TABLE('TD',        {}, html));
					return;
				}
				// otherwise use tags from specified list
				for (tag in tags[typ]) {
					i++;
					html= this.html;
					has_events = true; // must be after html= ; otherwise some firefox complain with NS_ERROR_XPC_SECURITY_MANAGER_VETO; crazy ...
					if (tags[typ][tag]!=null) {
						if (tags[typ][tag].use!=null)   { /*alert('skip:'+tag);*/ continue; }
						if (tags[typ][tag].notext!=null){ /*alert('html:'+tag);*/ html = ''; }
						if (tags[typ][tag].input!=null) {
							for (var a in tags[typ][tag].input) {
								// create INPUT tags with of all types
//# TODO: check what the intention for this is
								parent.appendChild(this.tag_form(tag, typ, {type:a}, html, has_events));
							}
						}
					}
					var attr = {};
					if (tags[typ][tag]!==null) {
						// tags with file: attribute are different
						if (tags[typ][tag].file!==undefined) {
							html = "";
							has_events = false;
							attr = {'url':'emir-'+tag.toLowerCase()+'.html'};
						}
					}
					parent.appendChild(this.tag_form(tag, typ, attr, html, has_events)); // TODO: inline should be configurable
				}
				return;
			}, // tags

			'CHECKBOX': function(dummytag,arg_hash)  {//#? return <label><input type=checkbox></label>
				var args= arg_hash; // style: is for the surounding LABEL tag, all others for INPUT tag
				var t   = document.createElement('LABEL');
				var id  = args.id;
				if (args.event!==undefined) { id += '-' + args.event; }
				if (args.title!==undefined) { t.title   = args.title; }
				if (args.display===false)   { t.setAttribute('style', 'display:none'); }
				t.id    = 'l-' + id;
				t.setAttribute('for', id);
				t.innerHTML = args.html;
				if (args.disable===true) {
					t.appendChild(this.tag('INPUT', {'id':id, 'type':args.type, disabled:'1'}, ''));
				} else {
					t.appendChild(this.tag('INPUT', {'id':id, 'type':args.type, onClick:args.onClick}, ''));
				}
				return t;
			}, // CHECKBOX

			'FIELDSET': function(tag,arg_hash,html,has_events)   {//#? return <fieldset><span> tag </span> </fieldset>
				var t   = this.tag('FIELDSET', {}, '');
				var cls = 'tag';
				var txt = 'tag to be tested';
				if (false===has_events) {
					cls += ' tag_file';
					txt = 'tag to be tested: please use linked file';
				}
				t.appendChild(this.tag('SPAN', {cls:cls,title:txt}, tag.toUpperCase() ));
				this.innerHTML(t,html);
				return t;
			}, // FIELDSET

			'tag_form': function(tag,typ,arg_hash,html,has_events) {//#? return <div><fieldset><span> tag </span> <tag>..</tag> </fieldset></div>
				var args= arg_hash; // attributes for generated tag
				var err = '';
				var id  = tag;
				var t   = null;
				if (tag.match(/^INPUT$/i)!=null) {  // need special id 'cause multiple tags
					if(args.type!=null) { id = this.inputID(tag, args.type); }
				}
				var f = this.FIELDSET(tag, {}, '', has_events);
				if(args.url!==undefined) {
					f.appendChild(document.createTextNode('\xa0see:\xa0'));
					f.appendChild(this.tag( 'A', {'href':args.url, 'target':'_new'}, args.url));
					t = this.tag('DIV', {'id':'z-'+tag}, '');
					t.appendChild(f);  delete this.f;
					//return t;
				}
				// create tag
				t = this.tag( tag, {'id':id}, '');
				if(tags[typ][tag]!=null) {
					if(tags[typ][tag].attr!=null) {
						for (var a in tags[typ][tag].attr) { t.setAttribute(a, tags[typ][tag].attr[a]); }
					}
					if(tags[typ][tag].action) {
						t.setAttribute('action', "return $e$(this,'action');");
					}
				}
				this.innerHTML(t,html);
				// set tag attributes
				for (var arg in args) { try { t.setAttribute(arg, args[arg]); }catch(e){/*IE hack*/} }
				// set tag events and add hidden checkboxes
				if (true===has_events) {
					if (0 < debug.max_events) {
						err = this.onEvent(t, 'debug');
					} else {
						err = this.onEvent(t, 'all');
					}
					// this.checkboxes(tag, id, f, err); // done later, so that checkboxes appear after the tag (if not hidden)
				}
				f.appendChild(t);
				if (true===has_events) {
					this.checkboxes(tag, id, f, err);
				}
				delete this.t;
				t = this.tag('DIV', {'id':'z-'+tag}, '');
				t.appendChild(f);
				delete this.f;
				return t;
			}, // tag_form

			'SELECT':   function(tag,arg_hash,html)  {//#? return <select><optgroup><option> text </option></optgroup></select>
				/* event attributes are set to given "tag" only */
				var id  = '';
				var err = '';
				var sid = {}, stx = '';
				var gid = {}, gtx = '';
				var oid = {}, otx = '';
				switch (tag) {
				  case 'select':
				  case 'SELECT':   id='select.select';   sid={'id':id}; stx = html; break;
				  case 'option':
				  case 'OPTION':   id='select.option';   oid={'id':id}; otx = html; break;
				  case 'optgroup':
				  case 'OPTGROUP': id='select.optgroup'; gid={'id':id}; gtx = html; break;
				}
				var o = this.tag('option',   oid, otx);
				var t = this.tag('select',   sid, stx);
				var g = this.tag('optgroup', gid, gtx);
				if (stx!=='') { err = this.onEvent(t, 'all'); }
				if (gtx!=='') { err = this.onEvent(g, 'all'); }
				if (otx!=='') { err = this.onEvent(o, 'all'); }
				g.label = (gtx==='') ? '-no test-' : gtx;
				g.appendChild(o);
				g.appendChild(this.tag('OPTION', {}, '-no test-'));
				t.appendChild(g);  delete this.g;
				g = this.FIELDSET(tag, {}, '', true);
				g.appendChild(t);  delete this.t;
				this.checkboxes(tag, id, g, err);
				t = this.tag('DIV', {'id':'z-'+tag}, '');
				t.appendChild(g);  delete this.g;
				return t;
			}, // SELECT

			'TABLE':    function(tag,arg_hash,html)  {//#? return table <tag></tag>
				var id  = '';
				var err = '';
				var tid = {'cls':'table'}, ttx = '';
				var hid = {}, htx = '';
				var bid = {}, btx = '';
				var fid = {}, ftx = '';
				var rid = {}, rtx = '';
				var did = {}, dtx = '';
				var cid = {}, ctx = '';
				switch (tag) {
				  case 'table':
				  case 'TABLE': id='table.table';   tid={'id':id, 'cls':'table'}; ttx = html; break;
				  case 'thead':
				  case 'THEAD': id='table.thead';   hid={'id':id}; htx = html; break;
				  case 'tbody':
				  case 'TBODY': id='table.tbody';   bid={'id':id}; btx = html; break;
				  case 'tfoot':
				  case 'TFOOT': id='table.tfoot';   fid={'id':id}; ftx = html; break;
				  case 'caption':
				  case 'CAPTION':id='table.caption';cid={'id':id}; ctx = html; break;
				  case 'tr':
				  case 'TR':    id='table.tr';      rid={'id':id}; rtx = html; break;
				  case 'td':
				  case 'TD':    id='table.td';      did={'id':id}; dtx = html; break;
				  case 'th':
				  case 'TH':    id='table.th';      did={'id':id}; dtx = html; break;
				}
				var t = this.tag('table',   tid, ttx);
				var h = this.tag('thead',   hid, htx);
				var b = this.tag('tbody',   bid, btx);
				var f = this.tag('tfoot',   fid, ftx);
				var c = this.tag('caption', cid, ctx);
				var r = this.tag('tr',      rid, rtx);
				var d = this.tag('td',      did, dtx);
				if (ttx!=='') { err = this.onEvent(t, 'all'); }
				if (htx!=='') { err = this.onEvent(h, 'all'); }
				if (btx!=='') { err = this.onEvent(b, 'all'); }
				if (ftx!=='') { err = this.onEvent(f, 'all'); }
				if (dtx!=='') { err = this.onEvent(d, 'all'); }
				if (rtx!=='') { err = this.onEvent(r, 'all'); }
				r.appendChild(d);
				r.appendChild(this.tag('TD', {}, '-no test-'));
				b.appendChild(r);  delete this.r;
				t.appendChild(b);  delete this.b;
				t.appendChild(h);  delete this.h;
				t.appendChild(f);  delete this.f;
				d = this.FIELDSET(tag, {}, '', true);
				d.appendChild(t);  delete this.t;
				this.checkboxes(tag, id, d, err);
				t = this.tag('DIV', {'id':'z-'+tag}, '');
				t.appendChild(d);  delete this.d;
				return t;
			}, // TABLE

			'LI':       function(tag,arg_hash,html)  {//#? return <li><a ...>html</a></li>
				var args= arg_hash;
				var t = document.createElement('LI');
				t.appendChild(this.tag('A', arg_hash, html));
				return t;
			}, // LI

		}, // create

		'create_sectionevents':function() {//#? init Section: Events
			this.status('  create_sectionevents');
			var typ = 'use-event-'; // event is key used in .selected{}
			var t = this.create.tag('FIELDSET',  {cls:'e'}, '');
			    t.appendChild(this.create.tag('LEGEND', {}, 'Show Events for each tag'));
			var u = this.create.tag('UL',  {}, '');
			var e = null;
			var f = null;
			var c = 'otab_fg';  // TODO: need to have at least on *_fg, otherwise $t$ will not work
			for (e in events.w3c) {
				u.appendChild(this.create.LI('',
					{'id':typ + e, 'cls':c, 'href':'', 'onClick':'return $t$(this,"o");', title:events.w3c[e].desc},
					e)
				);
				c = 'otab_bg';
			}
			f = this.create.tag('DIV', {'id':'otab', cls:'otab'}, '');
			f.appendChild(u);
			t.appendChild(f);
			f = this.create.tag('DIV', {cls:'text'}, '');
			var event_cnt = 0;
			for (var e in ((0 < debug.max_events) ? events.debug : events.all)) {
				event_cnt++;
				f.appendChild(this.create.CHECKBOX( 'LABEL INPUT checkbox',
				   {'id':       typ + e,
					'type':     'checkbox',
					'event':    e,
					'cls':      'chck',
					'html':     '|\xa0' + e + ':',
					'display':  true,
					'onClick':  'return $c$(this,"' + e + '");'
				   }
				));
			}
			t.appendChild(f);
			u = this.create.tag('UL',  {}, '');
			c = 'utab_fg';
			u.appendChild(this.create.tag('SPAN', {}, 'Category: '));  // TODO: dirty hack
			for (e in events) {
				if (e==='w3c')        { continue; }
				if (e==='debug')      { continue; }
				if (e==='categories') { continue; }
				if (events.categories[e]===undefined) { continue; }
				if (e==='Safari'){
					u.appendChild(document.createElement('BR')); // TODO: dirty hack
					u.appendChild(this.create.tag('SPAN', {}, 'Browser:&#160;&#160;'));
				}
				u.appendChild(this.create.LI('',
					{'id':typ + e, 'cls':c, 'href':'', 'onClick':'return $t$(this,"u");', title:events.categories[e].desc},
					e)
//					events.categories[e].label)
				);
				c = 'utab_bg';
			}
			f = this.create.tag('DIV', {'id':'utab', cls:'utab'}, '');
			f.appendChild(u);
			t.appendChild(f);
			delete this.u; u = null;
			delete this.f; f = null;
			t.appendChild(document.createElement('HR'));
			f = document.createElement('BUTTON');
			f.innerHTML = 'get list of events ';
			f.setAttribute('onClick', 'return $l$("events");');
			f.setAttribute('title',	  'display sorted list of '+event_cnt+' events in new window');
			t.appendChild(f);
			t.appendChild(document.createTextNode(' highlighted:\xa0\xa0'));
			f = document.createElement('BUTTON');
			f.innerHTML = 'check';
			f.setAttribute('onClick', 'return $s$(this,"check");');
			f.setAttribute('title',	  'display all checkboxes for highlighted events in tags in Testing section');
			t.appendChild(f);
			f = document.createElement('BUTTON');
			f.innerHTML = 'uncheck';
			f.setAttribute('onClick', 'return $s$(this,"uncheck");');
			f.setAttribute('title',	  'hide all checkboxes for highlighted events in tags in Testing section');
			t.appendChild(f);
			f = document.createElement('SUB');
			f.innerHTML = ' (NOTE: will take up to 10 seconds)  ';
			t.appendChild(f);
			$('events').appendChild(t);
			delete this.f; f = null;
			delete this.t; t = null;
			return;
		}, // create_sectionevents

		'create_sectiontags': function()  {//#? init Section: Tags
			this.status('  create_sectiontags');
			var typ = 'use-tag-'; // tag is key used in .selected{}
			var t = this.create.tag('FIELDSET',  {cls:'e'}, '');
			    t.appendChild(this.create.tag('LEGEND', {}, 'Tag Categories'));
			var u = this.create.tag('UL',  {}, '');
			var c = 'otab_fg';  // TODO:
			var e = null;
			var f = null;
			var tag_cnt = 0;
			for (e in tags.w3c) {
				u.appendChild(this.create.LI('',
					{'id':typ + e, 'cls':c, 'href':'', 'onClick':'return $t$(this,"o");', title:tags.w3c[e].desc},
					e)
				);
				c = 'otab_bg';
			}
			var f = this.create.tag('DIV', {'id':'otab', cls:'otab'}, '');
			f.appendChild(u);
			t.appendChild(f);
			f = this.create.tag('DIV', {cls:'text'}, '');
			for (e in tags['HTML 4']) {
				tag_cnt++;
				f.appendChild(this.create.CHECKBOX( 'LABEL INPUT checkbox',
				   {'id':       typ + e,
					'type':     'checkbox',
					'event':    e,
					'cls':      'chck',
					'html':     '|\xa0' + e + ':',
					'display':  true,
					'onClick':  'return $c$(this,"' + e + '");'
				   }
				));
			}
			for (e in tags['HTML 5']) {
				tag_cnt++;
				f.appendChild(this.create.CHECKBOX( 'LABEL INPUT checkbox',
				   {'id':       typ + e,
					'type':     'checkbox',
					'event':    e,
					'cls':      'chck',
					'html':     '|\xa0' + e + ':',
					'display':  true,
					'onClick':  'return $c$(this,"' + e + '");'
				   }
				));
			}
			t.appendChild(f);
			f = document.createElement('SUB');
			f.innerHTML = "(checking these boxes have currently no effect, it's just informational)";
			f.setAttribute('style', 'display:block;padding-top:0.8em');  // dirty hack :-((
			t.appendChild(f);
			t.appendChild(document.createElement('HR'));
			f = document.createElement('BUTTON');
			f.innerHTML = 'get list of tags ';
			f.setAttribute('onClick', 'return $l$("tags");');
			f.setAttribute('title',	  'display sorted list of '+tag_cnt+' tags in new window');
			t.appendChild(f);
			f = document.createElement('BUTTON');
			f.innerHTML = 'get list of HTML tags ';
			f.setAttribute('onClick', 'return $l$("html");');
			f.setAttribute('title',	  'display sorted list of '+tag_cnt+' tags in new window');
			t.appendChild(f);
			$('tags').appendChild(t);
			delete this.f; f = null;
			delete this.u; u = null;
			delete this.t; t = null;
			return;
		}, // create_sectiontags

		'create_sectiontest': function()  {//#? init Section: Testing Tags
			this.status('  remove existing content');
			this.delet.tags($('tag-result'));
			this.delet.tags($('err-result'));
			if (typeof(emir_file)==='undefined') {
				// emir_file exists in emir-*.html files only,
				// no tags should be generated in these pages
				var dummy = 'to keep strict silent';
			} else {
				return;
			}
			this.delet.tags($('testing'));
			this.status('  create common tags');
			if (0 < debug.max_tags) {
				this.create.tags($('testing'), 'debug');    // create tags for debugging only
			} else {
				this.create.tags($('testing'), 'HTML 4');   // create all tags to be tested; IE most likely crashes here
				this.create.tags($('testing'), 'HTML 5');   // ..
				this.status('  create special tags');
				this.create.tags($('testing'), 'SELECT');   // create special select tags
				this.create.tags($('testing'), 'TABLE');    // create special table tags
				// more specials for: (MAP, AREA); (UL, OL, LI); (DD, DL, DT); (OBJECT, PARAM)
			}
			return;
		}, // create_sectiontest

		'create_sectionbuttons':function(){//#? init Section: Testing Buttons
			this.status('  create testings buttons at bottom');
			$('testing').appendChild(this.create.tag('A', {'id':'mailto', href:'', style:'display:none', title:'dummy for mailto:'}, 'm'));
			$('testing').appendChild(this.create.tag('INPUT', {'id':'reset', type:'button', value:'Reset', onClick:'return emir.resetevents();', title:'destroy and re-create events'}, ''));
			$('testing').appendChild(document.createTextNode('  '));
			$('testing').appendChild(this.create.tag('INPUT', {'id':'submit', type:'submit', value:'Submit', onClick:'return emir.result("show");', title:'send result as mail'}, ''));
			$('testing').appendChild(document.createTextNode('  '));
			$('testing').appendChild(this.create.tag('INPUT', {'id':'result', type:'button', value:'Result', onClick:'return emir.result("tags");', title:'show results'}, ''));
			$('testing').appendChild(document.createTextNode('  '));
			$('testing').appendChild(this.create.tag('INPUT', {'id':'fire',   type:'button', value:'fire',   onClick:'return emir.fire();', title:'try to fire all events'}, ''));
			return;
		}, // create_sectionbuttons

		//#? delete functions #################################################
		'delet':    {
			// IE does not allow 'delete'
			'tags':      function(obj)       {//#? delete all tags in DOM for given element
				if (obj.hasChildNodes()) {
					while (obj.childNodes.length>=1) {
						obj.removeChild(obj.firstChild);
					}
				}
				return;
			} // tags
		}, // delet

		//#? find   functions #################################################
		'find':     {
			'reset':     function()          {//#? clear array of objects[]
				var c = null;
				while((c=objects.shift())!=null){}
			},

			'checked':   function(arg_hash)  {//#? find all checkboxes in tags of given type
				var args= arg_hash;
				var arr = document.getElementsByTagName('LABEL');
				var c   = null;
				var t   = null;
				this.reset();
				for (c in arr) {
					if (c==='indexOf')                    { continue; } // contribution to old Mozilla 1.x
					if (arr[c].id           ===undefined) { continue; } // some browers like this ..
					if (arr[c].id                ===null) { continue; } // .. others like this
					if (arr[c].id.match(/^useal/)!==null) { continue; } // ignore ower own
					if (arr[c].id.match(/^use-/) !==null) { continue; } // ignore ower own
					if (arr[c].id.match(/^l-use/)!==null) { continue; } // ignore labels in "Show Events"
					if (args.type===undefined) { objects.push(arr[c].id); }
					if (args.type!==null) {
						if (arr[c].id.match(new RegExp('-'+args.type+'$'))===null) { continue; }
					}
					objects.push(arr[c].id);
				}
				return false;
			},  // checked

			'show':      function(val)       {//#? (show) display all objects from objects[]
				var c = null;
				while ((c=objects.shift())!=null) { $(c).style.display = val; }
				c = null;
				return false;
			}, // show

			'mark':      function(obj)       {//#? mark all checkboxes in "Show Events" which belong to events[tab]
				var arr = obj.id.split('-'); // we get: use-event-* or use-tag-*
				var typ = arr[1];
				var tab = arr[2];
				var c   = null;
				while ((c=objects.shift())!=null) {}    // clear array
				switch (typ) {
				  case 'event': for (var e in events[tab]) { objects.push(e); }; break;
				  case 'tag':   for (var e in tags[tab])   { objects.push(e); }; break;
				}
				var rex = new RegExp('-(' + objects.join('|') + ')$');
				arr = document.getElementsByTagName('INPUT');
				for (c in arr) {
					if (c==='indexOf')          { continue; } // contribution to old Mozilla 1.x
					if (arr[c].id===undefined)  { continue }; // unknown onject
					if (arr[c].id.split('-')[1]!==typ) { continue };  // skip tabs in other list
					if (arr[c].id===null)       { continue; }
					if (arr[c].id===undefined)  { continue; }
					if (arr[c].id.match(/^use-/)!=null) {
						//#dbx# arr[c].checked= true;
						$('l-' + arr[c].id).style.backgroundColor = '#ffffff';
						if (arr[c].id.match(rex)===null) { continue; }
						$('l-' + arr[c].id).style.backgroundColor = '#afffaf';
					}
				}
				rex = null;
				return;
			} // mark
		}, // find

		//#? result functions #################################################
		'result':     function(mode)  {//#? called when Result button clicked
			//#mode? show: show result in mailto: application
			//#mode? tags: show reult in "Result" area
			//#mode? ajax: send a request to the remote server for each recorded event
			if (emir.selected.event===undefined) { return false; }
			this.status('result: ');
			var sort = this.cfg.sortkey;
			var c = null;
			var f = null;
			var i = 0;
			var e = '';
			var arr = document.getElementsByTagName('INPUT');
			var keys= {};
			var r = document.getElementById('tag-result');
			if (mode!=='show') { r.innerHTML = ''; }
			for (i=0; i<arr.length; i++) {
				c=arr[i];
				if (c.id===undefined) { continue; } // some browers like this ..
				if (c.id     ===null) { continue; } // .. others like this
				if ((this.cfg.e_empty===true)||(c.checked===true)) {
					e = c.id.split('-'); // id='tag-event': [0] is tag name, [1] is event name
					if(e.length===2) {  // all others are unexpected
						if (sort==='tags') {
							e[0] = e[0].toUpperCase();
							if (keys[e[0]]===undefined) { keys[e[0]] = []; }
							if (c.checked===true) { keys[e[0]].push(e[1]); }
						} else {
							if (keys[e[1]]===undefined) { keys[e[1]] = []; }
							if (c.checked===true) { keys[e[1]].push(e[0].toUpperCase()); }
						}
					}
					while (e.pop()) {}
				}
				delete arr[i];
			}
			/* if the tag name contains a . (dot), then it's one of the special tags
			 * which has child tags (see EMiR.init() for details)
			 * we simply replace the . in the name with >< which shows the tag tree
			 * then
			 */
			for (c in keys) {
				if (mode==='ajax') { // TODO: NOT YET implemented
					for (i=0; i<keys[c].length; i++) {
						this.http.post_event(tag.tagName, evt);
					}
					continue;
				}
				if (mode==='show') {
					if (sort==='tags') {
						e += '%0a<' + c.replace(/\./g, '><') + '>,' + keys[c].join(',');
					} else {
						e += '%0a' + c + ':,' + keys[c].join(',');
					}
				} else {
					e = false;
					f = document.createElement('B');
					if (sort==='tags') {
						f.appendChild(document.createTextNode('<' + c.replace(/\./g, '><') + '>, '));
					} else {
						f.appendChild(document.createTextNode( c + ', '));
					}
					r.appendChild(f);
					f = document.createElement('SPAN');
					f.appendChild(document.createTextNode(keys[c].join(', ')));
					r.appendChild(f);
					r.appendChild(document.createElement('BR'));
					delete this.f; f = null;
				}
			}
			if (mode==='show') {
				r = document.getElementById('mailto');
				r.href = 'mailto:' + this.http.mail + '?subject=Events for: ' + this.http.ua + '&body=' + e;
				r.focus();
				r.click();
				e = false;
			}
			c = null; r = null;
			return e;
		}, // result

		//#? fire functions ###################################################
		'fire':       function()      {//#? called to fire all known events
			var e_list  = this.get_events('all');
			var t_list  = this.get_tags(  'all');
//# TODO:
t_list = ['a', 'b', 'footer'];  // user specified list
			var err     = '';
			var err_cnt = 0;
			/*
			 * Each tag's id is the tag name.
			 * Perfom all our events for each tag. Some of the event names are
			 * prefixed with "on". This prefix is removed because JavaScript's
			 * Event object expects the bare name (without prefix "on") and all
			 * letters lower case. Note that the definitions of event names use 
			 * camel case notations; only the names with the prefix "on" will
			 * be converted to lower case.
			 * Examples:
			 *     onClick  =>  click
			 *     Click    =>  Click
			 *     click    =>  click
			*/
			for (var i in t_list) {
				var tag_name = t_list[i];
				for (var k in e_list) {
					var event_name = e_list[k].replace(/^on/,'');
					if (event_name!=e_list[k]) {
						// 
						event_name = event_name.replace(/(.)/g, function(c){return c.toLowerCase();});
					}
					var obj    = document.getElementById(tag_name);
					var event  = new Event(event_name);
					try      { obj.dispatchEvent(event, {bubbles:false}); } // fire
					catch(e) {  // collect failed events
						err_cnt++;
						err += '\t' + tag_name + '[' + event_name + ']';
					}
					//#dbx# alert(tag_name+"."+event_name+" : "+event+" : "+err); // noisy!
				}
			}
			// show errors, if any
			obj = document.getElementById('err-result');
			obj.innerHTML = err;
			return false;
		}, // fire

		//#? status functions #################################################
		'status':     function(txt)   {//#? set text in status line
			var t = new Date;
			var obj = $('status');
			obj.value += "\x0a" + t.toLocaleTimeString() + ' ' + txt;
			obj.scrollTop = obj.scrollHeight;// adjust to bottom in textarea
			return;
		}, // status

		'status_':    function(txt)   {//#? append text to status line
			$('status').value += txt;
			return;
		}, // status_

		//#? init   functions #################################################
		'initdone': false,  // avoid multiple calls

		'resetevents':function()      {//#? reset results and events
			this.create_sectiontest();   //# TODO: generates buttons multiple times (see emir_file)
			this.create_sectionbuttons();
			return;
		}, // resetevents

		'init':       function()      {//#? init variables and GUI
			var html = '';
			//#dbx# alert ('done '+this.initdone);
			if (this.initdone===true) { return; }
			this.initdone = true;

			$('status').value = "";  // empty status, even after reloading page
			this.status('Init events[all]..');      // -----------------------
			var t = [];  // all types of events
			// need emir.events['all']; generate from all others
			for (typ in events['w3c'])        { t.push(typ); }
			for (typ in events['categories']) { t.push(typ); }
			for (typ in t) {
				for (e in events[t[typ]]) {
					v = events[t[typ]][e];
					events['all'][e] = v;  // multiple entries are silently overwritten
				}
			}

			this.status('Init tags..');             // -----------------------
			for (typ in tags) {
				if (typ==='w3c')   { continue; }
				if (typ==='debug') { continue; }
				for (tag in tags[typ]) {
					if (! tags[typ][tag])  { continue; }
					if (tags[typ][tag].file!==undefined) { tags.tags_file.push(tag); }
				}
			}
			this.status('Init GUI variables..');    // -----------------------
			$('emir.e.mail').value     = this.http.mail;
			$('emir.e.host').value     = this.http.host;
			$('emir.e.ua').value       = this.http.ua;
			$('emir.e.result').value   = this.http.result;
			$('emir.e.gettoken').value = this.http.gettoken;
			$('emir.e.token').value    = this.http.token;
			$('emir.e.send').checked   = this.cfg.e_send;
			$('emir.e.show').checked   = this.cfg.e_show;

			this.status('Build GUI Show Events..'); // -----------------------
			this.create_sectionevents();

			this.status('Build GUI Show Tags..');   // -----------------------
			this.create_sectiontags();

/* / TODO: does not work (destroys event handling in some browsers completely
			e = this.get_events('all');
			for (c=0; c<e.length; c++) {
				typ = e[c].replace(/^on/,'');
				f = document.createEvent('Events');
				f.initEvent(typ, true, true);
				document.dispatchEvent(f);
			}
*/
			this.status('Build GUI Testing..');     // -----------------------
			//#? initialize "Testing"
			var a = 0, b = 0;
			var tag;
			// debug.max_* not checked here because confirm() is only important
			// if all tags and events are used; when debugging, the message is
			// useless, somehow ...
			for (tag in tags['HTML 4']) { a++; }
			for (tag in tags['HTML 5']) { a++; }
			for (tag in events.all)     { b++; }
			if (confirm('creating approx. '+a+'*'+b+' (='+a*b+') elements, will take some seconds ...')===false) {
				this.status('  elements not created; please reload page.');  // -----------------------
				$('testing').appendChild(this.create.tag('INPUT', {'id':'reset', type:'button', value:'Reset', onClick:'return emir.resetevents();', title:'destroy and re-create events'}, ''));
				this.initdone = false;
				return;
			}
			this.create_sectiontest();
			this.create_sectionbuttons();
			this.status('Init done.'); // -----------------------
			return;
		}, // init

		uselessdummytokeepjavascriptsyntaxhappy: null
	}; // obj
	return function() { return new obj(); };
}(); // EMiR object
	//# } emir__JS__
	</script>
</head>
<!-- { //# emir__BODY__ -->
<body id="body">
<ul class="c1" href="" ><li>&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;
	&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;
	&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;
	&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;
	<ul class="nav">
		<li><a href="#Top">Top</a> &#160;</li>
		<li><a href="#SelectEvents">Selection: Events</a> &#160;</li>
		<li><a href="#SelectTags">Selection: Tags</a> &#160;</li>
		<li><a href="#Config">Config</a> &#160;</li>
		<li><a href="#Testing">Testing</a> &#160;</li>
		<li><a href="#Results">Results</a> &#160;</li>
		<li><a href="#Errors">Event Errors</a> &#160;</li>
	</ul>
</li></ul>
<div class="c2">
	<a name="Top"></a>
<h2>Test Suite for Events in Tag Attributes</h2>
	<div>
	The purpose of this page is to identify the events which are bound to a
	HTML tag using the event attributes (like <i>onClick</i>, <i>onMouseOver</i>, etc.).
	</div>
	<h3>Usage</h3>
	<div>
	In the <span class="nav"><a href="#Testing">Testing</a></span> section events bound to a
	<span class="tag">tag</span> call a log function when they are triggered.
	The logged events for each tag can be shown with the <button>Result</button> button.<br>
	For more functionality, please see the following descriptions.
	</div>
	<h3>How It Works in Detail</h3>
	<div>
	In the <span class="nav"><a href="#Testing">Testing</a></span> section below, all known tags are listed.
	Each <span class="tag">tag</span> contains a text <b class="testme"></b>.
	All known JavaScript events are bound to that tag as tag attribute. If the
	event is triggered, the corresponding checkbox will be ticked.
	</div>
	<div>
	Some tags need to be tested in a specific context. Such a tag contains a
	link to be clicked, the <i>onClick</i> attribute is not set.<br>
	The content of the called link uses the tag in its intented context.
	</div>
	<div>
	As some events are interactive, they must be triggered manually by:
	<ol>
		<li>move the mouse over the <b></b> text</li>
		<li>click the mouse's select button on the <b></b> text</li>
		<li>click the mouse's context button on the <b></b> text</li>
		<li>double click the mouse's select button on the <b></b> text</li>
		<li>click the mouse's select button on the <b></b> text and move while button clicked</li>
		<li>press a key after selcting <b></b> text</li>
		<li>try to paste something on the <b></b> text</li>
		<li>use the mouse wheel on the <b></b> text</li>
	</ol>
	</div>
	<div>
	Finally click the <button>Result</button> button at end of the <span class="nav"><a href="#Testing">Testing</a></span>
    section to get the triggerd events for the tags in the <span class="nav"><a href="#Results">Results</a></span> section.
	</div>
	<h3>GUI</h3>
	<div>
	All checkboxes for the events in the tags are invisible by default.<br>
	Clicking the appropriate checkbox in the <span class="nav"><a href="#SelectEvents">Selection: Events</a></span>
	section shows this event checkbox for each tag. Unchecking the checkbox hides
	the tag's event checkbox.
	</div>
	<h4>Config</h4>
	<div>
	Moving the mouse over the <span class="nav"><a href="#Config">Config</a></span> section pops up a inset window with some
	configuration settings which are used for the result.
	</div>
	<h4>Event Errors</h4>
	<div>
	The <span class="nav"><a href="#Errors">Event Errors</a></span> section shows all tag events which threw an exception
	when triggered with the <button>fire</button> button.
	</div>
	<h4>GUI Buttons</h4>
	<div>
	Buttons at the end of the <span class="nav"><a href="#Testing">Testing</a></span> area:
	<ul>
		<li><button>Submit</button><br>
			will open the default mail client to send all triggered events for each tag.</li>
		<li><button>Result</button><br>
			will show all triggered events for each tag.</li>
		<li><button>fire</button><br>
			tries to trigger all events for each tag.</li>
	</ul>
	Some of these action may take 5-20 seconds, depending on the browser.
	</div>
	<div>
	The tabs (like "HTML 4" or "Keys") are just used to highlight all events of
	this category. These tabs provide no other functionality.
	</div>
	<h3>Note</h3>
	<div>
	<ul>
		<li>automatic event generation (<button>fire</button> button) works on some <span class="tag">FORM</span> tags only</li>
		<li>some (all?) <span class="tag">FORM</span> tags (<span class="tag">INPUT</span>, <span class="tag">TEXTAREA</span>, <span class="tag">SELECT</span> ..) may not get, and hence
			list, all events 'cause of the assiged tag attributes to catch the event</li>
		<li>some tags are not inside correct hierachy (i.e. <span class="tag">PARAM</span> inside <span class="tag">OBJECT</span> or <span class="tag">EMBED</span>)</li>
		<li>FF3 seems to have changed the event bubbling, hence tests are unreliable</li>

<!-- times: loading page and building DOM (150 tags, 330 events =~ 99.000 objects)
    * Intel Dual-Core 2.8GHz:
	Mac OS X,  Safari 4.04:	               >120 seconds
	Mac OS X,  Safari 5.03:	               >190 seconds    ~500MB
	Mac OS X,  Webkit r51708:              >120 seconds
	Mac OS X,  Firefox 2.0.20:             ~ 10 seconds    ~200MB
	Mac OS X,  Opera 10.10:	               ~  1 second
	WindowsXP, Chrome 3.0.195.33:          >120 seconds
	WindowsXP, Firefox 2.0.20:             ~ 20 seconds
	WindowsXP, Opera 10.10:	               ~ 10 second
    * Intel Quat-Core 3.1GHz:
	Linux,     Chrome 8.0.552.237:         >180 seconds
	Linux,     Chromium 73.0.3683.75:      ~ 15 seconds    ~400MB
	Linux,     Epiphany 2.30.2 (WebKit):   ~120 seconds
	Linux,     Firefox 3.6.13:             ~  6 seconds
	Linux,     Firefox 68.6:               ~  3 seconds    ~200MB
	Linux,     Midori 2.30.2 (WebKit):     ~120 seconds
-->
		<li>there is no additional garbage collection implemented, some browsers may consume huge amount of memory</li>
		<li>the <button>fire</button> butten triggers "onClick", "onChange", "onFocus", "onSelect" and "onBlur" in most browsers only.</li>
	</ul>
	</div>
	<h3>Closing Tags</h3>
	<div>
	For events in closing tags see <a href="tags-close.html">tags-close.html</a> (<b>Warning:</b> ~4.7MB)
	</div>
	<h3>Not (yet) automatically testable</h3>
	<div>
	Some tag attributes if used invoke an event too, for example:
	<i>checked</i>, <i>selected</i> or <i>autofocus</i><br>
	A working test case for these events is currently missing.
	</div>
	<h3>CGI</h3>
	<div>
	This tool can be used to collect browser events automatically.
	<br>
	If <label>send each event to server</label> is checked in <span class="nav"><a href="#Config">Config</a></span>
	section then each event will be send to the server specified in <label>FQDN to send event to</label> using the URL specified in <label>URL to send event to</label>. This request will use
    the string set in <label>User-Agent to be send</label> as value for the "User-Agent" HTTP header.
	</div>
	<h3>Debugging / Internals</h3>
		<button id="emir.d.internal" onClick="return alert(dbx_tree(emir,0));">show internal functions</button><br>
	<div>
	</div>

	<hr>
	<a name="SelectEvents"><h2>Selection: Events</h2></a>
	<form id="events"  action="dont-know-where-to-send-to" method="POST"></form>
	<a name="SelectTags"><h2>Selection: Tags</h2></a>
	<form id="tags"    action="dont-know-where-to-send-to" method="POST">
	</form>
	<hr>
<ul class="conf">
	<a name="Config"><h2>Config</h2></a>
<li>
	<form id="config"  action="#">
	<span>&#160;</span><fieldset>
		<label for="emir.e.show">&#160;show status for each event: <input id="emir.e.show"  type="checkbox" onChange="emir.set_config(this);"/></label>
		&#160;sort result by:
		<label for="emir.e.stag">   <input id="emir.e.stag"   name="sort" type="radio" onChange="emir.set_config(this);" checked />tags&#160 </label>
		<label for="emir.e.sevent"> <input id="emir.e.sevent" name="sort" type="radio" onChange="emir.set_config(this);"/>events</label>
		<label for="emir.e.empty">&#160;  list empty events, tags: <input id="emir.e.empty" type="checkbox" onChange="emir.set_config(this);" checked /></label>
		<hr>
		<label for="emir.e.mail">&#160;email address to send results to:  <input id="emir.e.mail"  type="text"     onChange="emir.set_config(this);"/></label><br>
		<label for="emir.e.send">&#160;send each event to server:  <input id="emir.e.send"  type="checkbox" onChange="emir.set_config(this);"/></label>
		<br>
		<label for="emir.e.host"     >&#160;FQDN to send event to:<input id="emir.e.host"   type="text"     onChange="emir.set_config(this);" size="20" value="" /></label>
		<br>
		<label for="emir.e.result"   >&#160;URL to send event to: <input id="emir.e.result" type="text"     onChange="emir.set_config(this);" size="60" value="" /></label><br>
		<br>
		<label for="emir.e.gettoken" >&#160;URL to get token from:<input id="emir.e.gettoken" type="text"   onChange="emir.set_config(this);" size="60" value="" /></label><br>
		<br>
		<label for="emir.e.token"    >&#160;token for sending event:<input id="emir.e.token"  type="text"   onChange="emir.set_config(this);" size="20" value="" /></label>
		<button id="emir.e.get" onClick="return emir.set_config(this);">get token</button><br>
		<br>
		<label for="emir.e.ua"       >&#160;User-Agent to be send:<input id="emir.e.ua"     type="text"     onChange="emir.set_config(this);" size="80" value="" /></label>
	</fieldset>
	</form>
</li>
</ul>
	<hr>
	<a name="Testing"><h2>Testing</h2></a>
	<form id="testing" action="dont-know-where-to-send-to" method="POST">
	<!-- //# emir__CHECK__ -->
	<!-- //# emir__FIELDSET__ -->
	</form>
	<hr>
	<a name="Results"><h2>Result</h2></a>
	<div id="tag-result"></div><br>
	<hr>
	<a name="Errors"><h2>Event Errors</h2></a>
	<div id="err-result"></div><br>
	<br>
</div>
	<textarea id="status" class="status"
		title="Status: click in field, the scroll text"
	></textarea>
	<script type="text/javascript">
emir=EMiR(); // generate and initilize "Testing" section
$t$(document.getElementById('use-event-HTML 4'),'o'); // mark checkboxes (o is prefix for classname)
$t$(document.getElementById('use-tag-HTML 4'),  'o'); // mark checkboxes (o is prefix for classname)
	</script>
</body> <!-- } //# emir__BODY__ -->
</html>