<!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] + ': <' + o[a] + '></' + o[a] + '>'; 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', ' ': {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'}, ' ': {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:''}, ' ': {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 ' ': {}, '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 ' ': {}, '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'}, ' ': {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:  ')); } 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>                                                                                                                  <ul class="nav"> <li><a href="#Top">Top</a>  </li> <li><a href="#SelectEvents">Selection: Events</a>  </li> <li><a href="#SelectTags">Selection: Tags</a>  </li> <li><a href="#Config">Config</a>  </li> <li><a href="#Testing">Testing</a>  </li> <li><a href="#Results">Results</a>  </li> <li><a href="#Errors">Event Errors</a>  </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> </span><fieldset> <label for="emir.e.show"> show status for each event: <input id="emir.e.show" type="checkbox" onChange="emir.set_config(this);"/></label>  sort result by: <label for="emir.e.stag"> <input id="emir.e.stag" name="sort" type="radio" onChange="emir.set_config(this);" checked />tags  </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">  list empty events, tags: <input id="emir.e.empty" type="checkbox" onChange="emir.set_config(this);" checked /></label> <hr> <label for="emir.e.mail"> 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"> send each event to server: <input id="emir.e.send" type="checkbox" onChange="emir.set_config(this);"/></label> <br> <label for="emir.e.host" > 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" > 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" > 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" > 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" > 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>