0

When I click the link the first time, the popup is not centered, but the second time it is. I've followed the answers of other questions that say to use 'positionTo': 'window', but the problem happens whether I have it or not. There are other solutions that say to use a timeout, but I don't want to use that.

function setImage()
{
  $('#image-popup img').attr('src', 'https://upload.wikimedia.org/wikipedia/commons/7/7b/Orange-Whole-%26-Split.jpg');

  $('#image-popup img').on('load', function() {
    console.log('loaded image from click');
    $('#image-popup').popup('reposition', {'positionTo': 'window'});
  });
}
<html>
<head>

  <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
  <script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
  <script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>

</head>
  
<body>

  <a href='#image-popup' data-rel="popup" data-position-to="window" onclick='setImage()'>Open image</a>

  <div id='image-popup' data-role='popup'>
    <a href="#" data-rel="back" class="ui-btn ui-corner-all ui-shadow ui-btn-a ui-icon-delete ui-btn-icon-notext ui-btn-right">Close</a>
    <img class="popphoto" src="" alt="orange">
  </div>

</body>
  
</html>

Note that you'll need to empty the cache and hard reload if you run this multiple times.

Community
  • 1
  • 1
user2233706
  • 6,148
  • 5
  • 44
  • 86

1 Answers1

1

You are opening the popup before the image has been downloaded, there is no solution, as the framework is not knowing the size of the image, and therefore which size the popup shall be.

Please, note: if you open the popup in img.onload, the popup will be displayed with the right size at the right position, i.e. centered to the window with the size of the image:

  $('#image-popup img').on('load', function() {
    $('#image-popup').popup('open', {'positionTo': 'window'});
  });

So, i think your question here is something like: "How to open the popup as fast as possible - to give the user a feedback - but with the correct size, and moreover while the image is still downloading?"

Now, my proposal is to get the image size as fast as possible, through an extra XHR request. Obviously, this is also just fast as allowed by the network condition, but we always have the possibility to show briefly the loader, and the XHR will get just only the first few bytes, not the whole image data.

To do that, we need to change the way the popup is opened:

HTML:

<a href='#' onclick='openPopupWithSize("https://upload.wikimedia.org/wikipedia/commons/7/7b/Orange-Whole-%26-Split.jpg"); return false;'>Open image</a>

JavaScript - see comments:

// helper function to get byte value
function readByte(data, offset) {
    return data.charCodeAt(offset) & 0xff;
}
// request size, assign src, open popup & look how the image is downloading
function openPopupWithSize(pngUrl){
    // clean-up before, if we have to deal with some more images
    $('#image-popup img').attr('src', "");
    // set various parameters
    var xhr = new XMLHttpRequest();
    xhr.open("GET", pngUrl, true);
    // just get only what is strictly necessary
    xhr.setRequestHeader("range', 'bytes=0-23");
    xhr.overrideMimeType("text\/plain; charset=x-user-defined"); 
    xhr.onprogress = function(e){
        // read the few bytes needed to get width & height of the png
        var data = e.currentTarget.response;
        // offset are: 16 & 20 - see PNG specifications
        var w = readByte(data, 19) | (readByte(data, 18) << 8) | (readByte(data, 17) << 16) | (readByte(data, 16) << 24);
        var h = readByte(data, 23) | (readByte(data, 22) << 8) | (readByte(data, 21) << 16) | (readByte(data, 20) << 24);
        // set size of the container, will be reset by the framework as needed
        $('#image-popup-popup').css("width", w+"px");
        $('#image-popup-popup').css("height", h+"px");
        // assign image src like you did it in your example
        $('#image-popup img').attr('src', pngUrl);
        // finally, open the popup - JQM is allowed now to reposition correctly
        $('#image-popup').popup("open", {"positionTo": "window"});
    };
    xhr.send(null);
}

Please, feel free to share your thoughts in a comment, if this is what you need.

deblocker
  • 7,629
  • 2
  • 24
  • 59
  • Your first code snippet is what I ended up doing. I wanted to see if I could do this without adding any JS code. To give the user feedback, I just show the JQM loader before the load event and hide it in the event handler. – user2233706 Mar 21 '17 at 02:39
  • @user2233706: ok, if you stick with the onload event, don't forget the hotfix for cached images: `if(img.complete) img.onload();` like the onload function, shall be written before the img.src assignement. – deblocker Mar 21 '17 at 07:47