Alternative to iframe - javascript

So I've been looking around and am a bit lost on this topic. People have said that there's alternatives to iframes, but I don't see any that fit the bill for what I'm trying to do. I essentially created a small game that uses videos and plays particular ones based on corret button input from the keyboard.
All of that is in a seperate html file, and I want to display it on a different html file to be in an iframe like state on a different webpage. But I can't seem to figure out the best approach to this.
The iframe is just too slow, the game itself runs fine, but when I put it in an iframe it lags like crazy half the time, or stuff doesn't render because it's going so slowly.
Any ideas of where to start?

There is one alternative to <iframe> and that's the <object> tag. It can display content from different sources as well. The pro is it being conform to the xhtml-standards and encouraged to use but there's not such a broad / usable support in older browsers (you have to mess with it to get it right in IE). It's used as followed:
<object data="page.html" width="400" height="300" type="text/html">
Alternative Content
</object>
That being the direct answer to you question I don't think it will give you any speed advantage. Already for the reason that the <iframe>-element is much more used and so more tested and cared for than <object>.
I for myself never saw an <iframe> being the cause for a slowdown, but that still might be possible. If that is an option, you should definitely try what ocanal said before in the comments: Let your script work on an wrapper container-div instead of the body-element and so embed it directly on the mainpage.
For the browser it shouldn't be much more than some overhead from handling a second document, so you could guess that it's just that little more to make your pc run slow. So it might be a good idea to optimize the code in general:
Look if you can find the bottleneck causing the slowdown. Possible causes could be
altering the DOM a lot - which is always slow
acting a lot on things not even visible on screen
getting attributes from objects. For every additional period you use it means more work for your cpu:
// instead of using this over and over again
house.roof.window.handle.open();
house.roof.window.handle.close();
// save it to a var and use that instead
var handle = house.roof.window.handle;
handle.open();
handle.close();
Updating the game in short equal intervals by window.setTimeout() may also be too fast and waste cpu power unnecessarily (or too slow and won't look fine then, but never really right) - so you can use the new window.requestAnimationFrame. The vendor-prefixed variants are implemented in the current versions of all important browsers and it's easy to provide a fallback to the old method.
As a last thought: Maybe it even helps in some meta-magical way to include the script file itself on the mainpage and not in the embeded document

Related

Display DOM node in multiple places w/o cloning/copying

Disclaimer:
I've blathered on kind-of excessively here in an attempt to provide enough context to pre-empt all questions you folks might have of me. Don't be scared by the length of this question: much of what I've written is very skim-able (especially the potential solutions I've come up with).
Goal:
The effect I'm hoping to achieve is displaying the same element (and all descendants) in multiple places on the same page. My current solution (see below for more detail) involves having to clone/copy and then append in all the other places I want it to appear in the DOM. What I'm asking for here is a better (more efficient) solution. I have a few ideas for potentially more efficient solutions (see below). Please judge/criticize/dismiss/augment those, or add your own more-brilliant-er solution!
"Why?" you ask?
Well, the element (and it's descendants) that I'm wanting to display more than once potentially has lots of attributes and contents - so cloning it, and appending it someplace else (sometimes more than one other place) can get to be quite a resource-hogging DOM manipulation operation.
Some context:
I can't describe the situation exactly (damn NDA's!) but essentially what I've got is a WYSIWYG html document editor. When a person is editing the DOM, I'm actually saving the "original" node and the "changed" node by wrapping them both in a div, hiding the "original" and letting the user modify the new ("changed") node to their heart's content. This way, the user can easily review the changes they've made before saving them.
Before, I'd just been letting the user navigate through the "diff divs" and temporarily unhiding the "original" node, to show the changes "inline". What I'm trying to do now is let the user see the whole "original" document, and their edited ("changed") document in a side-by-side view. And, potentially, I'd like to save the changes through multiple edit sessions, and show 'N' number of versions side-by-side simultaneously.
Current Solution:
My current solution to achieve this effect is the following:
Wrap the whole dang dom (well, except the "toolbars" and stuff that they aren't actually editing) in a div (that I'll call "pane1"), and create a new div (that I'll call "pane2"). Then deep-clone pane1's contents into pane2, and in pane1 only show the "original" nodes, and in pane2 only show the "changed" nodes (in the diff regions - everything outside of that would be displayed/hidden by a toggle switch in a toolbar). Then, repeat this for panes 3-through-N.
Problem with Current Solution:
If the document the user is editing gets super long, or contains pictures/videos (with different src attributes) or contains lots of fancy styling things (columns, tables and the like) then the DOM can potentially get very large/complex, and trying to clone and manipulate it can make the browser slow to a crawl or die (depending on the DOM's size/complexity and how many clones need to be made as well as the efficiency of the browser/the machine it's running on). If size is the issue I can certainly do things like actually remove the hidden nodes from the DOM, but that's yet more DOM manipulation operations hogging resources.
Potential Solutions:
1. Find a way to make the DOM more simple/lightweight
so that the cloning/manipulating that I'm currently doing is more efficient. (of course, I'm trying to do this as much as I can anyway, but perhaps it's all I can really do).
2. Create static representations of the versions with Canvas elements or something.
I've heard there's a trick where you can wrap HTML in an SVG element, then use that as an image source and draw it onto a canvas. I'd think that those static canvasses (canvi?) would have a much smaller memory footprint than cloned DOM nodes. And manipulating the DOM (hiding/showing the appropriate nodes), then drawing an image (rinse & repeat) should be quicker & more efficient than cloning a node and manipulating the clones. (maybe I'm wrong about that? Please tell me!)
I've tried this in a limited capacity, but wrapping my HTML in SVG messes with the way it's rendered in a couple of weird cases - perhaps I just need to message the elements a bit to get them to display properly.
3. Find some magic element
that just refers to another node and looks/acts like it without being a real clone (and therefore being somehow magically much more lightweight). Even if this meant that I couldn't manipulate this magic element separately from the node it's "referencing" (or its fake children) - in that case I could still use this for the unchanged parts, and hopefully shave off some memory usage/DOM Manipulation operations.
4. Perform some of the steps on the server side.
I do have the ability to execute server side code, so maybe it's a lot more efficient (some of my users might be on mobile or old devices) to get all ajax-y and send the relevant part of the DOM (could be the "root" of the document the user is editing, or just particularly heavy "diff divs") to the server to be cloned/manipulated, then request the server-manipulated "clones" and stick 'em in their appropriate panes/places.
5. Fake it to make it "feel" more efficient
Rather than doing these operations all in one go and making the browser wait till the operations are done to re-draw the UI, I could do the operations in "chunks" and let the browser re-render and catch a breather before doing the next chunk. This probably actually would result in more time spent, but to the casual user it might "feel" quicker (haha, silly fools...). In the end, I suppose, it is user experience that is what's most important.
Footnote:
Again, I'm NDA'd which prevents me from posting the actual code here, as much as I'd like to. I think I've thoroughly explained the situation (perhaps too thoroughly - if such a thing exists) so it shouldn't be necessary for you to see code to give me a general answer. If need be, I suppose I could write up some example code that differs enough from my company's IP and post it here. Let me know if you'd like me to do that, and I'll be happy to oblige (well, not really, but I'll do it anyway).
Take a look at CSS background elements. They allow you to display DOM nodes elsewhere/repeatedly. They are of course they are read-only, but should update live.
You may still have to come up with a lot of magic around them, but it is a similar solution to:
Create static representations of the versions with Canvas elements or something.
CSS background elements are also very experimental, so you may not get very far with them if you have to support a range of browsers.
To be honest, after reading the question I almost left thinking it belongs in the "too-hard-basket", but after some thought perhaps I have some ideas.
This is a really difficult problem and the more I think about it the more I realise that there is no real way to escape needing to clone. You're right in that you can create an SVG or Canvas but it won't look the same, though with a fair amount of effort I'm sure you can get quite close but not sure how efficient it will be. You could render the HTML server-side, take a snapshot and send the image to the client but that's definitely not scalable.
The only suggestions I can think of are as follows, sorry if they are long-winded:
How are you doing this clone? If you're going through each element and as you go through each you are creating a clone and copying the attributes one by one then this is heaavvvyy. I would strongly suggest using jQuery clone as my guess is that it's more efficient than your solution. Also, when you are making structural changes it might be useful to take advantage of jQuery's detach/remove (native JS: removeChild()) methods as this will take the element out of the DOM so you can alter it before reinserting.
I'm not sure how you'v got your WYSIWYG, but avoid using inputs as they are heavy. If you must then I'm assuming they don't look like inputs so just swap them out with another element and style (CSS) to match. Make sure you do these swaps before you reinsert the clone in to the DOM.
Don't literally put video at the time of showing the user comparisions. The last thing we want to do is inject 3rd party objects in to the page. Use an image, you only have to do it while comparing. Once again, do the swap before inserting the clone in to the DOM.
I'm assuming the cloned elements won't have javascript attached to them (if there is then remove it, less moving parts is more efficiency). However, the "changed" elements will probably have some JS events attached so perhaps remove them for the period of comparision.
Use Chrome/FF repaint/reflow tools to see how your page is working when you restructure the DOM. This is important because you could be doing some "awesome" animations that are costing you intense resources. See http://paulirish.com/2011/viewing-chromes-paint-cycle/
Use CSS over inline styling where possible as modern browsers are optimised to handle CSS documents
Can you make it so your users use a fast modern browser like Chrome? If it's internal then might be worth it.
Can you do these things in Silverlight or Adobe Air? These objects get special resource privileges, so this will most likely solve your problem (according to what I'm imagining the depth of the problem is)
This one is a bit left-field but could you open in another window? Modern browsers like Chrome will run the other window in its own process which may help.
No doubt you've probably looked in to these things more than I but good luck with it. Would be curious how you solved it.
You may also try: http://html2canvas.hertzen.com/
If it works for you canvas has way better support.
In order to get your "side-by-side" original doc and modified doc.. rather than cloning all pane1 into pane2.. could you just load the original document in an iframe next to the content you are editing? A lot less bulky?
You could tweak how the document is displayed when it's in an iframe (e.g. hide stuff outside editable content).
And maybe when you 'save' a change, write changes to the file (or a temp) and open it up in a new iframe? That might accomplish your "multiple edit sessions"... having multiple iframes displaying the document in various states.
Just thinking out loud...
(Sorry in advance if I'm missing/misunderstanding any of your goals/requirements)
I don't know if it's already the case for you but you should consider using jQuery library as it allows to perform different kinds of DOM elements manipulation such as create content and insert it into several elements at once or select an element on the page and insert it into another.
Have a look on .appendTo(), .html(), .text(), .addClass(), .css(), .attr(), .clone()
http://api.jquery.com/category/manipulation/
Sorry if I'm just pointing out something you already know or even work with but your NDA is in the way of a more accurate answer.

Javascript widget implementation

I have a question about Javascript widgets. The widget I am working on simply embeds content on a page instead of using iframes. So far it looks good. But there are cases where some users layouts are messing up the widget. For example, the widget might require a width of 300px to appear. But the parent div is set to 250px and hence the right part of the widget is cut off.
I was wondering what sort of precautions should be taken to prevent this? I was talking to the product manager who mentioned he wanted me to check the parent div elements and get the size and then show an alternate message if their size is not accurate. But again, since this is Javascript and the widget is supported in many diff browsers(including IE6), I am wondering how fail-safe this method would be? What if I need to iterate the DOM all the way up before getting a valid size? I am also worried about performance here. This extra checks would slow down the delivery of my widget content to "good users" since I am adding a layer of complexity to all users. I don't want to penalize good users just because of the few errant ones.
I am not using any sort of JS library here, so any solution should not suggest the use of one. Also, the reason for not using a library was simply not to add extra weight to the page load to deliver a widget. I understand that "jquery" for example is small, but in my case, even 24k compressed seems like an overkill for a widget delivery that contains no core code for the widget.
Has anyone dealt with such issues before? What are your solutions to these?
There are reliable ways of determining the size of an element using JavaScript. You're quite right that you may need to iterate up the tree in some cases, but the answer you get will ultimately be quite valid.
Although you don't want to directly include any library code in this project, you may consider looking at how the major libraries implement their "what's the width of this element" functions to drive your own implementation.
Beware of quirks mode too.
I'd check to see of the page has Jquery, if not load it into the page using no-conflict mode. Then use jQuery to examine the page.
See: How to embed Javascript widget that depends on jQuery into an unknown environment

Question - Setting dynamic HTML using Javascript to iFrames on Windows Mobile 6.1 - IE Mobile6

(excuse me if this is not the right forum to post - i couldn't find anything related to non-native programming and related to this topic)
I Am trying to set a dynamic HTML into an iFrame on the webpage. I have tried a couple of things but none of them seem to work. I m able to read the innerHTML but can't seem to update it.
// Able to read using
document.getElementById('iFrameIdentifier').innerHTML;
// On Desktop IE, this code works
document.getElementById('iFrameId').contentWindow.document.open();
document.getElementById('iFrameId').contentWindow.document.write(dynamicHTML);
document.getElementById('iFrameId').contentWindow.document.close();
Ideally the same function should work as how it works for div's but it says 'Object doesn't support this method or property".
I have also tried document.getElementById('iFrameId').document.body.innerHTML.
This apparently replaces the whole HTML of the page and not just the innerHTML.
I have tried out a couple of things and they didn't work
document.getElementById('iFrameId').body.innerHTML
document.frames[0].document.body.innerHTML
My purpose is to have a container element which can contain dynamic HTML that's set to it.
I've been using it well till now when I observed that the setting innerHTML on a div is taking increasing amount of time because of the onClicks or other JS methods that are attached to the anchors and images in the dynamic HTML. Appears the JS methods or the HTML is some how not getting cleaned up properly (memory leak?)
Also being discussed - http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/Q_26185526.html#a32779090
I have tried a couple of things but none of them seem to work.
Welcome to IEMobile! Nothing you know about DOM scripting applies here.
Unfortunately, cross-iframe scripting does not appear to be possible in IEMobile6-7.
frameelement.contentDocument (the standard DOM method) isn't available
frameelement.contentWindow.document (the IE6-7 workaround version) isn't available
the old-school Netscape window.frames array only works for frames, not iframes
having the child document pass up its document object to the window.parent only works for frames, not iframes. In an iframe, window.parent===window.
So the only ways forward I can see are:
use frames instead of iframes. Nasty. Or,
use document.cookie to communicate between parent and child: the child document is just a script, that checks for a particular cookie in document.cookie on a poller, and when it's found that's a message from the parent, and it can write some HTML or whatever. Slow and nasty. Or,
using the server-side to inject content into the frames, passing it in as an argument to a script. Slow, nasty, and potentially insecure. Or,
avoid frames completely (best, if you can). Or,
drop support from IEMobile6-7 (best for preserving your sanity, if you can get away with it!)
Appears the JS methods or the HTML is some how not getting cleaned up properly (memory leak?)
Yes, probably. IEMobile6-7(*) is close to unusable at dynamic HTML. It gives you a lovely flavour of what scripting used to be like for us poor gits back in the Netscape 4 days.
Try to avoid creating and destroying lots of nodes and event handlers. Keep the page as static as possible, re-using element nodes where possible and setting text node data properties in preference to tearing everything down and making anew with createElement or innerHTML. Use an event stub (onclick="return this._onclick()") in the HTML together with writing to _onclick if you need to set event handlers from JavaScript, in preference to recreating the HTML with a new event handler (or just trying to set the property, which of course doesn't work in IEMobile). Avoid long-running single pages when you can.
It'll still crash, but hopefully it'll take longer.
*: that is, the versions of IE present on WinMo before version 6.1.4, where it became the infinitely better IEMobile8, marketed as “Internet Explorer Mobile 6” (thank you Microsoft).
Okay, I kinda resolved the issues that i was facing earlier and the bigger issue which was setting HTML to an iFrame on IEMobile. But i still have one more PIA which is related to double scollbars - which i am currently looking into. There seems to be more poor souls facing similar problem - if i fix that too. I will post an update here.
How did i finally write to iFrame on IEMobile?
Have 2 divs one to wrap the iFrame and the other to write inside an iFrame.
document.getElementById('OuterDiv').innerHTML = '';
document.getElementById('OuterDiv').innerHTML = '<iframe id="iFrameId" src="somefile.html"></iframe>';
This creates an iFrame each time and in the somefile.html on load there is a InnerDiv.innerHTML which doesn't seem to leak the memory.
In the somefile.html there will be an onLoad method which will fetch the HTML (explained below on how i managed to get it) and do a
document.getElementById('InnerDiv').innerHTML = dynamicHTML;
How did I manage to pass the HTML between parent and child iFrame
As well explained by #bobince earlier, one has to rely on 3rd party service like a cookie or a server to pass around the data between parent and the child iFrame.
I infact used an ActiveXControl to set and get data from the parent and child iFrame's javascript respectively. I won't recommend doing this if you have to introduce an ActiveX Control just for this. I accidentally already have one which I use to get the Dynamic HTML in the first place.
If you need any help you can DM me - Twitter #Swaroop
Thanks #bobince for your help. I am marking this one as an answer because it says what i did to fix the issue.

Tips on optimizing javascript

The things I'm trying to get my website to do are getting fairly complex, some of the things that need to be done take long enough that it gives visible delays.
Mainly, adding content to the document slows things down as well as jquery animations that I'm using.
I create elements using document.createElement("div") rather than just doing document.write("<div id='someId'></div>"), and the animations are the custom animation using .animation();
I'm wondering how I can continue to add content as I am but prevent the browser from freezing every time I want to add something.
Any suggestions for speeding things up so there is less of a delay?
Tips on what to avoid in javascript programming that gives increased delay would be really helpful.
This sounds more like you want to improve the DOM interaction performance rather than javascript, so in that vein:
Yes, document.write is bad, it blocks additional loading (any JS executing before your pages has finished loading basically requires all other processing to stop -- modern browsers like Safari (and by proxy Chrome) and Firefox do a degree of content preloading in order to prevents loads from blocking but subsequent style resolution, etc is largely blocked.
document.createElement is in general the best solution, although their are certain cases where just manipulating innerHTML on an element may be faster -- but that is not yet cross browser compatible (i think innerHTML doesn't exist till Firefox 3.5) and the perform characteristics are tricky.
Reduce the amount of content you load initially -- eg. if you have lots of content (or content that requires large scripts) attempt to delay loading until after the initial page load has completed.
Oh, for animations you should look at CSS animations and they perform much better than any JS implementations, but they're only present in Safari (and by proxy Chrome) and Firefox 3.5 -- definitely not in IE :-(
In terms of JavaScript performance, avoid with and getters/setters like the plague and you should be fine in most modern JS implementations.
I know this is a couple of years late but better late than never considering this question popped up at the top of google's list for javascript animation optimization.
If you need to add a large amount of elements to the DOM and don't want to use innerHTML to do so you can speed that up I believe by adding the elements to a documentFragment first and then injecting the documentFragment all at once into the DOM. I remember reading that DOM injection is the slowest part of using the standard API to create and add elements. documentFragment allows you to inject all of its contents into the DOM in one go eliminating a large amount of overhead caused by calling appendChild or other insertion methods multiple times. appendChild and other insertion methods supposedly don't suffer the same costs when inserting into a documentFragment opposed to inserting into the DOM. I wish I could find the article I read this in as it had some really nice benchmark tests and explanations. I'm sure you can find more information by doing some searches.
As always though which method to use should be determined by testing on a case by case basis. Eventually you'd probably learn which one to use based on structure of the elements, amount, and use.
PS. There may be an issue with styles and documentFragment but I can't remember what was said about them, either way it'd be something worth checking out.
JQuery is great for manipulating the DOM. I'd take a look at their code in order to get some ideas. Or, seeing how I'm way lazy, I'd just use their stuff.
In one of the podcasts Jeff Atwood mentioned you'd have to be crazy to write your own javascript... after using JQuery, I'd have to agree with him.
Although I am a huge fan of jQuery, and it makes development much easier, note that a jQuery statement (or in any JavaScript library) will never be as fast as its semantic equivalent in plain JavaScript because of the extra overhead.
That being said, these are my goto references whenever I want to speed up my JavaScript.
http://home.earthlink.net/~kendrasg/info/js_opt/
http://www.miislita.com/searchito/javascript-optimization.html
There is document fragment function which can make life much more easier. Here is the example use.
function appendDivs(element){
var fragment = document.createDocumentFragment();
for(var i=0;i<10;i++){
var div = document.createElement("div");
fragment.appendChild(div);
}
element.appendChild(fragment);
}
For a complete reference, you can see this post on my blog.
What surprises most people is that using innerHTML is, actually, the fastest way there is to manipulate the DOM.
You can see one benchmark here for example.
// Some functions for easier coding in DOM
function createEl(el){
return document.createElement(el);
}
function addElBody(el){
return document.body.appendChild(el);
}
function addElChild(el, child){ //el- parent
return el.appendChild(child);
}
// Example :
var container=createEl('div');
container.setAttribute('id', 'container');
addElBody(container);
var item=createEl('ul');
item.setAttribute('id', 'list');
addElBody(item);
addElChild(container, item);

JavaScript in Flash

I have a java script code that works fine when run through a browser, is there a way i can use that code in flash without much editing, i want the to get the input from user through flash and have the code do the computing and display the result in flash, any clues?
Well, ActionScript 1 is essentially javascript, and 2 is just some syntactical sugar on top of it. If you're creating a Flash 8 or earlier movie then you should be able to use the javascript code without much tweaking (preferably switching to use classes instead of prototype). Moving it to ActionScript 3 (for Flash 9 or later) would be a little more work as it's more strict about types and such, but still probably not too difficult.
As others have mentioned, the UI-related stuff is quite different in Flash than Javascript, as there is no DOM. I assumed the methods you were talking about are for doing calculations and not really related to the UI at all. If your javascript methods are actually doing UI stuff then moving them to Flash would be much more involved.
Another possibility, if you want to keep your code in javascript (perhaps so you can reuse it with other javascript stuff) then you could create a Flash movie that takes the input, passes it to javascript, and then have javascript report the results back to Flash. Take a look at the Flash ExternalInterface documentation (see also here).
Check out ExternalInterface, which lets you call javascript functions from actionscript, and vice versa. We use it without a problem at my work.
The syntax is much the same, but there is no DOM. You have object references instead. It's a bit more like you do in something like VB. Variable scoping works differently too.
Instead of showing or hiding DIVS, or going to pages, you're moving to a different place in the timeline where different objects are shown or hidden. It take a bit of effort to wrap your head around it if you're a traditional programmer, but it still feels very much like JavaScript on the inside.
You can probably take a lot of your logic and recycle it, but the UI hooks will need to change a bit.

Categories