locked
setting iFrame innerHTML causes tags being "disabled", < > becoming &lt and &gt RRS feed

  • Question

  • Hello,

    Is it really impossible to load html into a iFrame but loading from package html files or from the web?

    I put html code without any script into iFrame.innerHTML but tags are disabled (< > becoming &lt and &gt). Note: no scripts inside.

    I also tried with iFrame.src=file.path; (file is from Storage).

    Thanks in advance for your advice or suggestions.

    Thursday, April 5, 2012 7:27 PM

Answers

All replies

  • Hi.

    It appears that you would like your app to render html pages that are stored in the user's documents folder.  While this could be done easily in a desktop program with WPF, security restrictions on Metro, may not permit this scenario.  This is interesting to me because there may be certain types of applications that just can't be done in Metro.  On the other hand, maybe they can be done in Metro but with a different architecture, that is, by choosing to do things differently in a "Metro style of thinking."

    Would you tell more about your application?  That is, how are the html pages to be used in your app?  Will your app modify the pages or just view them?  If viewing, what does your app do that is different from the browser?

    Maybe there is a way to do your app such that you are not up against Metro restrictions but can take advantage of Merto features.







    • Edited by jrboddie Friday, April 6, 2012 5:39 PM
    Friday, April 6, 2012 11:41 AM
  • I would be eager to write my app in WPF (or Metro C#/XAML) but I encountered many bugs or other difficulties dealing with invokeScript or other javascript tecniques I need so I looked for HTML5/Javascript+iFrames technology in W8 where I am "inside" the browser. But I see that there are other problems (security issues the like you wrote about).
    Saturday, April 7, 2012 12:14 PM
  • Hi, 

    maybe you can make iframe load a page(html file) which in your project, and then write "document.body.innerHTML = '...'" in the loaded html file.

    Monday, April 9, 2012 2:46 AM
  • I think the html code would be sort of "deactivated" (by replacing <> with &lt and &gt) in this way too. I cannot try today however.
    • Edited by P5music Monday, April 9, 2012 10:02 AM
    Monday, April 9, 2012 9:57 AM
  • You must have some weird encoding issue with your code.

    Please share a very simple repro of your code.

    -Jeff


    Jeff Sanders (MSFT)

    Monday, April 9, 2012 12:25 PM
    Moderator
  • PS, see the link I put in your other post:

    You can load any HTML as unsafe as well, so copying it is not necessary:

    http://msdn.microsoft.com/en-us/library/windows/apps/hh465380.aspx

    Do this judiciously however as you open your app as a potential security hole for a customer.


    Jeff Sanders (MSFT)

    Monday, April 9, 2012 12:47 PM
    Moderator
  • Jeff,

    I have been incredibly frustrated by a similar issue as this customer. The OP isn't encoding his stuff wrong or weirdly, I think it's a defect in IE. See my SO investigation of this issue here for more.

    In my answer, I say this:


    The key was that I wasn't initially setting the src attribute on the iframe in my markup. Because it wasn't set, iframe.contentDocument wasn't getting created and set.

    however, that was only an answer that worked around the original issue, not a resolution.

    I don't think I can begin to account for all of the hours I've spent over the past few months trying to make this quite simple scenario work. Really quite frustrating to the point of abject helplessness.

    Friday, December 14, 2012 5:45 PM
  • Thanks for sharing!

    Sorry that you struggled with this.  Did you post the problem to this forum?  I don't recall seeing it.

    -Jeff


    Jeff Sanders (MSFT)

    Friday, December 14, 2012 7:00 PM
    Moderator
  • I have not posted it - I haven't really been able to frame the issue in such a way that makes it different from existing questions posted. I'm building an Instapaper client app, so it fits broadly into the News Reader category of apps. I discovered Chris Jones' Reader Walkthrough yesterday (http://msdn.microsoft.com/en-us/library/windows/apps/Hh780610.aspx, where was that one a few months ago<grin>?) and essentially re-implemented my layout engine to use CSS regions. It looks great when I use a static HTML sample file I generated, but no matter what I try, I can't get the iframe which feeds the regions to perform correct pagination or layout.

    What adds to this is that I must sign all outgoing Instapaper API requests (protocol is xAuth), including the one that returns an HTML document of an article. To allow for offline reading, I do this up front and save the string into indexedDB (I've also tried saving it as a temp or local file, don't think I need to tell you how that ended up working), so etcetera etcetera, I can't just set the src attribute of an iframe to a URL.

    I'm still struggling mightily with this, and I could use some help. I've tried so many different ways of solving this problem that I'm just not sure that I have the necessary conceptual understanding to be able to understand or describe my problem succinctly in a forum or SO post :(

    Friday, December 14, 2012 8:02 PM
  • Oh I see.  You really need a custom browser experience.  There is really no easy way to accomplish this.  You would basically implement the read and write logic and have to massage the HTML yourself.  You have the added complexity of grabbing navigation from the HTML that gets loaded and managing the interaction with the user yourself.  Depending on the type of content, a .NET solution may be better using the WebView control.  You would not have the same iframe issues then.

    Jeff Sanders (MSFT)

    Friday, December 14, 2012 8:40 PM
    Moderator
  • Perhaps a custom browsing experience is what is needed, but I sure don't feel that I should have to resort to that given the relatively simple requirement of Displaying an in-memory HTML string in the App.

    The path of HTML massaging is one that I've been trying to avoid, but it isn't all that bad -- I've got numerous ways to parse through and extract the content between body tags... the article HTML isn't that tricky, there's a single inline JS call to a (non-existent) method called loadFont on the body tag, and other than a style tag in the head, it's just straight markup.

    I don't need to manage navigation triggered from anchors within the framed content since I can simply allow them to behave in the default manner. I guess I'm not able to tell whether I'm headed down a dead-end path even though I can get different aspects functioning correctly, or whether I'm just fumbling my way to a working solution.

    When using msContentFlowInto (as demo'ed in the Dynamic CSS Regions example), I'm not able to get the pages to correctly paginate - it displays the article, but with an incorrect layout as compared to the same article rendered statically.

    Since this issue has so many moving parts, it would probably be best to contact me directly for a screencast or other form of sharing details on my issue and what I've attempted to work around. Let me know if that is considered an option of value.

    Thanks,

    Josh
    Saturday, December 15, 2012 6:51 AM
  • Hi Josh,

    OK I think I am getting a better idea of what you are doing.  Have you considered using HTML fragments then?  That may be a much better solution for what you are doing.  http://code.msdn.microsoft.com/windowsapps/Fragments-91f66b07

    As you probably know it is difficult to support something this complex via the forums.  You can contact myself and other engineers through a support case if you are really getting stuck however.  Otherwise we can continue to dialog this way!

    -Jeff


    Jeff Sanders (MSFT)

    Monday, December 17, 2012 12:47 PM
    Moderator
  • I think that the HTML fragment path is going to end up being the route... I made a hard push on the problem this weekend, and I think I finally have it nailed down enough to consider it a possible solution.

    I ended up borrowing heavily from the dynamic CSS region templates example, which uses the Fragments API as part of the dynamic pagination process. It would be awesome if the Fragments API supported rendering an HTML string instead of only a url (I've tried createObjectURL on a string variable; "no such interface supported" is the error). As well, I still have to do some massaging to get it to play nice.

    I'm not fully confident of its' stability or efficiency, but I've decided to push profiling lower in favor of testing overall stability and cleaning up other various features since performance doesn't yet seem to be an issue.

    Essentially, I have a 'paginationRequested' event which is queued up whenever a new article has been selected for reading. The handler for that does some checking and ends up doing this:

    MSApp.execUnsafeLocalFunction(function () {
    
                frameDoc.body.innerHTML = window.toStaticHTML(evt.text);
                var style = frameDoc.querySelector("style");
                if (style) {
                    style.innerHTML = '';
                }
                createPages();
            });

    The problem I encountered with just having this logic is that empty pages aren't removed when the user selects a second article with fewer pages. That seems to be because changing the innerHTML causes the iframe's readyState to change (IE doesn't fire 'complete' in cases where the doc has been modified by script) and resizing (empty page culling) occurs too early.

    Eventually, the solution I came to (and I'm hoping this is not causing any other issues i've yet to find) is to put the call to resizePages() into a separate thread by wrapping it in a setTimeout call:

    setTimeout(resizePages, 10);

    The example's resizePages method works fine here in many cases, but isn't particularly robust, so I modified it to make better use of query selectors and such:

    function resizePages() {
            console.log('resize called');
            
            var flexboxElement = document.getElementById('pageContainer');
            var qry = WinJS.Utilities.query('.articlePage div', flexboxElement);
            var newQry = [];
            qry.filter(function (i) {
                return i.msRegionOverflow === 'empty';
            }).forEach(function (i) {
                if (newQry.indexOf(i) >= 0) {
                    return; // aggregate results so that array has 1 region/page
                }
                newQry.push(i.parentElement);
            });
            
            while(newQry.length > 0) {
                var item = newQry.pop();
                flexboxElement.removeChild(item);
            }
        }

    My theory on how this works (please let me know how accurate it is - I'm speculating!) is that async-ish call to setTimeout makes the browser engine sync state before executing the resize fn. I worry that this could result in intermittent, hard to diagnose errors, but I don't know enough about the internals to really say.

    I know it's a long response - I might blog about this issue since I imagine I can't be the only one that will encounter this!

    Upcoming challenge in this vein: figure out a better way to cache the html locally along with images and such. I'd like to use the HTML5 app cache by spawning a .manifest for each article, but with no real URL to point the browser at, I'm not sure how that can work.


    Monday, December 17, 2012 6:41 PM