Adjusting IFrame Trick I would like to implement in TW

230 views
Skip to first unread message

Jan

unread,
Sep 4, 2020, 5:50:16 PM9/4/20
to TiddlyWiki
Hello community,
recently I stumbled upon a script which is able to adjust the size of an Iframe to the content.
Because I like to work with external files like etherpads for interaction, this would make a lot of things possible.

Here's a Demo https://css-tricks.com/examples/iFrameResize/crossdomain.php#
<script type="application/javascript">

function resizeIFrameToFitContent( iFrame ) {

    iFrame.width  = iFrame.contentWindow.document.body.scrollWidth;
    iFrame.height = iFrame.contentWindow.document.body.scrollHeight;
}

window.addEventListener('DOMContentLoaded', function(e) {

    var iFrame = document.getElementById( 'iFrame1' );
    resizeIFrameToFitContent( iFrame );

    // or, to resize all iframes:
    var iframes = document.querySelectorAll("iframe");
    for( var i = 0; i < iframes.length; i++) {
        resizeIFrameToFitContent( iframes[i] );
    }
} );

</script>

<iframe src="usagelogs/default.aspx" id="iFrame1"></iframe>
I wonder if this could be implemented to tiddlywiki.

Two things to change
-It needs to hav flexible Ids to allow multiple instances.
-width should be fixed only the height should adapt.

What do you think, is this possible?
Best wishes Jan



Eric Shulman

unread,
Sep 4, 2020, 8:24:32 PM9/4/20
to TiddlyWiki
On Friday, September 4, 2020 at 2:50:16 PM UTC-7, Jan wrote:
recently I stumbled upon a script which is able to adjust the size of an Iframe to the content.
Because I like to work with external files like etherpads for interaction, this would make a lot of things possible.
Here's a Demo https://css-tricks.com/examples/iFrameResize/crossdomain.php#
 
<script type="application/javascript">
function resizeIFrameToFitContent( iFrame ) {
    iFrame
.width  = iFrame.contentWindow.document.body.scrollWidth;
    iFrame
.height = iFrame.contentWindow.document.body.scrollHeight;
}
window
.addEventListener('DOMContentLoaded', function(e) {
   
var iFrame = document.getElementById( 'iFrame1' );
    resizeIFrameToFitContent
( iFrame );
   
// or, to resize all iframes:
   
var iframes = document.querySelectorAll("iframe");
   
for( var i = 0; i < iframes.length; i++) {
        resizeIFrameToFitContent
( iframes[i] );
   
}
} );
</script>

I wonder if this could be implemented to tiddlywiki.

Two things to change
-It needs to have flexible Ids to allow multiple instances.

The first two lines from the event listener are looking for an iframe with a specific ID.  The rest of the listener does the same for ALL iframes, regardless of ID.  Thus, you can simply omit the first two lines and keep the rest.

-width should be fixed only the height should adapt.

Just omit the "iFrame.width  = ... " line from the resizeIFrameToFitContent function, so that only the height is adjusted.
 
What do you think, is this possible?

Normally, this kind of code would be added to the <head> section of the HTML file.  To do this in TiddlyWiki, you would place the code in a tiddler tagged with $:/tags/RawMarkup and then save-and-reload so the code is inserted into the <head> of the HTML file.

HOWEVER... having said all of the above... This code, as written, will NOT work in TiddlyWiki.

The problem is that, in TiddlyWiki, any IFrame that is contained in a tiddler will not even *exist* until that tiddler is actually displayed... and at the time that the document is *loaded*, no tiddlers are displayed yet.  Thus, the above code will not find any "iframe" elements to modify.  To make this work in TiddlyWiki, you need to trigger the code whenever a tiddler is opened or refreshed rather than when the DOM content is loaded.

Here's some EXPERIMENTAL code that uses the TiddlyWiki core "hook" mechanism instead of window.addEventListener()
/*\
title: ResizeIFrame
type: application/javascript
module-type: startup

\*/

(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";

// Export name and synchronous status
exports
.name = "resizeIFrame";
exports
.platforms = ["browser"];
exports
.after = ["startup"];
exports
.synchronous = true;
exports
.startup = function() {
   $tw
.hooks.addHook("th-page-refreshed",function() {
      setTimeout
(function() {

         
var iframes = document.querySelectorAll("iframe");
         
for( var i = 0; i < iframes.length; i++) {

            iframes
[i].height = iframes[i].contentWindow.document.body.scrollHeight;
         }
     
}, 100);
   
});
   $tw
.hooks.addHook("th-navigating",function(event) {
      setTimeout
(function() {

         
var iframes = document.querySelectorAll("iframe");
         
for( var i = 0; i < iframes.length; i++) {

            iframes
[i].height = iframes[i].contentWindow.document.body.scrollHeight;
         
}
     
}, 100);
     
return event;
   
});
};
})();

Notes:
* Enter the code above into the text field of a tiddler (e.g., "ResizeIFrame")
* Set the tiddler's type field to a value of "application/javascript" and create a "module-type" field with value of "startup"
* Save-and-reload for the code to take effect.

To test:
* Create a tiddler containing an iframe, like this:
<iframe src="somefile.html" width="100%" height="480"></iframe>
* IMPORTANT NOTE: the src="..." file must be from the *same domain* as your TiddlyWiki file because, for security reasons, modern browsers do not permit "cross-domain" access to the "document" object of another file.

How it works:
* The code defines a "startup" function that is invoked when your TiddlyWiki file is loaded.
* This code sets up two "hooks" that will be triggered in response to TWCore activities
* The "th-page-refreshed" hook is triggered when the page is first displayed and whenever it is refreshed (e.g., if you edit the PageTemplate)
* The "th-navigating" hook is triggered whenever you open a tiddler or follow a link to an already opened tiddler.
* Each hook uses setTimeout(...) to delay it's action by 100 milliseconds.  This is needed because the hooks are triggered *before* the IFrame contents are actually rendered, so we need to wait just a little bit for the Iframe to do it's thing.  You might need to increase this delay depending upon the speed of your system and/or the complexity of the IFrame contents.

I've tested this code on my own system by viewing a local file (actually another TiddlyWiki file!) in an IFrame, and it *SEEMS* to work.

Give this a try and let me know how it goes...

enjoy,
-e

TW Tones

unread,
Sep 4, 2020, 11:55:14 PM9/4/20
to TiddlyWiki
Jan,

I just had a look at etherpad, and reminds me of document part the now defunct Google Wave, but various google and Microsoft products have similar editing opportunities. 

I see why you value having a iframe to access such documents. In addition to multi-user documents it gives rise to a WYSIWYG editor. 

Always wishing to extend the functionality within tiddlywiki, I can see how this may be away to address some of out multi-user issues with tiddlywiki.

Given it is an open source environment, and tiddlywiki is too, perhaps this is an opportunity to bring the two projects together. Either read only or read/write tiddlywikis could delegate shared documents to etherpad as a special kind of tiddler, but tiddlywiki is in an ideal position to manage the multiple document view into multiple etherpad documents. 

Much of this may already be the case with the iframe solution you are working on, so thanks for raising it here. But I think a little deeper integration would help both projects.

What may deeper integration look like?
  • Create a new etherpad document from within a special tiddler
  • Seed it with the content of the tiddler before conversion
  • Be able to use the wiki to manage/wrap multiple etherpads
    • Includes searchable and other features
  • Be able to import.export cut/copy and paste between etherpad and tiddlers
    • Include drag and drop and handle conversions if needed.
  • Perhaps the etherpad client component can be made a plugin in tiddlywiki
  • and the etherpad server component deployed with the tiddlywiki node server install
If the technology or the etherpad community is not open to this valuable contribution, perhaps the tiddlywiki community could build a method for collaborative and external tiddler by tiddler server. Kind of taking the external tiddler model further. If we took this path we may be able to designer even tighter integration to the extent that once implemented interactive "shared" tiddlers could become a feature.

just thinking.

Regards
Tones 

Jan

unread,
Sep 5, 2020, 7:07:29 AM9/5/20
to tiddl...@googlegroups.com
Hi Eric,
so far it does not work yet...thought I took a really small but long page and gave it a 1000 milliseconds.
But at least it does not throw an error-message like my brute first attempt did.

If you want to inspect the installation look here:
https://www.szen.io/Kunstgeschichte/#FlexframeTest

Best wishes Jan
--
You received this message because you are subscribed to the Google Groups "TiddlyWiki" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tiddlywiki+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/tiddlywiki/8ec7c9eb-3277-4594-bae7-3832547b7497o%40googlegroups.com.

Jan

unread,
Sep 5, 2020, 7:16:48 AM9/5/20
to tiddl...@googlegroups.com
Am 05.09.2020 um 05:55 schrieb TW Tones:
Jan,

I just had a look at etherpad, and reminds me of document part the now defunct Google Wave, but various google and Microsoft products have similar editing opportunities. 

I see why you value having a iframe to access such documents. In addition to multi-user documents it gives rise to a WYSIWYG editor. 

Always wishing to extend the functionality within tiddlywiki, I can see how this may be away to address some of out multi-user issues with tiddlywiki.

Given it is an open source environment, and tiddlywiki is too, perhaps this is an opportunity to bring the two projects together. Either read only or read/write tiddlywikis could delegate shared documents to etherpad as a special kind of tiddler, but tiddlywiki is in an ideal position to manage the multiple document view into multiple etherpad documents. 

Much of this may already be the case with the iframe solution you are working on, so thanks for raising it here. But I think a little deeper integration would help both projects.

What may deeper integration look like?
  • Create a new etherpad document from within a special tiddler
  • Seed it with the content of the tiddler before conversion
  • Be able to use the wiki to manage/wrap multiple etherpads
    • Includes searchable and other features
  • Be able to import.export cut/copy and paste between etherpad and tiddlers
    • Include drag and drop and handle conversions if needed.
  • Perhaps the etherpad client component can be made a plugin in tiddlywiki
  • and the etherpad server component deployed with the tiddlywiki node server install
If the technology or the etherpad community is not open to this valuable contribution, perhaps the tiddlywiki community could build a method for collaborative and external tiddler by tiddler server. Kind of taking the external tiddler model further. If we took this path we may be able to designer even tighter integration to the extent that once implemented interactive "shared" tiddlers could become a feature.

just thinking.

Regards
Tones
Hi Tones,
Etherpad also uses node.js on the server. For using it in class the possibility of using realtime cooperation is great.
I also think, the ability to create and show an etherpad in TW would be a great enhancement because reatime cooperation is difficult in TW so far.

Best wishes Jan

Eric Shulman

unread,
Sep 5, 2020, 7:27:15 AM9/5/20
to tiddl...@googlegroups.com
On Saturday, September 5, 2020 at 4:07:29 AM UTC-7, Jan wrote:
so far it does not work yet...thought I took a really small but long page and gave it a 1000 milliseconds.
But at least it does not throw an error-message like my brute first attempt did.

If you want to inspect the installation look here:
https://www.szen.io/Kunstgeschichte/#FlexframeTest

In my instructions, I wrote:
* Set the tiddler's type field to a value of "application/javascript" and create a "module-type" field with value of "startup"

However, when I checked your test, $:/plugins/es/FlexFrame.js did NOT have a module-type field.
This field is required in order to cause the code to be invoked.  Without it, the hooks are not
actually being defined.

You need to edit $:/plugins/es/FlexFrame.js and add a field named "module-type", with a value of "startup".
Then save-and-reload.

-e

Jan

unread,
Sep 5, 2020, 3:17:05 PM9/5/20
to tiddl...@googlegroups.com
Hello Eric,
it's marvelous. Your instruction was perfect. (...and I see that I was not really awake this morning.)
This is a great help to integrate external content into tiddlywiki, thanks a lot!

All best wishes Jan
You need to edit $:/plugins/es/FlexFrame.js and add that field.  Then save-and-reload.

-e
--
You received this message because you are subscribed to the Google Groups "TiddlyWiki" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tiddlywiki+...@googlegroups.com.

Eric Shulman

unread,
Sep 5, 2020, 4:34:35 PM9/5/20
to TiddlyWiki
On Saturday, September 5, 2020 at 12:17:05 PM UTC-7, Jan wrote:
it's marvelous. Your instruction was perfect. (...and I see that I was not really awake this morning.)
This is a great help to integrate external content into tiddlywiki, thanks a lot!

Good to know it's working.

One more suggestion:

When I checked your latest test case at https://www.szen.io/Kunstgeschichte/#FlexframeTest, it gave a RMOD (Red Message of Death) to report an "Uncaught Security Error".  This is due to the fact that your test is attempting to modify a "cross-origin" IFrame (with contents from wikipedia).  As I noted in my instructions:

* IMPORTANT NOTE: the src="..." file must be from the *same domain* as your TiddlyWiki file because, for security reasons, modern browsers do not permit "cross-domain" access to the "document" object of another file.

There's no way to make the code work for cross-origin references... but you *can* suppress the error message by adding a try/catch wrapper around the hook code, like this:
exports.startup = function() {
   $tw
.hooks.addHook("th-page-refreshed",function() {
      setTimeout
(function() {

         try {
            
var iframes = document.querySelectorAll("iframe");

            
for( var i = 0; i < iframes.length; i++) {
               iframes
[i].height = iframes[i].contentWindow.document.body.scrollHeight;
         } catch(e) { /* do nothing */;   }
      }, 1000);

   
});
   $tw
.hooks.addHook("th-navigating",function(event) {
      setTimeout
(function() {
         try {
            
var iframes = document.querySelectorAll("iframe");

            
for( var i = 0; i < iframes.length; i++) {
               iframes
[i].height = iframes[i].contentWindow.document.body.scrollHeight;
         } catch(e) { /* do nothing */;   }
      
}, 1000);
     
return event;
   
});
};

Let me know how it goes...

enjoy,
-e

TW Tones

unread,
Sep 5, 2020, 8:59:17 PM9/5/20
to TiddlyWiki
Folks,

I just wanted to share a thought, what if we introduce a new window that can be brought forward or pushed to the back that retains an Iframe in a no refresh mode indefinitely? 

This would allow iframes into other services to avoid the tiddlywiki refresh!

You could call them no refresh tiddler windows, and allow a longer term consistent iframe.

Regards
Tony

Ste

unread,
Sep 6, 2020, 6:00:55 AM9/6/20
to TiddlyWiki
Could this be used with ethercalc (https://ethercalc.net/) or other node.js apps?

I remember someone dropped social Calc spreadsheets into tiddlywiki ages and ages ago.

Jan

unread,
Sep 6, 2020, 5:20:32 PM9/6/20
to tiddl...@googlegroups.com
Hi Steve,
to adjust the size -as Eric pointed out- the source of the Iframe has to
point to the same domain.
So if you are running an instance of ethercalc there, this should work.

Best wishes Jan.
Reply all
Reply to author
Forward
0 new messages