does anyone know of a way to make only a certain part of a collapsible widget actually toggle the collapsible part? I have been trying to figure this out for hours and can't seem to get it.
Basically, I don't want a whole <li> to trigger the expand/collapse, but only a small area on the right.
Thanks.
This is my solution:
block default events
create a clickable element on the right side
manage expand/collapse status
HTML
<div data-role="page" id="page">
<div data-role="content">
<div data-role="collapsible" data-inset="false" data-collapsed="true">
<h1>Title <span class="clickme">Click me</span></h1>
<h5>Content</h5>
</div>
<div data-role="collapsible" data-inset="false" data-collapsed="true">
<h1>Title <span class="clickme">Click me</span></h1>
<h5>Content</h5>
</div>
<div data-role="collapsible" data-inset="false" data-collapsed="true">
<h1>Title <span class="clickme">Click me</span></h1>
<h5>Content</h5>
</div>
</div>
</div>
JavaScript
$(document).on("pagecreate", "#page", function()
{
$("[data-role=collapsible] a").on("click", function()
{
event.preventDefault();
event.stopPropagation();
});
$(".clickme").on("click", function()
{
var element = $(this).closest("[data-role=collapsible]");
if (element.attr("data-collapsed") == "true")
{
element.attr("data-collapsed", "false");
element.collapsible("expand");
}
else
{
element.attr("data-collapsed", "true");
element.collapsible("collapse");
}
});
});
JSFiddle
So there were a few things I was doing incorrectly, helpfully pointed out by Sga.
You can't use vclick. For whatever reason, this jQM plugin isn't using an established jQM event to handle it's stuff. I was previously listening to the vclick event:
$parent.on('vclick', '[data-role=collapsible] a', function() {});
You can't bind the thing you want to prevent default on on a parent. For example:
$parent.on('click', '[data-role=collapsible] a', function() {});
That doesn't work, you have to bind it after the elements are rendered a la:
$('.collapse-target', $list).on('click', function() {});
After doing all that, which totally isn't optimal, I was able to achieve the effect I wanted. It's too bad this feature wasn't included out of the box for the collapsible widget. Hopefully this helps someone.
Related
I have a list view inside a popup , when the user select a list element I want to change this element "li" background color , I have tried the following code it was working on jQuery mobile 1.3.2 but it didn't work when i upgraded my app to 1.4.0 , How can I change the background color of the list element when the user click on it ? please help me
<div data-role="page" id="index">
<div data-role="header" data-theme="b">Main</div>
<div data-role="content">
Show Popup
</div>
<div data-role="popup" id="MyPOPUP" data-position-to="window" data-corners="false" data- overlay-theme="a" data-dismissible="false">
<div data-role="header" data-theme="a">
<div style="text-align:center;float:center;padding-top:11px;">
<font size="6px" color="white">Countries</font>
</div>
</div>
<div id="scrollContent" class="content" data-role="content" style="background-color: white;">
<ul data-role="listview" id="countrieslist" style="margin: 0 !important;">
</ul>
</div>
</div>
</div>
Java script code
$('#index').on( 'pageinit',function(){
for(var i=1;i<=50;i++)
{
$('#countrieslist').append('<li id="'+i+'">'+''+'<font>'+Country+i+'</font>' +'</li>');
}
$('#countrieslist').listview('refresh');
});
$('#Btn1').on('touchstart', function(){
$(this).css({background: 'white'});
$(this).attr('href','#MyPOPUP');
});
$('#countrieslist').on('click','li', function() {
$(this).css({background: 'blue'});
selected_elem = $(this).attr('id');
alert('you selected' + selected_elem);
$('#MyPOPUP').popup('close');
});
You have a little typo in your loop that creates the countries, but other than that the code seems to work,
Here is a working DEMO
Because pageinit is deprecated n 1.4, I have used pagecreate; and in the for loop the word country after the font tag should be within the single quotes as it is not a variable. Also, in the li click, I reset all other countries to transparent background before setting the newly selected one:
$(document).on( 'pagecreate', '#index',function(){
for(var i=1;i<=50;i++) {
$('#countrieslist').append('<li id="'+i+'"><font>Country' + i +'</font></li>');
}
$('#countrieslist').listview('refresh');
$('#Btn1').on('click', function(){
$(this).css({background: 'white'});
$(this).attr('href','#MyPOPUP');
});
$('#countrieslist').on('click','li', function() {
$('#countrieslist li').css({background: 'transparent'});
$(this).css({background: 'blue'});
selected_elem = $(this).attr('id');
alert('you selected' + selected_elem);
$('#MyPOPUP').popup('close');
});
});
I want to change dynamically (click event) a data-theme of a list item in a jQueryMobile listview. Firebug shows me that the change is performed but the list is not refreshed. (If I add elements it works, but with attribute changes the list won't be refreshed.) For example I want to change the data-theme from c to f when the item is clicked.
I tried everything I read in this forum, from trigger('mouseout') over trigger('create') on parents to refreshing the whole page, but no effect at all, so I guess I am blind to see something obvious. Maybe somebody can give me a hint... :)
<script>
function fillList() {
var li = '<li data-theme="c">List item</li>';
$("#alist").empty().append(li).promise().done(function () {
$(this).off("click").on("click", ".info", function (e) {
e.stopImmediatePropagation();
e.preventDefault();
var theLiElem = $(this).closest('li');
theLiElem.attr('data-theme','f').trigger('mouseout');
theLiElem.trigger("create");
});
$(this).listview("refresh");
});
}
$(document).on("pageinit", "#info-page", function () {
fillList();
});
</script>
<div data-role="page" id="info-page">
<div data-role="content">
<ul data-role="listview" id="alist" data-inset="true">
</ul>
</div>
</div>
Kind regards,
Steve
JQM 1.3 Iscrollview 1.3.1
I have a list of links to events using data-iscroll. Each event is also a list (title/date-location/description).
Each time I click on the event list, the event is displayed. If I scroll down the content, when I go back to the event list and then click on another event, the view scrolls to where the previous view was stopped.
I've successfully stopped this by launching an empty() on the event content and then calling updatelayout on the back button of the event content :
$("#bhome").on('vclick', function(e) {
$('#econt').empty().trigger('updatelayout');
$.mobile.loading('show');
e.preventDefault();
$.mobile.changePage("#page1");
});
But, of course, android users don't use a back button and use the back key instead.
I've tried to empty() and updatelayout on the pagebeforehide event but apparently, the position is saved before that event happens :
$('#event').on('pagebeforehide', function(event, data) {
$('#econt').empty();
$('#econt').trigger('updatelayout');
$('#escroll').trigger('updatelayout');
});
I've also tried to use the silentscroll function but it's not working either :
$(document).on('pageshow', '#event', function(){
$.mobile.silentScroll(0);
});
How can I make sure that on viewing a new event, the position is back to the top ?
Here is a snippet of my index.html file :
<div id='container'>
<div data-role='page' id='page1' data-theme="c" style="background: black;">
</div>
<div data-iscroll style='background-color:#ddd;'>
<ul id="el"></ul>
</div>
<div data-role='footer' data-position='fixed' data-theme="a" data-tap-toggle="false">
</div>
</div>
<div data-role="page" id="event" data-theme="c" style="background:black;">
<div data-role='header' data-position='fixed' data-theme="a" style="height:42px;">
<a id="bhome" class="ui-btn-left ret" data-icon="arrow-l" href="#" data-iconshadow="false">Back</a>
<h1 id='eh1'></h1>
</div>
<!-- data-role='content' entraine un scroll horizontal -->
<div data-iscroll style='background-color:white;' id='escroll'>
<ul id='econt'></ul>
</div>
</div>
The answer was given by the iscrollview author (works perfectly) :
$("#escroll").iscrollview("scrollTo", 0, 0, 0, false);
I have just encountered a strange problem when using jQuery Mobile.
I have a link inside a form element label - a checkbox label to be exact but the link does not work.
I have tried reading the docs but can't seem to find anything on it.
Here is my markup:
<div data-role="fieldcontain">
<fieldset data-role="controlgroup">
<input type="checkbox" class="cbox" name="OptIn" id="OptIn"/>
<label for="OptIn">Receive E-mails From Us</label>
<input type="checkbox" value="1" class="cbox" name="tandc" id="tandc"/>
<label for="tandc">I agree to the <a href="/tandcs.html" target="_BLANK" >Terms & Conditions</a></label>
</fieldset>
</div>
When the link is clicked it just toggles the checkbox state.
UPDATE
Just realised I can open the link by right clicking but obviously on a mobile device that's not very useful....
this is the correct solution for mobile and non mobile browsers
$('.ui-checkbox a').bind("tap click", function( event, data ){
event.stopPropagation();
$.mobile.changePage($(this).attr('href'));
});
Had the same problem and solved it using:
$('.ui-btn-text a').click(function(event) {
var $this = $(this);
window.open($this.attr('href'), $this.attr('target'));
});
So if any link within a button-text is clicked it will be opened in a new window. If you want it in the same window just use $.mobile.changePage as Phil showed.
I tried the above mentioned solutions on jQuery Mobile 1.1.0 with jQuery 1.7.2 without success.
After a bit of tinkering and reading into the new jQuery event functions I came up with my own solution to make all anchors in labels clickable without loosing jQuery Mobile default behaviour on the rest of the label:
jQuery('label').each(function(){
var e = jQuery(this).data('events');
jQuery('.agree label').undelegate();
jQuery('.agree label *:not(a)').delegate(e);
});
use on() and off() instead
$('label').each(function(){
var e = $(this).data('events');
$('label').off();
$('label').not('a').on(e);
});
There a some improvements that can be made but here is a rough draft:
http://jsfiddle.net/KADqA/
JS
$('.ui-btn-text').click(function(event) {
var checked = $("#tandc[type='checkbox']").is(":checked");
var $this = $(this);
if($this.children('a').length) {
$.mobile.changePage('#tc', {
transition : 'pop',
role : 'dialog'
});
}
stateOfCheckbox(checked);
});
function stateOfCheckbox(checked) {
$('#home').live( 'pagebeforeshow',function(event){
$("#tandc[type='checkbox']").attr("checked",checked).checkboxradio("refresh");
});
}
HTML
<div data-role="page" id="home">
<div data-role="fieldcontain">
<fieldset data-role="controlgroup">
<input type="checkbox" class="cbox" name="OptIn" id="OptIn"/>
<label for="OptIn">Receive E-mails From Us</label>
<input type="checkbox" value="1" class="cbox" name="tandc" id="tandc"/>
<label for="tandc">I agree to the <a href="#tc" data-rel="dialog" >Terms & Conditions</a></label>
</fieldset>
</div>
</div>
<div data-role="page" id="tc">
<div data-role="header">
<h1>T and C</h1>
</div>
Read me
</div>
You could also just override the event:
$('.ui-checkbox a').click(function(e) {
e.stopPropagation();
})
On Android the solutions above did not work on Android.
It only works when using on pagecreate and without event delegation.
$(document).on('pagecreate', function(event, ui) {
$(".ui-checkbox a").on("click tap", function() {
$(':mobile-pagecontainer').pagecontainer('change', this.href);
return false;
});
} );
This is posible solution if you want to open the link in a popup.
$('.ui-checkbox a').bind('click tap', function (event) {
event.stopPropagation();
$($(this).attr('href')).popup('open');
});
Add Id or class into parent label have a tag
and using script of #alex dms
$('#field-contain label a').bind("tap click", function( event, data ){
event.stopPropagation();
$.mobile.changePage($(this).attr('href'));
});
Try it, work perfecly on my mobile and desktop
https://jsfiddle.net/vulieumang/p91zhmnp/
I have jQuery Mobile on iPad Safari and for some reason touch swipe events are firing twice.
People have reported the same problem over the past year as recently as this week but I cannot find an explanation for how to fix the double event without modifying jQuery Mobile and I do not want to do that. Thread on jQuery forums
The follwoing element bindings for the swipe handler all have the same incorrect double-event result where the alert is called twice for every one swipe.
How should jQuery Mobile touch events be bound in order to avoid double bubbling?
// Test 1: Binding directly to document with delegate()
$(document).delegate(document, 'swipeleft swiperight', function (event) {
alert('You just ' + event.type + 'ed!');
});
// Test 2: Binding to document with on() handler recommended as of 1.7 with and without preventDefault
$(document).on('swipeleft',function(event, data){
event.preventDefault();
alert('You just ' + event.type + 'ed!');
});
// Test 3: Binding to body with on() with and without event.stopPropagation
$('body').on('swipeleft',function(event, data){
event.stopPropagation();
alert('You just ' + event.type + 'ed!');
});
// Test 4: Binding to div by class
$('.container').on('swipeleft',function(event, data){
event.stopPropagation();
alert('You just ' + event.type + 'ed!');
});
event.stopImmediatePropagation() was the trick, which is different from stopPropagation(). Ensuring the jQuery on() method is called in document.ready seems to help. I was able to use any element selector to bind the events including using the swipeup and swipe down from here
$(document).ready(function(){
$(document).on('swipeleft swiperight swipedown swipeup',function(event, data){
event.stopImmediatePropagation();
console.log('(document).Stop prop: You just ' + event.type + 'ed!');
});
});
Well, had the same problem with swipe event been called twice.
The workaround is to bind the event this way:
$(document).on('swipeleft', '#div_id', function(event){
//console.log("swipleft"+event);
// code
});
it really helped in my case too. I was trying to swipe pages with mobile jquery and swipe events( left and right ) were triggering several times. event.stopImmediatePropagation() it worked like a charm. Thank you !!
here is my code.
<script type="text/javascript">
$(document).bind( 'pageinit', function(event) {
$("div:jqmData(role='page')").live('swipeleft swiperight',function(event){
if (event.type == 'swipeleft') {
var prev = $(this).prev("div:jqmData(role='page')");
if(typeof(prev.data('url')) !='undefined') {
$.mobile.changePage(prev.data('url'), { transition: 'slide', reverse: false});
event.stopImmediatePropagation();
}
}
if (event.type == 'swiperight') {
var next = $(this).next("div:jqmData(role='page')");
if(typeof(next.data('url')) != 'undefined') {
$.mobile.changePage(next.data('url'), { transition: 'slide', reverse: false});
event.stopImmediatePropagation();
}
}
});
});
</script>
HTML -
<div data-role="page" id="page1" data-url="#page1">
<div data-role="content">
<div>
<h1> Page 1 </h1>
<p>I'm first in the source order so I'm shown as the page.</p>
<p>View internal page called</p>
<ul data-role="listview" data-inset="true" data-theme="c">
<li>Swipe Right to view Page 2</li>
</ul>
</div>
</div>
</div>
<div data-role="page" id="page2" data-url="#page2">
<div data-role="content">
<div>
<h1> Page 2 </h1>
<p>I'm first in the source order so I'm shown as the page.</p>
<p>View internal page called</p>
<ul data-role="listview" data-inset="true" data-theme="c">
<li>Swipe Right to view Page 3</li>
</ul>
</div>
</div>
</div>