I am currently workking with Jquery 1.4.2 on a mobile app. I have a list of questions.As soon as a user taps on item, a popup with its response is diplayed. each response is a checkbox radio. Responses are inside a fieldset with data-role=control group.
If a user has already respond to the question, i want to activate the checkbox radio, else just nothing. I wrote some code, It works well under desktop's browsers, but it does not work with mobile's browser. I do not know why. Actually, during few milliseconds, the activate checkbox radio is well displayed (it is checked), then that switches to an other response (so an other checkbox radio). I do not know why I get this behavior ???
My code when a listitem is clicked/tapped. It allows to load dynamically question's response in a popup.
var fieldset = $("#contentResponse");
fieldset.empty();
var radioSurvey="";
for(var i = 0; i < response.length; i++){
var label="";
if(status == 'active'){
if(userHasAlreadyAnswered != "null" && userHasAlreadyAnswered == response[i].RESPONSE_ID){
console.log("checked ...");
radiochecked = "#"+response[i].RESPONSE_ID;
label = '<label>' + '<input type="radio" checked="checked" name="radioSurvey" value="'+question_id+'_'+response[i].RESPONSE_ID+'_'+survey_id+'" id="'+response[i].RESPONSE_ID+'"/>' + response[i].RESPONSE_TEXT+'</label>';
}else{
console.log("no checked ...");
label = '<label>' + '<input type="radio" name="radioSurvey" value="'+question_id+'_'+response[i].RESPONSE_ID+'_'+survey_id+'" id="'+response[i].RESPONSE_ID+'"/>' + response[i].RESPONSE_TEXT+'</label>';
}
}
radioSurvey += label;
}
fieldset.html(radioSurvey);
fieldset.trigger("create");
if(status == 'completed' || status == 'published'){
$('#sendSurveyButton').hide();
}else{
$('#sendSurveyButton').show();
}
$("#popupSurveyList").popup("open");
EDIT : I saw an overriding from JQM thanks to google developer console.Apparently, JQM append automatically some classes (it is not my code) for label tag, especially the class ui-radio-on !! finally, it is not the first but a random checkbox radio which is checked !
How to resolve this ?
Related
I have a jQuery mobile panel which slides in from the side, it works great.
But lets say you have a login page, that redirects to a main page with a panel. Now if the user opens the panel, and then clicks the back button, he expects the panel to close. But instead the browser navigates back to the login page.
I´ve tried adding something to the url:
window.location.hash = "panelOpen";
But that just messes up the jQuery mobile history state pattern. I´ve also tried to listen to the navigate event, and prevent it if a panel is open:
$(window).on('navigate', function (e, hans) {
var panels = $('[data-role="panel"].ui-panel-open');
if (panels&&panels.length>0) {
e.preventDefault();
e.stopPropagation();
$('#' + panels[0].id).panel('close');
return false;
}
});
This kind of works, except that the url is changed, and I cannot grab the event that changes the url. Furthermore, it also messes up the jQuery mobile history pattern.
So how does people achieve this expected 'app-like' behaviour with a jQuery mobile panel; open panel > history back > close panel. And thats it.
Thanks alot!
Updated
Instead of retrieving current URL from jQuery Mobile's history, It is safer to retrieve it from hashchange event event.originalEvent.newURL and then pass it to popstate event to be replaceState() with that URL.
Instead of listening to navigate, listen to popstate which fires before. The trick here is manipulate both browser's history and jQuery Mobile's history by replaceState() and reload same page without transition.
var newUrl;
$(window).on("hashchange", function (e) {
/* retrieve URL */
newUrl = e.originalEvent.newURL;
}).on("popstate", function (e) {
var direction = e.historyState.direction == "back" ? true : false,
activePanel = $(".ui-panel-open").length > 0 ? true : false,
url = newUrl,
title = document.title;
if (direction && activePanel) {
$(".ui-panel-open").panel("close");
$(".ui-header .ui-btn-active").removeClass("ui-btn-active");
/* reload same page to maintain jQM's history */
$.mobile.pageContainer.pagecontainer("change", url, {
allowSamePageTransition: true
});
/* replace state to maintain browsers history */
window.history.replaceState({}, title, url);
/* prevent navigating into history */
return false;
}
});
This part is meant to maintain same transition used previously as transition is set to none when reloading same page.
$(document).on("pagebeforechange", function (e, data) {
if (data.options && data.options.allowSamePageTransition) {
data.options.transition = "none";
} else {
data.options.transition = $.mobile.defaultPageTransition;
}
});
Demo - Code
I am a little bit late on the party, but i had recently the same requirements and i would like to share how i did it. So, i extended the requirement in the original question to Panels, Popups and Pages:
...an expected 'app-like' behaviour, history back > close
whaterver is open. And thats it.
In .on("panelopen"), .on("popupafteropen") and .on("pagecontainershow") i simply add another entry to the window history, by using the HTML5 API (https://developer.mozilla.org/en-US/docs/Web/API/History_API) (I believe there is no need to use the JQM navigate browser quirks for that):
window.history.pushState({}, window.document.title, window.location.href);
After that, i'm using more or less Omar's function to intercept the popstate event:
$(window).on("popstate", function (e) {
var pageId = $(":mobile-pagecontainer").pagecontainer("getActivePage").prop("id");
var pageOpen = (pageId != "page-home");
var panelOpen = $(".ui-panel-open").length > 0;
var popupOpen = $(".ui-popup-active").length > 0;
if(pageOpen) {
$.mobile.pageContainer.pagecontainer("change", "#page-home", {reverse: true});
return false;
}
if(panelOpen) {
$(".ui-panel-open").panel("close");
return false;
}
if(popupOpen) {
$(".ui-popup-active .ui-popup").popup("close")
return false;
}
});
As you see, the is just only one level to the home-page, but this can be easily extended by using JQM history implementation to get the previous page:
var activeId = $.mobile.navigate.history.activeIndex;
var jqmHistory = $.mobile.navigate.history.stack; // array of pages
and use pagecontainer to change to the active entry - 1.
As last note, this works well also by completely disabling the built-in JQM Ajax navigation system:
/* Completely disable navigation for mobile app */
$.mobile.ajaxEnabled = false;
$.mobile.loadingMessage = false;
$.mobile.pushStateEnabled = false;
$.mobile.hashListeningEnabled = false;
$.mobile.changePage.defaults.changeHash = false;
$.mobile.popup.prototype.options.history = false;
(Tested in Browser, on real Android and iOS devices)
Is there any way to handle back button (device backbutton) as default functionality to move back page? I need to implement the same functionality on back button goes to previous page. If there is no previous page (first page) it exit the application. Is this possible in PhoneGap?
I also need to pop page before going to push another page is this posible in jQuery?
Checking window.location.length would be the easiest way to determine if you're on the first page, but this isn't available in Phonegap.
But since you're using JQM, you can either use the navigate event as Omar suggests or could manually count the number of pages shown and the number of pages gone back (same thing) and use this to determine if the first page is being shown and whether to exit the app. Something like this would work:
var pageHistoryCount = 0;
var goingBack = false;
$(document).bind("pageshow", function(e, data) {
if (goingBack) {
goingBack = false;
} else {
pageHistoryCount++;
console.log("Showing page #"+pageHistoryCount);
}
});
function exitApp() {
console.log("Exiting app");
navigator.app.exitApp();
}
function onPressBack(e) {
e.preventDefault();
if(pageHistoryCount > 0) pageHistoryCount--;
if (pageHistoryCount == 0) {
navigator.notification.confirm("Are you sure you want to quit?", function(result){
if(result == 2){
exitApp();
}else{
pageHistoryCount++;
}
}, 'Quit My App', 'Cancel,Ok');
} else {
goingBack = true;
console.log("Going back to page #"+pageHistoryCount);
window.history.back();
}
}
function deviceready() {
$(document).bind('backbutton', onPressBack);
}
$(document).bind('deviceready', deviceready);
As for the second part of your question:
Secondly i need to pop page before going to push another page is this
posible in jquery ?
It's not clear what you're asking here. Do you mean you want to show some kind of popup content like a dialog between every page change? Please clarify then I can help you :-)
I would think this is a common pattern:
I have a jquery mobile searchbox <input type="search"...>
When entering enter, the submit is performed, but the keypad remains (on my android)
Keypad is hidden in my development envirnoment on desktop.
After lots of seaching, I've tried:
if (e.keyCode == 13) {
console.log("Im here");
$('.ui-input-text').trigger('blur');
$(this).trigger('blur');
$("input").trigger('blur');
$("#goSomewhereElse").focus();
$('input#SearchText').blur();
}
Nothing seems to work. Any suggestions on how to hide the keyboard?
if (event.keyCode == 13)
{
window.location.hash = '#submit_chat_msg';
}
where 'submit_chat_msg' is ID of a button or something else.
I'm developing an MVC4 mobile app using Visual Studio 2012 with jQuery Mobile. I need to remember the state of checkboxes and radio buttons so I store their value in a cookie. When I come back to the page in the pageinit event I set the values but the controls never update visually. Using Firebug with the page rendering as mobile I can see that the values changed correctly. I've tried calling checkboxradio('refresh') on the element like this:
$('#btnCompany').prop('checked', true)checkboxradio('refresh');
but I always get an error saying checkboxradio is undefined and not supported. I know the control is a radio button. To try and work around the problem I extracted the code in jQuery Mobile to refresh a radio button and checkbox which I call and again I can clearly see in Firebug that not only is the input checked correctly but the label classes have changed appropriately. However, visually nothing changes, they look like they did originally. Am I missing something? Why am I getting an error saying checkboxradio is not supported even when I call this in the pageinit event:
$("input[type='radio']").checkboxradio("refresh");
I've tried refreshing by hiding then showing the containing div but that failed. Nothing I've tried refreshes the controls visually. Any and all help would be greatly appreciated!!!
Here are the functions I'm calling to refresh the page bypassing checkboxradio. Here is the function I call to try and work around the problem:
function SetSearchFormState() {
if ($.cookie('cmdSearchForm') != null) {
//$('#searchParamsDiv').hide();
var formData = JSON.parse($.cookie('cmdSearchForm'));
$('#SearchText').val(formData.SearchText);
// Set all search buttons to not selected.
$('.searchBtn').each(function () {
$(this).prop('checked', false);
RefreshCheckboxRadio(this, false);
});
// Set the appropriate search button selected.
$('#hidSearch').val(formData.hidSearch);
switch (formData.hidSearch) {
case 'Opportunity':
$('#btnOpportunity').prop('checked', true);
RefreshCheckboxRadio($('#btnOpportunity'), true);
break;
case 'Company':
$('#btnCompany').prop('checked', true);
RefreshCheckboxRadio($('#btnCompany'), true);
break;
case 'Contact':
$('#btnContact').prop('checked', true);
RefreshCheckboxRadio($('#btnContact'), true);
break;
}
// Set all status buttons to not selected.
$('.statusBtn').each(function () {
$(this).prop('checked', false);
RefreshCheckboxRadio(this, false);
});
// Set the appropriate status button selected.
$('#hidStatus').val(formData.hidStatus);
switch (formData.hidStatus) {
case 'Lead':
$('#btnLead').prop('checked', true);
RefreshCheckboxRadio($('#btnLead'), true);
break;
case 'Prospect':
$('#btnProspect').prop('checked', true);
RefreshCheckboxRadio($('#btnProspect'), true);
break;
case 'Customer':
$('#btnCustomer').prop('checked', true);
RefreshCheckboxRadio($('#btnCustomer'), true);
break;
}
// Set the appropriate include button selected.
$('#hidAllUsers').val(formData.hidAllUsers);
$('#btnAllUsers').prop('checked', false);
RefreshCheckboxRadio($('#btnAllUsers'), false);
if (formData.hidAllUsers == 'True') {
$('#btnAllUsers').prop('checked', true);
RefreshCheckboxRadio($('#btnAllUsers'), true);
}
$('#hidDead').val(formData.hidDead);
$('#btnDead').prop('checked', false);
RefreshCheckboxRadio($('#btnDead'), false);
if (formData.hidDead == 'True') {
$('#btnDead').prop('checked', true);
RefreshCheckboxRadio($('#btnDead'), true);
}
//$('#searchParamsDiv').show();
$("input[type='radio']").checkboxradio("refresh");
$("input[type='checkbox']").checkboxradio("refresh");
}
};
And here is the function that I extracted out of jQuery mobile's checkboxradio refresh method:
function RefreshCheckboxRadio(control, value) {
if ($(control).is(':radio')) {
var parent = $(control).parent('div');
var controlId = $(control).attr('id');
var label = $(parent).find("label[for='" + controlId + "']");
var icon = $(label).find(".ui-icon");
//$(parent).hide();
if (value == false) {
$(control).removeAttr('checked');
$(label).removeClass('ui-radio-on ui-button-active').addClass('ui-radio-off');
$(icon).removeClass('ui-icon-radio-on').addClass('ui-icon-radio-off');
} else if (value == true) {
$(control).attr('checked', 'checked');
$(label).addClass('ui-radio-on ui-button-active').removeClass('ui-radio-off');
$(icon).addClass('ui-icon-radio-on').removeClass('ui-icon-radio-off');
}
//$(parent).show();
} else if ($(control).is(':checkbox')) {
var parent = $(control).parent('div');
var controlId = $(control).attr('id');
var label = $(parent).find("label[for='" + controlId + "']");
var icon = $(label).find(".ui-icon");
//$(parent).hide();
if (value == false) {
$(control).removeAttr('checked');
$(label).removeClass('ui-checkbox-on ui-button-active').addClass('ui-checkbox-off');
$(icon).removeClass('ui-icon-checkbox-on').addClass('ui-icon-checkbox-off');
} else if (value == true) {
$(control).attr('checked', 'checked');
$(label).addClass('ui-checkbox-on ui-button-active').removeClass('ui-checkbox-off');
$(icon).addClass('ui-icon-checkbox-on').removeClass('ui-icon-checkbox-off');
}
// $(parent).show();
}
};
After this code is run I can see the values are correct and exactly as they would be if checkboxradio('refresh') had been called. So even though I can't get checkboxradio to work, performing the work manually should work and in fact does when I view the changes in Firebug yet the controls still don't change their appearance.
After much experimentation I finally threw out this code, disabled Ajax in jQuery Mobile, then handled all of the Ajax manually. I could write a book about what I learned about developing jQuery Mobile apps with MVC4 and probably help many folks out there but alas I don't have the time nor do I get paid for doing so, sorry. I can only hope that someday somebody documents how to do things the right way so there's a single source people can turn to instead of having to spend hours searching for bits and pieces here and there.
I am trying to get a website that runs fullscreen for all pages, I have looked over here: iPad WebApp Full Screen in Safari and followed that and my index page fills the screen just nicely, but whenever I click a link to another page even though that page is all setup with the meta tags it pulls the chrome bar back in and all the alignment goes out.
There must be a way or is that a limitation of safari that will be fixed in a later revision.
I have written a jQuery plugin for this exact purpose: https://github.com/mrmoses/jQuery.stayInWebApp
Include the plugin somehow , then run it like so:
$(function() {
$.stayInWebApp();
});
By default it will attach to all <a /> elements. You can pass a different selector to attach it to specific links. For example, $.stayInWebApp('a.stay'); will attach to all links that have class="stay"
Because its so small, I usually just copy the minified version into one of my other external javascript files to include it, rather than having to add another external js reference.
Also available on plugins.jquery.com
You can try something like this:
if ((navigator.userAgent.indexOf('iPad') != -1)) {
// for standalone (app) fulscreen mode
if (window.innerHeight == 748 || window.innerHeight == 1004) {
var a = document.getElementsByTagName("a");
for (var i = 0, len = a.length; i < len; i++) {
if (a[i].getAttribute("href");) {
a[i].onclick = function() {
window.location = this.getAttribute("href");
return false;
}
}
}
}
}