javascript: var FocusIndicatorBookmarklet;!function(e){let t;!function(e){e.Accessibility="x",e.Autolog="a",e.ClearDiff="c",e.Diff="d",e.LogFocused="l",e.LogFormat="f",e.Help="h",e.Indicator="i",e.Style="s",e.Mode="q",e.Modifier="ctrlKey"}(t||(t={}));const o=[["outline-style","solid"],["outline-width","2px"],["z-index","100"]],n=[["outline-offset","2px"],["outline-color","black"],["box-shadow","0 0 0 2px white"]],l=[["outline-offset","-2px"],["outline-color","white"],["box-shadow","inset 0 0 0 4px black"]];!function(){let e=(s=o,{createFocusCSSSelector:function(e,t){return`.${t}:focus\n { ${(e=[...s,...e]).map((e=>`${e[0]}: ${e[1]};`)).join("\n")} }`}});var s;let a=function(){function o(e){if(e===t.Mode)event.preventDefault(),r=!r,i.printStatus("Navigation mode: ",r)}function n(e,o){switch(c.preventDefault(o)&&event.preventDefault(),o){case t.LogFocused:i.logAttributes(e);break;case t.Accessibility:i.logA11yAttributes(e);break;case t.Diff:i.logDiff(e);break;case t.ClearDiff:c.clearDiffSnapshots();break;case t.Autolog:i.toggleAutologStatus();break;case t.LogFormat:i.toggleLogFormat();break;case t.Style:a.toggleStyleName();break;case t.Indicator:a.toggleIndicatorStyleOnOff();break;case t.Help:console.log("Hot keys:\n---------"),console.log("Active when the document has focus."),console.log(`${t.Style}: Toggle between available focus indicator styles.`),console.log(`${t.Indicator}: Toggle focus indicator style on/off.`),console.log(`${t.LogFormat}: Toggle auto-logging format.`),console.log(`${t.Autolog}: Toggle auto-logging on/off.`),console.log(`${t.Accessibility}: Log the focused element's accessibility attributes as a list.`),console.log(`${t.LogFocused}: Log all of the focused element's attributes as a list.`),console.log(`${t.Diff}: Save an element's diff snapshot. Reports the diff status if available.`),console.log(`${t.ClearDiff}: Clear all diff statuses.`),console.log(`CTRL + ${t.Mode}: Toggle navigation mode on/off -> disable/enable hotkeys.`)}}function l(e){e[t.Modifier]?o(e.key):r||n(e.target,e.key)}function s(e){const t=e.target;c.setFocusStyle(t),i.autologElement(t)}let r=!1,u=[],f=0;return{addEventListeners:function(){document.body.addEventListener("focus",s,!0),document.body.addEventListener("keydown",l,!0)},createFocusStyles:function(t,o){return t.map(((t,n)=>{let l=o.concat("-",(n+1).toString());return u.push(l),function(t,o){let n=document.createElement("style");return n.setAttribute("type","text/css"),n.innerHTML=e.createFocusCSSSelector(t,o),n}(t,l)}))},insertStylesInDocument:function(e){let t=document.getElementsByTagName("head")[0];return t?!!e.every((e=>t.appendChild(e)))||(console.log("Error: Cannot insert a style element into the <head> tag."),!1):(console.log("Error: The page is missing a <head> tag --\x3e Not a web page?"),!1)},getActiveStyleName:function(){return f>=0?u[f]:void 0},getInactiveStyleNames:function(){return f>=0?u.filter(((e,t)=>t!==f)):u},toggleStyleName:function(){f=f+1<u.length?f+1:0,i.printStatus("Focus style: ",`#${f+1}`)},toggleIndicatorStyleOnOff:function(){f=f>=0?-1:0,i.printStatus("Focus style: ",f>=0)}}}(),c=function(){function e(e){const t=a.getActiveStyleName();t&&e.classList.remove(t),o(e)}function o(e){0===e.classList.length&&e.removeAttribute("class")}function n(t){let o=new Map,n=t.cloneNode();return e(n),[...n.attributes].forEach((e=>o.set(e.nodeName,e.value))),o}function l(e,t){t||(t=n(e)),s.set(e,t)}let s=new Map;return{preventDefault:function(e){return Object.values(t).includes(e)},setFocusStyle:function(e){const t=a.getActiveStyleName(),n=a.getInactiveStyleNames();t&&e.classList.add(t),e.classList.remove(...n),o(e)},unsetFocusStyle:e,getDiff:function(e,t=!1){const o=n(e),a=s.has(e)?new Map(s.get(e)):new Map;let c=new Set,i=new Set,r=new Map;return o.forEach(((e,t)=>{let o=a.get(t);void 0===o?c.add(t):o!==e&&r.set(t,[o,e]),a.delete(t)})),a.forEach(((e,t)=>i.add(t))),t&&l(e,o),{added:c,removed:i,changed:r}},hasDiffSnapshot:function(e){return s.has(e)},saveDiffSnapshot:l,clearDiffSnapshots:function(){s=new Map,console.log("Diff data cleared.")}}}(),i=function(e,t){const o=function(){const e=new Map;return e.set("object",(e=>console.log(e))),e.set("standard",(e=>Object.values(e).forEach((e=>console.log(e))))),function(t,o){e.get(o)(t)}}();function n(e,t){function n(){let e=[];return["class","style"].forEach((t=>function(t){let o=a.findIndex((e=>e.name===t));o>-1&&e.push(a.splice(o,1)[0])}(t))),a.sort(((e,t)=>e.name<t.name?-1:1)),[...a,...e]}function l(){let e="";return n().forEach((({name:t,value:o})=>{e=e.concat(`• ${t}`,o?`: ${o}`:"","\n")})),e}let s=e.cloneNode();c.unsetFocusStyle(s);let a=[...s.attributes].map((e=>({name:e.nodeName,value:e.nodeValue})));if(t&&(a=a.filter((e=>t(e)))),0===a.length)return void console.log("No attributes.");const i={attributes:l()};console.log(`\n${e.nodeName} / ${a.length}:`),o(i,"standard")}function l(e,t){const o="boolean"==typeof t?t?"ON":"OFF":t;console.log(`${e}${o}`)}let s=!0,a="standard";return{logDiff:function(e){if(!c.hasDiffSnapshot(e))return c.saveDiffSnapshot(e),void console.log("Diff set.");let{added:t,removed:o,changed:n}=c.getDiff(e,!0);const l=t.size+o.size+n.size;0!==l?(console.log(`\nDIFF / ${l}:`),t.size>0&&function(){let e="";[...t].sort().forEach((t=>e+=`\n• ${t}`)),console.log("Added",e)}(),o.size>0&&function(){let e="";[...o].sort().forEach((t=>e+=`\n• ${t}`)),console.log("Removed",e)}(),n.size>0&&function(){let e="";[...n.entries()].sort().forEach((([t,o])=>e+=`\n• ${t}: ${o[0]} -> ${o[1]}`)),console.log("Changed",e)}()):console.log("DIFF: No changes.")},logAttributes:n,logA11yAttributes:function(e){n(e,(function(e){return t.some((t=>e.name.match(t)))}))},toggleAutologStatus:function(){s=!s,l("Auto log: ",s)},toggleLogFormat:function(){a="standard"===a?"object":"standard",l("Log format: ",a)},autologElement:function(t){if(!s)return;let n=[];e.forEach((e=>{t.hasAttribute(e)&&n.push(`${e}: ${t.getAttribute(e)}`)}));const l=Object.assign({element:t},n.length&&{attributes:n.join(", ")});o(l,a)},printStatus:l}}(["id","role","tabindex"],[/^aria-/,/role/,/tabindex/,/alt/,/title/,/autocomplete/,/placeholder/,/disabled/,/draggable/]);!function(){const e=[n,l],t=a.createFocusStyles(e,"bookmarklet-focusstyle");console.log("Keyboard Testing Bookmarklet\n(v2023.06.02)"),console.log("Active focus style: ",t[0]),a.insertStylesInDocument(t)?(a.addEventListeners(),console.log("Bookmarklet running."),console.log("For help, press 'h'.")):console.log("Start-up aborted.")}()}()}(FocusIndicatorBookmarklet||(FocusIndicatorBookmarklet={}));
