JqueryMobile issue when working with Knockoutjs - javascript

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.

Related

jQuery document ready with Knockout.js

I just got thrown into the Umbraco ASP.NET CMS for my latest project, I'm not sure if this is how it across the board but for my setup Knockout.js is doing all the templating.
I'm not too keen on knockout.js but so far it's been pretty straight forward except for when I start adding in some jQuery stuff, the problem I'm having is jQuery is firing before knockout has finished populating the page with all the elements.
The only solution that's worked for me thus far is all my jQuery stuff is wrapped in the setTimeout() function, which obviously is no good.
What's the most efficient way to make jQuery and Knockout work together so jQuery doesn't before knockout is done?
I recently had the same issue with the jSignature plugin and my Knockout view. I needed the KO view to have fully rendered before I invoked jSignature, otherwise it didn't size itself correctly.
I fixed it with a template binding and an afterRender callback function to invoke the jQuery work.
Here's the KO docs:
http://knockoutjs.com/documentation/template-binding.html
Here's a quick jsfiddle showing how you can use it:
http://jsfiddle.net/PCbFZ/
The trick is that you can use the afterRender callback of the template binding without actually using a template itself. Instead, you wrap all your existing HTML in a div that will invoke the afterRender callback:
<div data-bind="template: {afterRender: initApp}">
<!-- your existing HTML here -->
</div>
initApp is the function that does the jQuery work.
I think that should generally do what you need, though if your HTML is particularly complex, or you have many views you need to render inside the one page, you might need to do a bit more work. Let me know how you get on - maybe I can try to help a bit more if this doesn't quite fix your issue as easily as it did mine!
Update - following the comment from JACL below - here's an extended version of the fiddle showing this technique also working with ko-if. Each time you show/hide the 'widget' using the checkbox, a different random colour is applied to indicate the afterRender function doing its work.
http://jsfiddle.net/PCbFZ/15/
You might use:
$(window).load(function(){ /* code */ }); instead of $(document).ready();
Perhaps window.load instead of document.ready will do the trick

What part of jQuery UI puts the ui-widget-loading class on and how can it be removed?

I am attempting to integrate jQuery UI tabs with knockout and I'm having a problem with tabs added at the start of my js. They seem to have a class ui-tabs-loading and I'm not sure why.
Here is the fiddle: http://jsfiddle.net/edhedges/mPbAL/
As you can see at the bottom of the js I am removing that class, but if you comment that out it breaks the first three tabs.
To "answer" your question, the ui-tabs-loading class appears to be added when an ajax request is spawned to fill the tab content (source: line #801 - https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.tabs.js). As to why this particular case is being treated as ajax by jQuery UI, I'm still looking into that because I'm curious.
I know that jQuery plugins historically don't work well with javascript data-binding frameworks, but there's definitely always a work around.
I'll update my answer if I figure something out.

Use part jQuery mobile only

I would like to use widgets from jQuery Mobile - buttons, drop down list, etc.
I already have a site that has been developed without the use of jQuery mobile, which has its own menus and links - and when I try to add jQuery mobile framework to it, it causes all sorts of problems (overrides CSS, tries to hijack page transitions, etc).
Is it possible to disable some features of the framework?
This is related to the question: Removing unused jQuery Mobile elements? - but it deals with minimizing the script size. I only want to disable certain functinality, so it doesnt interfere with the rest of my app.
Update: Part of the problem caused by using jQuery Mobile "as is" stems from the fact that it will attempt to load all links via ajax. It can be mitigated by adding rel="external" to links, so jQM won't attempt to load it via ajax.
There is a builder for JQM coming soon. As of 5/4/2012 its still in beta. Hang in there and the feature will be available any time now. I will try to update this answer when its released.
Update here is a link to the JQM builder http://jquerymobile.com/download-builder/
Adding the data-role="none" attribute to any form or button element tells the framework to not apply any enhanced styles or scripting
Building your package with only needed components is the first step that you should do but sometimes it is not enough.
There is also a piece of code which we found recently and used to stop loading jQuery Mobile panes on one page. This is very usefull if you want to use jQuery Mobile components separately without the framework itself. In other words, you still want to have a normal page behaviour (i.e. page reloads by clicking links) and use some jQuery Mobile components.
And here is this code that did a trick for our Symfony 2 project:
(function($) {
$(document).bind('mobileinit',function() {
$.mobile.ajaxEnabled = false;
});
})(jQuery);

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

Categories