In mobile theme popup doesn't hide when we click outside popup - jquery-ui

I am using jquery.blockUI.js to show a popup for mobile application. Popup is shown when I click on button. But when I try to hide that popup on clicking outside that popup then it does not hide.
I am using this code to hide popup:-
jQuery('.blockOverlay').attr('title','Click to unblock').click(jQuery.unblockUI);
It works perfectly in desktop version of magento but Doesn't work for mobile theme.
Please help me how to solve this problem.

Try something like this..
function togglePopup(){
var selector = '#popup',
$popup = $(selector),
callback = function(e) {
if (!$(e.target).parents().andSelf().is(selector)) {
$popup.hide();
$(document).off('click', callback);
}
};
$popup.toggle();
if ($popup.is(':visible')) {
$(document).on('click', callback);
}
return false;
}

Related

Blank Firefox addon panel page with multiple windows

I've followed MDN's document to create a toggle button addon.
Everything works fine except one problem:
Open a second browser window (cmd+n or ctrl+n) and click on the toggle button there
Click on the toggle button on the original browser window without closing the toggle button on the second window
the toggle button's panel becomes blank with the following error message:
JavaScript error: resource:///modules/WindowsPreviewPerTab.jsm, line 406: NS_ERR
OR_FAILURE: Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIT
askbarTabPreview.invalidate]
// ./lib/main.js
var { ToggleButton } = require("sdk/ui/button/toggle");
var panels = require("sdk/panel");
var self = require("sdk/self");
var buttonIndex = 0;
var lastKnownButtonIndex = 0;
var button = ToggleButton({
id: "button",
label: "my button",
icon: {
"16": "./icon-16.png"
},
onClick: handleChange,
});
var panel = panels.Panel({
contentURL: self.data.url("menu.html"),
onHide: handleHide
});
function handleChange(state) {
if (state.checked) {
panel.show({
position: button
});
}
}
function handleHide() {
button.state('window', {checked: false});
}
function assignButtonIndex() {
return (buttonIndex++).toString();
}
The complete addon is here: https://goo.gl/9N3jle
To reproduce: Extract the zip file and $ cd testButton; cfx run and follow the above steps.
I really hope someone can help me with this. Thank you in advance!
It's a bug; you're not doing anything wrong. It's a racing condition between the windows' focus events, and the panel's event, that prevent somehow the panel's hidden event to be emitted properly.
You can try to mitigate with a workaround the issue until is properly fixed. I added some explanation in the bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1174425#c2 but in short, you can try to add a setTimeout to delay a bit when the panel is shown, in order to avoid the racing condition with the window's focus. Something like:
const { setTimeout } = require("sdk/timers");
/* ... your code here ... */
function handleChange(state) {
if (state.checked) {
setTimeout(() => panel.show({ position: button }), 100);
}
}
I am currently using a workaround where I dynamically create a new Panel every time the user presses the toolbar button.
It is faster than the 100ms workaround and also handles a scenario where the user outright closes one of the browser windows while the panel is open. (The 100ms workaround fails in this case and a blank panel is still displayed.)
It works like this:
let myPanel = null;
const toolbarButton = ToggleButton({
...,
onChange: function (state) {
if (state.checked) {
createPanel();
}
}
});
function createPanel(){
// Prevent memory leaks
if(myPanel){
myPanel.destroy();
}
// Create a new instance of the panel
myPanel = Panel({
...,
onHide: function(){
// Destroy the panel instead of just hiding it.
myPanel.destroy();
}
});
// Display the panel immediately
myPanel.show();
}

set bootbox dialog window focus through select2-open event

I am opening a bootbox dialog box when the user click inside select-2 input box using the following code
$("#categoryfinder").on("select2-open", function () {
bootbox.confirm("Are you sure?", function (result) {
Example.show("Confirm result: " + result);
});
});
Once it is opened, the popup window is not active and I have to click twice to close or to trigger any event on the popup
Please let me know if there is any solution for this.
EDIT: when I click inside 1, the popup is not active at 1,2,3, I have to click once to make it active.
I fixed this issue by doing the following changes
$("#allergenfinder").on("select2-opening", function (e) {
e.preventDefault();
excludeAllergenPrompt();
});

Stop the back history, juste close panel [duplicate]

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)

Back button handler in jQuery Mobile (Android) PhoneGap

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 :-)

Phonegap Android Back Button - close app with back button on homepage

I am developing a Android app using Jquery Mobile/Phonegap. I have the following code to control the phone's back button:
document.addEventListener("backbutton", backKeyDown, true);
function backKeyDown() {
// Call my back key code here.
$.mobile.changePage("#homepage", "slideup");
}
This all works fine, but I would like the app to close when pressing the back button on the homepage only, is this possible?
Update: this has stopped working with a latest Phonegap update (supposedly). Feel free to offer a working solution if you know it.
Here's how I do it:
document.addEventListener("backbutton", function(e){
if($.mobile.activePage.is('#homepage')){
/*
Event preventDefault/stopPropagation not required as adding backbutton
listener itself override the default behaviour. Refer below PhoneGap link.
*/
//e.preventDefault();
navigator.app.exitApp();
}
else {
navigator.app.backHistory()
}
}, false);
For further information, here you can find the related documentation with a full example: http://docs.phonegap.com/en/2.0.0/cordova_events_events.md.html#backbutton
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
document.addEventListener("backbutton", onBackKeyDown, false);
}
function onBackKeyDown()
{
navigator.app.exitApp();
}
Thank you spader.
You would need to keep track of when the homepage is being displayed. When you know you are on the homepage call:
navigator.app.exitApp();
If you don't want to use jQuery Mobile, change $.mobile.activePage.is('#homepage') to document.getElementById('#homepage') on #Spadar Shut answer, as on following code:
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady(){
document.addEventListener("backbutton", function(e){
if(document.getElementById('#homepage')){
e.preventDefault();
navigator.app.exitApp();
}
else {
navigator.app.backHistory()
}
}, false);
}
Through this way, don't need to download Jquery Mobile gibberish only for this purpose. Also, activePage is deprecated as of JQuery mobile 1.4.0 and will be removed from 1.5.0. (Use the getActivePage() method from the pagecontainer widget instead)

Resources