jQuery Mobile Losing Style After Updating DOM - jquery-mobile

A question similar to this has been posted several time, but I cannot find a solution that works. Hopefully, someone can help!
I am using jQuery Mobile 1.1 and jQuery 1.7.2, so I'm on the most recent stable releases. I want to create a dynamic page header. Using this HTML code, it works fine:
<div data-role="page" id="levela">
<div data-role="header" id="hdr_levela">
<h1>Title</h1>
</div>
</div>
So I then go to dynamically create the title. I change the HTML to this:
<div data-role="page" id="levela">
<div data-role="header" id="hdr_levela">
</div>
</div>
And added the following jQuery code:
// Set the header
var dirHeader = $('#hdr_levela');
dirHeader.append('<h1>' + title+ '</h1>');
The title appears, but is not styled. I have found several posts about this. In the jQuery Mobile Documentation, it says:
"However, if you generate new markup client-side or load in content via Ajax and inject it into a page, you can trigger the create event to handle the auto-initialization for all the plugins contained within the new markup. This can be triggered on any element (even the page div itself), saving you the task of manually initializing each plugin (listview button, select, etc.).
For example, if a block of HTML markup (say a login form) was loaded in through Ajax, trigger the create event to automatically transform all the widgets it contains (inputs and buttons in this case) into the enhanced versions. The code for this scenario would be:
$( ...new markup that contains widgets... ).appendTo( ".ui-page" ).trigger( "create" );
So I tried several things. After the above code, I added the following:
dirHeader.trigger("create");
This had no effect. So I tried to put it on the actual append itself:
dirHeader.append('<h1>' + folderName + '</h1>').trigger("create");
This had no effect. I then tried the process on the parent element (in this case, the id of the parent div is "levela"). So I tried this:
$('#levela').trigger("create");
This also had no effect. At this point, I am completely lost. Every solution involves doing one of the things I have tried and is just not working. I must be missing something incredibly basic but I just can't seem to find it.
Thanks in advance for your help!

You can update the content by calling .page:
See this working Fiddle Example!
// Set the header
var title = 'super hyper BuBu',
$dirHeader = $('#hdr_levela');
$dirHeader.append('<h1>' + title+ '</h1>').page();

I just solved a similar problem -- it appears that jQM headers and footers do not have the "create" method, so as far as I can tell, the css classes and roles need to be added manually.
For reference, I posted an example fix on this (old) question: JQuery Mobile trigger('create') command not working

Related

jQuery mobile force full reload when link clicked

I have a "normal" link in my jqm page like this:
<a href="http://www.mysite.com/mobile/page.php?attribute=value">
And if I click it it won't properly refresh taking into account the attribute value and loading everything that's needed for it dynamically based on the attribute value. I understand that this is due to the fact that jqm tries to do an ajax call like mentioned here:
When you use pageChange an Ajax request will be made to that url and it will be
loaded only the content inside the div with data-role="page". So everything you
have out of this element will be ignored (JS and CSS).
So, I found out in the docs that I should use $.mobile.ajaxEnabled=false; or rel=external on links or target=_blank on the link.
Strange thing though for me is that only when I set the target=_blank property to my links will this truly happen. So, am wondering if someone had this kind of a problem and how did you solve it? The thing is, I would like to refrain myself form using target=_blank as it opens a new tab in my browser (as expected, but this is not nice from users' POV).
jqm version I use is 1.2
This question now at the top of google search results, so figured I'd answer:
Use the data-ajax attribute and set it to false to force reload upon clicking a link:
data-ajax="false"
use it like:
<a href="/" data-ajax="false">
<img id="mainLogo" src="logo.svg" width="215" />
</a>
And then your link will force reload the page!
Linking without Ajax
Links that point to other domains or that have rel="external",
data-ajax="false" or target attributes will not be loaded with Ajax.
Instead, these links will cause a full page refresh with no animated
transition. Both attributes (rel="external" and data-ajax="false")
have the same effect, but a different semantic meaning: rel="external"
should be used when linking to another site or domain, while
data-ajax="false" is useful for simply opting a page within your
domain from being loaded via Ajax. Because of security restrictions,
the framework always opts links to external domains out of the Ajax
behavior.
Parts taken from https://stackoverflow.com/a/22951472
Make function for the onclick event of the link.See the below code example.Hope this helps!
<script type="text/javascript">
function loadPage(url){
document.location.href = url;
}
<script/>
<a href="#" onClick="loadPage('http://www.mysite.com/mobile/page.php?attribute=value');">

Jquery Mobile Javascript not working on ajax load

Have the following markup in my html page to toggle a search bar based on if a search icon is clicked:
<a id="searchIcon" href="/"></a>
<div id="searchWrapOuter" style="display:none;">
<div id="searchWrapInner">
<div id="formContainer">
<form id="searchForm" action="#">
<div>
<input type="search" name="search-mini" id="search-mini" value="" data-mini="true" />
</div>
</form>
</div>
</div>
</div>
Width the following javascipt/jquery:
$(function() {
$(document).on("click", "#searchIcon", function () {
var searchWrapper = $("#searchWrapOuter");
$(searchWrapper).slideToggle();
return false;
});
});
This code works as expected on a page load direct off a Url. When coming into the page off a link which is Ajax loaded, loads the contents of the page into the DOM, and the DOM ready handler only executes for the first page.
I have read about using the
$(document).on('pageinit'), not $(document).ready()/$(function()
I still haven't been able to get this to work when coming in off an ajax link however. What would be the correct way to implement these events to get the code to work coming in from an Ajax link?
Thanks,
Most likely it is because you are using IDs instead of classes. jQuery Mobile doesn't work well with IDs because it caches pages into the DOM so if you open a page, close it, then go back to the page, you might have your page twice inside the DOM (one visible, one hidden/cached). So when you do $("#searchWrapOuter") you don't know which element you are actually dealing with (in your case, probably the hidden one).
The solution is to change your IDs to classes. This is not very intuitive but I found that is the best way to work with jQuery Mobile.
Also note this comment in the doc which might also be relevant to you:
The id attribute of all your elements must be not only unique on a given page, but also unique across the pages in a site. This is because jQuery Mobile's single-page navigation model allows many different "pages" to be present in the DOM at the same time. This also applies when using a multi-page template, since all "pages" on the template are loaded at once.
http://jquerymobile.com/demos/1.2.0/docs/pages/page-anatomy.html
You can manually adjust delay time to 500ms and 1s.
$(searchWrapper).delay(1000).slideToggle();
My issue is that the page id was below the pages tags. So once I moved the page div above it, the javascript was included in the ajax page load. Previous to this

How can I get Meteor's reactivity and view rendering to work correctly with Jquery Mobile and it's view rendering?

I have Jquery Mobile working and have found the best way to get it to work is by including it in the /client/ directory. So, I have the following files in my /client/ directory
jquery.js
jquery-mobile.js
jquery-mobile.css
Then I include this in my index.html
<script type="text/javascript">
$( document ).bind( "mobileinit", function( event, data ){
$.mobile.autoInitializePage = false;
}
</script>
I tried creating a smart package but then the loading order invalidated jquery plugins for some reason. I tried just using references in the HEAD but that do invalidated jquery plug ins for some reason. The above works, pages transition, views render and I can even use the Meteor auth branch and render subscriptions.
The problem I am having now is when Meteor updates the DOM with data and renders the data it is not rendered with JQM.
For example, if I try to use a JQM Listview to display a Meteor subscription it just formats like a regular un-ordered list .
Here is the template code.
{{#each get_groups}}
<ul data-role="listview" data-theme="a">
<li>{{name}}</li>
</ul>
{{/each}}
Which just renders as bulleted items. If I use static data like the JQM tuts show it renders fine.
<ul data-role="listview" data-theme="a">
<li>Acura</li>
<li>Audi</li>
<li>BMW</li>
</ul>
I am suspect I may need to call some kind of refresh, which means I would have to use observe on the collection subscriptions I imagine.
I am having the same problem with a custom login button. I use a template helper to return the Meteor.user().username and the button doesn't get formatted by JQM. If I don't use return the username the button of course renders find through JQM.
I also have the same problem when I try to access the Handlebars current user. If I try to do the following the publicPage will load.
{{#if currentUser}}
{{>privatePage}}
{{else}}
{{>publicPage}}
{{/if}}
Once I login the privatePage flickers quickly and then just a white screen. If I remove the references to currentUser then I can login and use the JQM changePage method to load the privatePage.
$.mobile.changePage("#privatePage");
I only have a rough understanding but I believe it is related to how and when JQM formats data for rendering vs. how and when Meteor formats data for rendering.
Does anyone has any ideas on how I might get JQM to behave nicely with Meteor? or if I should even bother and maybe use another mobile front end alongside Meteor?
Thanks
Steeve
You do have to refresh when data changes. Here's a full sample app with Meteor and JQM:
http://jqm.meteor.com/
Source code here:
https://github.com/snez/jqm-meteor
Notice on lines 17 and 38 that when an element is rendered, you have to refresh it and rebind any custom events to it.

JQuery Mobile apply style to newly added elements

In JQuery Mobile, I have a navigation bar like the following:
<div id="nav_bar" data-role="navbar">
<ul>
<li><a>video</a></li>
<li><a>music</a></li>
<li><a>picture</a></li>
</ul>
</div>
Say now I want the nav bar to display "some content" only. This is my code:
$("#nav_bar ul").html("<li><a>some content</a></li>");
But the built-in JQuery Mobile style is not applied to it. How can I do this?
Thanks in advance.
When a page is opened, a script runs to add all the necessary classes. Replacing an item does not rerun the script.
I don't think you can do this without adding in the class manually by either specifying the classes in the text/using a variable or the following:
$("#nav_bar ul").html('<li><a>some content</a></li>').children('li').addClass('class-one class-two');
$("#nav_bar ul").html("<li><a>some content</a></li>");
.html() method destroys ul element and its contents then adds new content.
You should use .append() instead.
$("#nav_bar ul").append("<li><a>some content</a></li>");
If you actually want to replace the original content.
Target the div and use .html() method
$("#nav_bar").html("<ul><li><a>some content</a></li></ul>");​

Integrating Django-dynamic-formsets with JQuery Mobile's Radio Buttons

I am using Django and the django-dynamic-formset plugin to generate a JQuery Mobile (JQM) site. I have nested forms that allow the user to click a "Add" link to another line to the form. This works great without JQM, but when JQM is used to style the form widgets the radio button labels do not trigger the correct radio button.
I have put up a static example of the behaviour, based on the generated HTML. Click the "Add" link, then try choosing a severity for the added item. The "for" attributes of the labels appear to update correctly, so I do not know what I'm doing wrong.
The django-dynamic-formset guide provides me with a way to call a JavaScript function after the user clicks the "Add" button, but I do not know if there's a JQM method I should be calling that will fix the issue. When I use JQM's enhanceWithin function it triggers a page load, which submits my form to Django, which I don't want at that point because the form won't validate yet.
Edit: I uploaded a much better example to the same URL.
After enough caffeine and peanut M&M's I have figured it out.
Reason for Failure: The django-dynamic-formset (DDF) plugin duplicates the form you give it. But the form is cloned as-is, which already includes all the JQuery Mobile (JQM) processing. This causes JQM to ignore it and makes the radio buttons misbehave.
The Solution: The DDF plugin allows you to specify what form to clone by its formTemplate parameter. JQM allows you to disable automatic mobile-enhancement of certain elements. Create an un-enhanced version of your form, and pass that to DDF as your formTemplate.
More Details:
I put this coded into my HTML head, before the reference to JQM:
<script>
$(document).bind('mobileinit',function(){
$.mobile.ignoreContentEnabled = true; // required for using the natural forms
});
</script>
And included this style to hide my "natural" form:
<style>
.natural-form { visibility: hidden; display: none; }
</style>
In the Django code I added a <div class='natural-form> and put a dummy version of my form in it (being sure to surround it another <div> with a unique ID for reference later). In my initialization of DDF I give it the unique ID as the parameter to formTemplate.
I was told on another forum I would have to hack DDF and JQM to get this to work. I am impressed at the design of both of these libraries - flexible enough that a newbie to JQuery can stick all the pieces in the right places and get something out of it.

Resources