Jump to content


Popular Content

Showing content with the highest reputation since 08/18/2019 in all areas

  1. 28 points
    Hope you guys are having a great week. I'll keep this week's update short since everything I'm working on is in-progress rather than ready to post. But I can tell you about a few things you'll likely see in next week's post: First is that I've got multi-page/paginated form support just about ready to release in FormBuilder. What this means is that you can take forms (especially long forms) and break them up into multiple paginations. This makes for multi-part forms that are more digestible and easy to use for users. The end of each pagination has "Next" and "Prev" buttons for navigation between them. FormBuilder validates each pagination independently as it is submitted so that any errors are taken care of as the user proceeds rather than all at the end. And these are true paginated forms, rather than a JS manipulation of existing forms. More on this next week. I'm also working here on a new Inputfield module called InputfieldToggle. It's an alternative to the core InputfieldCheckbox and the intention here is to make it a selectable alternative for FieldtypeCheckbox fields. Unlike InputfieldCheckbox, it is presented as two radio buttons for "on" and "off" states. (It's also possible to have a "no selection" state distinct from the "no" state, where supported). It comes predefined with several toggle types (Yes/No, On/Off, True/False, Enabled/Disabled), along with the ability to specify your own (multi-language too of course). Like a checkbox, because it is a toggle, it holds a value of either true (1) or false (0). There is also null for no selection. While this is a relatively simple Inputfield, it answers a common need (at least in my experience) and often can provide a better experience than a standard checkbox, depending on the input need. Not to mention, it's a lot more efficient than using an Options or Page field to accomplish the same thing. In addition to sites and apps running in ProcessWire, I think this particular Inputfield has a lot of potential use in the core and its administrative forms, so I might include it in the core, though not yet certain. I'm already using it quite a bit in forms I'm developing for clients in FormBuilder, where in many cases I find it a better fit than InputfieldCheckbox. Lastly, there are some nice UI enhancements just about ready for manipulating column widths of fields in ProcessWire. It makes it a much simpler and quicker job than it currently is, so I'll have more on that next week too. Have a great weekend!
  2. 13 points
    Hello everyone, Recently I spent some time researching how I can update my workflow. I really enjoy working with TailwindCSS however, when it comes to Javascript, I often find myself having to search around to find a good package. Often I find myself having a package for lazy loading, a package for sliders, a package for animation, a package for parallax and a package for ajax. Before you know it, you are worrying about dependicies, conflicts and vunrabilities for many different packages. Since the push is to get rid of jQuery and use native javascript, often each will have their own utility classes, some of which do the same thing. This adds a lot of bulk to the website. This is what I love about UIKit, it provides plenty of functionality for a small ~130KB unminified. Not many know this, but the UIKit helper classes are exposed via the API too. So it means you will not have to worry about your javascript working cross-browser (https://github.com/uikit/uikit-site/blob/feature/js-utils/docs/pages/javascript-utilities.md). The perfect thing would be to combine UIKit and TailwindCSS, but the best way to achieve this is up for grabs. I personally use TailwindCSS base and implement components from UIKit. I then use PurgeCSS on the CSS file to make sure anything unused by either UIKit or Tailwind isn't making it to production. I do this using Parcel JS. I have used Webpack and Gulp previously, but I find Parcel is a simple and easy way to get a project started (and it's fast!). The next thing I've found is UIKit is not always the answer. There are now more than ever better ways of achieving things in browser. Such as CSS Grid, `position: sticky`, and `object-fit` try to use these CSS alternatives where possible. Purge will always make sure that you get the smallest possible file size, so avoid using the uk-grid element where possible and use CSS Grid. I have setup a github starter template (https://github.com/TomS-/UIKit-TailwindCSS/tree/master) if you want to have a look at it. CSS Grid will introduce intrinsic design (https://www.youtube.com/watch?v=lZ2JX_6SGNI - Great series) Next will be to use WebP, there is plenty going around on the blogs now about this, but this will make a massive improvement to your Google Page Insight rating (https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Fwww.tikari.co.uk%2F&tab=desktop). I would love to hear your web manifesto - and ask me anything about mine ๐Ÿ™‚
  3. 10 points
    Paginated forms: Looking > Forward > To > This > Alot. Thank-you!
  4. 9 points
    This module will log information about all mails that are sent via WireMail to the PW logs https://github.com/BernhardBaumrock/RockMailLogger https://modules.processwire.com/modules/rock-mail-logger/
  5. 6 points
    Fixed! Not completely sure why, but switching: $mail = new WireMail(); to this: $mail = $this->wire('mail')->new(); in the LoginRegister module did the trick โ€” line 684. Now Gmail's sending my registration emails too ๐Ÿ™‚ Gotta say, I am hugely grateful for Processwire. Ryan, and all you fantastic moderators and commentersโ€”this is such a great place to learn, and goddamn if the sky doesn't seem to be the limit.
  6. 5 points
    https://www.fieggen.com/shoelace/index.htm Website I bookmarked some time ago.
  7. 5 points
    https://github.com/processwire/processwire-issues/issues/252#issuecomment-467473684 Quote: "If a page is saved (in the admin) and errors are generated by the page editor form, the page receives a Page::statusIncomplete status, indicating something may be missing on the page. When the page is saved without error, this status is removed." There is more about it in the GitHub issue.
  8. 5 points
    The notes on the Settings tab of Page Edit are a good summary of what the statuses mean: Hidden and unpublished pages are both excluded from selectors (unless you override this) - the difference is that a hidden page is viewable if the URL is known, whereas an unpublished page cannot be viewed unless the user is logged in and has edit access for the page.
  9. 5 points
    The newest version of RockGrid now supports RockFinder2 as data source ๐Ÿ˜Ž $finder = new RockFinder2(); $finder->find('template=basic-page'); $finder->addColumns([ 'title', 'body' ]); $this->setData($finder); Data is available on the JS side via the RockFinder2 property in the GridItem object:
  10. 4 points
    I wouldn't call it a manifesto but anyway... let's talk about my workflow. TL;DR I build 90% from scratch. Every time. Each and every project. I don't use frameworks of any flavour.* * except from some JS stuff - see below Long version My boilerplate for new projects: SCSS Skeleton (my personal collection of SCSS Magic) JS Skeleton (my personal collection of JS Magic) HTML/Kit files depending on templates and elements the project needs (inspired by http://bradfrost.com/blog/post/atomic-web-design/) just an empty folder would work totally fine as well Tools I use and need: git Prepros/CodeKit (or ProCache ๐Ÿ˜Ž) Tools that may be added later (if absolutely necessary): Lazysizes SVGinline jQuery for Slider scripts (slick, OwlCarousel) MixItUp Tools I never use (because I'm too old for that - I guess) Grunt, Gulp, Bower, Webpack, Parcel, ... you get the idea Benefits Projects are portable Projects run everywhere Every part of project can be changed without affecting other things (most of the time) No need for a special setup (at least for the compiled files) Small(est) file sizes and therefore fast websites (in most cases) Downsides Working with others means I have to trust them and their capability to write good CSS/SCSS You have to think at least twice for each step, every time It takes much more time to build everything from scratch It's much more expensive at first Clients often don't understand the benefits and sometimes WANT a Bootstrap website ๐Ÿ˜ฑ FAQ What if you work with others? As mentioned before I have to trust others that they are capable of writing good CSS/SCSS and therefore I tend to work only with very good people I really trust. Is it worth it? Yes! Why? When stuff breaks or needs to be changed, I know where to look, what to change and can do my stuff without the need to take care of any version upgrades, incompatibilities in or with newer version, I don't need a special setup or whatever. AND... if I want to I can still add whatever is needed. Try it the other way around. That's much harder. Are there exceptions? Of course. Backend stuff, admin interfaces and things like - ProcessWire admin is the perfect example. I wouldn't build something like that from scratch. I guess that's my manifesto.
  11. 4 points
    Please do โ€“ the core would definitely benefit from this ๐Ÿ™‚
  12. 4 points
    A neat new Github feature: https://help.github.com/en/articles/navigating-code-on-github And while I'm at it: If you're frequently navigating through GH repos, I can highly recommend this browser add-on: https://www.octotree.io/
  13. 4 points
    No problem! When I have some time here I'm planning to build a site profile using Tailwind CSS so more people can see how it can be integrated with PW. Using both the CDN version, which gzipped is around 60kb and using brotli compression goes down to less than 20kb and the webpack installation I mentioned. :)
  14. 4 points
    /* * Example of how to clone a locked page, remove the lock on the copy, and clear the value of a field in the copy. * Reset stockCode Field when copying a page using a specific template, also remove locked status. * This code is included in the /site/ready.php file. */ $wire->addHookAfter('Pages::cloned', function($event) { /* * Important: The event arguments include both the copied page and the newly created page. * Don't use $event->arguments('page') as this returns the page that is being cloned rather than the cloned copy. * Instead use $event->arguments(1) which correctly refers to the new copy. */ $currentPage = $event->arguments(1); if ($currentPage->template == 'bom') { $currentPage->stockCode = ''; $currentPage->status = $currentPage->status & ~Page::statusLocked; //probably better to use removeStatus(Page::statusLocked) $currentPage->save(array('quiet' => true)); } }); Here's my documented example of how I got this to work.
  15. 3 points
    Just to add to this a bit: I've found it a bit problematic if you're, for an example, working with nested structures where the nesting level should affect things. That's one example where, to my best knowledge so far, it's usually easier to rely on custom classes. You can still make use of @apply and similar features behind the scenes to make use of Tailwind's features as much as possible, but the point is that you can't always rely on directly applied Tailwind classes alone โ€“ at least not without creating solutions that are either inflexible, or unnecessarily complex ๐Ÿ™‚ As a disclaimer I'm currently building my first site with Tailwind. It's been a bit of an emotional rollercoaster: at times I find Tailwind utterly awesome, while the very next moment I can be really frustrated with it as I'm once again struggling to figure out what's the Tailwind version of some CSS rule I already have in mind. (For the record, https://nerdcave.com/tailwind-cheat-sheet has been a big help in this regard.) I've been constantly tweaking my approach, going back and forth with things like components and custom utility classes, trying to figure out how to best combine those with native Tailwind features, when to add a new "spacing" or color (or something similar) to Tailwind's config vs. just applying a one-off custom value instead, etc. That being said, I've already got a list of do's and don'ts for my next Tailwind project, so it should go a lot smoother. For the past year or so I've been deeply invested in a BEM type approach, and in some ways Tailwind is the opposite of that. That shift in mental models has definitely been holding me back a bit. After my next project with Tailwind I hope to have a more informed opinion, but currently if someone asked me if they should use Tailwind for their next project, I'd have to reply with "it's complicated" ๐Ÿ˜…
  16. 3 points
    I prefer to change the pagination style on _init.php, or _func.php, for instance, to use Tailwind classes, using Ryan's modified example:
  17. 3 points
    Thanks @Sergio, @apeisa and @Tom. for bringing Tailwind CSS to our attention. Incidentally, I checked out the Tailwind screencasts and ended up picking up Vue.js as well :-). Anyway, to my first question. @apeisa, could you please clarify this statement about ProcessWire custom classes. Does it mean you use Tailwind in the backend/admin/modules or does it mean you use ProcessWire inputfields in the frontend? Thanks. Cross-posting Tom's Tailwind + UIKit + Grid resource:
  18. 3 points
    I am not sure how I feel about this... It reminds me of lings cars, but not so flashy/bad (apologies if you had a hand in this, not trying to offend anyone). However, It is awesome to see that it is responsive.
  19. 3 points
    Hi, I agree it is a bit hidden, but it is here -> https://processwire.com/api/ref/page/#pwapi-methods-constants.
  20. 3 points
  21. 3 points
    Hi @Soma, Could you please add this very useful module to the PW modules directory? Thanks!
  22. 3 points
    The map still seems broken. It would be really sweet if Ryan could put the website code on Github so other people can contribute as well through PR's.
  23. 3 points
    I wrote an api-module a few years ago, where the module generated a custom template (e.g. "api-page"), which could be used to create one or more endpoint-pages. To handle calls to these pages I used ProcessPageView::pageNotFound like @bernhard did: $this->addHookBefore('ProcessPageView::pageNotFound', $this, 'handleApiRequest'); public function handleApiRequest(HookEvent $e) { $page = $e->arguments[0]; if ($page->template === 'api-page') { // handle request here... $otherEvent = $e->arguments(0); // grab event provided to PageRender::renderPage $e->replace = true; // prevent PageRender::renderPage from being called } } It worked nice for me, but I cannot say if caching or multi-language works better in this hook. pageNotFound should be called later than execute, so there is a chance that it helps ๐Ÿคทโ€โ™‚๏ธ
  24. 3 points
    @Gadgetto My bad. I misled you a bit. I can't find it now, but @teppo made an excellent post about the executeWhatever() aspect of Process modules. In Process Modules, unlike URL segments in the frontend, ProcessWire will 'jealously guard' the first URL Segment, i.e. the Whatever part of execute....(). In other words, if your Process module has a first URL segment, it will look for a method in your Process module named executeYourFirstURLSegment(). If it doesn't find that, rather than render what is in execute(), it returns the error, Processwire: Unrecognized Path and the content The process returned no content. However, this only applies to the first URL Segment. After that, i.e. 2nd, 3rd, etc URL segments will resolve to whatever you decide based on the code you have in the method of the first URL Segment. For instance, in the case /admin/mymodule/firsturlsegment/whatever/, ProcessWire will not complain if there is no 'whatever' as long as firsturlsegment has content. Please find an example Process module below and the demo of it. The example is a bit rudimentary but you get the idea. Normally, I don't include the content of what I want the 2nd, etc URL segments to resolve to within the executeWhatever() method itself. I usually throw those in their own methods or even class. Example In this example, executeColours() is our gateway to anything we want the 2nd URL segment to resolve to. The 'red', 'green', etc segments do not exist independently (i.e. no corresponding executeXXX() methods for them). ProcessWire does not complain since the first segment /colours/ exists as executeColours(). Demo
  25. 3 points
    Hey folks โ€“ a quick update: Wireframe 0.5.0 was released couple of days ago. Compared to 0.4.x this version mainly fixes bugs and improves performance โ€“ nothing particularly major, but if you're using Wireframe, it's a recommended update. On a loosely related note, Tracy Debugger has been really helpful in figuring things out, identifying bottlenecks, etc. Brilliant module ๐Ÿ™‚
  26. 2 points
    Tailwind is utility-first framework. The key difference between something like Uikit and Tailwind is that latter has none of the typical CSS framework components built-in. For an example, here's an example from the docs for creating a "button component": <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> Button </button> Colors and sizes (such as the "2" in "py-2" etc.) are configurable, so you can have as many or as few of them as you want, and the names can pretty much be whatever you want them to be (py-thon). Either way you're always building your UI using really simple (the word "atomic" comes to mind) rules. While Uikit has some similar utility classes (and so does Bootstrap), Tailwind has a massive number of them, even without counting the pseudo states (bg-blue hover:bg-blue-dark), responsive classes (p-6 md:p-8 lg:p-10), etc. You can still create your own "custom" components, so that when you add some class โ€“ such as "btn" โ€“ to an element, you actually get the same thing you would with the rules in the example above. Typically this is done by defining the class in SCSS: .btn { @apply font-bold py-2 px-4 rounded bg-blue-500 text-white; } .btn:hover { @apply bg-blue-700; } Technically that this is something you should only do if you really have to repeat the same string of classes multiple times, though ๐Ÿ™‚ Personally one thing I've always struggled with "traditional" CSS frameworks are the components they come with. While they often look quite nice, I've almost never had the chance to actually use them as-is (either there's a predefined PSD layout or something like that, or the client demands changes, or the component is just plain bad) and thus I've basically ended up designing my own component library on top of the one provided by the framework. In most of my projects I've only used a framework like Foundation for the grid implementation. That's where Tailwind comes in: you can build exactly the components you need, BUT you still get certain benefits of a framework, such as globally defined fonts, colours, spacings, etc. I've struggled with this a bit, and I have to agree that to me personally the utility class approach often looks really ugly, and the shortcut class names etc. are hard to decipher. I'm not yet at the point where I can just glance over an element and instantly see what it is or how it's styled. That being said, I don't really think that this is a major issue for most projects: the size of your HTML is really unlikely to become a bottleneck. ... and if it does, you can always use the extracting components approach mentioned above. Use Tailwind for prototyping, and then convert the combinations you use often to custom components (or custom utility classes) ๐Ÿ™‚
  27. 2 points
  28. 2 points
    After digging through several PW forum threads, I think the following approach might work: Create each of the 200 pages via API as the user it will be later assigned to (or create as superuser, and later change the owner) Install this module
  29. 2 points
    That's Brutalism, right? Well... the design is a challenge but the estimated traffic and SEO coverage is quite nice or almost impressive to be honest.
  30. 2 points
    Hello folks! Recently we published a new website for Brightline, a Project Management Institute (PMI) initiative together with leading global organizations dedicated to helping executives bridge the expensive and unproductive gap between strategy design and delivery. The previous website was made in Hugo as in the beginning it was a very simple website, but as the business needs changed, I decided to build this version in ProcessWire. Nothing fancy occurs behind the curtains, the need was more on getting some data in a way that makes it easier to create reports and to give access to PW's great admin to another team member. For the other website, that you can see here, I didn't implement a CMS on top of Hugo because for me it was quicker to edit the files and push to the repository. Some content is still being copied but 98% is done. A quick list of modules used: - ProCache, FormBuilder, ProFields, SeoMaestro, PageHits, TracyDebugger, MenuBuilder, AutoSmush, and other custom ones. I'm biased, but there a lot of good and useful content created by us and also by partners and all is free to download. :)
  31. 2 points
    @ryan any news on this? It works really great in my setup and I think this approach can open up a lot of great options for a better DEV/LIVE workflow with processwire. In my current project where I modified the core file it was really just doing a git clone myrepo.git git submodule update --init --recursive # restore db dump And I had a working copy of the site that downloaded all assets on demand while working with it! This is really awesome but it would break on every core update. I could implement some hack that does a str_replace and file_put_contents in my dev environment to prevent updates breaking this feature, but it's really just adding three underscores to one core file thanks to the ingenious hook system ๐Ÿ™‚ PS: I've created an issue for this: https://github.com/processwire/processwire-issues/issues/954
  32. 2 points
    $wire->addHookAfter("InputfieldForm(name=form-application)::processInput", function($event) { $form = $event->object; /** @var InputfieldForm $form */ if(count($form->getErrors())) return; // do your stuff $input = $event->arguments(0); }); Something like this? See https://processwire.com/api/ref/inputfield-form/process-input/
  33. 2 points
    This reminded me of endless hours making my Geocities site look perfect. And your the site looks awesome! And then I proceeded to spend an hour learning about shoelaces. ๐Ÿค” Fascinating stuff! ๐Ÿ™‚
  34. 2 points
    Status update links (inside this thread) for SnipWire development will be always posted here: 2019-08-08 2019-06-15 2019-06-02 2019-05-25 If you are interested, you can test the current state of development: https://github.com/gadgetto/SnipWire Please note that the software is not yet intended for use in a production system (alpha version). If you like, you can also submit feature requests and suggestions for improvement. I also accept pull requests. ---- INITIAL POST FROM 2019-05-25 ---- I wanted to let you know that I am currently working on a new ProcessWire module that fully integrates the Snipcart Shopping Cart System into ProcessWire. (this is a customer project, so I had to postpone the development of my other module GroupMailer). The new module SnipWire offers full integration of the Snipcart Shopping Cart System into ProcessWire. Here are some highlights: simple setup with (optional) pre-installed templates, product fields, sample products (quasi a complete shop system to get started immediately) store dashboard with all data from the snipcart system (no change to the snipcart dashboard itself required) Integrated REST API for controlling and querying snipcart data webhooks to trigger events from Snipcart (new order, new customer, etc.) multi currency support self-defined/configurable tax rates etc. Development is already well advanced and I plan to release the module in the next 2-3 months. I'm not sure yet if this will be a "Pro" module or if it will be made available for free. I would be grateful for suggestions and hints! (please have a look at the screenshots to get an idea what I'm talking about)
  35. 2 points
  36. 2 points
  37. 2 points
    You can use the Connect Page Fields module by @Robin S. This makes it easy to connect both page fields.
  38. 2 points
    That feeling is simply awesome! Welcome to the community :)
  39. 2 points
    The easiest way I've found is to use Laravel Mix with two plugins, Laravel Mix Tailwind and Laravel Mix PurgeCSS to reduce file size by going through all php templates. But note, the website is not running the purged version yet, as I'm working on some configs on javascript generated classes and classes set by the user via admin (using RepeaterMatrix). But I also reduced manually Tailwinds output by using just a few colors and removing other pieces. Take a look on my webpack.mix.js file: And here goes Tailwind Config file. Note: I'm using Tailwind earlier version (prior to 1.0). Will upgrade it when possible, but it works just fine.
  40. 2 points
    It's all in the facebook docs: https://developers.facebook.com/docs/plugins/comments/
  41. 2 points
    For anyone having a similar issue, I finally resolved the issue after reading this post... https://processwire.com/blog/posts/pw-3.0.111/ Adding: $event->name = $pages->names()->uniquePageName($event->name) before: $event->save(); sorted it. Many thanks Nik
  42. 2 points
  43. 2 points
    Nothing in that regard yet. Let's just try to meet over a drink and learn from that point on whether to set up any form of "infrastructure" at all ๐Ÿ™‚
  44. 2 points
    @iipa Pasting stuff from Word should be no problem ... I think most of our clients likely do this. So you definitely shouldn't get an internal server error from PW at least. Though you might try setting $config->debug=true; in your /site/config.php file (temporarily) and trying again, just in case โ€” that will make it produce a verbose error message. But it's more likely that it is coming from mod_security or some other Apache or PHP module on the server that is monitoring input and halting the request when it comes across something it doesn't like. I don't blame it, as MS word can produce some pretty sketchy looking markup. But between CKEditor and htmlpurifier, PW should be able to clean it up just fine once the server lets it through. But if it's an Apache/PHP module doing this (which seems likely) then nothing you adjust in PW can fix it since the module examines the request before PW even boots, so you'd instead have to disable or configure the Apache module (mod_security, suhosin, or whatever it might be).
  45. 2 points
    Affinity used it in a clever way. I like(d) their software.
  46. 2 points
    ProcessWire added WebP image support this year and many have been adopting it enthusiastically in existing projects. In this post weโ€™ll look at a process used for migrating an existing website to use WebP images. Weโ€™ll cover everything from preliminary considerations to implementation and testing, with lots of tips and tricks along the wayโ€” https://processwire.com/blog/posts/webp-images-on-an-existing-site/
  47. 2 points
    Offtopic, but have you (@zeka) had a look at RockFinder and RockGrid? And the upcoming RockFinder2 and RockTabulator? ๐Ÿ˜‰
  48. 2 points
    Definitely, I would recommend PW. In my case, the client didn't like the tree structure of pages, so I had to create separate Process modules for managing news, tags, banners, categories. I have found that it's much easier to control permissions and workflow via custom modules.
  49. 2 points
    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 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.123 is required to use this module.
  50. 2 points
    Well, I use personally use UIkit 3 + TailwindCSS. Tailwind you are going to hear a whole lot more about in the upcoming months. I know you are talking about file size and this is exactly why UIkit + Tailwind is great! I don't really use UIkit's CSS at all. I just use the JavaScript because the amount of utilities they have manage to pack into 130kb (less than most images) is amazing. I'm talking Parallax, Sliders, Lazy Loading Images, Srcset utilities, placeholder generators, scrollspy, sticky. Most of which can be and usually is utilised in any project. I challenge you to get all of that under 130kb. Also it doesn't have any dependencies. Tailwind you can get down to about 3KB per website using Purge and Gulp/Webpack. It truly is amazing and Utility first CSS is such a refreshing way to work with CSS. I know all the arguments, and I'm a minimalist. I don't like all the classes too. But Tailwind's benifits out weigh the cost. 1. You don't have to struggle with inherited styles, or coming up with class names to define each section, some of which may look the same but be very different in content. 2. Consistency, it puts pressure on you to keep things consistent. So you hardly stray to loads of different type sizes and colours. 3. With Purge, you can have an entire website styles in ~3kb. I believe Ryan chose UIkit 3 because he has learnt the classes and is confident with the framework, and is impressed with the JavaScript utilities. And because you can build website much quicker using it. I see it as a hybrid between utility and a standard framework. It offers many utility classes. You could also Purge UIkit's CSS and get it around 160KB. I don't believe that this isn't a good fit for ProcessWire as you have previously mentioned. Many who use ProcessWire love UIkit. It follows the same philosophy: A powerful framework, that is easy to understand and learn to get things done quicker. Just like ProcessWire gives developers confidence in that they can do challenging bits of functionality easily with the power of ProcessWire's amazing API (like seriously, I built a real estate system using ProcessWire, something I wouldn't have dreamed of doing on any other platform). Well UIkit also gives that confidence to the front-end. But if I was to choose for myself, I much prefer pairing Tailwind for the CSS and UIkit for the JavaScript. That ~140KB (Tailwind + UIkit) covers me for most websites I build.
  • Create New...