Jump to content
nbcommunication

PageimageSrcset

Recommended Posts

I've spent the last while experimenting with srcset implementation - and PageimageSrcset is the result:

PageimageSrcset

Provides configurable srcset and sizes properties/methods for Pageimage.

Overview

The main purpose of this module is to make srcset implementation as simple as possible in your template code. It does not handle images rendered in CKEditor or similar fields.

For an introduction to srcset and sizes, please read this Mozilla article about responsive images.

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],
]);

// Use the default set rules with portrait images generated for mobile/tablet devices
$srcset = $image->srcset(true);

// Return the srcset using all arguments
$srcset = $image->srcset("320, 480, 640x480 768w, 1240, 2048 2x", [
	"portrait" => "320, 640",
]);

// 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. On large sites this may still result in a lot of images being generated. If you have limited storage, please use this module wisely.

Portrait Mode

In many situations, the ratio of the image does not need to change at different screen sizes. However, images that cover the entire viewport are an exception to this and are often the ones that benefit most from srcset implementation.

The main problem with cover images is that they need to display landscape on desktop devices and portrait when this orientation is used on mobile and tablet devices.

You can automatically generate portrait images by enabling portrait mode. It is recommended that you use this in combination with Pageimage::focus() so that the portrait variations retain the correct subject.

The generated variations are HiDPI/Retina versions. Their height is determined by the portrait ratio (e.g. 9:16). Variations are always generated, regardless of whether the original image is smaller. Upscaling is disabled though, so you may find that some variations are actually smaller than they say they are in their filename.

The sizes attribute should be used when portrait mode is enabled. Pageimage::sizes will return (orientation: portrait) and (max-width: {maxWidth}px) 50vw by default, which handles the use of these images for retina devices. The maximum width used in this rule is the largest set width.

Pageimage::sizes()

There is no option to configure default sizes because in most cases 100vw is all you need, and you do not need to output this anyway as it is inferred when using the srcset attribute. You can use the method for custom sizes though:

// The property
$sizes = $image->sizes;
// Returns 100vw in most cases
// Returns '(orientation: portrait) and (max-width: {maxWidth}px)50vw' if portrait mode enabled

// A method call, using a mixture of integer widths and media query rules
// Integer widths are treated as a min-width media query rule
$sizes = $image->sizes([
	480 => 50,
	"(orientation: portrait) and (max-width: 640px)" => 100,
	960 => 25,
]);
// (min-width: 480px) 50vw, (orientation: portrait) and (max-width: 640px) 100vw, (min-width: 960px) 25vw

// Determine widths by UIkit 'child-width' classes
$sizes = $image->sizes([
	"uk-child-width-1-2@s",
	"uk-child-width-1-3@l",
]);
// (min-width: 640px) 50vw, (min-width: 1200px) 33.33vw

// Determine widths by UIkit 'width' classes
$sizes = $image->sizes([
	"uk-width-1-2@m",
	"uk-width-1-3@xl",
]);
// (min-width: 960px) 50vw, (min-width: 1600px) 33.33vw

// Return the portrait size rule
$sizes = $image->sizes(true);
// (orientation: portrait) and (max-width: {maxWidth}px) 50vw

// The arguments above are a demonstration, not a recommendation!

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: Only used if specified. Any values in the formats described above can be passed.
  • uk-img: If passed, as either true or as a valid uk-img value, then this attribute will be added. The srcset attribute will also become data-srcset.

Please refer to the API Reference for more information about this method.

// Render an image using the default set rules
echo $image->render();
// <img src='image.jpg' alt='' srcset='{default set rules}'>

// Render an image using custom set rules
echo $image->render(["srcset" => "480, 1240x640"]);
// <img src='image.jpg' alt='' srcset='image.480x0-srcset.jpg 480w, image.1240x640-srcset.jpg 1240w'>

// Render an image using custom set rules and sizes
// Also use the `markup` argument
echo $image->render("<img class='image' src='{url}' alt='Image'>", [
	"srcset" => "480, 1240",
	"sizes" => [1240 => 50],
]);
// <img class='image' src='image.jpg' alt='Image' srcset='image.480x0-srcset.jpg 480w, image.1240x640-srcset.jpg 1240w' sizes='(min-width: 1240px) 50vw'>

// Render an image using custom set rules and sizes
// Enable uk-img
echo $image->render([
	"srcset" => "480, 1240",
	"sizes" => ["uk-child-width-1-2@m"],
	"uk-img" => true,
]);
// <img src='image.jpg' alt='' data-uk-img data-srcset='image.480x0-srcset.jpg 480w, image.1240x640-srcset.jpg 1240w' sizes='(min-width: 960px) 50vw'>

// Render an image using portrait mode
// Default rule sets used: 320, 640, 768, 1024, 1366, 1600
// Portrait widths used: 320, 640, 768
// Original image is 1000px wide
// Not possible to use portrait mode and custom sets or portrait widths in render()
// Sizes attribute automatically added
echo $image->render(["srcset" => true]);
// <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.jpg 1024w' sizes='(orientation: portrait) and (max-width: 768px) 50vw'>

Configuration

To configure this module, go to Modules > Configure > PageimageSrcset.

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.

Portrait Mode

Set Widths

A comma limited list of widths to create HiDPI/Retina portrait variations for.

Crop Ratio

The portrait ratio that should be used to crop the image. The default of 9:16 should be fine for most circumstances as this is the standard portrait ratio of most devices. However, you can specify something different if you want. If you add a landscape ratio, it will be switched to portrait when used.

Any crops in the set rules ({width}x{height}) are ignored for portrait mode variations as this ratio is used instead.

UIkit Widths

If your website theme uses UIkit, you can pass an array of UIkit width classes to Pageimage::sizes to be converted to sizes. The values stored here are used to do this. If you have customised the breakpoints on your theme, you should also customise them here.

Please note that only 1- widths are evaluated by Pageimage::sizes, e.g. uk-width-2-3 will not work.

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.

Image Suffix

You will see this field when Remove Variations is checked. The value is appended to the name of the images generated by this module and is used to identify variations. You should not encounter any issues with the default suffix, but if you find that it conflicts with any other functionality on your site, you can set a custom suffix instead.

Debug Mode

When this is enabled, a range of information is logged to pageimage-srcset.

PageimageSrcsetDebug.js is also added to the <head> of your HTML pages. This will console.log a range of information about the images and nodes using srcset on your page after a window.onresize event is triggered. This can assist you in debugging your implementation.

The browser will always use the highest resolution image it has loaded or has cached. You may need to disable browser caching to determine whether your set rules are working, and it makes sense to work from a small screen size and up. If you do it the other way, the browser is going to continue to use the higher resolution image it loaded first.

UIkit Features

This module implements some additional features that are tailored towards UIkit being used as the front-end theme framework, but this is not required to use the module.

Installation

  1. Download the zip file at Github or clone the repo into your site/modules directory.
  2. If you downloaded the zip file, extract it in your sites/modules directory.
  3. In your admin, go to Modules > Refresh, then Modules > New, then click on the Install button for this module.

ProcessWire >= 3.0.123 is required to use this module.

  • Like 17
  • Thanks 2

Share this post


Link to post
Share on other sites

@nbcommunication what a great module! Thank you.

Just a quick one:

I've noticed that in the renderImageSrcset() method you are setting the uk-img attribute as data-uk-img but I'm pretty certain it should in fact be uk-img as this is what I've always used and is stated in the documents here: https://getuikit.com/docs/image

Update: Also, I've noticed that if you are using uk-img it outputting data-srcset as well as srcset. The srcset should be omitted as uk-img adds the srcset attribute when required.

Edited by alexmercenary
Update

Share this post


Link to post
Share on other sites

Hi @alexmercenary,

"uk-img" doesn't validate as HTML5. I always use the data- prefix for this reason, it's one of the ways to use UIkit components: https://getuikit.com/docs/javascript#component-usage.

As for the srcset attribute - I think they've updated the docs here, they had it without the data- prefix until recently. I'll update this when I get a chance - the current implementation will still work.

Cheers,

Chris

Share this post


Link to post
Share on other sites

@nbcommunication ok cool. That's interetsing. Yeah, I've noticed this, it's due to the lack of img src tag when using uk-img isn't it?

But what I noticed when I used data- prefix is that the images weren't lazy loading when checking the waterfall on the network panel and scrolling down the page.

Share this post


Link to post
Share on other sites

Hi @alexmercenary - aye I didn't have the "uk-img" enabled by way of the data-src attribute. I've fixed that now, should be on the repo.

Worth noting that enabling uk-img changes the src attribute to data-src, and adds a src attribute with a blank pixel: src='data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='. The src attribute is required for valid HTML5, so I've been in the habit of adding this blank pixel for this purpose.

  • Like 1

Share this post


Link to post
Share on other sites

With the default settings, running this:

echo $page->image->render(["srcset" => true, "uk-img" => true]);

Outputs this:

<img src='/myprocesswire/site/assets/files/1/la1.jpg' alt='' data-uk-img data-srcset='/myprocesswire/site/assets/files/1/la1.320x569-srcset-hidpi.jpg 320w, /myprocesswire/site/assets/files/1/la1.640x1138-srcset-hidpi.jpg 640w, /myprocesswire/site/assets/files/1/la1.768x1365-srcset-hidpi.jpg 768w, /myprocesswire/site/assets/files/1/la1.1024x557-srcset.jpg 1024w, /myprocesswire/site/assets/files/1/la1.2048x1115-srcset.jpg 2x' sizes='(orientation: portrait) and (max-width: 768px) 50vw'>

Notice how "src" is not "data-src" as per UIkit's documentation:
https://getuikit.com/docs/image#srcset

As a result, according to Chrome DevTools network graph, 2 images are loaded as in the attached screenshot.

Shouldn't 'data-' be added to 'src' in UIkit mode?

2019-11-20_11-25-23.png

Share this post


Link to post
Share on other sites

Hi @Jonathan Lahijani,

I'm not seeing this with the latest version (0.0.7) - I get the data-src attribute and the src attribute is the blank pixel gif:

<img data-src='/site/assets/files/1033/placeholder-city.webp' alt='' data-uk-img src='data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==' data-srcset='/site/assets/files/1033/placeholder-city.320x569-srcset-hidpi.jpg 320w, /site/assets/files/1033/placeholder-city.640x1138-srcset-hidpi.jpg 640w, /site/assets/files/1033/placeholder-city.768x1365-srcset-hidpi.jpg 768w, /site/assets/files/1033/placeholder-city.webp 1024w' data-sizes='(orientation: portrait) and (max-width: 768px) 50vw'>

It isn't actually necessary to pass "srcset" as true by the way. This is actually telling the module to use portrait mode:

echo $page->image->render(["uk-img" => true]);
// Should return the above <img> tag but without the "sizes" attribute.

The render() method is a bit limited unfortunately - you can't access all the options that can be accessed by using $page->image->srcset() and $page->image->sizes(). However, what you are trying to do should work - are you on the latest version?

Cheers,

Chris

Share this post


Link to post
Share on other sites

Hey @nbcommunication!

Just wondering: do you think it would make sense to implement picture support into this module, or do you see that as a completely unrelated thing? 🙂

The background is that I'm currently looking into ways of handling webp+srcset. Since IE and Safari don't support webp, a fallback is necessary, yet none of the .htaccess fallback solutions are (in my opinion) really up to the task. Every solution I've found so far comes with drawbacks that would eventually cause issues for our clients.

Best solution so far seems to be <picture> with fallback <img> element. I could build a (very simple) markup module that just outputs the picture element for me (it's not a whole lot of boilerplate, but still a bit bothersome to write all over the place), but then it occurred to me that since I'm going to need this module anyway, wouldn't it be awesome if I could just call Pageimage::render() and this module would handle the rest.

What do you think? 😅

Share this post


Link to post
Share on other sites

Hi @teppo,

I've not used <picture> myself, so will need time to do a bit of research. Off the top of my head though, I do feel that this module wouldn't necessarily be the best place for it.

When I get a chance I'll have a think through the implications.

Cheers,

Chris

  • Like 1

Share this post


Link to post
Share on other sites

Hello @nbcommunication,

Thank you for this module. I'm using it to generate all the images on my website I'm building. Using hannacode, I'm even using it to generate the img markup from a textarea (like the blog_body) which is pretty neat!

I'm wondering if you could consider incorporating an option where instead of pointing the src to the original jpeg file, the module would instead use one of the srcset images that it generated (maybe the largest setting or the user selectable size)? The reason why I'm interested in this option is that my original images are very large and I've currently disallowed access to the original jpeg (using htaccess lockout that I found in this forum). I plan to have a download original image later on for customers so that why I need the original image on the website.

Is this doable? Thank you for reading.

Regards,

montero4

Share this post


Link to post
Share on other sites

Hi @montero4,

Can you please give a code example? From your description, it seems to me that all you need to do is resize the pageimage before rendering/getting attributes.

Cheers,

Chris

Share this post


Link to post
Share on other sites

@teppo, having read a bit about <picture>, it probably would make sense to provide this functionality in the module, but possibly as a separate method distinct from render(). 

I’ve got a fair bit I want to do on this module, but it’s behind a lot of other work at the moment. I’ll add this to the todo list, but for the time being, I would go with writing something for your own use. 

Cheers,

Chris

Share this post


Link to post
Share on other sites

Thanks @nbcommunication, makes sense!

If I happen to find time for this I might send you a pull request for this feature, but no pressure – I've got plenty of stuff on my plate as well, and even if I do send such a PR, it's perfectly fine if you don't think the suggested solution is good enough... 😛

  • Like 1

Share this post


Link to post
Share on other sites

For folk using the module - is the configuration of sets in the textarea working OK for you? I've been mulling over trying to build something a bit more user-friendly, like a kind of repeater field for entering data, but I'm not convinced that it would actually be easier to work with, particularly as I usually only enter an image width per line and that's it.

In a future version I want to add the configuration on a per-field basis (maybe even per-image even though that would be overkill), so I want to get the configuration method as solid as possible first.

Perhaps retaining the textarea, but with a live preview would be the best option?

I'm also not sure whether it is useful to have portrait mode and UIkit widths as config options. Ultimately the module is meant to extend Pageimage so that srcset and sizes can be used - I feel these config options are a result of my own bias in how I use the module, and yet I don't think I've used the portrait option at all!

Any ideas/thoughts you have, please come with them!

Cheers,

Chris

  • Like 1

Share this post


Link to post
Share on other sites
19 hours ago, nbcommunication said:

Hi @montero4,

Can you please give a code example? From your description, it seems to me that all you need to do is resize the pageimage before rendering/getting attributes.

Hello @nbcommunication,

Here is a sample output being rendered on the page

<img src="/site/assets/files/1633/ve08195.jpg" alt="Beach Resort" srcset="/site/assets/files/1633/ve08195.480x181-srcset.jpg 480w, /site/assets/files/1633/ve08195.1240x468-srcset.jpg 1240w" sizes="(orientation: portrait) and (max-width: 768px) 50vw">
 

I wonder if instead of using "/site/assets/files/1633/ve08195.jpg" as the src, there could be a user selectable option to use the max size for the src, as in "/site/assets/files/1633/ve08195.1240x468-srcset.jpg" instead? It might also make sense for user to maybe select the smallest size if that works with some lazy loading scripts that does progressive loading(?).

Currently in my setup, the original image cannot be accessed if the user attempts to paste the actual address on the browser. I wonder what the SEO impact is of doing this, so I'm not completely happy with this current setup... However...last night, I actually figured out a way to assemble the markup for <img> using some string manipulations on the output of the your module (although I haven't implemented it yet), so maybe my original request is no longer necessary? It would be easier though if the module had this option out of the box.

Thank you and regards,

 

Share this post


Link to post
Share on other sites
5 hours ago, nbcommunication said:

For folk using the module - is the configuration of sets in the textarea working OK for you?

I'm also not sure whether it is useful to have portrait mode and UIkit widths as config options.

I thought based on the module overview that you had that "It does not handle images rendered in CKEditor or similar fields." So with your question above, does it work on the textarea? I'm completely new to PW and php/html/css so maybe I'm misunderstanding your question. If yes, please ignore and no need to reply :-) I'm using hannacode in the ckeditor textarea to generate the srcset and it's working fine for me. My size settings are still not final, but it's so easy to change later so I'm not worried. I could also delete all the past srcset images using your module (that's why I love your module and I'm using it to generate all the image markup on the website). If I need a different srcset configuration set, I could always create a different hannacode, so I think it's going to be fine.

I haven't read enough on the portrait mode to know if I'm going to use this feature.

Regards,

Edited by montero4
too rushed in my reply.

Share this post


Link to post
Share on other sites
On 2/1/2020 at 2:28 AM, montero4 said:

Hello @nbcommunication,

Here is a sample output being rendered on the page

<img src="/site/assets/files/1633/ve08195.jpg" alt="Beach Resort" srcset="/site/assets/files/1633/ve08195.480x181-srcset.jpg 480w, /site/assets/files/1633/ve08195.1240x468-srcset.jpg 1240w" sizes="(orientation: portrait) and (max-width: 768px) 50vw">

I wonder if instead of using "/site/assets/files/1633/ve08195.jpg" as the src, there could be a user selectable option to use the max size for the src, as in "/site/assets/files/1633/ve08195.1240x468-srcset.jpg" instead? It might also make sense for user to maybe select the smallest size if that works with some lazy loading scripts that does progressive loading(?).

 

Hi @montero4,

I'm sorry, I'm still not following? There's nothing stopping you changing the src - you should resize the image first:

// Get the image
$image = $page->images->first;

// Resize the image
$image = $image->size(1024, 468);

// Output the image
echo "<img src='$image->url' alt='$image->description' srcset='$image->srcset'>";

// Or alternatively
echo $image->render();

PageimageSrcset recognises that it is an image variation and then uses the original to generate srcset variations.

It isn't really this module's job to handle the src attribute. In theory you could do some manipulations of the "srcset" value to extract the first or last image for use, but I'd say it is a lot cleaner just to resize the image.

Cheers,

Chris

  • Like 1

Share this post


Link to post
Share on other sites

Hi @nbcommunication

Thank you for your reply. That's a neat solution. I didn't realize that if you resized or manipulated an image, it's -that- variation image that gets used as the src in the <img> tag. That actually makes sense. However, in my case, that approach wouldn't work because I'm disallowing access to the original jpeg images through an htaccess lockout method posted by horst in this forum. The way that method works is that it disallows all access to .jpeg files unless it has a certain suffix (like -piacontain, -pim2-full,-blogthumb, etc.). I want the jpegs to therefore have the "-srcset" suffix so that it is accessible.

Here's the solution I came up with for future reference as the approach might help other people.

	//assemble img markup
    $image = $page->image;
    $string = $image->srcset("1200"); //create srcset of image 1200px wide
    $address = explode(" ", $string);
    $address = $address[0];
    
    //create srcset using pageimagesrcset module default settings
    $srcset = $image->srcset;
    
    echo "<img src=\"$address\" alt=\"$alt_text\" srcset=\"$srcset\">";


	The result of above code:

	<img src="/pw/site/assets/files/1070/test.1200x619-srcset.jpg" alt="alt_test" srcset="/pw/site/assets/files/1070/test.320x165-srcset.jpg 320w, /pw/site/assets/files/1070/test.640x330-srcset.jpg 640w, /pw/site/assets/files/1070/test.768x480-srcset.jpg 960w, /pw/site/assets/files/1070/test.1200x619-srcset.jpg 1200w">

This approach works and the htaccess gatekeeper lets the image request go through, but if a user attempts to access test.jpg directly, then it will not pass through. Thank you for module. As mentioned, I'm using it to serve all the images on my website.

Regards,

  • Like 2

Share this post


Link to post
Share on other sites

Hi @montero4,

That all makes sense. You can also do the following:

// Create an image variation 1200px wide with -srcset suffix
$image = $page->image->width(1200, ["suffix" => "srcset"]);
echo "<img src='$image->url' alt='$alt_text' srcset='$image->srcset'>";
// PageimageSrcset will use the original to generate the srcset value

If you have a look at the Pageimage options, you can add a suffix to the filename when resizing.

Cheers,

Chris

  • Like 2

Share this post


Link to post
Share on other sites

I have two questions:

1. Why does this code:

$content .= $img->render([
    'alt'=> $img->name,
    'height' => $img->height,
    'width' => $img->width,
    'srcset' => '883, 687, 369',
    ]);

generate this where I have the portrait sizes setting even though I haven't set the portrait mode on?

<img src="/site/assets/files/1185/image.691x499.jpg" 
    alt="image" 
    srcset="/site/assets/files/1185/image.369x266-srcset.jpg 369w,
            /site/assets/files/1185/image.687x496-srcset.jpg 687w, 
            /site/assets/files/1185/image.jpg 883w" 
    sizes="(orientation: portrait) and (max-width: 768px) 50vw">

How is the portrait mode set on? I think, it needs 

'portrait' => true
or
srcset('true')

2. render should extend PageImage::render, but  the width or height attributes don't remain in my code with the above example. Why is that?

Share this post


Link to post
Share on other sites

Hi @lpa,

Apologies for the late response. I've had a look at this...

Number 2 - width and height attributes not rendering - this isn't anything to do with PageimageSrcset. These options, when passed to Pageimage::render(), resize the image, but don't get rendered as attributes. If you want this behaviour, adding a markup option should do the trick:

$content .= $img->render([
    'alt'=> $img->name,
    'height' => $img->height,
    'width' => $img->width,
    'srcset' => '883, 687, 369',
	'markup' => "<img src='{url}' alt='{alt}' width='{width}' height='{height}' />"
    ]);

As for portrait mode, I'm not getting this when I test. I get:

<img 
     src='/site/assets/files/1033/placeholder-city.691x499.1000x667.webp'
     alt='placeholder-city.jpg'
     srcset='
             /site/assets/files/1033/placeholder-city.369x266-srcset.webp 369w,
             /site/assets/files/1033/placeholder-city.687x496-srcset.webp 687w,
             /site/assets/files/1033/placeholder-city.691x499.webp 883w'
>

In your example, the image isn't being resized as portrait, so it is odd that the sizes attribute is being added.

What settings do you have in the module config for Portrait mode? Are you on the latest version of the module (1.01)?

Cheers,

Chris

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By teppo
      Needed a really simple solution to embed audio files within page content and couldn't find a module for that, so here we go. Textformatter Audio Embed works a bit like Textformatter Video Embed, converting this:
      <p>https://www.domain.tld/path/to/file.mp3</p> Into this:
      <audio controls class="TextformatterAudioEmbed"> <source src="https://www.domain.tld/path/to/file.mp3" type="audio/mpeg"> </audio> The audio element has pretty good browser support, so quite often this should be enough to get things rolling 🙂
      GitHub repository: https://github.com/teppokoivula/TextformatterAudioEmbed Modules directory: https://modules.processwire.com/modules/textformatter-audio-embed/
    • By Richard Jedlička
      Tense    
      Tense (Test ENvironment Setup & Execution) is a command-line tool to easily run tests agains multiple versions of ProcessWire CMF.
      Are you building a module, or a template and you need to make sure it works in all supported ProcessWire versions? Then Tense is exactly what you need. Write the tests in any testing framework, tell Tense which ProcessWire versions you are interested in and it will do the rest for you.

      See example or see usage in a real project.
      How to use?
      1. Install it: 
      composer global require uiii/tense 2. Create tense.yml config:
      tense init 3. Run it:
      tense run  
      For detailed instructions see Github page: https://github.com/uiii/tense
       
      This is made possible thanks to the great wireshell tool by @justb3a, @marcus and others.
       
      What do you think about it? Do you find it useful? Do you have some idea? Did you find some bug? Tell me you opinion. Write it here or in the issue tracker.
    • By Chris Bennett
      Hi all, I am going round and round in circles and would greatly appreciate if anyone can point me in the right direction.
      I am sure I am doing something dumb, or missing something I should know, but don't. Story of my life 😉

      Playing round with a module and my basic problem is I want to upload an image and also use InputfieldMarkup and other Inputfields.
      Going back and forth between trying an api generated page defining Fieldgroup, Template, Fields, Page and the InputfieldWrapper method.

      InputfieldWrapper method works great for all the markup stuff, but I just can't wrap my head around what I need to do to save the image to the database.
      Can generate a Field for it (thanks to the api investigations) but not sure what I need to do to link the Inputfield to that. Tried a lot of stuff from various threads, of varying dates without luck.
      Undoubtedly not helped by me not knowing enough.

      Defining Fieldgroup etc through the api seems nice and clean and works great for the images but I can't wrap my head around how/if I can add/append/hook the InputfieldWrapper/InputfieldMarkup stuff I'd like to include on that template as well. Not even sure if it should be where it is on ___install with the Fieldtype stuff or later on . Not getting Tracy errors, just nothing seems to happen.
      If anyone has any ideas or can point me in the right direction, that would be great because at the moment I am stumbling round in the dark.
       
      public function ___install() { parent::___install(); $page = $this->pages->get('name='.self::PAGE_NAME); if (!$page->id) { // Create fieldgroup, template, fields and page // Create new fieldgroup $fmFieldgroup = new Fieldgroup(); $fmFieldgroup->name = MODULE_NAME.'-fieldgroup'; $fmFieldgroup->add($this->fields->get('title')); // needed title field $fmFieldgroup->save(); // Create new template using the fieldgroup $fmTemplate = new Template(); $fmTemplate->name = MODULE_NAME; $fmTemplate->fieldgroup = $fmFieldgroup; $fmTemplate->noSettings = 1; $fmTemplate->noChildren = 1; $fmTemplate->allowNewPages = 0; $fmTemplate->tabContent = MODULE_NAME; $fmTemplate->noChangeTemplate = 1; $fmTemplate->setIcon(ICON); $fmTemplate->save(); // Favicon source $fmField = new Field(); $fmField->type = $this->modules->get("FieldtypeImage"); $fmField->name = 'fmFavicon'; $fmField->label = 'Favicon'; $fmField->focusMode = 'off'; $fmField->gridMode = 'grid'; $fmField->extensions = 'svg png'; $fmField->columnWidth = 50; $fmField->collapsed = Inputfield::collapsedNever; $fmField->setIcon(ICON); $fmField->addTag(MODULE_NAME); $fmField->save(); $fmFieldgroup->add($fmField); // Favicon Silhouette source $fmField = new Field(); $fmField->type = $this->modules->get("FieldtypeImage"); $fmField->name = 'fmFaviconSilhouette'; $fmField->label = 'SVG Silhouette'; $fmField->notes = 'When creating a silhouette/mask svg version for Safari Pinned Tabs and Windows Tiles, we recommend setting your viewbox for 0 0 16 16, as this is what Apple requires. In many cases, the easiest way to do this in something like illustrator is a sacrificial rectangle with no fill, and no stroke at 16 x 16. This forces the desired viewbox and can then be discarded easily using something as simple as notepad. Easy is good, especially when you get the result you want without a lot of hassle.'; $fmField->focusMode = 'off'; $fmField->extensions = 'svg'; $fmField->columnWidth = 50; $fmField->collapsed = Inputfield::collapsedNever; $fmField->setIcon(ICON); $fmField->addTag(MODULE_NAME); $fmField->save(); $fmFieldgroup->add($fmField); // Create: Open Settings Tab $tabOpener = new Field(); $tabOpener->type = new FieldtypeFieldsetTabOpen(); $tabOpener->name = 'fmTab1'; $tabOpener->label = "Favicon Settings"; $tabOpener->collapsed = Inputfield::collapsedNever; $tabOpener->addTag(MODULE_NAME); $tabOpener->save(); // Create: Close Settings Tab $tabCloser = new Field(); $tabCloser->type = new FieldtypeFieldsetClose; $tabCloser->name = 'fmTab1' . FieldtypeFieldsetTabOpen::fieldsetCloseIdentifier; $tabCloser->label = "Close open tab"; $tabCloser->addTag(MODULE_NAME); $tabCloser->save(); // Create: Opens wrapper for Favicon Folder Name $filesOpener = new Field(); $filesOpener->type = new FieldtypeFieldsetOpen(); $filesOpener->name = 'fmOpenFolderName'; $filesOpener->label = 'Wrap Folder Name'; $filesOpener->class = 'inline'; $filesOpener->collapsed = Inputfield::collapsedNever; $filesOpener->addTag(MODULE_NAME); $filesOpener->save(); // Create: Close wrapper for Favicon Folder Name $filesCloser = new Field(); $filesCloser->type = new FieldtypeFieldsetClose(); $filesCloser->name = 'fmOpenFolderName' . FieldtypeFieldsetOpen::fieldsetCloseIdentifier; $filesCloser->label = "Close open fieldset"; $filesCloser->addTag(MODULE_NAME); $filesCloser->save(); // Create Favicon Folder Name $fmField = new Field(); $fmField->type = $this->modules->get("FieldtypeText"); $fmField->name = 'folderName'; $fmField->label = 'Favicon Folder:'; $fmField->description = $this->config->urls->files; $fmField->placeholder = 'Destination Folder for your generated favicons, webmanifest and browserconfig'; $fmField->columnWidth = 100; $fmField->collapsed = Inputfield::collapsedNever; $fmField->setIcon('folder'); $fmField->addTag(MODULE_NAME); $fmField->save(); $fmFieldgroup->add($tabOpener); $fmFieldgroup->add($filesOpener); $fmFieldgroup->add($fmField); $fmFieldgroup->add($filesCloser); $fmFieldgroup->add($tabCloser); $fmFieldgroup->save(); /////////////////////////////////////////////////////////////// // Experimental Markup Tests $wrapperFaviconMagic = new InputfieldWrapper(); $wrapperFaviconMagic->attr('id','faviconMagicWrapper'); $wrapperFaviconMagic->attr('title',$this->_('Favicon Magic')); // field show info what $field = $this->modules->get('InputfieldMarkup'); $field->name = 'use'; $field->label = __('How do I use it?'); $field->collapsed = Inputfield::collapsedNever; $field->icon('info'); $field->attr('value', 'Does this even begin to vaguely work?'); $field->columnWidth = 50; $wrapperFaviconMagic->add($field); $fmTemplate->fields->add($wrapperFaviconMagic); $fmTemplate->fields->save(); ///////////////////////////////////////////////////////////// // Create page $page = $this->wire( new Page() ); $page->template = MODULE_NAME; $page->parent = $this->wire('pages')->get('/'); $page->addStatus(Page::statusHidden); $page->title = 'Favicons'; $page->name = self::PAGE_NAME; $page->process = $this; $page->save(); } }  
    • By Sebi
      Since it's featured in ProcessWire Weekly #310, now is the time to make it official:
      Here is Twack!
      I really like the following introduction from ProcessWire Weekly, so I hope it is ok if I use it here, too. Look at the project's README for more details!
      Twack is a new — or rather newish — third party module for ProcessWire that provides support for reusable components in an Angular-inspired way. Twack is implemented as an installable module, and a collection of helper and base classes. Key concepts introduced by this module are:
      Components, which have separate views and controllers. Views are simple PHP files that handle the output for the component, whereas controllers extend the TwackComponent base class and provide additional data handling capabilities. Services, which are singletons that provide a shared service where components can request data. The README for Twack uses a NewsService, which returns data related to news items, as an example of a service. Twack components are designed for reusability and encapsulating a set of features for easy maintainability, can handle hierarchical or recursive use (child components), and are simple to integrate with an existing site — even when said site wasn't originally developed with Twack.
      A very basic Twack component view could look something like this:
      <?php namespace ProcessWire; ?> <h1>Hello World!</h1> And here's how you could render it via the API:
      <?php namespace Processwire; $twack = $modules->get('Twack'); $hello = $twack->getNewComponent('HelloWorld'); ?> <html> <head> <title>Hello World</title> </head> <body> <?= $hello->render() ?> </body> </html> Now, just to add a bit more context, here's a simple component controller:
      <?php namespace ProcessWire; class HelloWorld extends TwackComponent { public function __construct($args) { parent::__construct($args); $this->title = 'Hello World!'; if(isset($args['title'])) { $this->title = $args['title']; } } } As you can see, there's not a whole lot new stuff to learn here if you'd like to give Twack a try in one of your projects. The Twack README provides a really informative and easy to follow introduction to all the key concepts (as well as some additional examples) so be sure to check that out before getting started. 
      Twack is in development for several years and I use it for every new project I build. Also integrated is an easy to handle workflow to make outputs as JSON, so it can be used to build responses for a REST-api as well. I will work that out in one section in the readme as well. 
      If you want to see the module in an actual project, I have published the code of www.musical-fabrik.de in a repository. It runs completely with Twack and has an app-endpoint with ajax-output as well.
      I really look forward to hear, what you think of Twack🥳!
      Features Installation Usage Quickstart: Creating a component Naming conventions & component variants Component Parameters directory page parameters viewname Asset handling Services Named components Global components Ajax-Output Configuration Versioning License Changelog
    • By Robin S
      Page Reference Default Value
      Most ProcessWire core inputfield types that can be used with a Page Reference field support a "Default value" setting. This module extends support for default values to the following core inputfield types:
      Page List Select Page List Select Multiple Page Autocomplete (single and multiple) Seeing as these inputfield types only support the selection of pages a Page List Select / Page List Select Multiple is used for defining the default value instead of the Text / Textarea field used by the core for other inputfield types. This makes defining a default value a bit more user-friendly.
      Note that as per the core "Default value" setting, the Page Reference field must be set to "required" in order for the default value to be used.
      Screenshot

       
      https://github.com/Toutouwai/PageReferenceDefaultValue
      https://modules.processwire.com/modules/page-reference-default-value/
×
×
  • Create New...