bytesource Posted September 17, 2014 Share Posted September 17, 2014 Hi, I am currently evaluating the Responsive Images plugin that dynamically provides adaptive images and that was introduced in this forum by Oliver, its creator, some time ago. I will probably have some more questions while exploring the features, but for now I just wanted to ask if it was OK to place the javascript portion of the plugin at the end of the body tag instead of in the head section as mentioned on Github. On the site bildbau.net that uses the plugin, the javascript is located at the end. I, too, prefer placing my javascript in one minified file at the end of a page, but I am not sure if then all images would load as usual before the plugin could do its work. Cheers, Stefan Link to comment Share on other sites More sharing options...
Torsten Baldes Posted September 17, 2014 Share Posted September 17, 2014 the cookie setting script should be placed as high as possible in the dom. if you place this line at the bottom, the images on the first page load will load normal, as the php-script can't read the cookie, because it's not yet set. once the cookie is set, it will work as intended. 1 Link to comment Share on other sites More sharing options...
bytesource Posted September 18, 2014 Author Share Posted September 18, 2014 Thanks for this information! I placed the cookie inside <head> and the JQuery part of the plugin before the closing <body> tag. So far it seems to work just fine. Cheers, Stefan Link to comment Share on other sites More sharing options...
bytesource Posted September 18, 2014 Author Share Posted September 18, 2014 I have been trying to make the Responsive Images (RI) plugin work with the Magnific Popup (MP) image gallery. The basic markup of MP is as follows: echo "<a href='{$image->url}'><img src='{$thumb->url}' /></a>"; The url of the thumbnail is modified by RI as usual, but the url to the larger image is not detected, as it is not the value of an image's src attribute. The idea is to call the MP's elementParse function, then call RI on the url to the large image, and replace the current value of the href attribute with the new modified url. In the documentation, elementParse is described as follows. If you want to modify how the source is parsed, you may hook into the elementParse callback. For example: $('.image-link').magnificPopup({ type:'image', callbacks: { elementParse: function(item) { // Function will fire for each target element // "item.el" is a target DOM element (if present) // "item.src" is a source that you may modify console.log(item); // Do whatever you want with "item" object } }}); The following code does not work. It returns 'undefined' for container and a 404 error for the url: GET http://localhost/sovonex/top-drive-services/null 404 (Page Not Found) This is the code I have come up with (elementParse is the important part): $('.product-gallery').magnificPopup({ delegate: 'a', // child items selector, by clicking on it popup will open type: 'image', gallery: { enabled: true, // set to true to enable gallery preload: [1,2], // read about this option in next Lazy-loading section navigateByImgClick: true, arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>', // markup of an arrow button tPrev: 'Previous (Left arrow key)', // title for left button tNext: 'Next (Right arrow key)', // title for right button // tCounter: '<span class="mfp-counter">%curr% of %total%</span>' // markup of counter }, callbacks: { elementParse: function(item) { var container = $(item).parent(); // test element alert(container.attr('name')); item.src = container.responsiveImages('getURL', item.src, { swidth: screen.width, pwidth: screen.width, pxratio: window.devicePixelRatio || 1 }); } } }); Unfortunately, I have almost no JQuery skills, and cannot even say for sure if the above code is syntactically correct. Therefore, I would be very grateful if someone could take a quick look at the code and point me to the most obvious errors. Cheers, Stefan Link to comment Share on other sites More sharing options...
bytesource Posted September 18, 2014 Author Share Posted September 18, 2014 I inspected the item object that is passed to elementParse when clicking on a thumbnail, and this is the result: container: undefined item: Object el: x.fn.x.init[1] index: 0 parsed: true src: "/sovonex/site/assets/files/1037/top_drive_services_in_nigeria_2_186.jpg" type: "image" __proto__: Object this: MagnificPopup bgOverlay: x.fn.x.init[1] container: x.fn.x.init[1] contentContainer: x.fn.x.init[1] currTemplate: Object direction: true ev: x.fn.x.init[1] fixedContentPos: true index: 0 isAndroid: false isIE7: false isIE8: false isIOS: false isLowIE: false items: Array[6] popupsCache: Object preloader: x.fn.x.init[1] probablyMobile: false scrollbarSize: 15 st: Object supportsTransition: true types: Array[4] wH: 146 wrap: x.fn.x.init[1] __proto__: Object So I guess there is not much I could do with this object. Makes me wonder were to bind the responsiveImages function to. Cheers, Stefan Link to comment Share on other sites More sharing options...
bytesource Posted September 19, 2014 Author Share Posted September 19, 2014 On taking a closer look at the Magnific Popup API I realized that in order to get hold on the current item, I probably should use the change callback. Also, as the large gallery images will be displayed at near full-screen size, I decided to call responsiveImages directly and simply set pwidth to equal the width of the screen. Unfortunately, the following code results in the image url of the large image being set to http://localhost/sovonex/top-drive-services/undefined So I guess I am still not calling resonsiveImages correctly. $('.product-gallery').magnificPopup({ // ... callbacks: { change: function() { var pathname = window.location.pathname; var target = this.currItem; var $tempImage = $('<img />'); $tempImage.attr('src', $tempImage.responsiveImages( pathname, target.src, { swidth: screen.width, pwidth: screen.width, // ** pxratio: window.devicePixelRatio || 1 })); // ** // For simplicity, pwidth equals screen width, // as we are dealing with images displayed full-screen. target.src = $tempImage.attr('src'); } } }); Any suggestions from anyone familiar with the Responsive Images plugin are highly welcome! Cheers, Stefan Link to comment Share on other sites More sharing options...
Oliver Posted September 19, 2014 Share Posted September 19, 2014 Try something like this: $('.product-gallery').magnificPopup({ // ... callbacks: { change: function() { var $container = $(this.contentContainer); $container.responsiveImages({ respondToResize: true, respondToUpscaleOnly: true, reset: true }); } } }); As far as I can see, you can access the content container created by Magnific Popup via this.contentContainer within its callbacks. That’s all you need. Responsive Images will find all img tags within and process them. If you want to just get a responsive image url for the current screen width from a normal image url, you can do it like: // As you need an instance of responsiveImages (you can use any you already have instanciated before) $('body').responsiveImages({...}); ... // get responsive image url from any image path var respImgUrl = $('body').responsivesImage('getURL', 'my/image/path.jpg', { swidth: screen.width, pwidth: screen.width, pxratio: window.devicePixelRatio || 1 }); // pxratio is optional here Link to comment Share on other sites More sharing options...
bytesource Posted September 19, 2014 Author Share Posted September 19, 2014 Oliver, Thanks for your suggestions. Unfortunately, I had not that much luck with the examples. The first example that uses $(this.contentContainer) freezed my computer so that I could not even inspect the problem. The second example, as shown below, made all images on the page disappear (the image url was not modified by the plugin, either): $('.product-gallery').magnificPopup({ // ... callbacks: { change: function() { var pathname = window.location.pathname; var target = this.currItem; target.src = $('body').responsiveImages( pathname, target.src, { swidth: screen.width, pwidth: $(window).width(), pxratio: window.devicePixelRatio || 1 })); } } }); I probably just made a silly mistake, I just can't find it. Cheers, Stefan Link to comment Share on other sites More sharing options...
Oliver Posted September 19, 2014 Share Posted September 19, 2014 The way you call responsiveImages is invalid. On init the plugin only expects an object containing option settings. There is no path or target object to be set for responsiveImages. You just call it on an element of the DOM and the plugin takes care of all images contained in the element. If you want to keep going the way of assining an responsive image url to the current item, it should work like this: $('.product-gallery') .magnificPopup({ // ... callbacks: { change: function() { var pathname = this.currItem.src; // here you have to get the original image url, not window.location.pathname. You have to find out where it is stored. This is just a guess. var target = this.currItem; target.src = $('body').responsiveImages( // asuming you initiated responsiveImages on $('body') before 'getURL', pathname, { swidth: screen.width, pwidth: $(window).width(), pxratio: window.devicePixelRatio || 1 })); } } }); Because, if there is an instance set up, you can access some methods via $(element).responsiveImages(methodName, arg1, arg2, ...); like 'getURL'. Link to comment Share on other sites More sharing options...
bytesource Posted September 20, 2014 Author Share Posted September 20, 2014 Oliver, Thanks for your explanations that helped clear up a lot of questions. There already is an instance of Responsive Images, so I went with the following solution, adapted from the code in your last comment: $('.product-gallery').magnificPopup({ // ... callbacks: { change: function() { var target = this.currItem; var pathname = target.src; var newPath = $('body').responsiveImages( 'getURL', pathname, { swidth: screen.width, pwidth: $(window).width(), pxratio: window.devicePixelRatio || 1 }); pathname = newPath; } } }); However, newPath returns null. I also checked that this.currItem.src is indeed the current image path. Do you have an idea what the problem might be? Cheers, Stefan Link to comment Share on other sites More sharing options...
Oliver Posted September 20, 2014 Share Posted September 20, 2014 Can’t say. Looks good so far. The thing is, that there is no case defined for getURL to return null. Could you log target.src and newPath to the console and post the results? Link to comment Share on other sites More sharing options...
bytesource Posted September 20, 2014 Author Share Posted September 20, 2014 Oliver, That's odd. I logged the variables, and null is returned for newPath: $('.product-gallery').magnificPopup({ // ... callbacks: { change: function() { var target = this.currItem; var pathname = target.src; console.log("pathname: " + pathname); var newPath = $('body').responsiveImages( 'getURL', pathname, { swidth: screen.width, pwidth: $(window).width(), pxratio: window.devicePixelRatio || 1 }); console.log("newPath: " + newPath); pathname = newPath; } } }); Console output: pathname: /sovonex/site/assets/files/1037/pim_watermark3_top-drive-services_-_top_drive_operations_in_saudi_arabia_185.jpgnewPath: null Still, somewhere I must have made a mistake. I just can't figure out where. Cheers, Stefan Link to comment Share on other sites More sharing options...
bytesource Posted September 20, 2014 Author Share Posted September 20, 2014 Oliver, I assume you mean this function: // Generates new URL name from original getURL: function(original_url, params, debug) { console.log("getURL: input url: " + original_url); var swidth = params.swidth || 0, pwidth = params.pwidth || 0, pxratio = params.pxratio || 1; var url = original_url.replace(/(\.[a-z]+)$/, '.s' + swidth + '.p' + pwidth + '.r' + pxratio + '$1'); console.log("getURL: output url: " + url); return url; } Could it be that getURL never gets called inside the change callback? I logged the original url as well as the return value of this function, which output the urls - original and modified - of all images on the page, like this: getURL: input url: /sovonex/site/assets/files/1076/rig-components_-_mast_-_1_165.440x295.jpg js_65e0f5e4d5c7444a9301374984dc5cae_dev.js?no-cache=1411218743:2888getURL: output url: /sovonex/site/assets/files/1076/rig-components_-_mast_-_1_165.440x295.s1366.p400.r1.jpg However, when I clicked on a thumbnail to trigger the change callback, nothing is output from getURL. Cheers, Stefan Link to comment Share on other sites More sharing options...
bytesource Posted September 20, 2014 Author Share Posted September 20, 2014 When I set the initial value of newPath to the string "test", the final value after calling responsiveImages() is still null. So it seems that at least something does happen inside repsonsiveImages(). Link to comment Share on other sites More sharing options...
Oliver Posted September 20, 2014 Share Posted September 20, 2014 So it returns null to newPath while url is logged with a seemingly correct value? Hard to tell from here. Could you load your setup up to server or make your local setup accessible somehow, so I can look into it? Link to comment Share on other sites More sharing options...
bytesource Posted September 21, 2014 Author Share Posted September 21, 2014 Oliver, Neither the original url nor the return value of getPath is logged when clicking on a thumbnail (= calling the change callback). This is why I suspect getPath does not get called in this case. I uploaded the latest changes as requested. One of the galleries on this site can be found at: http://staging.sovonex.com/top-drive-services/ The non-minified javascript file is located at /site/assets/aiom/. I really appreciate your support and patience! Cheers, Stefan Link to comment Share on other sites More sharing options...
Oliver Posted September 21, 2014 Share Posted September 21, 2014 Thanks, Stefan. When I look at your code it seems to me, your initialization of responsiveImages isn’t executed on document.ready, what may cause the instance being not set up correctly. I repeated initialization via console after the page had been loaded completely. After doing this $('body').responsiveImages('getURL', ...) returned a path as expected. So I recommend to change your init code to something like this: /*-----------------------------------------------------------------------------------*/ /* RESPONSIVE IMGAGES PLUGIN */ /*-----------------------------------------------------------------------------------*/ $(function() { $('body').responsiveImages({ respondToResize: true, // if you want to load other image sizes on resize, respondToUpscaleOnly: true, // load other sizes only on upscale resolutionInterval: 50, // load image size of closest multiple of 50px (rendered 430px -> load 450px) imgSelector: 'img.adaptive', // if you want to be more selective, change it loadingClass: 'is-loading', // add a class to img while loading callOnUpdate: null, // optional callback when images are updated //callOnEach: null, //optional callback called for each images after loading callOnEach: function(image) { // http://stackoverflow.com/questions/21363955/get-each-image-natural-height-with-jquery var tempImage = new Image(); tempImage.src = image.attr('src'); var width = tempImage.naturalWidth; var height = tempImage.naturalHeight; image.attr('width', width); image.attr('height', height); var attribute = image.attr('data-original'); if (attribute) image.attr('data-original', image.attr('src')); }, debug: false // set to true to enable console output }); }); BTW: Responsive Images preloads images automatically. When callOnEach callback is called, the image has already been loaded. So you don’t need to create a new Image() and can access naturalHeight of the image directly to set the dimensions via html attributes. Link to comment Share on other sites More sharing options...
bytesource Posted September 22, 2014 Author Share Posted September 22, 2014 Dear Oliver, Thanks for taking a look at my site. I wrapped the initialization call inside $(function() {...}). I also used $(document).ready(function () {...}), but to no avail as getPath still does not get called. So, assuming the plugin is initialized correctly, do you see any reason of why getPath can be called on the console, but not on the server? Also, thanks for you tip about setting the image width and height! Cheers, Stefan Link to comment Share on other sites More sharing options...
Oliver Posted September 22, 2014 Share Posted September 22, 2014 Could you update your remote setup so I can check? Thanks. Link to comment Share on other sites More sharing options...
bytesource Posted September 22, 2014 Author Share Posted September 22, 2014 Oliver, Unfortunately reaching web pages outside China has become so slow that this will take some time. So I guess, the updated version won't be online until tomorrow. Cheers, Stefan Link to comment Share on other sites More sharing options...
bytesource Posted September 22, 2014 Author Share Posted September 22, 2014 Oliver,I finally managed to update the site. I hope you find the changes useful.Cheers,Stefan Link to comment Share on other sites More sharing options...
Oliver Posted September 26, 2014 Share Posted September 26, 2014 I’ll push a little update for the plugin this weekend. I recommend we try again with the new files. Btw: You got some errors in your js, one because you wrote “jquery” instead of “jQuery”. Link to comment Share on other sites More sharing options...
bytesource Posted September 26, 2014 Author Share Posted September 26, 2014 Oliver, I am anxious to try out the new version of your plugin! Also thanks for mentioning the typos. They should be all fixed by now. Cheers, Stefan Link to comment Share on other sites More sharing options...
bytesource Posted September 27, 2014 Author Share Posted September 27, 2014 Some more observations: I get different behaviours on different devices: Desktop, Ubuntu, Firefox or Chrome: The large gallery images don't load. Mobile, Android, Firefox: The large gallery images load on all pages tested (except for one single image, which did not load). iPad, Safari: The large gallery images don't load. In addition, the thumbnail images first appear and then disappear again, leaving the gallery without images. Cheers, Stefan Link to comment Share on other sites More sharing options...
Recommended Posts