Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by nbcommunication

  1. Hi @Krlos, Apologies for the late reply, I've been on leave. I actually find srcset/sizes quite hard to get my head around, even more so to try and explain its use! I'd recommend having a read over https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images and perhaps https://www.sitepoint.com/how-to-build-responsive-images-with-srcset/ From what you've posted above, Try using a sizes value e.g. sizes="33vw". You may need this to use media queries e.g sizes="(min-width: 640px) 50.00vw, (min-width: 960px) 33.33vw". You should also experiment with a different srcset configuration - you shouldn't need all the variations from the default rules in this case. Some browsers cache the largest resolution image loaded and use it regardless of resolution which makes debugging srcset really tricky. Hope that helps! Cheers, Chris
  2. Hi @totoff, It really depends how you've used the module. I probably wouldn't recommend it unless you have just used the sizes call ($image->srcset) without any additional options in the call. We've got plenty of sites using PageimageSrcset, and almost all of them are just using the srcset call, but I don't plan on changing this as PageimageSrcset works and will continue to. The development of PageimageSource is more about a change in approach, focusing more on extending Pageimage::render(). If you were to attempt a migration, be aware that the majority of the additional functionality of PageimageSrcset is no longer present. It would make sense to tackle a new project with PageimageSource first to get a feel for the differences. Cheers, Chris
  3. Hello, I've just released a new module called PageimageSource which effectively supersedes PageimageSrcset. I've wanted to rewrite this module for a while now, to remove some features that I feel aren't necessary (e.g. UIkit widths / portrait mode), and have a more stripped back module that is more focused on specific functionality. I'd hoped to be able to do this by having a version 2.0.0, indicating breaking changes, but PW doesn't indicate this when upgrading, so the situation where users upgrade and things break would almost certainly happen. I therefore decided to rewrite the module and release it under a different name. I don't expect to do any more work on PageimageSrcset, but will apply any fixes as required. If you are starting from scratch on a project, PageimageSource is the one to use. If you are thinking to migrate a project using PageimageSrcset to PageimageSource, this list of changes should hopefully allow you determine if it is possible: The sizes() method/property has been removed The portrait mode has been removed (still possible through settings though - see the PageimageSource README for an example) UIkit widths -> sizes has been removed All the debug stuff has been removed The render() method behaves differently. It is more geared toward a <picture> implementation (requested by @teppo) Basically if all you've used is the default configuration and the srcset property, migration shouldn't cause any issues. Pretty much any other situation isn't suitable for migration. Cheers, Chris
  4. I've been meaning to revise PageimageSrcset for a while now, to remove some features that I felt were unnecessary and to implement a better rendering strategy. The result is PageimageSource. What does it do? It provides a configurable srcset method/property for Pageimage It allows WebP to be enabled for images it generates. It allows Pageimage:render() to return a <picture> element It provides a Textformatter that replaces <img> elements with the output of Pageimage:render() Although it is based on a current module, this should still be considered beta and not used in production without a prior development stage. Here's the README: PageimageSource Extends Pageimage with a srcset property/method plus additional rendering options. Overview The main purpose of this module is to make srcset implementation as simple as possible in your template code. For an introduction to srcset, please read this Mozilla article about responsive images. Installation Download the zip file at Github or clone the repo into your site/modules directory. If you downloaded the zip file, extract it in your sites/modules directory. In your admin, go to Modules > Refresh, then Modules > New, then click on the Install button for this module. ProcessWire >= 3.0.165 and PHP >= 7.3 are required to use this module. Configuration To configure this module, go to Modules > Configure > PageimageSource. Default Set Rules These are the default set rules that will be used when none are specified, e.g. when calling the property: $image->srcset. Each set rule should be entered on a new line, in the format {width}x{height} {inherentwidth}w|{resolution}x. Not all arguments are required - you will probably find that specifying the width is sufficient for most cases. Here's a few examples of valid set rules and the sets they generate: Set Rule Set Generated Arguments Used 320 image.320x0-srcset.jpg 320w {width} 480x540 image.480x540-srcset.jpg 480w {width}x{height} 640x480 768w image.640x480-srcset.jpg 768w {width}x{height} {inherentwidth}w 2048 2x image.2048x0-srcset.jpg 2x {width} {resolution}x How you configure your rules is dependent on the needs of the site you are developing; there are no prescriptive rules that will meet the needs of most situations. This article gives a good overview of some of the things to consider. When you save your rules, a preview of the sets generated and an equivalent method call will be displayed to the right. Invalid rules will not be used, and you will be notified of this. WebP If enabled, WebP versions of the image and srcset variations will be generated and these will be returned by Pageimage::srcset(). As with the default implementation, the image with the smaller file size is returned. In most cases this is the WebP version, but sometimes can be the source. Make sure to experiment with the quality setting to find a value you find suitable. The default value of 90 is fine, but it is possible that lower values will give you excellent kB savings with little change in overall quality. For more information on WebP implementation please read the blog posts on the ProcessWire website. Rendering These settings control how the output of Pageimage::render() is modified. Use Lazy Loading? When enabled this adds loading="lazy" to the <img> attributes. It is useful to have this on by default, and you can always override it in the options for a specific image. Use the <picture> element? When enabled, the <img> element is wrapped in a <picture> element and <source> elements for original and WebP variations are provided. This requires WebP to be enabled. For more information on what this does, have a look at the examples in Pageimage::render() below. Remove Variations If checked, the image variations generated by this module are cleared on Submit. On large sites, this may take a while. It makes sense to run this after you have made changes to the set rules. Please note that although the module will generate WebP versions of all images if enabled, it will only remove the variations with the 'srcset' suffix. Usage Pageimage::srcset() // The property, which uses the set rules in the module configuration $srcset = $image->srcset; // A method call, using a set rules string // Delimiting with a newline (\n) would also work, but not as readable $srcset = $image->srcset('320, 480, 640x480 768w, 1240, 2048 2x'); // The same as above but using an indexed/sequential array $srcset = $image->srcset([ '320', '480', '640x480 768w', '1240', '2048 2x', ]); // The same as above but using an associative array // No rule checking is performed $srcset = $image->srcset([ '320w' => [320], '480w' => [480], '768w' => [640, 480], '1240w' => [1240], '2x' => [2048], ]); // The set rules above are a demonstration, not a recommendation! Image variations are only created for set rules which require a smaller image than the Pageimage itself. This may still result in a lot of images being generated. If you have limited storage, please use this module wisely. Pageimage::render() This module extends the options available to this method with: srcset: When the module is installed, this will always be added, unless set to false. Any values in the formats described above can be passed. sizes: If no sizes are specified, a default of 100vw is assumed. lazy: Pass true to add loading=lazy, otherwise false to disable if enabled in the module configuration. picture: Pass true to use the <picture> element, otherwise false to disable if enabled in the module configuration. Please refer to the API Reference for more information about this method. // Render an image using the default set rules // WebP and lazy loading are enabled, and example output is given for <picture> disabled and enabled echo $image->render(); // <img src='image.webp' alt='' srcset='image.jpg...' sizes='100vw' loading='lazy'> /* <picture> <source srcset="image.webp..." sizes="100vw" type="image/webp"> <source srcset="image.jpg..." sizes="100vw" type="image/jpeg"> <img src="image.jpg" alt="" loading="lazy"> </picture> */ // Render an image using custom set rules echo $image->render(['srcset' => '480, 1240x640']); // <img src='image.webp' alt='' srcset='image.480x0-srcset.webp 480w, image.1240x640-srcset.webp 1240w' sizes='100vw' loading='lazy'> /* <picture> <source srcset="image.480x0-srcset.webp 480w, image.1240x640-srcset.webp 1240w" sizes="100vw" type="image/webp"> <source srcset="image.480x0-srcset.jpg 480w, image.1240x640-srcset.jpg 1240w" sizes="100vw" type="image/jpeg"> <img src="image.jpg" alt="" loading="lazy"> </picture> */ // Render an image using custom set rules and sizes // Also use the `markup` argument // Also disable lazy loading // In this example the original jpg is smaller than the webp version echo $image->render('<img class="image" src="{url}" alt="Image">', [ 'srcset' => '480, 1240', 'sizes' => '(min-width: 1240px) 50vw', 'lazy' => false, ]); // <img class='image' src='image.jpg' alt='Image' srcset='image.480x0-srcset.webp 480w, image.1240x0-srcset.webp 1240w' sizes='(min-width: 1240px) 50vw'> /* <picture> <source srcset="image.480x0-srcset.webp 480w, image.1240x0-srcset.webp 1240w" sizes="(min-width: 1240px) 50vw" type="image/webp"> <source srcset="image.480x0-srcset.jpg 480w, image.1240x0-srcset.jpg 1240w" sizes="(min-width: 1240px) 50vw" type="image/jpeg"> <img class='image' src='image.jpg' alt='Image'> </picture> */ // Render an image using custom set rules and sizes // These rules will render 'portrait' versions of the image for tablet and mobile // Note the advanced use of the `srcset` option passing both `rules` and image `options` // WebP is disabled // Picture is disabled echo $image->render([ 'srcset' => [ 'rules' => '320x569, 640x1138, 768x1365, 1024, 1366, 1600, 1920', 'options' => [ 'upscaling' => true, 'hidpi' => true, ], ], 'sizes' => '(orientation: portrait) and (max-width: 640px) 50vw', 'picture' => false, ]); // <img src='image.jpg' alt='' srcset='image.320x569-srcset-hidpi.jpg 320w, image.640x1138-srcset-hidpi.jpg 640w, image.768x1365-srcset-hidpi.jpg 768w, image.1024x0-srcset-hidpi.jpg 1024w, image.1366x0-srcset-hidpi.jpg 1366w, image.1600x0-srcset-hidpi.jpg 1600w, image.jpg 1920w' sizes='(orientation: portrait) and (max-width: 768px) 50vw' loading="lazy"> TextformatterPageimageSource Bundled with this module is a Textformatter largely based on TextformatterWebpImages by Ryan Cramer. When applied to a field, it searches for <img> elements and replaces them with the default output of Pageimage::render() for each image/image variation. Assuming a default set of 480, 960 and lazy loading enabled, here are some examples of what would be returned: Example <figure class="align_right hidpi"> <a href="/site/assets/files/1/example.jpg"> <img alt="" src="/site/assets/files/1/example.300x0-is-hidpi.jpg" width="300" /> </a> </figure> WebP enabled <figure class="align_right hidpi"> <a href="/site/assets/files/1/example.jpg"> <img alt="" src="/site/assets/files/1/example.300x0-is-hidpi.webp" width="300" srcset="/site/assets/files/1/example.300x0-is-hidpi.webp 480w" sizes="100vw" loading="lazy" /> </a> </figure> <picture> enabled <figure class="align_right hidpi"> <a href="/site/assets/files/1/example.jpg"> <picture> <source srcset="/site/assets/files/1/example.300x0-is-hidpi.webp 480w" sizes="100vw" type="image/webp"> <source srcset="/site/assets/files/1/example.300x0-is-hidpi.jpg 480w" sizes="100vw" type="image/jpeg"> <img alt="" src="/site/assets/files/1/example.300x0-is-hidpi.jpg" width="300" loading="lazy" /> </picture> </a> </figure> Because the variation is small - 300px wide - the srcset only returns the source image variation at the lowest set width (480w). If the source image was > 1000px wide, there would be a variation at both 480w and 960w. PageimageSrcset This module is built upon work done for PageimageSrcset, which can be considered a first iteration of this module, and is now deprecated. Migration PageimageSource is a simplified version of PageimageSrcset with a different approach to rendering. Most of the features of the old module have been removed. If you were just using $image->srcset(), migration should be possible, as this functionality is essentially the same albeit with some improvements to image variation generation.
  5. Hi @Scar, My apologies, I thought I was getting notifications for this thread but I wasn't! You need to upgrade to PHP 7, PHP 7.3 at a minimum. The spaceship operator <=> that is used is a PHP 7 addition. I'll add this as an installation condition on the module. Cheers, Chris
  6. Hi @cjx2240, I've tried to replicate this without success. I tried adding another account with a valid token from a different account, and I just got the 'User could not be added' response. Adding the second user with an incorrect token should not have resulted in a record being added to the database - I'm sure that this is what has caused the subsequent issues. It sounds like the original user details were partially overwritten with the new (incorrect) ones. No idea how this could've happened. Are there similarities in the usernames/ids? Are the two accounts linked in some way on the IG side? Cheers, Chris
  7. Hi @cjx2240, I've not come across this before. Hoping to have some time toward the end of next week, so will look at it then and see if I can replicate. Cheers, Chris
  8. Hi @Tyssen, No idea why it says that in the README! It does use OAuth. Quick solution if you have access to phpMyAdmin, find the record in the instagram-basic-display-api table and copy it to your local copy. Cheers, Chris
  9. Hi @Tyssen, I never got a bug report submitted yesterday (there's a lot of hoops to jump through). I've just been to check the process again and it has worked for me this time. Can you please try again? You may need to regenerate the access token from inside the Facebook developer admin, but worth trying the one you already have first. Cheers, Chris
  10. Hi @Tyssen, The message that the API is returning when I try to add my own account is "Error validating access token: Session has expired on Saturday, 24-Oct-20 00:35:05 PDT. The current time is Monday, 15-Mar-21 09:08:47 PDT". I tried regenerating the access token and got exactly the same message. This looks to me to be an issue on Facebook's end. I'll submit a bug report and see if they get back to me. Cheers, Chris
  11. Excellent, thanks @fruid, That's the change pushed to the repo as v 1.0.8. Cheers, Chris
  12. Hi @fruid, I've never seen an id attribute on the <title> tag before! Can you please edit line 258 of MarkupContentSecurityPolicy.module to remove the '>'? <?php // Line 258 $node = '<title'; I think that'll fix it. If so I'll push that change to the repo. Cheers, Chris
  13. Hi @Kiwi Chris, There's a lot of Shetland-New Zealand connections! I've an uncle that lives there (in Christchurch I think), and other aunties and uncles have been over to visit. One of our project managers travelled around NZ a few years back too! Cheers, Chris
  14. Hi @Marco Ro, The map uses LeafletJS with two layers, OS Maps (UK only) for the road map, and Mapbox for the satellite. For analytics, we're still experimenting with explicit consent. Matomo has a cookie-less option so theoretically we're able to record every site visit using it, but can only record those that have consented using GA. I really hope Google figure out a cookie-less analytics implementation soon, it is an absolute nuisance! Cheers, Chris
  15. Hi @3fingers, Both a and c are part of an internal (proprietary) GraphQL API implementation. The short explanation is: A GraphQL query is generated from the filters when the form is 'submitted' The GraphQL endpoint is queried and returns results The result is rendered b would take an age to explain properly, but basically the query string ends up in sessionStorage (JS) and the filter strip JS checks this to set the active option(s). When the filter options are changed the sessionStorage values change too so that the state is essentially retained throughout the user session. I can't give you any indication on budget unfortunately. We run the Promote Shetland contract, which is much more than just the website, so the redevelopment project is effectively 'in-house'. Timespan was just short of 6 months (design/development) I think, I wasn't involved in the early stages so can't say exactly when it began, but my involvement as developer started in August and we launched mid-November. Cheers, Chris
  16. Shetland.org is a website run by Promote Shetland which inspires people to visit Shetland, encourages people to move to Shetland to live, work and study, and attracts people to invest in commercial activities in the isles. We (NB Communication) have run the Promote Shetland service on behalf of the Shetland Islands Council since 2017, and as part of the contract undertook a project to redevelop the existing Shetland.org website. In this showcase we’ll highlight a selection of modules we used and what they helped us achieve. Visit the site: www.shetland.org Pro Modules ProCache We use this on almost every site we build. Indispensable. The cache settings used are pretty simple – most templates are set to 1 week, with the entire cache being cleared on save. We use ProCache’s CDN functionality to serve assets from CloudFront via c.shetland.org. We also use the API provided by ProCache to compile (SCSS), minify and collate our styles and scripts via $procache->css() and $procache->js(). We then use the URLs returned to preload the assets, making the site even faster! ProFields: Repeater Matrix Again, we use this on almost every site we build. Another must have Pro module. This module allows us to create a really powerful page builder field (we call it ‘blocks’) that handles the majority of the content on the site. On a simple development, we just use two block types - Content and Images - the latter displaying as a gallery or a slideshow. On this site we have 13 different types, including ‘Quotes’, ‘Video’, ‘Accordion’, and ‘Links’. Additionally many of these are configurable in different ways, and some render in different ways depending on the template and context. Have a look at the links below for some examples: https://www.shetland.org/visit/do/outdoors/walk https://www.shetland.org/blog/how-shetland-inspires-me-artist-ruth-brownlee https://www.shetland.org/life/why/teach-shetland-school NB Modules We also used a number of modules we've authored: Instagram Basic Display API Used to retrieve the 6 latest images from instagram.com/promoteshetland. Markup Content Security Policy Used to implement a CSP for the site. Currently scoring a C on observatory.mozilla.org – not the best score possible but significantly better than all the other destination marketing websites I tested (all got an F but one which was a D-). Pageimage Srcset Used throughout to generate and serve images of different sizes via the srcset and sizes attributes. This module is really useful if you are looking to optimise the serving of images to improve page speed times/scores. Video markup for YouTube/Vimeo This module was developed specifically for use on this website, as we wanted more control over the rendering of the oEmbed data. In the example below, the video thumbnail is displayed with a text overlay – when clicked the video (YouTube embed) opens in a lightbox. And a big shout out to… Page Path History The previous site was also built by us in ProcessWire, but a number of years ago now. The new site has significant changes to the sitemap, but 1000+ blog posts were also migrated. Instead of an .htaccess file with thousands of 301 redirects, we were able to use the functionality provided by this module to implement redirects where required, and in the case of the blog posts which were migrated via an import script, implement the redirects via the API - $page->addUrl(). ... The above is just a fragment of the features present on this site, and the development just a part of a much larger project itself. We're really proud of what we've achieved, and we couldn't have done it without ProcessWire. Cheers, Chris (NB Communication)
  17. Hi @Roych, What is the template (in config) that you're using to output the oEmbed data? Are you using any hooks? Does the page have a og:description tag in the <head> and if so what does this show in the source? Cheers, Chris EDIT - apologies for the late response, was on holiday last week!
  18. Hi @ryan, The new modules directory is looking great and what I've used so far has worked great 🙂 I've a request for you to consider. Would it be possible to mark major version changes as not backwards compatible? The use case: We have a module PageimageSrcset, that contains a number of features that I thought would be useful at the time of writing, but I myself have never/rarely used (e.g. generating the sizes attribute value from an array of UIkit classes). In a future version I'd like to remove these features, and have the module be more in line with its purpose. I have enquired on the board, but not had any response to say that any of the features are being used. The solution as I see it, would be to release a new 2.0.0 version (currently 1.1.0) which removes these features, and any users with 1.1.0 installed would either not be able to upgrade directly (would require manual upload), or would be given an additional warning that the version introduces breaking changes and to check GitHub/support board before upgrading. Is this possible? Cheers, Chris
  19. Hi @Crowdland Technology, Thanks for the feedback! Yes, this would be the case. I'd advise a cache of 1 hour (3600). The request to the API itself isn't heavy, but there is rate limiting on IGs end which a cache time of an hour helps to manage. Yes this is odd, but this is what the Instagram Basic Display API provides. If you request media of the type IMAGE, you also get the poster of media of the type VIDEO and the first image from media of the type CAROUSEL_ALBUM so this is what the module returns. If you only want single image posts, then using getMedia() and then only using items of the type 'IMAGE' is the way to go. getMedia() returns all media, of the three types. IMAGE is accessed through the src property, VIDEO through src (the video) and poster (the thumbnail image) and CAROUSEL_ALBUM through children (all the images in the collection). I think what you're asking here is that if the tester user did have a CAROUSEL_ALBUM, how do you get just the first image from this? <?php foreach ($insta_media as $media): switch($media->type) { case 'VIDEO': $media_src = $media->poster; break; case 'CAROUSEL_ALBUM': // Just get the first item $media_src = $media->children->first->src; break; default: $media_src = $media->src; break; } ?> I haven't tested it, but I'm pretty sure that would get the first image from the album. Worth looking closer at the README as there's a lot there that isn't explicitly explained, but makes sense one you review the code examples 🙂 Hope that helps! Cheers, Chris
  20. Hi @alexmercenary, getImages() returns images, the main carousel album image, and the poster image of videos. To filter these so it is only IMAGEs you could do something like: <?php $images = $modules->get('InstagramBasicDisplayApi')->getImages(); foreach($images as $image) { if($image->type !== 'IMAGE') continue; echo "<img src=$image->src alt=$image->alt>"; } I think that getMedia() is maybe the call you are looking for? https://github.com/nbcommunication/InstagramBasicDisplayApi#getmediastring-username-int-limit Cheers, Chris
  21. Found another one tonight while testing a sandbox install with a lot of Lorem Ipsum.... Wasn't loading a page with the name 'praesent-vel-quam-porttitor-nulla' because of 'null' being in the name. Seems a little extreme, or not very well implemented, but I just removed it from the name as it is unlikely that 'null' would appear in a page name. Worth noting though! Cheers, Chris
  22. Hi, I added the 7G firewall htaccess rules to a site, and was getting errors in the PW admin as JS files were failing to load. The culprit is line 85 (v1.2): RewriteCond %{REQUEST_URI} (/)((php|web)?shell|conf(ig)?|crossdomain|fileditor|locus7|nstview|php(get|remoteview|writer)|r57|remview|sshphp|storm7|webadmin)(.*)(\.|\() [NC,OR] It is the conf(ig) part that prevents some PW admin JS files from being loaded (e.g. /wire/modules/AdminTheme/AdminThemeUikit/config-field.js). I removed this so the line becomes: RewriteCond %{REQUEST_URI} (/)((php|web)?shell|crossdomain|fileditor|locus7|nstview|php(get|remoteview|writer)|r57|remview|sshphp|storm7|webadmin)(.*)(\.|\() [NC,OR] Hopefully this will same some future users of the 7G firewall some time! If you come across any other issues using 7G with PW, please post them here! Cheers, Chris
  23. Hi @Roych, If CKEditor is automatically making a <a>link</a> when you paste in the URL, then you need to unlink it using that option from the toolbar (chain icon with the cross in the bottom right). Cheers, Chris
  24. Hi @Roych, Thanks - the issue is the link. Both this and TextformatterVideoEmbed don't work on <a>links</a>, only plain URLs inside <p> tags. If you remove that it'll work *hopefully*! Cheers, Chris
  25. Hi @Roych, I think I know what the issue might be, and I may add a config option to prevent it. Answers to the following should clarify: In the Details tab of your body field is Content Type set to Markup/HTML? (it was on the screenshot you posted, but I note that the CKEditor iframe method requires this to be set to unknown). When you paste directly into CKEditor, what source HTML is generated for that line? Conversely, if you paste into the source code, then come out of the dialog, then go back in, what source HTML is generated for the line? Cheers, Chris
  • Create New...