MDL on dynamic websites downgrading - javascript

We have a old large ajax based GUI adapted to MDL.
The whole page content is build dynamically (from xml description).
componentHandler.downgradeElements( /all old notes/ ;
remove all old notes form DOM
add new page content to DOM
componentHandler.upgradeAllRegistered();
This works fine, but it leaks memory if the component MaterialLayout is alos created dynamically .
With the "downgrading fix (#2009" the internal references are removed.
The reason for the memory leak is that the component MaterialLayout adds a listener to the MediaQueryList (MDL 1.1).
this.screenSizeMediaQuery_.addListener(this.screenSizeHandler_.bind(this));
In MDL 1.1.2 there are two windows event handler added which lead to the same problem.
window.addEventListener('pageshow', function (e) { ... } );
...
window.addEventListener('resize', windowResizeHandler);
This listeners are not removed by downgradeElements. And therefore the DOM elements are not GC.
Questions:
Is it not indented to delete the element with MaterialLayout?
Is it completely wrong what I doing here?
Is this an MDL issue?
Is there a workaround without changing MDL code?

There was a issue report for MDL Layout downgrade #1340
The final conclusion was:
MDL is geared towards stateless sites with 1.x. Destroying the entire layout is not something that was thought about during the initial build of the layout component.
So right answer is:
It is not indented to delete the element with MaterialLayout for MDL 1.x.
Additional information:
For a hack work around (for testing) I removed adding the MediaQueryList listener from material.js (still 1.0.4 with deconstructComponentInternal form 1.1.2). This seems to work for our solution. I did not found any drawbacks (again in our solution) up to now.

Related

Angular Wrap Broken Between Versions?

Take a look at this Fiddle that's running Angular 1.0.
Hover over the image, and it works fine (you'll see an overlay over the image.)
What I'm doing is wrapping the element with a container div using .wrap(..) function, and later binding the mouseover event to the container div. It works fine.
However, in Angular 1.3 like in this Fiddle with exactly the same code, the container div doesn't recognize my element as its child, which affects the mouseover event from being triggered.
Am I doing something wrong or is it broken in 1.3 ?
The jump from Angular 1.2.x to 1.3.0 involved a few changes to jqLite. One of which was commit #77d3e75 - fix(jqLite): clone wrapNode in jqlite/wrap.
If you run each, the commit before that works, says 1 child exists. That commit says 0. This is intentional, though. This was to prevent unintended side-effects, and to better match JQuery's implementation.
In fact, a test assertion for your exact usage was added in that commit:
expect(root.children().length).toBe(0);
A solution to this particular case might be to change the code slightly, from:
el = angular.element('<div class="overlay-container"></div>');
iElement.wrap(el);
To:
iElement.wrap('<div class="overlay-container"></div>');
el = iElement.parent();
That said, I'm not sure why this behaviour was changed. Given that a angular.element was already created, it doesn't make much sense to me that another is being created.
Angular.js doesn't use semver. It means that your code can be broken by any update of angular. (I don't see the reason why angular team creates that dependency hell)
For each update of angular version you should check changelog and update your code for each breaking change.
You can't even rely on minor version number. There are breaking changes for patch updates in changelog.
If you update your application from 1.0 to 1.3 I advise you to start from changelog, as there can be bugs that isn't visible at first. Because there is huge number of breakings (159 for me using find in browser) and most of them was between v1.0 to v1.4.

Auto-refresh HTML tab in internet explorer

I made a nice website that does a lot of DOM manipulation. Works very nicely in chrome and firefox. Though the client has requested now that it also works in Internet Explorer. The latest version is good enough to start with (that would be 10.0.9200.16721 in my case).
So the adventure starts, i press F12 and see a set of pretty familiar developer tools (coming from chrome and firebug). As i'm tracking the JS code i notice that the HTML tab (with the DOM) doesn't actually update.
According to the manual here http://msdn.microsoft.com/en-us/library/ie/gg589512(v=vs.85).aspx it's "a good idea to refresh the HTML tab to get the current DOM, especially when you use dynamic elements." (d0h ??) problem is .. i can't find a button to enable automatic update of the HTML tab. So i would have to click the refresh button everytime i step into a new line of JS (never mind of real-time DOM view).
But that's not all ... every time i click the refresh button the whole DOM tree view collapses. And i have to click a bunch of pluses to view the node i'm interested in.
Does anyone have a solution for this? Because what would take days will take weeks this way...
Duplicate of How to inspect elements on dynamically created DOM by using IE developers tools
From doing a little digging aroung, it seems like this is an issue other people have reported too. This thread might be of some interest to you.
The most relevant part of it:
The problem is when you modify the dom (with or without jquery) from a callback which is called by a timeout, which is in a callback bound to an event, IE freaks out and doesn't update the dom tree in the development tool. Subsequent modifications to the changed tag in the dev tool won't have any effect.
According to my tests, it's the combination of that sequence of calls that make this happen. If the dom is modified from a settimeout callback but without being inside of an event callback, it works. If instead of settimeout you directly call a function that modifies the dom, it works.
Here's a working example of what you're saying to compound the issue.
Basically, this is an issue with IE. There is no fix available at the moment. The accepted answer on the other thread seems like a very poor workaround.

JqueryMobile issue when working with Knockoutjs

I found jquery mobile is not rendering correctly when the element is generated by knockoutjs (or probably not rendering correctly when element is generated dynamically). See the demo at http://jsfiddle.net/wRRZk/1/
updates:
One solution is to load jquery-mobile js file after KO binding finished as shown in http://jsfiddle.net/wRRZk/3/, however this doesn't solve the problem that jquerymobile render fail when changing KO model dynamically, as shown in http://jsfiddle.net/wRRZk/4/
I think you'll need to tell jQueryMobile to create those elements into the jQM enhanced version using the API. Check here :: http://jquerymobile.com/demos/1.1.1/docs/pages/page-scripting.html and look halfway down for "Enhancing new markup" and the section just below.
As for the create/refresh ... might need to be somewhat judicious in know when and where you're adding new stuff, and whether a create or refresh is needed.
I've done a new version of the jsFiddle here :: http://jsfiddle.net/wRRZk/5/.
I'm also removing from the model afterwards, which does seem to remove the links too, BUT, I think that may also be because the jQM enhancement is keeping the same anchor, thus the reference knockout as is still valid.
Not too sure how well that will work for the other enhancements done by jQM.

Dojo 1.6 dialog widget losing content attachpoints

We've recently upgraded a project from Dojo 1.5 to 1.6 [for the basic IE9 support] and its broken one of our widgets. We have a dialog widget [dijit.Dialog] with another widget within it [any widget here will produce the same behavior], the expected behavior is for the inner widget to be placed within the dialog widget's contentNode, and each of their attachpoints to be available through the main widget.
This isn't happening, instead we only find the dialog's attachpoint. More details below:
We're doing something like this in our main widget's template:
<div dojoType="dijit.Dialog" dojoAttachPoint="dia_widget"
autofocus="true" draggable="false" open="false" preventCache="true">
<div dojoType="dijit.form.ValidationTextBox" doLayout="false" dojoAttachPoint="val_widget">
</div>
</div>
This provides us a parent widget [main_widget] with two attach points: dia_widget and val_widget, which could be accessed within the main widget [after the buildRendering() function] by calling this.dia_widget and this.val_widget respectively.
After upgrading to 1.6.0 things go awry.
My guess is that when a dialog widget gets parsed it removes the domNode of its content into its new containerNode. When the rootnode is having attachpoints assigned, since the domNode is no longer available, it wont get added.
I've been debugging and from what I can see buildRendering() calls _attachTemplateNodes() in dijit/_Templated.js. This loops over the nodes in the widget, looking for their dojoattachpoint attribute and pushing them in the widget's _attachpoints attribute.
The first loop has two nodes [our dia_widget and val_widget] nodes. At this point it then begins parsing each node individually, beginning by calling buildRendering() on dia_widget and finding the attachpoints of all its children.
At some point here the main_widget's dom is modified to include the parsed/rendered dia_widget. The loop then returns to the main node _attachTemplateNodes() call, where it only sees dia_widget as a child node, having lost the val_widget entry. Since the node isn't found, it never gets added as an attachpoint in main_widget, and we can't access it down the line.
I hope this isn't too convoluted to follow, I'm new to Dojo and chasing through the code in firebug wasn't the most fun experience in the world, so I've written things up as they make sense to me.
I'm left wondering why the behavior varies from 1.5 to 1.6, is this simply a feature/parameter I should be passing to the dialog to behave as it did before? Is this a bug in the way I'm creating the nested widget? Is this a [known?] bug in dojo itself?
Thanks,
vic
There are some changes in 1.6.0 that potentially adds a "lang" attribute to dynamically-loaded content. Sometimes this "lang" attribute value is undefined and causes problems.
See if you are having problems with a "lang" attribute -- if so, this is likely to go away with 1.6.1.

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.

Categories