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 David Karich
      ProcessWire InputfieldRepeaterMatrixDuplicate
      Thanks to the great ProModule "RepeaterMatrix" I have the possibility to create complex repeater items. With it I have created a quite powerful page builder. Many different content modules, with many more possible design options. The RepeaterMatrix module supports the cloning of items, but only within the same page. Now I often have the case that very design-intensive pages and items are created. If you want to use a content module on a different page (e.g. in the same design), you have to rebuild each item manually every time.
      This module extends the commercial ProModule "RepeaterMatrix" by the function to duplicate repeater items from one page to another page. The condition is that the target field is the same matrix field from which the item is duplicated. This module is currently understood as proof of concept. There are a few limitations that need to be considered. The intention of the module is that this functionality is integrated into the core of RepeaterMatrix and does not require an extra module.
      Check out the screencast
      What the module can do
      Duplicate multible repeater items from one page to another No matter how complex the item is Full support for file and image fields Multilingual support Support of Min and Max settings Live synchronization of clipboard between multiple browser tabs. Copy an item and simply switch the browser tab to the target page and you will immediately see the past button Support of multiple RepeaterMatrix fields on one page Configurable which roles and fields are excluded Configurable dialogs for copy and paste Duplicated items are automatically pasted to the end of the target field and set to hidden status so that changes are not directly published Automatic clipboard update when other items are picked Automatically removes old clipboard data if it is not pasted within 6 hours Delete clipboard itself by clicking the selected item again Benefit: unbelievably fast workflow and content replication What the module can't do
      Before an item can be duplicated in its current version, the source page must be saved. This means that if you make changes to an item and copy this, the old saved state will be duplicated Dynamic loading is currently not possible. Means no AJAX. When pasting, the target page is saved completely No support for nested repeater items. Currently only first level items can be duplicated. Means a repeater field in a repeater field cannot be duplicated. Workaround: simply duplicate the parent item Dynamic reloading and adding of repeater items cannot be registered. Several interfaces and events from the core are missing. The initialization occurs only once after the page load event Changelog
      2.0.0
      Feature: Copy multiple items at once! The fundament for copying multiple items was created by @Autofahrn - THX! Feature: Optionally you can disable the copy and/or paste dialog Bug fix: A fix suggestion when additional and normal repeater fields are present was contributed by @joshua - THX! 1.0.4
      Bug fix: Various bug fixes and improvements in live synchronization Bug fix: Items are no longer inserted when the normal save button is clicked. Only when the past button is explicitly clicked Feature: Support of multiple repeater fields in one page Feature: Support of repeater Min/Max settings Feature: Configurable roles and fields Enhancement: Improved clipboard management Enhancement: Documentation improvement Enhancement: Corrected few typos #1 1.0.3
      Feature: Live synchronization Enhancement: Load the module only in the backend Enhancement: Documentation improvement 1.0.2
      Bug fix: Various bug fixes and improvements in JS functions Enhancement: Documentation improvement Enhancement: Corrected few typos 1.0.1
      Bug fix: Various bug fixes and improvements in the duplication process 1.0.0
      Initial release Support this module
      If this module is useful for you, I am very thankful for your small donation: Donate 5,- Euro (via PayPal – or an amount of your choice. Thank you!)
      Download this module (Version 2.0.0)
      > Github: https://github.com/FlipZoomMedia/InputfieldRepeaterMatrixDuplicate
      > PW module directory: https://modules.processwire.com/modules/inputfield-repeater-matrix-duplicate/
      > Old stable version (1.0.4): https://github.com/FlipZoomMedia/InputfieldRepeaterMatrixDuplicate/releases/tag/1.0.4
    • By Robin S
      A new module that hasn't had a lot of testing yet. Please do your own testing before deploying on any production website.
      Custom Paths
      Allows any page to have a custom path/URL.
      Note: Custom Paths is incompatible with the core LanguageSupportPageNames module. I have no experience working with LanguageSupportPageNames or multi-language sites in general so I'm not in a position to work out if a fix is possible. If anyone with multi-language experience can contribute a fix it would be much appreciated!
      Screenshot

      Usage
      The module creates a field named custom_path on install. Add the custom_path field to the template of any page you want to set a custom path for. Whatever path is entered into this field determines the path and URL of the page ($page->path and $page->url). Page numbers and URL segments are supported if these are enabled for the template, and previous custom paths are managed by PagePathHistory if that module is installed.
      The custom_path field appears on the Settings tab in Page Edit by default but there is an option in the module configuration to disable this if you want to position the field among the other template fields.
      If the custom_path field is populated for a page it should be a path that is relative to the site root and that starts with a forward slash. The module prevents the same custom path being set for more than one page.
      The custom_path value takes precedence over any ProcessWire path. You can even override the Home page by setting a custom path of "/" for a page.
      It is highly recommended to set access controls on the custom_path field so that only privileged roles can edit it: superuser-only is recommended.
      It is up to the user to set and maintain suitable custom paths for any pages where the module is in use. Make sure your custom paths are compatible with ProcessWire's $config and .htaccess settings, and if you are basing the custom path on the names of parent pages you will probably want to have a strategy for updating custom paths if parent pages are renamed or moved.
      Example hooks to Pages::saveReady
      You might want to use a Pages::saveReady hook to automatically set the custom path for some pages. Below are a couple of examples.
      1. In this example the start of the custom path is fixed but the end of the path will update dynamically according to the name of the page:
      $pages->addHookAfter('saveReady', function(HookEvent $event) { $page = $event->arguments(0); if($page->template == 'my_template') { $page->custom_path = "/some-custom/path-segments/$page->name/"; } }); 2. The Custom Paths module adds a new Page::realPath method/property that can be used to get the "real" ProcessWire path to a page that might have a custom path set. In this example the custom path for news items is derived from the real ProcessWire path but a parent named "news-items" is removed:
      $pages->addHookAfter('saveReady', function(HookEvent $event) { $page = $event->arguments(0); if($page->template == 'news_item') { $page->custom_path = str_replace('/news-items/', '/', $page->realPath); } }); Caveats
      The custom paths will be used automatically for links created in CKEditor fields, but if you have the "link abstraction" option enabled for CKEditor fields (Details > Markup/HTML (Content Type) > HTML Options) then you will see notices from MarkupQA warning you that it is unable to resolve the links.
      Installation
      Install the Custom Paths module.
      Uninstallation
      The custom_path field is not automatically deleted when the module is uninstalled. You can delete it manually if the field is no longer needed.
       
      https://github.com/Toutouwai/CustomPaths
      https://modules.processwire.com/modules/custom-paths/
    • By teppo
      Hey folks!
      I'm happy to finally introduce a project I've been working on for quite a while now: it's called Wireframe, and it is an output framework for ProcessWire.
      Note that I'm posting this in the module development area, maily because this project is still in rather early stage. I've built a couple of sites with it myself, and parts of the codebase have been powering some pretty big and complex sites for many years now, but this should still be considered a soft launch 🙂
      --
      Long story short, Wireframe is a module that provides the "backbone" for building sites (and apps) with ProcessWire using an MVC (or perhaps MVVM... one of those three or four letter acronyms anyway) inspired methodology. You could say that it's an output strategy, but I prefer the term "output framework", since in my mind the word "strategy" means something less tangible. A way of doing things, rather than a tool that actually does things.
      Wireframe (the module) provides a basic implementation for some familiar MVC concepts, such as Controllers and a View layer – the latter of which consists of layouts, partials, and template-specific views. There's no "model" layer, since in this context ProcessWire is the model. As a module Wireframe is actually quite simple – not even nearly the biggest one I've built – but there's still quite a bit of stuff to "get", so I've put together a demo & documentation site for it at https://wireframe-framework.com/.
      In addition to the core module, I'm also working on a couple of site profiles based on it. My current idea is actually to keep the module very light-weight, and implement most of the "opinionated" stuff in site profiles and/or companion modules. For an example MarkupMenu (which I released a while ago) was developed as one of those "companion modules" when I needed a menu module to use on the site profiles.
      Currently there are two public site profiles based on Wireframe:
      site-wireframe-docs is the demo&docs site mentioned above, just with placeholder content replaced with placeholder content. It's not a particularly complex site, but I believe it's still a pretty nice way to dig into the Wireframe module. site-wireframe-boilerplate is a boilerplate (or starter) site profile based on the docs site. This is still very much a work in progress, but essentially I'm trying to build a flexible yet full-featured starter profile you can just grab and start building upon. There will be a proper build process for resources, it will include most of the basic features one tends to need from site to site, etc. --
      Requirements and getting started:
      Wireframe can be installed just like any ProcessWire module. Just clone or download it to your site/modules/ directory and install. It doesn't, though, do a whole lot of stuff on itself – please check out the documentation site for a step-by-step guide on setting up the directory structure, adding the "bootstrap file", etc. You may find it easier to install one of the site profiles mentioned above, but note that this process involves the use of Composer. In the case of the site profiles you can install ProcessWire as usual and download or clone the site profile directory into your setup, but after that you should run "composer install" to get all the dependencies – including the Wireframe module – in place. Hard requirements for Wireframe are ProcessWire 3.0.112 and PHP 7.1+. The codebase is authored with current PHP versions in mind, and while running it on 7.0 may be possible, anything below that definitely won't work. A feature I added just today to the Wireframe module is that in case ProcessWire has write access to your site/templates/ directory, you can use the module settings screen to create the expected directories automatically. Currently that's all, and the module won't – for an example – create Controllers or layouts for you, so you should check out the site profiles for examples on these. (I'm probably going to include some additional helper features in the near future.)
      --
      This project is loosely based on an earlier project called pw-mvc, i.e. the main concepts (such as Controllers and the View layer) are very similar. That being said, Wireframe is a major upgrade in terms of both functionality and architecture: namespaces and autoloader support are now baked in, the codebase requires PHP 7, Controllers are classes extending \Wireframe\Controller (instead of regular "flat" PHP files), implementation based on a module instead of a collection of drop-in files, etc.
      While Wireframe is indeed still in a relatively early stage (0.3.0 was launched today, in case version numbers matter) for the most part I'm happy with the way it works, and likely won't change it too drastically anytime soon – so feel free to give it a try, and if you do, please let me know how it went. I will continue building upon this project, and I am also constantly working on various side projects, such as the site profiles and a few unannounced helper modules.
      I should probably add that while Wireframe is not hard to use, it is more geared towards those interested in "software development" type methodology. With future updates to the module, the site profiles, and the docs I hope to lower the learning curve, but certain level of "developer focus" will remain. Although of course the optimal outcome would be if I could use this project to lure more folks towards that end of the spectrum... 🙂
      --
      Please let me know what you think – and thanks in advance!
    • By tcnet
      PageViewStatistic for ProcessWire is a module to log page visits of the CMS. The records including some basic information like IP-address, browser, operating system, requested page and originate page. Please note that this module doesn't claim to be the best or most accurate.
      Advantages
      One of the biggest advantage is that this module doesn't require any external service like Google Analytics or similar. You don't have to modify your templates either. There is also no JavaScript or image required.
      Disadvantages
      There is only one disadvantage. This module doesn't record visits if the browser loads the page from its browser cache. To prevent the browser from loading the page from its cache, add the following meta tags to the header of your page:
      <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" /> <meta http-equiv="Pragma" content="no-cache" /> <meta http-equiv="Expires" content="0" /> How to use
      The records can be accessed via the Setup-menu of the CMS backend. The first dropdown control changes the view mode. There are 4 different view modes.
      View mode "Day" shows all visits of the selected day individually with IP-address, browser, operating system, requested page and originate page. Click the update button to see new added records. View mode "Month" shows the total of all visitors per day from the first to the last day of the selected month. View mode "Year" shows the total of all visitors per month from the first to the last month of the selected year. View mode "Total" shows the total of all visitors per year for all recorded years. Please note that multiple visits from the same IP address within the selected period are counted as a single visitor.
      Settings
      You can access the module settings by clicking the Configuration button at the bottom of the records page. The settings page is also available in the menu: Modules->Configure->ProcessPageViewStat.
      IP2Location
      This module uses the IP2Location database from: http://www.ip2location.com. This database is required to obtain the country from the IP address. IP2Location updates this database at the begin of every month. The settings of ProcessPageViewStat offers the ability to automatically download the database monthly. Please note, that automatically download will not work if your webspace doesn't allow allow_url_fopen.
      Dragscroll
      This module uses DragScroll. A JavaScript available from: http://github.com/asvd/dragscroll. Dragscroll adds the ability in view mode "Day" to drag the records horizontally with the mouse pointer.
      parseUserAgentStringClass
      This module uses the PHP class parseUserAgentStringClass available from: http://www.toms-world.org/blog/parseuseragentstring/. This class is required to filter out the browser type and operating system from the server request.
      Special Feature
      PageViewStatistic for ProcessWire can record the time a visitor viewed the page. This feature is deactivated by default. To activate open the module configuration page and activate "Record view time". If activated you will find a new column "S." in the records which means the time of view in seconds. With every page request, a Javascript code is inserted directly after the <body> tag. Every time the visitor switches to another tab or closes the tab, this script reports the number of seconds the tab was visible. The initial page request is recorded only as a hyphen (-).
       
    • By MoritzLost
      This module allows you to integrate hCaptcha bot / spam protection into ProcessWire forms. hCaptcha is a great alternative to Google ReCaptcha, especially if you are in the EU and need to comply with privacy regulations.

      The development of this module is sponsored by schwarzdesign.
      The module is built as an Inputfield, allowing you to integrate it into any ProcessWire form you want. It's primarily intended for frontend forms and can be added to Form Builder forms for automatic spam protection. There's a step-by-step guide for adding the hCaptcha widget to Form Builder forms in the README, as well as instructions for API usage.
      Features
      Inputfield that displays an hCaptcha widget in ProcessWire forms. The inputfield verifies the hCaptcha response upon submission, and adds a field error if it is invalid. All hCaptcha configuration options for the widget (theme, display size etc) can be changed through the inputfield configuration, as well as programmatically. hCaptcha script options can be changed through a hook. Error messages can be translated through ProcessWire's site translations. hCaptcha secret keys and site-keys can be set for each individual inputfield or globally in your config.php. Error codes and failures are logged to help you find configuration errors. Please check the README for setup instructions.
      Links
      Github Repository and documentation InputfieldHCaptcha in the module directory Screenshots (configuration)

      Screenshots (hCaptcha widget)

       
       

       
×
×
  • Create New...