Issue with LightSwitch restyling custom control with delayed rendering - javascript

I was playing around with a LightSwitch custom control using the simple code:
myapp.Facility_Details.ScreenContent_render = function (element, contentItem) {
$(element).append("<ul><li><label><input type='checkbox'/><span>Test</span></li></ul>");
}
And I notice LightSwitch makes a valiant effort to rewrite my HTML after I render it, adding it's own control styling classes to the HTML and doing a bit of re-organizing. I figured I could live with this & just get used to what it did, but then I hit a worse issue when I added some AJAX to the mix. When I do my actual rendering in the done method of a Promise the post-processing doesn't happen.
EG:
myapp.Facility_Details.ScreenContent_render = function (element, contentItem) {
contentItem.data.getCommodityGroups().done(function (data) {
$(element).append("<ul><li><label><input type='checkbox'/><span>Test</span></li></ul>");
});
}
Renders totally differently (Doesn't edit the HTML). I could live with this too, but then if I browse away from this page & back to it then it swaps over to the first display... I tried returning the Promise from render thinking maybe that'd let it wait for me to be done, but no dice.
Does anyone know how can I either:
a) Prevent this reprocessing so I get the HTML I write every time.
b) Trigger this reprocessing explicitly so I can make sure it happens after I render inside a Promise.

It is jQuery doing the work so wrap into jQuery object before appending it perhaps?
Look at the samples down the page here MSDN article.

This restyling is coming from jQuery Mobile. Turns out the solution is to trigger a create event after editing the HTML (EG: $(element).trigger('create');) to tell jQuery Mobile there's new HTML to style.
Another approach is to add data-role='none' so jQuery Mobile leaves your HTML alone. I'll probably mostly use the latter, but it's good to know both exist.
Actually found the answer over at another StackOverflow question - the trick was knowing it was jQuery Mobile that mattered which is a lot easier to find info for than LightSwitch itself.

Related

Update HTML5 page text before render

I've written a small HTML5 page that I need to be able to support multiple languages. I've implemented the language control by making the page load a JSON file into memory (in the HEAD) and then running a jQuery command to change the text of any element as required.
Everything works fine except that as the change is being called post render (if the document ready function) there is a slight flash as the language gets changed.
Is there an event that is called before the page is rendered but after the DOM is available? If not, are there any suggestions to change implementation.
Cheers..
UPDATE
I've found a few answers to this on other sites. The general consensus appears to be that this isn't possible as most browsers render as they parse. The workaround that is suggested is to hide (display:'none') the body in script and then show it (display:'') after the updates in the document ready function. It sort of works for me although isn't 100% perfect.
Sounds like you are having an issue with FOUC (Flash Of Unstyled Content)
There are a few ways to get around it. You could add this to your body:
<body class="fouc">
And then have this CSS:
.fouc{display:none;}
And finally this script:
$(function(){
$('.fouc').show();
});
This works by initially hiding the page, and then once you are ready, turning it on with javascript. You may need to ensure your manipulation occurs ahead of the $('.fouc').show(); call.
One effective solution, though not the one you are probably looking for, is to use OUTPUT BUFFERING ... What is output buffering?

How to find a form element inside multiple frames using jquery

I am working on a website that currently uses the old style frames. I want to go through a replace some javascript DOM calls because I am running into cross-browser issues. This is what I would like to replace.
window.parent.frames['topdisplay'].document.FORMSV2DISPLAY.action = 'what ever action';
In the above code my problem is that the 'document.FORMSV2DISPLAY' part doesn't work in IE I have to replace that part with document.form(0) and then of course neither of those work correctly in Chrome or Safari.
I would like to use jquery to find the form named FORMSV2DISPLAY and then perform my usual actions and submits.
I have tried things like
$(this).find('FORMSV2DISPLAY').action
$(parent).find('FORMSV2DISPLAY').action
$('topdisplay').find('FORMSV2DISPLAY').action
none of these return the same thing as the javascript DOM calls I am trying to replace. I am very new to jquery and help or understanding is greatly appreciated.
to set the action:
$('#topdisplay').find('#FORMSV2DISPLAY').attr('action', 'whateveraction');

Is $.empty() enough for big ajaxy apps?

Been working on an App and since it's getting a bit too big I've thinking of ways to improve memory management since the app runs mostly on Javascipt. So every time a navigation item is clicked I would call the jquery empty then show the html via ajax. ex:
//$.ajaxSetup(); called before this
//$this is the attached element
$.ajax({success:function(data){
$this.empty().html(data.output).fadeIn(400);
//more javascript stuff like loading tinymce or jquery ui
}});
is this enough to prevent memory leaks? I'm not entirely sure what empty does but I'm assuming it removes all DOM elements within that div along with any other objects and events? btw. You can find the app here http://webproposalgenerator.com/ and http://webproposalgenerator.com/demo.
any tips on improving the performance/security or any feedback at all would be greatly appreciated.
$.fn.empty should be enough, it deletes all data and events associated to the elements and then deletes the elements. It also calls .widget("destroy") on all jquery-ui widget.js based widgets that are defined on those elements.
It is also important to note that jquery's $.fn.html method calls $.fn.empty() on the given element before appending html, therefore, if you are using $.fn.html, you don't have to call $.fn.empty
actually my guess was that .html implies .empty anyway, also I'm not sure that's true. for the perforamnce part: according to jqfundamentals excelent book it is a recommanded best practice to add content while the element is in .detach() from the DOM. tried to lock at the code for advice but didn't find it. nice site btw

jQuery Mobile - Dynamically creating form elements

I'm creating a web-database driven offline web-app targeted at iOS devices. I'm trying to use jQuery Mobile, but I have a problem in creating the various forms.
The form options are taken from a database query, so they are inserted into the page after it has loaded, so the "jQuery-Mobilification" doesn't happen. Taking a quick look through the source, there doesn't seem to be any obvious way to call into this at this stage (of course it's an alpha release, and I think this would be a reasonably common request, so I'm hopeful it will come). Is there some kind of workaround I can put in to do this? I'm particularly interested in radio buttons, check boxes and select lists.
UPDATE
Beta2 has a create event. I will update my faq when the beta2 gets released. See http://jquerymobile.com/blog/2011/07/22/jquery-mobile-team-update-week-of-july-18th/
Updated faq: http://jquerymobiledictionary.pl/faq.html
As CaffeineFueled proposed - .page() is the way to make JQM work with any part of HTML
.page() can be called only once for an element. Call it on a wrapping element you add to the page. It should handle everything.
The current selected answer is slightly out of date. Use 'refresh', not 'page', for styling dynamically added content (lists or forms).
If you add items to a listview, you'll
need to call the refresh() method on
it to update the styles and create any
nested lists that are added. For
example, $('ul').listview('refresh');
via the jQuery Mobile docs, 1.0.4a
This is messing around in undocumented internals, but the following is working for me:
$("#some-div").load("/html/fragment/",
function() {
$(this).find("input").customTextInput();
});
There are equivalent methods for buttons, checkboxes etc.
Have a look at the _enchanceControls [sic] method in http://code.jquery.com/mobile/1.0a1/jquery.mobile-1.0a1.js.
Update for 1.0Alpha2: As can be expected when playing around with the internals of a library, this no longer works in the latest version. Changing customTextInput() to textinput() fixes it a bit, but the theme isn't fully applied for some reason. We were warned...
After your AJAX call finishes and you insert the form elements try calling:
$("#the-page-id").page();
I believe the jquery-mobile team will be adding a .refresh() method on the various UI elements to solve this issue in the future.
Yeah the issue is as you described. The 'mobilization' is fired when the document is ready. But since your offline DB queries are asynchronous it ends after the document.ready is fired. So the DOM is updated later in the process and doesn't have the extra CSS added to all the divs and list items.
I think you would have to change the source of the mobile js to not run on document ready but run when you tell it to run. Then you would have to call that function in your database callback.
Looks like that is the only option at the moment.
Traditionally I used jqtouch and now sencha. I haven't played much with jQuery mobile.
ALTERNATIVELY - you could write out your HTML after querying it out of the database with the necessary CSS styles on it. If you use Firebug plugin for Firefox you can see what styles / classes are getting applied when the mobilization runs. You could just write out your HTML using those conventions. Not ideal, but would work.
naugtur is right, you have to call .page() on any element that you add to the dom, then it works out nicely:
var el = $('<input type="text"/>')
el.page();
$('#something').append(el);
This worked for me (jquerymobile1.7.0):
$('#formular').append('<div data-role="fieldcontain" class="ui-hide-label">' +
'<label for="name" class="ui-hidden-accessible">Name:</label>' +
'<input type="text" name="name" size="25" id="name" placeholder="Name"/>' +
'</div>');
$('#name').textinput();
There are currently so called plugin functions for all kind of form elements (e.g. slider, textinput etc.) to create them.
Here's a link to the docs for this feature that Tom talked about. Not sure exactly when they were added, but I'm using it and it works for me!
http://jquerymobile.com/test/docs/forms/plugin-eventsmethods.html

Is there a way to tell when a div has been added to an element?

Say I have a third party Twitter widget on a page which keeps updating whenever there is a new tweet. Is there some way to figure out when a new div has been added to this widget? Is there an event or something I can hook onto (on maybe the widgets parent div)?
If there isn't, how do I do this? Maybe hook onto the ajax calls the widget is making? How do I do that? It seems possible as firebug seems to be doing this but I can't tell how.
If you're using any kind of modern browser, you can use the DOM Mutation Events to listen for node changes. From the description of your question you're probably looking for DOMNodeInserted. If you must you can use a horrible setTimeout() hack, but in general it's better to wait for events than spin around waiting for something to happen.
Heck here is some example code because I am bored:
var widget = document.getElementById('mywidget');
widget.addEventListener('DOMNodeInserted', function (e) {
if (e.target.nodeName !== 'DIV') return;
// do some other code here
}, false);
Don't ktow if this is a good solution but you can periodicaly compare content of this div.
Giving the simplest answer first: I would suggest checking if the div exists after a second (time depending on many factors - I'm sure you understand the time specifics for your site). When adding a new element (such as your twitter widget) it's important to understand that each element (in your case, "a widget") comes with certain specifications which can have major differences compared to similar (on the surface similar) "widgets"
For a short answer: "It depends on the third party widget"
For the medium answer: "If you can look at how the widget is created, you can probably find a way to 'talk to it'"
For the longer answer: "It's actually not very difficult to create something to communicate with Twitter, so if that's what you want to learn I would suggest being more specific."
Hope SOMETHING OF THIS HELPS...
edit: Knowing nothing about the widget, I would probably set an interval to make requests from client to server, either by using javascript:setInterval() or setTimeout()... If I had time/resources, I would prefer a solution where you understand both Twitter and the widget though (saves time in the future if you want to think about what you've done)...

Categories