Autogenerate does not work within iframes
Closed this issue · 7 comments
It shouldn't be that hard to traverse an iframe to iframe.contentWindow.document
document.getElementById()
does not find the ids within the iframe.
That element can be found using document.getElementById("iframeID").contentWindow.document.getElementById("actual_id")
.
That only works if the iframe is from the same origin though. So we cannot assume this will work in all cases.
The autogenerateWithinId Function actually makes use of the id again when the link hint is activated. So iframes would need special handling.
pseudocode:
function autogenerateWithin(..., container_is_an_iframe) {
let container = iframe_element.contentWindow.document.body if container_is_an_iframe else document.getElementById(containerID);
...
if not container_is_an_iframe {
let f = new Function(`document.getElementById(\"${containerID}\").querySelector(\"[`+this.AUTOGEN_LINKHINT_ATTRIBUTE+"='"+this.global_index+"']\").click();");
} else {
let f = new Function(`document.getElementById(\"${containerID}\").contentWindow.document.body.querySelector(\"[`+this.AUTOGEN_LINKHINT_ATTRIBUTE+"='"+this.global_index+"']\").click();");
}
}
I could just replace document.getElementById(containerID)
with a function that returns normally unless it's an iframe. When it's an iframe, it returns the iframe document.
That should be disableable with a parameter.
I assume that showKeys()
also requires modification, because it uses document.getElementsByClassName()
.
It should not only get all elements in the document, but also in the iframes specified.
Options:
- track iframes that should be traversed in autogenerate. This means that only iframes with autogenerated key hints would be activated - not ones with manually added key hints. It is reasonable to assume that a user would not manually add hints to iframe content though. (And if they did, they can also modify this library or inject some iframes into the tracking array).
- traverse all first-class iframes because it will do nothing unless the tags are in there. This option is preferrable due to ease of code and ease of use. Will have to check performance. Might cause issues if the iframe content uses the same class tags. So better not choose this option.
- let user specify all iframes that should be traversed both in autogenerate and showKeys. This is annoying for the user if they have many iframes though.
I'm not supporting nested iframes for the moment. YAGNI.
TODO:
- implement
getElementOrIframeBodyById
- track iframes that we use in autogenerate
- show keys for those iframes in
showKeys
as well.
implemented in 02e6862 but there's still an inconvenience:
if the iframe was clicked (not the surrounding content), it seems to capture the keys - brotkeys does not react to them
it works when running manager.autogenerateWithinId("ifrem", manager.GenerationEnum.tag_anchor)
from the browser console, but not from the file itself...
That is because the iframe content must already be loaded. so this works:
<iframe id="ifrem" src="./mf_classic_access_conditions.md.html" frameborder="0" scrolling="no" style="border:0; margin:0; padding:0; width:100%;" onload="resizeIframe(this);removeTopPaddingOfContent();brotkeysSupportIframeContent();">Your browser does not support iframes.</iframe>
</body>
<script src="../libs/jquery/jquery-3.3.1.min.js"></script>
<script src="../libs/bootstrap/js/bootstrap.min.js"></script>
<script src="../libs/jaywcjlove_hotkeys/hotkeys.min.js"></script>
<script src="../libs/lucidbrot_brotkeys/brotkeys.js"></script>
<script src="../keyjs/everywhere.js"></script>
</html>
This is a snippet I use in my website. most of this is not relevant to this issue. Important is just that onload="brotkeysSupportIframeContent();". In my case, I defined that function in
everywhere.js`:
// must be called in iframe onload
// iframe handling for iframe that has id "ifrem". That is mostly the case in publications using markdown (see _dummy_md.html)
function brotkeysSupportIframeContent(){
let myifrem = document.getElementById("ifrem");
if (myifrem != undefined && myifrem.tagName == "IFRAME"){
console.log("special handling for iframe: ");
manager.autogenerateWithinId("ifrem", manager.GenerationEnum.tag_anchor);
}
}