jQuery Mobile 1.3 Panel Not Working After Page Change - javascript

I seem to be having issues with programmatic opening and closing of a JQM 1.3 Panel.
EDIT: This is for JQM 1.3.x not 1.4+
It is somewhat hard to explain, so I just made a fiddle :)
There is a lot going on in the fiddle, but it is just a sample of a much larger app and conveys the issue.
How to replicate:
Go to Fiddle
On Fiddle open the Panel and go to Page Two
On Page Two open Panel and go to Page One
Try to Open the Panel now on page one, it does nothing.
Browsers Affected:
EDIT: This seems to be fixed in Chrome 30.0.1599.101 m
Chrome 28.0.1500.95 m
IE 10.0.9200.16635
Safari // Latest Ver
Android WebView (4.2.2)
Browsers NOT Affected:
Firefox 23
Opera 12.16
Link to Fiddle:
http://jsfiddle.net/q2YH3/
Link to Other Posts
https://github.com/jquery/jquery-mobile/issues/6308
http://forum.jquery.com/topic/panel-not-responding-after-page-change
EDIT: So Firefox gives me an error that neither Chrome or IE do.
When I click to go back to page one, I get:
Type Error: elem is undefined
The error is thrown by JQ 1.9.1, I trace it back to this:
A method for determining if a DOM node can handle the data expando
acceptData: function( elem ) {
// Do not set data on non-element because it will not be cleared (#8335).
if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {
return false;
}
var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
// nodes accept data unless otherwise specified; rejection can be conditional
return !noData || noData !== true && elem.getAttribute("classid") === noData;
}
`
Note the :
Do not set data on non-element because it will not be cleared (#8335).
Github Issue Link:
https://github.com/jquery/jquery/pull/1232
OG Code:
$('.showMenu').on('click', function(){
$.mobile.loading('hide');
$.mobile.activePage.find('#'+$.mobile.activePage.attr('id')+'P').panel("toggle");
});
$('.btnMenuItem').on('click', function(event){
myPgActions.nav(event, function(target){
$.mobile.changePage(target);
}, false);
});
var myPgActions = {};
myPgActions = {
nav: function(event, callback, manualHash){
var PID = $.mobile.activePage.attr('id'),
target = (!!event) ? event.target.name : manualHash;
$("#"+PID+"P").panel( "close" );
if(PID != 'loading') $("#"+PID+"Iframe").hide();
if(PID == target){
$("#"+PID+"Iframe").hide('fast', function(){
$("#"+PID+"Iframe").attr('src', "");
myPgActions.update(PID, target, 'refresh', function(target){
callback(target)
});
});
}else{
this.update(PID, target, 'change', function(target){
callback(target);
});
}
},// end get
update: function(PID, target, type, updateCallback){
var ifReady = $.Deferred();
if(type == 'refresh'){
this.buildUrl(PID, function(url){
$('#'+PID+'Iframe').attr( 'src', url);
ifReady.resolve();
$.when(ifReady).then(function(){
updateCallback('#'+PID+'Iframe')
});
});
}else if(type == 'change'){
this.buildUrl(target, function(url){
$('#'+target+'Iframe').attr( 'src', url);
ifReady.resolve();
});
$.when(ifReady).then(function(){
updateCallback('#'+target);
});
}
}, // end set
buildUrl: function(page, buildCallback){
switch(page){
case 'dash':
var mobileSiteUrl = 'URL with options for iframe'
setTimeout(function(){buildCallback(mobileSiteUrl);},25);
break;
case 'local':
var mobileSiteUrl = 'URL with options for iframe'
setTimeout(function(){buildCallback(mobileSiteUrl);},25);
break;
}// End Switch
}
}// End Obj

Had the same problem, panel not showing after page changes.
Two small changes can fix that:
what I did was to change the panel from id="myPanel" to class="myPanel", then changed the call to the panel to open: $('.myPanel:visible').panel('open'); - that's it!
The problem is that the panel has to be inside of a jQuery "page", and after the transition, if you have the panel set in the target page, you actually have two (or more) panels with the same id which is wrong or same class which is fine. So you just change the id to a class and call the visible one.
Took me too long, Hope it saves time to someone else.

I played around with your code a bit. I noticed that If I put an alert inside your update function, that it fixes everything. So I researched why an alert would make a program work, and found this page.
http://ubuntuforums.org/archive/index.php/t-930002.html
"You should probably know that JavaScript evaluation is of the 'look ahead' type: the script already runs when it is still being evaluated (and while the page itself is still being evaluated). Now that is why it is recommended to dump all references to scripts in the section of your page, as it will cause the JavaScript to be fully evaluated before you (usually) can call a function (event handlers), and hence avoid silly 'undefined' errors.
Now the alert(); call has 2 effects: (1) it pops up the message box (so far, so good);.but (2) it halts the thread the JavaScript is using! However the browser's other threads will still continue to go on (HTML rendering...). So it may be one of those cases that you would benefit from a more elegant halting method, which is to only execute this (part of the) script when the document has been fully loaded;"
The solution they suggest is putting your script inside of the . Or using "stateChanged() function of the ajax http request".

Well I upvoted #A.sharif 's post, as he got the gears in my head spinning.
The problem lies in the fact that the callback of the "BuildUrl" function was executing before the URL variable was built.
I thought I had allowed ample time with 25ms but it was not. I bumped the time before the callback is executed up to 600 ms and it works fine now.
I am sure there is a more elegant solution, but this is what I got ;)
New Fiddle:
http://jsfiddle.net/t8zyQ/
What was changed was the value of 25 in the setTimeout() to 600.
Changed Code:
buildUrl: function(page, buildCallback){
switch(page){
case 'dash':
var mobileSiteUrl = 'URL with options for iframe'
setTimeout(function(){buildCallback(mobileSiteUrl);},600);
break;
case 'local':
var mobileSiteUrl = 'URL with options for iframe'
setTimeout(function(){buildCallback(mobileSiteUrl);},600);
break;
}// End Switch

Related

issue in IE browser while opening a new window

i have this small piece of code
$("a").live("click",function(event) {
<% String lifeCare=LifeEventProperties.getInstance().getProperty("lifeCare");%>
var s="<%=lifeCare%>";
var href = $(this).attr('href');
if (href.indexOf(s) != -1) {
loadLifeCare(href) ;
event.preventDefault();
}
});
function loadLifeCare(href)
{
var wnd=window.open('/NASApp/benemain/LifeCareSite');
setTimeout(function() {
wnd.location.href = href;
}, 6000);
}
here in my jsp page i have checked for a particular word in url's using jquery and that word is like "something.com" which i am fetching from property file ,now if this something.com is found in the url which a user has clicked then i am calling a javascript function which then opens a new window with an internal site url which is taking care of user's session for that page which has this something.com and then i reload the page with "href" that user actually clicked .
the problem is its working good in all browser's other IE and my client loves IE,
IE is directly going to the link which bypassing loadLifeCare method and giving me this error on console
The value of the property 'loadLifeCare' is null or undefined, not a Function object
can any suggest something why it is happening ?is there anything in this code that IE don't understand ,i am getting a feeling that issue is with window.open() maybe but i am not sure and i don't even know any alternative if that's the case.
please help me and tell me if you need any clarification on anything..
Try this
fixed the deprecated live
used a better method to open windows (yours may very likely give access denied;
moved the function to before it is used and wrapped the click event handler in a a load handler
function loadLifeCare(href) {
var wnd=window.open('/NASApp/benemain/LifeCareSite',"lifeCareWin");
if (wnd) setTimeout(function() {
window.open(href,"lifeCareWin");
}, 6000);
}
$(function() {
$("a").on("click",function(event) {
<% String lifeCare=LifeEventProperties.getInstance().getProperty("lifeCare");%>
var s="<%=lifeCare%>";
var href = $(this).attr("href"); // this.href might be useful too
if (href.indexOf(s) != -1) {
loadLifeCare(href) ;
event.preventDefault();
}
});
});

Close/clear a chrome extension notification while notification panel is open

References: https://developer.chrome.com/apps/notifications
I am using the chrome.notifications.create(string id, object options, function callback); to create a chrome notification.
var id = 'list';
var options = {};
options.title = 'test';
options.iconUrl = 'notification_icon.png';
options.type = 'list';
options.message = "test";
options.buttons = [{title: 'test'}];
options.items = [{title: 'test', message:'test'}];
var createCallback = function(notificationId) { console.log(notificationId); };
chrome.notifications.create(id, options, createCallback); // returns 'list';
This creates a notification as expected. All working correctly.
I then call chrome.notification.clear(string id, function callback);
var id = 'list';
var clearCallback= function(wasCleared) { console.log(wasCleared); };
chrome.notification.clear(id, clearCallback); // returns true;
This does clear the notification. All working correctly.
EXCEPT it does not clear the notification out if the notification panel is open. This is not a major problem 99% of the time. Until I implemented the button code within the notification.
Using chrome.notifications.onButtonClicked.addListener(function callback); On click I am calling the clear notification panel code, and it reports back as it has been cleared.
var onButtonClickedCallback = function (notificationId, buttonIndex) {
console.log(notificationId, buttonIndex);
if ( notificationId == 'list' ) {
chrome.notification.clear(id, clearCallback); // returns true;
}
}
chrome.notifications.onButtonClicked.addListener(onButtonClickedCallback); // onClick it returns 'list', 0
But I am looking right at it.. Once the notification panel closes and opens again, I can confirm it has actually gone. But obviously since I am clicking a button on the notification, the panel is open, but it does not clear away as I would have liked.
All this is running in an extension background without the persistence: false property (so the script is always loaded, and since I can see the output, I know the functions are being called).
Have I overlooked something? I do not see any functions that deal with closing the notification panel. So as far as I can tell, I am clearing the notification but the panel is not updating it's display.
I am using Chrome 37.0.2019.0 canary on Win8
If anyone can suggest something I may have missed, I would be greatful. My google searches reveal people having problems with the HTML notification.
This is a known bug, or rather an old design decision, with little progress.
Star the issue to raise its priority. I also suffer from the same.
Here's the workaround solution I've been using for several months now:
// open a window to take focus away from notification and there it will close automatically
function openTemporaryWindowToRemoveFocus() {
var win = window.open("about:blank", "emptyWindow", "width=1, height=1, top=-500, left=-500");
win.close();
}
chrome.notifications.clear("", function(wasCleared) {
openTemporaryWindowToRemoveFocus()
});

addEventListener and setInterval fail silently in a Greasemonkey script

I am trying to get code to execute every x amount of time and begin doing so after the page has loaded for the first time, while my debug throws no errors, the script doesn't actually do anything.
So, I am at a bit of a loss and I am thinking it has something to do with the syntax or the way the code is nested. Can you be so kind as to look at my code below and tell me what in the heck I am doing wrong and if there is a better way to fix it?
window.addEventListener('load', function() {
setInterval(function setTitle(){
var sInfo = document.getElementById("play_info");
var iTags = sInfo.innerHTML.split("\">");
var pTags = iTags[3].split("<");
document.title = pTags[0];
return setTitle;
},5000);
});
This is a code inside a Greasemonkey script that will run inside Firefox. Thank you.
Update (Now that target page was given):
The question code did not match the structure of the actual page. It typically would throw TypeError: iTags[3] is undefined errors.
Using DOM methods, to get the desired info, does the job. A working script is:
// ==UserScript==
// #name _KROQ, song info to page title
// #include http://betaplayer.radio.com/player/*
// #grant GM_addStyle
// ==/UserScript==
/*- The #grant directive is needed to work around a design change
introduced in GM 1.0. It restores the sandbox.
*/
if (window.top != window.self) //-- Don't run on frames or iframes.
return;
window.addEventListener ('load', function () {
setInterval (setTitle, 5000);
}, false);
function setTitle () {
var songInfoNode = document.querySelector (
"#play_info #oflw_shield div.sleeve.hori"
);
if (songInfoNode) {
var songInfoText = songInfoNode.textContent.trim ();
//console.log ("songInfoText", songInfoText);
document.title = songInfoText;
}
}
That code is "brittle", but it will work fine on a site that has the structure you seem to expect. However, the only "output" is that the page title might change. That doesn't happen?
One or more of the following is the script's immediate problem:
The page does not have the structure you are expecting, so the code throws exceptions. You say, "My debug throws no errors". Verify that you checked Firefox's error console, ControlShiftJ, with the display set to "Errors" or to "All".
Something else in the script, that you are not showing us, is the problem. Include or link to the complete Greasemonkey script.
The script is operating on <iframe>d content, so changing document.title will have no visible effect. Link to the target page.
For reference, here is more robust version of that code, that also has a console message, so that you can verify operation:
window.addEventListener ('load', function () {
setInterval (setTitle, 5000);
}, false);
function setTitle () {
console.log ("Running setTitle().");
var sInfo = document.getElementById ("play_info");
if (sInfo) {
var iTags = sInfo.innerHTML.split ("\">");
if (iTags && iTags.length > 3) {
var pTags = iTags[3].split ("<");
if (pTags && pTags.length) {
document.title = pTags[0];
}
}
}
}
Note that it's not good practice to parse HTML that way, but without seeing the actual target page (or at least the structure of the play_info node), we can't provide a specific alternative.
As Brandon Boone stated, if you are looking for a pure JS solution to find cross-browser solutions for addEventListener, I suggest you use a solution like this.
var e = window.addEventListener ? window.addEventListener : window.attachEvent;
e('load',function(){ ... };

SYNTAX_ERR: DOM Exception 12 - Hmmm

I have been working on a small slideshow / public display for a client that uses HTML5 Rock's Slideshow code. I have run into a DOM Exception 12 - a syntax error that is supposedly related to CSS selectors - while monkeying around with it... but I can't trace it back to any changes I made in the code. I am thinking it might be something that was uncovered as I added features.
I have traced it down to this object (live version here):
var SlideShow = function(slides) {
this._slides = (slides || []).map(function(el, idx) {
return new Slide(el, idx);
});
var h = window.location.hash;
try {
this.current = h;
} catch (e) { /* squeltch */ }
this.current = (!this.current) ? "landing-slide" : this.current.replace('#', '');
if (!query('#' + this.current)) {
// if this happens is very likely that someone is coming from
// a link with the old permalink format, i.e. #slide24
alert('The format of the permalinks have recently changed. If you are coming ' +
'here from an old external link it\'s very likely you will land to the wrong slide');
this.current = "landing-slide";
}
var _t = this;
doc.addEventListener('keydown',
function(e) { _t.handleKeys(e); }, false);
doc.addEventListener('touchstart',
function(e) { _t.handleTouchStart(e); }, false);
doc.addEventListener('touchend',
function(e) { _t.handleTouchEnd(e); }, false);
window.addEventListener('popstate',
function(e) { if (e.state) { _t.go(e.state, true); } }, false);
};
Instantiation of SlideShow() (line 521 in main.js):
var slideshow = new SlideShow(queryAll('.slide'));
Calling queryAll('.slide') returns an array of all the slides with an class of .slide. However, when passing queryAll('.slide') as a parameter for instantiating SlideShow(), it returns a DOM Exception 12 error.
Has anybody seen this before?
You are using illegal id-attributes(illegal before HTML5) inside the document, e.g. 2-slide . Fix them.
To explain:
to solve the known misbehaviour of element.querySelectorAll() the selector .slide will be internally rewritten(by using the id of the element). This will result in something like that:
#2-slide .moreselectors
...and forces the error, because an ID may not start with a Number.
See the fiddle: http://jsfiddle.net/doktormolle/FGWhk/
If you are coming here after searching for this error in HTML5 rocks slides:
For some reason they remove the class 'to-build' with the following:
toBuild[0].classList.remove('to-build', '');
That breaks all slide decks the use build, even the Google demo right now is broken
Just change line 220 of default.js to
toBuild[0].classList.remove('to-build');
all is well!
In my case it was using self.postMessage(e.data); in the main thread while using web workers.
I know it's not related to the OP's issue, but it's an odd error so I'm leaving this here in hope it helps others.
Same problem to me but in my case a try to get elements from their attribute
document.querySelectorAll('input[name="path"]')
and SYNTAX_ERR: DOM Exception 12 occurred only on Safari. So i've change it to get the element directly from class and now work fine.
You can escape the quotes like in applescript then no issue on safari
do JavaScript "document.querySelector('span[" & attrName & "=\"" & attrValue & "\"]').click();"

How can I override the OnBeforeUnload dialog and replace it with my own?

I need to warn users about unsaved changes before they leave a page (a pretty common problem).
window.onbeforeunload = handler
This works but it raises a default dialog with an irritating standard message that wraps my own text. I need to either completely replace the standard message, so my text is clear, or (even better) replace the entire dialog with a modal dialog using jQuery.
So far I have failed and I haven't found anyone else who seems to have an answer. Is it even possible?
Javascript in my page:
<script type="text/javascript">
window.onbeforeunload = closeIt;
</script>
The closeIt() function:
function closeIt()
{
if (changes == "true" || files == "true")
{
return "Here you can append a custom message to the default dialog.";
}
}
Using jQuery and jqModal I have tried this kind of thing (using a custom confirm dialog):
$(window).beforeunload(function () {
confirm('new message: ' + this.href + ' !', this.href);
return false;
});
which also doesn't work - I cannot seem to bind to the beforeunload event.
You can't modify the default dialogue for onbeforeunload, so your best bet may be to work with it.
window.onbeforeunload = function() {
return 'You have unsaved changes!';
}
Here's a reference to this from Microsoft:
When a string is assigned to the returnValue property of window.event, a dialog box appears that gives users the option to stay on the current page and retain the string that was assigned to it. The default statement that appears in the dialog box, "Are you sure you want to navigate away from this page? ... Press OK to continue, or Cancel to stay on the current page.", cannot be removed or altered.
The problem seems to be:
When onbeforeunload is called, it will take the return value of the handler as window.event.returnValue.
It will then parse the return value as a string (unless it is null).
Since false is parsed as a string, the dialogue box will fire, which will then pass an appropriate true/false.
The result is, there doesn't seem to be a way of assigning false to onbeforeunload to prevent it from the default dialogue.
Additional notes on jQuery:
Setting the event in jQuery may be problematic, as that allows other onbeforeunload events to occur as well. If you wish only for your unload event to occur I'd stick to plain ol' JavaScript for it.
jQuery doesn't have a shortcut for onbeforeunload so you'd have to use the generic bind syntax.
$(window).bind('beforeunload', function() {} );
Edit 09/04/2018: custom messages in onbeforeunload dialogs are deprecated since chrome-51 (cf: release note)
What worked for me, using jQuery and tested in IE8, Chrome and Firefox, is:
$(window).bind("beforeunload",function(event) {
if(hasChanged) return "You have unsaved changes";
});
It is important not to return anything if no prompt is required as there are differences between IE and other browser behaviours here.
While there isn't anything you can do about the box in some circumstances, you can intercept someone clicking on a link. For me, this was worth the effort for most scenarios and as a fallback, I've left the unload event.
I've used Boxy instead of the standard jQuery Dialog, it is available here: http://onehackoranother.com/projects/jquery/boxy/
$(':input').change(function() {
if(!is_dirty){
// When the user changes a field on this page, set our is_dirty flag.
is_dirty = true;
}
});
$('a').mousedown(function(e) {
if(is_dirty) {
// if the user navigates away from this page via an anchor link,
// popup a new boxy confirmation.
answer = Boxy.confirm("You have made some changes which you might want to save.");
}
});
window.onbeforeunload = function() {
if((is_dirty)&&(!answer)){
// call this if the box wasn't shown.
return 'You have made some changes which you might want to save.';
}
};
You could attach to another event, and filter more on what kind of anchor was clicked, but this works for me and what I want to do and serves as an example for others to use or improve. Thought I would share this for those wanting this solution.
I have cut out code, so this may not work as is.
1) Use onbeforeunload, not onunload.
2) The important thing is to avoid executing a return statement. I don't mean, by this, to avoid returning from your handler. You return all right, but you do it by ensuring that you reach the end of the function and DO NOT execute a return statement. Under these conditions the built-in standard dialog does not occur.
3) You can, if you use onbeforeunload, run an ajax call in your unbeforeunload handler to tidy up on the server, but it must be a synchronous one, and you have to wait for and handle the reply in your onbeforeunload handler (still respecting condition (2) above). I do this and it works fine. If you do a synchronous ajax call, everything is held up until the response comes back. If you do an asynchronous one, thinking that you don't care about the reply from the server, the page unload continues and your ajax call is aborted by this process - including a remote script if it's running.
This can't be done in chrome now to avoid spamming, refer to javascript onbeforeunload not showing custom message for more details.
Angular 9 approach:
constructor() {
window.addEventListener('beforeunload', (event: BeforeUnloadEvent) => {
if (this.generatedBarcodeIndex) {
event.preventDefault(); // for Firefox
event.returnValue = ''; // for Chrome
return '';
}
return false;
});
}
Browsers support and the removal of the custom message:
Chrome removed support for the custom message in ver 51 min
Opera removed support for the custom message in ver 38 min
Firefox removed support for the custom message in ver 44.0 min
Safari removed support for the custom message in ver 9.1 min
Try placing a return; instead of a message.. this is working most browsers for me.
(This only really prevents dialog's presents)
window.onbeforeunload = function(evt) {
//Your Extra Code
return;
}
You can detect which button (ok or cancel) pressed by user, because the onunload function called only when the user choise leaveing the page. Althoug in this funcion the possibilities is limited, because the DOM is being collapsed. You can run javascript, but the ajax POST doesn't do anything therefore you can't use this methode for automatic logout. But there is a solution for that. The window.open('logout.php') executed in the onunload funcion, so the user will logged out with a new window opening.
function onunload = (){
window.open('logout.php');
}
This code called when user leave the page or close the active window and user logged out by 'logout.php'.
The new window close immediately when logout php consist of code:
window.close();
I faced the same problem, I was ok to get its own dialog box with my message, but the problem I faced was :
1) It was giving message on all navigations I want it only for close click.
2) with my own confirmation message if user selects cancel it still shows the browser's default dialog box.
Following is the solutions code I found, which I wrote on my Master page.
function closeMe(evt) {
if (typeof evt == 'undefined') {
evt = window.event; }
if (evt && evt.clientX >= (window.event.screenX - 150) &&
evt.clientY >= -150 && evt.clientY <= 0) {
return "Do you want to log out of your current session?";
}
}
window.onbeforeunload = closeMe;
<script type="text/javascript">
window.onbeforeunload = function(evt) {
var message = 'Are you sure you want to leave?';
if (typeof evt == 'undefined') {
evt = window.event;
}
if (evt) {
evt.returnValue = message;
}
return message;
}
</script>
refer from http://www.codeprojectdownload.com
What about to use the specialized version of the "bind" command "one". Once the event handler executes the first time, it’s automatically removed as an event handler.
$(window).one("beforeunload", BeforeUnload);
Try this
$(window).bind('beforeunload', function (event) {
setTimeout(function () {
var retVal = confirm("Do you want to continue ?");
if (retVal == true) {
alert("User wants to continue!");
return true;
}
else {
window.stop();
return false;
}
});
return;
});

Categories