简体   繁体   中英

jQuery Mobile 1.3 Panel Not Working After Page Change

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:

  1. Go to Fiddle
  2. On Fiddle open the Panel and go to Page Two
  3. On Page Two open Panel and go to Page One
  4. 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM