jquery Mobile - Auto Divider - jquery-mobile

I'm using the jquery Mobile AutoDivider for a web project of mine and it works great in IE8, but for some reason in Chrome it's not generating the headers for me.
My question is: How exactly does the AutoDivider determine what to make a 'divider'? Is is just the first item within your <li></li>?
Here's my basic HTML structure (it's ultimately placed in a ASP.Net Repeater:
<ul data-role="listview" data-autodividers="true">
<li>
<img src="mySource.jpg" alt="" />
<h3>John Doe</h3>
<p><strong>Company Name Here</strong></p>
<p>User Address</p>
<p class="ui-li-aside">
<strong style="display: none;"><!-- This is what seems to make the headers in IE, placing this right here: -->
Last Name of Employee</strong>
</p>
</li>
</ul>

see the docu http://jquerymobile.com/demos/1.2.0/docs/lists/docs-lists.html
Autodividers
A listview can be configured to automatically generate dividers for its items. This is
done by adding a data-autodividers="true" attribute to any listview.
By default, the text used to create dividers is the uppercased first letter of the
item's text. Alternatively you can specify divider text by setting the > autodividersSelector option on the listview programmatically.

Related

jQuery-UI Accordion with link in the header

I am using Dotclear blog software, which provide a widget for the blog categories with a resulting code looking like this:
<div class="widget categories ">
<h3>Catégories</h3>
<ul>
<li>Cat1</li>
<li>Cat2
<ul>
<li>Subcat1</li>
</ul>
</li>
<li>Cat3
<ul>
<li>Subcat2</li>
</ul>
</li>
<li>Cat4</li>
</ul>
</div>
What I am trying to achieve here is using the <a> tag (for Cat2 or Cat3) as header (or a dynamically added <h4> around it) and fold the subcategory list. If I call the accordion like this :
$(".categories").accordion({
header: "li:has(ul) > a",
});
the accordion does work, but when I click on the link it just folds/unfolds the item and doesn’t let me go to the link target (the category page, that is).
I tried wrapping the <a> in an <h4> tag and use that tag as header, but it doesn’t seem to make a difference. Is there a way to do what I seek or should I abandon the idea of collapsing subcategories and have functioning links within the header ?
Thanks for your time.
Well, after reading your comments, I realized I was using the wrong tool to achieve my objective. I have replaced jquery-ui’s accordion with a treemenu jQuery plugin which is actually made for my use. Sorry to have wasted your time and thanks for your kind answers.

Selecting Tabs by id on jQuery UI 1.9+ with hidden tabs

How to select a tab by id in recent versions of jQuery UI? I used to do this:
$(mytabs).tabs("select", "#tab_contents");
And it worked fine, even with some of the tabs hidden. Now I upgraded jQuery UI and the code above does not work anymore. I tried following some other suggestions on this site, and ended up with this:
$(mytabs).tabs("option", "active", $(mytabs).find("li").index("#tab_header"));
Not only it's way more verbose, but it doesn't select the correct tab, since some of them are hidden. How can it be done?
P.S. To hide some tabs, I used $("#tab_header").hide(). Is this still correct in recent versions, or is there a better way?
Found out a solution:
$(mytabs).tabs("option", "active", $("#tab_header").index());
This selects the correct tab, regardless of which ones are visible (it's even possible to select tabs currently invisible - the contents are shown, but the header is not).
<div id="tabs">
<ul>
<li id="ha">A</li>
<li id="hb">B</li>
<li id="hc">C</li>
<li id="hd">D</li>
<li id="he">E</li>
</ul>
<div id="a">AAA</div>
<div id="b">BBB</div>
<div id="c">CCC</div>
<div id="d">DDD</div>
<div id="e">EEE</div>
</div>
.index starts from 0,
$(mytabs).tabs("option", "active", $("#ha").index());
but if you use #a instead of #ha use like this
$(mytabs).tabs("option", "active", $("#a").index()-1);

Knockout, JQMobile, and generating a collapsible-set doesn't quite seem to work right

I've checked out a number of samples, but none are quite the same as what I'm trying to do.
What I've got works, mostly, but it doesn't quite work right.
Here's a fiddle to illustrate the issue.
http://jsfiddle.net/5yA6G/4/
Notice that the top set works fine, but it's statically defined.
The bottom set (Tom, steve, bob) "work" basically, but the header element ends up both in the collapsible header AND in the portion of the collapsible that gets hidden.
Seems like I must be doing something wrong, but I haven't been able to figure out what.
Any ideas?
Just for reference and for anyone else running into this problem, it turns out to be at least somewhat obvious in hindsight.
Knockout's built in "anonymous" templating works great in many cases, but with JQMobile, it can be a tad quirky.
That's because JQMobile will adjust the content of the anonymous template when the page loads, just as it does with all the other content.
Then, later, when you use knockout's ApplyBindings function, knockout will add the applicable elements, just as it should. As many posts and answers have hinted at, you then MUST call collapsible() on the newly created elements, via something like this.
$("div[data-role='collapsible']").collapsible({refresh: true});
No problem there. HOWEVER, if JQM has already applied formatting, then the anonymous template has already been "rendered" by JQM, so rendering it again by calling collapsible causing all sorts of funky results, including doubled heading, nested collapsibles, etc.
The solution for me was to use Knockout's "Named Template" feature, and just put the template to render the collapsible elements into a tag, like this:
<script type="text/html" id="alarm-template">
<div data-role="collapsible" data-collapsed="true" data-collapsed-icon="arrow-d" data-expanded-icon="arrow-u" data-enhance="false">
<h3 data-bind="text:name"></h3>
<p>The content here</p>
<p data-bind="text: name"></p>
</div>
</script>
Doing this prevents JQM from "rendering" the template elements when the page loads, so they'll be rendered properly when they're actually generated.
EDIT: The above works fine for collapsibles NOT in a collapsible-set, but, if they're in a set, I've found the styling of the elements (particularly, the corner rounding to indicate belonging to a set) doesn't work right.
From what I can tell, there are 2 problems:
The first is that just triggering "Create" doesn't actually refresh the styling of all the collapsibles in the set. to do that you have to do...
$("div[data-role='collapsible-set']").collapsibleset('refresh');
But, there's a worse problem. JQM "marks" the last item in the set as the "last item". That fact then gets used to determine how to style the last item as it's being expanded/collapsed.
Since Knockout doesn't actually rebuild the entire set (for speed), each time you call the refresh method, JQM dutifully marks the last item as "last", but never removes the marks on previous items. As a result, if you start from an empty list, EVERY item ends up being marked "last" and the styling fails because of this.
I've detailed the fix for that at github in an issue report.
https://github.com/jquery/jquery-mobile/issues/4645
I actually found a much easier way to do this:
Set up your foreach binding as you normally would for me it looked like this
<div data-bind="foreach: promotions">
<h3 data-bind="text: Title"></h3>
<p>Creator:<span data-bind="text: Creator"></span></p>
<p>Effective Date:<span data-bind="text: EffectiveDate"></span></p>
<span data-bind="text: Description"></span>
<a data-bind="text: ButtonText, attr: {href: ButtonLink}"></a>
Wrap that in a div with class="collapsible like so
<div data-role="collapsible-set" data-bind="foreach: promotions">
<div class="collapsible">
<h3 data-bind="text: Title"></h3>
<p>Creator:<span data-bind="text: Creator"></span></p>
<p>Effective Date:<span data-bind="text: EffectiveDate"></span></p>
<span data-bind="text: Description"></span>
<a data-bind="text: ButtonText, attr: {href: ButtonLink}"></a>
Apply the collapsible widget via jquery mobile after you do your binding like so:
$(document).ready(function () {
ko.mapping.fromJS(data, dataMappingOptions, PromotionViewModel.promotions);
ko.applyBindings(PromotionViewModel);
$('.collapsible').collapsible();
});
For a collapsible set the same idea can be applied just set the class="collapsible-set" on your foreach div. Hope this helps

Adding scroll bars to a listview using JqueryMobile

Trying to add scrollbars to a listview within a dialog in JQueryMobile with no joy.
I'm using the following code:
<div class="content-primary">
<ul id="lvPages" data-role="listview" data-filter="true" data-inset="true" data-scroll="true"></ul>
</div>
Which works perfect on desktop browsers yet when I test this on an iPad the scrollbars don't appear.
Is there something obvious I'm missing?
Sorry, should actually add:
I'm adding the items via Javascript and am calling a " $("#lvPages").listview('refresh');" upon the end of these additions.
According to this forum article, you have to include the jquery.mobile.scrollview.js script (and its associated CSS file) for the data-scroll attribute to be recognized and acted upon.

jQuery Mobile proper way to initialize a listview

Here is my problem. I have a few hard coded pseudo pages in my index. Some filled with content, some empty which will be filled on user interaction only by ajax. This ajax content contains html lists. When they load they don't have the nice jquery mobile look so I have to call a .listview() method so the jqm framework parse it on my ajax callback. That is where I often get this JS error:
Uncaught TypeError: Cannot read property 'jQuery162027575719612650573' of undefined
The number is never the same...
I wonder if I use the proper way to parse a listview after the page loads the ajax content. the error seems to be triggered when there is slight lag for the loading and the complete event is triggered too soon and my listview is not yet in the DOM at that moment, just a guess. what is the recommended way to initialize a listview after an ajax call?
It is very unfortunate because when the js error occurs it seems to freeze any further js execution...
so here is my empty pseudo page:
<div data-role="page" id="playlist" data-add-back-btn="true">
<div data-role="header">
<h1><g:message code="pd.playlist" /></h1>
</div>
<div data-role="content"></div>
</div>
right under it there is a script tag with the bind an ajax call on pageshow to activate the listview
<script type="text/javascript">
$('#playlist').bind('pageshow', function () {
$.ajax({
url: "updatePlaylistTemplate.gsp",
error:function(x,e){handleAjaxError(x,e);},
beforeSend:function(){$.mobile.showPageLoadingMsg();},
complete:function(){
$.mobile.hidePageLoadingMsg();
$('[data-role="listview"]').listview(); //re-active all listview
},
success:function(data, textStatus, jqXHR){
$('#playlist').find('[data-role="content"]').html(data);
}
});
});
</script>
The updatePlaylistTemplate return this (extract):
<ul data-role="listview" data-split-theme="d">
<li data-icon="delete">
Provider: Bell
</li>
<li data-icon="delete">
Rock - Classic Rock
</li>
<li data-icon="refresh" data-theme="e">Refresh list</li>
<li data-role="list-divider">Next song</li>
<li>
<a href="urlToViewSongInfo">
<img src="images/song.gif" />
<h3>Albert Flasher</h3>
<p>The Guess Who</p>
<p class="ui-li-aside">Next</p>
</a>
</li>
<li data-role="list-divider">Now playing</li>
<li>
<a href="urlToviewSongInfo">
<img src="images/song.gif" />
<h3>Crime of the Century</h3>
<p>Supertramp</p>
<p class="ui-li-aside">14h49</p>
</a>
</li>
<li data-role="list-divider">Previous songs</li>
<li>
<a href="urlToViewSongInfo">
<img src="images/song.gif"" />
<h3>Desperado</h3>
<p>Alice Cooper</p>
<p class="ui-li-aside">14h45</p>
</a>
</li>
[...]
</ul>
What version of jQuery Mobile are you using? In the latest beta (1.0b2) you can trigger the create event on a dom element to have the framework initialize it:
New “create” event: Easily enhance all widgets at once
While the page plugin no longer calls each plugin specifically, it
does dispatch a “pagecreate” event, which most widgets use to
auto-initialize themselves. As long as a widget plugin script is
referenced, it will automatically enhance any instances of the widgets
it finds on the page, just like before. For example, if the selectmenu
plugin is loaded, it will enhance any selects it finds within a newly
created page.
This structure now allows us to add a new create event that can be
triggered on any element, saving you the task of manually initializing
each plugin contained in that element. Until now, if a developer
loaded in content via Ajax or dynamically generated markup, they
needed to manually initialize all contained plugins (listview button,
select, etc.) to enhance the widgets in the markup.
Now, our handy create event will initialize all the necessary plugins
within that markup, just like how the page creation enhancement
process works. If you were to use Ajax to load in a block of HTML
markup (say a login form), you can trigger create 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" );
Create vs. refresh: An important distinction
Note that there is an important difference between the create event
and refresh method that some widgets have. The create event is suited
for enhancing raw markup that contains one or more widgets. The
refresh method that some widgets have should be used on existing
(already enhanced) widgets that have been manipulated programmatically
and need the UI be updated to match.
For example, if you had a page where you dynamically appended a new
unordered list with data-role=listview attribute after page creation,
triggering create on a parent element of that list would transform it
into a listview styled widget. If more list items were then
programmatically added, calling the listview’s refresh method would
update just those new list items to the enhanced state and leave the
existing list items untouched.
Link: http://jquerymobile.com/blog/
You can also copy the output that jQuery Mobile creates and use that structure rather than using <li> tags and depending on jQM to inititialize it:
<li data-role="list-divider" class="ui-li ui-li-divider ui-btn ui-bar-a ui-btn-up-undefined" role="heading"><span>List Divider</span></li>
<li data-theme="b" class="ui-li ui-li-static ui-body-b">Regular LI</li>

Resources