Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation since 02/05/2019 in all areas

  1. 35 points
    A module helping you to manage SEO related tasks like a boss! Automatically generates and maintains a XML sitemap from your pages. Includes a Fieldtype and Inputfield to manage sitemap settings and meta data for pages (Title, Description, Canonical URL, Opengraph, Twitter, Structured Data etc.) Multi language support for the sitemap and meta data. Configure default values for meta data on template level and let pages inherit or overwrite them individually. Map existing fields to meta data, reducing the need to duplicate content. Live preview for content editors how the entered meta data appears on Google. Live preview for content editors how the entered Opengraph data looks like when sharing a page with Facebook. Check out the README on GitHub for more details, including usage instructions. The module is currently released as beta and needs testing! Please report any issues on GitHub or in this forum thread, if you find time to give it a try 🙂 Examples Here is an example of rendered meta data you will get from a single SeoMaestro field: <title>Sed dictum eros quis massa semper rutrum. | acme.com</title> <meta name="description" content="Si lobortis singularis genitus ibidem saluto. Dolore ad nunc, mos accumsan paratus duis suscipit luptatum facilisis macto uxor iaceo quadrum. Demoveo, appellatio elit neque ad commodo ea. Wisi, iaceo, tincidunt at commoveo rusticus et, ludus."> <meta name="keywords" content="Foo,Bar"> <link rel="canonical" href="https://acme.com/en/about/"> <meta property="og:title" content="Sed dictum eros quis massa semper rutrum."> <meta property="og:description" content="Si lobortis singularis genitus ibidem saluto. Dolore ad nunc, mos accumsan paratus duis suscipit luptatum facilisis macto uxor iaceo quadrum. Demoveo, appellatio elit neque ad commodo ea. Wisi, iaceo, tincidunt at commoveo rusticus et, ludus."> <meta property="og:image" content="https://acme.com/site/assets/files/1001/og-image.jpg"> <meta property="og:image:type" content="image/jpg"> <meta property="og:image:width" content="1600"> <meta property="og:image:height" content="1200"> <meta property="og:image:alt" content="Lorem Ipsum"> <meta property="og:type" content="website"> <meta property="og:url" content="https://acme.com/en/about/"> <meta property="og:locale" content="en_EN"> <meta name="twitter:card" content="summary"> <meta name="twitter:creator" content="@schtifu"> <meta name="twitter:site" content="@schtifu"> <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [ { "@type": "ListItem", "position": 1, "name": "About", "item": "https://acme.com/en/about/" } ] } </script> <meta name="generator" content="ProcessWire"> <link rel="alternate" href="https://acme.com/en/about/" hreflang="en"> <link rel="alternate" href="https://acme.com/en/about/" hreflang="x-default"> <link rel="alternate" href="https://acme.com/de/ueber/" hreflang="de"> <link rel="alternate" href="https://acme.com/fi/tietoja/" hreflang="fi"> And some screenshots of the UI:
  2. 34 points
    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 abbreviations 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!
  3. 33 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!
  4. 33 points
    Just a quick update this week rather than a blog post. I’ve been continuing to work through the PW issues repo with Netcarver and it seems to be working well, so am planning to just keep working through it till we’ve covered everything there. Thanks to Netcarver and everyone else helping there. When we get the issues repo to the point where it’s pretty empty, I thought we’d then move on to the requests repo and PRs if possible. While there have been several commits to the core this week (mostly related to the issues repo), I don’t think there’s anything major enough to warrant a version bump, so will get another week’s worth of updates in place before bumping it to the next version number. This week I’ve been putting the finishing touches on the ProMailer module, getting that ready for release. A copy of ProMailer will be available to current subscribers of the ProDevTools package that want it. A few people have indicated that they’d also like to see it as a product independent of the ProDevTools, and actually I think that makes sense because ProMailer has become a much more comprehensive product than originally planned, and it really needs its own dedicated support board, as well as dedicated dev and agency versions. So I will make those available separately from ProDevTools. If you are a current ProDevTools subscriber and you’d like to get the first version of ProMailer when it is ready, please send me a PM here in the forums indicating that, and I will get a copy to you when it is released in beta. Even if you aren’t a ProDevTools subscriber, but would still like to be notified when ProMailer is available, please send me a PM as well. If all goes well, it should be available by this time next week or earlier. Next month we’ll hopefully be back to work on the website here as well, and develop the new modules directory.
  5. 30 points
    We recently rebuilt the Architekturführer Köln (architectural guide Cologne) as a mobile-first JavaScript web app, powered by VueJS in the frontend and ProcessWire in the backend. Concept, design and implementation by schwarzdesign! The Architekturführer Köln is a guidebook and now a web application about architectural highlights in Cologne, Germany. It contains detailled information about around 100 objects (architectural landmarks) in Cologne. The web app offers multiple ways to search through all available objects, including: An interactive live map A list of object near the user's location Filtering based on architect, district and category Favourites saved by the user The frontend is written entirely in JavaScript, with the data coming from a ProcessWire-powered API-first backend. Frontend The app is built with the Vue framework and compiled with Webpack 4. As a learning exercise and for greater customizability we opted to not use Vue CLI, and instead wrote our own Webpack config with individually defined dependencies. The site is a SPA (Single Page Application), which means all internal links are intercepted by the Vue app and the corresponding routes (pages) are generated by the framework directly in the browser, using data retrieved from the API. It's also a PWA (Progressive Web App), the main feature of which is that you can install it to your home screen on your phone and launch it from there like a regular app. It also includes a service worker which catches requests to the API and returns cached responses when the network is not available. The Architekturführer is supposed to be taken with you on a walk through the city, and will keep working even if you are completely offline. Notable mentions from the tech stack: Vue Vue Router for the SPA functionality VueX for state management and storage / caching of the data returned through the API Leaflet (with Mapbox tiles) for the interactive maps Webpack 4 for compilation of the app into a single distributable Babel for transpilation of ES6+ SASS & PostCSS with Autoprefixer as a convenience for SASS in SFCs Google Workbox to generate the service worker instead of writing lots of boilerplate code Bootstrap 4 is barely used here, but we still included it's reboot and grid system Backend The ProcessWire backend is API-only, there are no server-side rendered templates, which means the only PHP template is the one used for the API. For this API, we used a single content type (template) with a couple of pre-defined endpoints (url segments); most importantly we built entdpoints to get a list of all objects (either including the full data, or only the data necessary to show teaser tiles), as well as individual objects and taxonomies. The API template which acts as a controller contains all the necessary switches and selectors to serve the correct response in <100 lines of code. Since we wanted some flexibility regarding the format in which different fields were transmitted over the api, we wrote a function to extract arbitrary page fields from ProcessWire pages and return them as serializable standard objects. There's also a function that takes a Pageimage object, creates multiple variants in different sizes and returns an object containing their base path and an array of variants (identified by their basename and width). We use that one to generate responsive images in the frontend. Check out the code for both functions in this gist. We used native ProcessWire data wherever possible, so as to not duplicate that work in the frontend app. For example: Page names from the backend translate to URLs in the frontend in the form of route parameters for the Vue Router Page IDs from ProcessWire are included in the API responses, we use those to identify objects across the app, for example to store the user's favourites, and as render keys for object lists Taxonomies have their own API endpoints, and objects contain their taxonomies only as IDs (in the same way ProcessWire uses Page References) Finally, the raw JSON data is cached using the cache API and this handy trick by @LostKobrakai to store raw JSON strings over the cache API. Screenshots
  6. 30 points
    Just a brief update today. I’m going to give it another week before bumping the core version, as I don’t think there’s enough changes yet to warrant a version bump. For whatever reason, several of my clients have needed integration with Stripe (payments) over the last few weeks. I’d not worked with it before the last month or so, but now all of the sudden am working with it a lot, because that's what my clients have asked for. I’ve found myself working on four different Stripe integrations on existing PW sites, both Stripe Elements and Stripe Checkout. None of these are for sites that have an actual “store” where they would need a cart, but rather just “pay for your reservation”, “buy this book”, “buy this song”, and “make a donation of $10”, “make a recurring donation”, type things. After doing a few of these, I thought it would make a lot of sense to have this built into FormBuilder, which would save us time on this stuff. So this week I built Stripe support into FormBuilder (using the Stripe Elements API). It’s already fully functional, so I will be releasing a new version of FormBuilder with this capability quite soon. To add a Stripe payment input to your form you just add a new field of type “Stripe payment for FormBuilder”, and then it asks you for some info about it (like amount to charge) and then your form works as a payment processor. Stripe has a clever way of making this all work, so that the user never leaves your site, but your site (and FormBuilder) never sees credit card numbers or anything like that, so it’s secure and you don’t have to consider things like PCI compliance. I've also got some other unrelated updates for FormBuilder that I'll be covering soon as well. Have a great weekend!
  7. 28 points
    Good Morning ProcessWIre Community, PW Review is a website that has a lofty goal of covering ProcessWire on a regular basis. That may seem like an impossible task, however I believe I'm up to the challenge. First, this is a strictly non-commercial endeavor and a project I believe in. This is not Wired Magazine or anything like that. I'm not a serious programmer or pretending to be one. My goal is to cover the modules (commercial and non-commercial) that may not get that much press or attention. I will also be covering modules that maybe you haven't heard about in awhile. There will also be screenshots, information and videos regarding the Commercial modules. I've been with this community since 2012 and have benefitted tremendously from ProcessWire. So this is my way of giving back, which is important to me. It's my hope that over time that what I'm doing myself will get some community participation. One person that I've had nothing but positive support from is Ryan Cramer. That's enough to keep me going at this for some time. That's it. Have a nice day and I hope you find something to like with PW Review. If not, please send me an email. I'm a great listener. Best Regards, Charles
  8. 27 points
    RockFinder2 is the successor to RockFinder v1 and while the changes might not look that big on first sight they are quite huge behind the scenes. In RockFinder1 I used some kind of custom query builder because I didn't know of PW's built in one (see later). RockFinder2 will exist besides RockFinder1 because I have several projects relying on RockFinder1, but for any future projects you should definitely use RockFinder2. This is how RF2 builds the SQL query: So this is really easy to grasp, easy to maintain and easy to extend (like aggregations, selecting distinct values etc). RockFinder2 also comes with a custom UI where you can manage your Finders: You can then easily access those finders by name: This is a soft alpha release. The module can be downloaded from https://github.com/BernhardBaumrock/RockFinder2 and the docs are at the moment a mess. I'll work on several useful examples in the next weeks that showcase all the features.
  9. 27 points
    This week we’ll take a look at a new version of FormBuilder that's on the way (with a screencast), as well as the latest version of the core: ProcessWire 3.0.140— https://processwire.com/blog/posts/pw-3.0.140-and-formbuilder-v40/
  10. 25 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)
  11. 25 points
    Like in recent weeks past, the primary focus this week in core development was working through the queue of older issue reports. Relative to 3.0.128, ProcessWire 3.0.129 contains 17 commits over 1 week, most of which are focused on resolving and closing out older issue reports. However, there have also been a few very useful additions too, and I’m going to cover them in a blog post next week. In terms of our issues repository, we are now down to 65 open issues and 777 closed (the closed number is a total over the life of this repo). If we subtract issues that are tagged as being fixed, not a bug or ready to close, we’re around 55 open issue reports (give or take a couple depending on when we check). Which is to say, there’s a lot of great progress here. And many of the remaining issues are minor things that might only affect one person, though still important nonetheless. Thanks to everyone that’s helping figure things out (such as Toutouwai, Matjazpotocnik, Netcarver and others), your help is greatly appreciated. Just now I also released a new version of ProMailer (v7) which accommodates many of the recent feature requests and fixes a few minor issues as well. There has been a lot of enthusiasm for ProMailer, pleasantly more than expected—thanks for your interest and support. Here’s the changelog for the latest version (v7) below. There is also more good stuff in the works for v8 as well. Changed subscribers list interface to use tabs. Added ability to remove all subscribers from a list. Added ability to remove filtered subscribers from a list (matching find query). Added ability to import subscribers from another list (creating a merged list). Added support for single, multi-select and checkbox custom fields. Added support for PW 3.0.129+ core WireMail blacklist (more details in next week’s blog post). Added several new options for custom fields (see new custom fields reference). Added documentation for conditional placeholders. Split the rather large ProcessProMailer.module into separate files/classes. Fix some display issues in AdminThemeDefault and AdminThemeReno. Various minor bug fixes and other minor tweaks, additions and improvements. Thanks for reading this quick update and hope that you have a great weekend.
  12. 25 points
    Relative to the last dev branch version (3.0.127) version 3.0.128 contains 40 commits, mostly specific to resolving older GitHub issue reports. If you are interested, here is the commit log: https://github.com/processwire/processwire/commits/dev — version 3.0.128 covers commits between March 2nd and today. We're down to about 77 remaining issue reports, mostly older stuff that didn't get covered in the past for one reason or another, but we're making good progress. Similar updates will be continuing next week, and I've also got several ProMailer updates coming out next week too. Hope you all have a great weekend!
  13. 24 points
    This week I’m happy to report we now have WEBP support in ProcessWire thanks to a GitHub pull request from Horst Nogajski. This enables you to have highly optimized image output in PW and I think you’ll really like the difference it makes. Read on for all the details… https://processwire.com/blog/posts/webp-images-in-pw/
  14. 23 points
    Hi guys, today I want to share a little preview of my newly developed ModulesManager 2 module which is currently in beta. ModulesManager 2 provides an easy to use interface to download, update, install, uninstall and configure modules. It is meant to provide an optimized alternative to the ProcessModule dashboard. Maybe @ryan agrees to merge it to the core at some point when it is finished and polished. Features: Live-Search (aka find as you type) for categories Live-Search (aka find as you type) for module names Modern UIKit design Quick uninstall of a module Caches the module list from modules.processwire.com directory locally. There's a refresh button to get actual data. Preview video (with voiceover) Why a new module manager? Some people including myself think that the actual module installation in ProcessWire could be improved in many places. Make it easy for everybody! Lower the barrier for new users, and make it easier for existing users to find an install modules. That is one thing, that many other frameworks/CMS's have by default. Like ModX, WordPress or PrestaShop. What are the disadvantages of the actual core module interface? Installation of a module is not very user-friendly: You have to be aware where to get new modules, search for a module, copy or remember the module name or URL, go back to your ProcessWire installation, paste the module name , or URL, click on "get module info" and finally install the module It only displays installed modules, not the ones that are available in the modules directory, so it makes discovering modules hard. Uninstalling a module requires you to go to the module detail page, click a checkbox and then submit the change. After that you have to go back to the module overview page. It displays only limited information about the module History Back in 2012 Soma came up with ModuleManager, a module which displays modules as a table and provides functionality to download, update, install and configure modules (same as this module does). Sadly this module isn't maintained anymore (but it is still working) Then in 2019 Adrian came up with the idea of autocompleting the module name and Robin S developed the AutocompleteModuleClassName module which does this. This approachis a nice addition for devs who know which module they are looking for. But for all others we need a browsable experience, which provides more info than just the name. This was the perfect time for me to chime in, as I thought that module management is very cumbersome at its current state. A quick proof of concept / prototype was quickly developed. But then development slowed down, as I had to get more experience with vue.js first. Even as I was more experienced I stumbled into some problems that were to advanced for me to tackle. So I hired someone to help (yes, I even paid money for developing this module) TODO Install multiple modules at once like it is done in [ProcessModuleToolkit](https://github.com/adrianbj/ProcessModuleToolkit) add filter by installed/not installed / updateable / recommended Allow "search for module" to search in the description also, so a module can be found by its purpose and not only by its name Integrate the Readme or changelog of a module as it is done in [ModuleReleaseNotes](https://processwire.com/talk/topic/17767-module-release-notes/) This would have the following benefits: Make discovery of a module's changes prior to an upgrade a trivial task. Make breaking changes very obvious. Make reading of a module's support documentation post-install a trivial task. Make module authors start to think about how they can improve the change discovery process for their modules. Make sure the display of information from the module support files/commit messages doesn't introduce a vulnerability. I need your feedback This module is in development right now, and I am happy to discuss with you and get some feedback. I will publish it on github as soon as I have the time, so you can download it and analyze the code, and even provide pull requests. What do you like? What is missing? What could make the process even easier? Wink at @bernhard @adrian @Pete
  15. 23 points
    This latest version of ProcessWire on the dev branch adds a new Inputfield module called “Toggle” that is an alternative to the existing Checkbox Inputfield. It also adds a nicer way to make column width adjustments to your fields when editing a template. This post covers all the details with screenshots and a short video: https://processwire.com/blog/posts/pw-3.0.139/
  16. 23 points
    File Info A textformatter module for ProcessWire. The module can add information to local Pagefile links in two ways: As extra markup before, within or after the link As data attributes on the link (handy if you want to use a Javascript tooltip library, for instance) Screenshots Module config Example of output Installation Install the File Info module. Add the textformatter to one or more CKEditor fields. Configuration Add markup action (and general) Select "Add markup to links" Select the Pagefile attributes that will be retrieved. The attribute "filesizeStrCustom" is similar to the core "filesizeStr" attribute but allows for setting a custom number of decimal places. If you select the "modified" or "created" attributes then you can define a date format for the value. Enter a class string to add to the links if needed. Define the markup that will be added to the links. Surround Pagefile attribute names in {brackets}. Attributes must be selected in the "Pagefile attributes" section in order to be available in the added markup. If you want include a space character at the start or end of the markup then you'll need >= PW 3.0.128. Select where the markup should be added: prepended or appended within the link, before the link, or after the link. Add data attributes action Select "Add data attributes to links" Select the Pagefile attributes that will be retrieved. These attributes will be added to the file links as data attributes. Attributes with camelcase names will be converted to data attribute names that are all lowercase, i.e. filesizeStrCustom becomes data-filesizestrcustom. Hook If you want to customise or add to the attributes that are retrieved from the Pagefile you can hook TextformatterFileInfo::getFileAttributes(). For example: $wire->addHookAfter('TextformatterFileInfo::getFileAttributes', function(HookEvent $event) { $pagefile = $event->arguments(0); $page = $event->arguments(1); $field = $event->arguments(2); $attributes = $event->return; // Add a new attribute $attributes['sizeNote'] = $pagefile->filesize > 10000000 ? 'This file is pretty big' : 'This file is not so big'; $event->return = $attributes; }); https://github.com/Toutouwai/TextformatterFileInfo https://modules.processwire.com/modules/textformatter-file-info/
  17. 22 points
    Hey folks! Took a couple of late nights, but managed to turn this old gist of mine into a proper module. The name is SearchEngine, and currently it provides support for indexing page contents (into a hidden textarea field created automatically), and also includes a helper feature ("Finder") for querying said contents. No fancy features like stemming here yet, but something along those lines might be added later if it seems useful (and if I find a decent implementation to integrate). Though the API and selector engine make it really easy to create site search pages, I pretty much always end up duplicating the same features from site to site. Also – since it takes a bit of extra time – it's tempting to skip over some accessibility related things, and leave features like text highlighting out. Overall I think it makes sense to bundle all that into a module, which can then be reused over and over again 🙂 Note: markup generation is not yet built into the module, which is why the examples below use PageArray::render() method to produce a simple list of results. This will be added later on, as a part of the same module or a separate Markup module. There's also no fancy JS API or anything like that (yet). This is an early release, so be kind – I got the find feature working last night (or perhaps this morning), and some final tweaks and updates were made just an hour ago 😅 GitHub repository: https://github.com/teppokoivula/SearchEngine Modules directory: https://modules.processwire.com/modules/search-engine/ Demo: https://wireframe-framework.com/search/ Usage Install SearchEngine module. Note: the module will automatically create an index field install time, so be sure to define a custom field (via site config) before installation if you don't want it to be called "search_index". You can change the field name later as well, but you'll have to update the "index_field" option in site config or module settings (in Admin) after renaming it. Add the site search index field to templates you want to make searchable. Use selectors to query values in site search index. Note: you can use any operator for your selectors, you will likely find the '=' and '%=' operators most useful here. You can read more about selector operators from ProcessWire's documentation. Options By default the module will create a search index field called 'search_index' and store values from Page fields title, headline, summary, and body to said index field when a page is saved. You can modify this behaviour (field name and/or indexed page fields) either via the Module config screen in the PocessWire Admin, or by defining $config->SearchEngine array in your site config file or other applicable location: $config->SearchEngine = [ 'index_field' => 'search_index', 'indexed_fields' => [ 'title', 'headline', 'summary', 'body', ], 'prefixes' => [ 'link' => 'link:', ], 'find_args' => [ 'limit' => 25, 'sort' => 'sort', 'operator' => '%=', 'query_param' => null, 'selector_extra' => '', ], ]; You can access the search index field just like any other ProcessWire field with selectors: if ($q = $sanitizer->selectorValue($input->get->q)) { $results = $pages->find('search_index%=' . $query_string . ', limit=25'); echo $results->render(); echo $results->renderPager(); } Alternatively you can delegate the find operation to the SearchEngine module as well: $query = $modules->get('SearchEngine')->find($input->get->q); echo $query->resultsString; // alias for $query->results->render() echo $query->pager; // alias for $query->results->renderPager() Requirements ProcessWire >= 3.0.112 PHP >= 7.1.0 Note: later versions of the module may require Composer, or alternatively some additional features may require installing via Composer. This is still under consideration – so far there's nothing here that would really depend on it, but advanced features like stemming most likely would. Installing It's the usual thing: download or clone the SearchEngine directory into your /site/modules/ directory and install via Admin. Alternatively you can install SearchEngine with Composer by executing composer require teppokoivula/search-engine in your site directory.
  18. 21 points
    Mystique Module for ProcessWire CMS/CMF Github repo : https://github.com/trk/Mystique Mystique module allow you to create dynamic fields and store dynamic fields data on database by using a config file. Requirements ProcessWire 3.0 or newer PHP 7.0 or newer FieldtypeMystique InputfieldMystique Installation Install the module from the modules directory: Via Composer: composer require trk/mystique Via git clone: cd your-processwire-project-folder/ cd site/modules/ git clone https://github.com/trk/Mystique.git Module in live reaction with your Mystique config file This mean if you remove a field from your config file, field will be removed from edit screen. As you see on youtube video. Using Mystique with your module or use different configs path, autoload need to be true for modules Default configs path is site/templates/configs/, and your config file name need to start with Mystique. and need to end with .php extension. // Add your custom path inside ready or init function, didn't tested outside Mystique::add('your-configs-path'); All config files need to return a php array like examples. Same as ProcessWire Inputfield Api, only difference is set and showIf usage <?php namespace ProcessWire; /** * Resource : testing-mystique */ return [ 'title' => __('Testing Mystique'), 'fields' => [ 'text_field' => [ 'label' => __('You can use short named types'), 'description' => __('In file showIf working like example'), 'notes' => __('Also you can use $input->set() method'), 'type' => 'text', 'showIf' => [ 'another_text' => "=''" ], 'set' => [ 'showCount' => InputfieldText::showCountChars, 'maxlength' => 255 ], 'attr' => [ 'attr-foo' => 'bar', 'attr-bar' => 'foo' ] ], 'another_text' => [ 'label' => __('Another text field (default type is text)') ] ] ]; Example: site/templates/configs/Mystique.seo-fields.php <?php namespace ProcessWire; /** * Resource : seo-fields */ return [ 'title' => __('Seo fields'), 'fields' => [ 'window_title' => [ 'label' => __('Window title'), 'type' => Mystique::TEXT, // or InputfieldText 'useLanguages' => true, 'attr' => [ 'placeholder' => __('Enter a window title') ] ], 'navigation_title' => [ 'label' => __('Navigation title'), 'type' => Mystique::TEXT, // or InputfieldText 'useLanguages' => true, 'showIf' => [ 'window_title' => "!=''" ], 'attr' => [ 'placeholder' => __('Enter a navigation title') ] ], 'description' => [ 'label' => __('Description for search engines'), 'type' => Mystique::TEXTAREA, 'useLanguages' => true ], 'page_tpye' => [ 'label' => __('Type'), 'type' => Mystique::SELECT, 'options' => [ 'basic' => __('Basic page'), 'gallery' => __('Gallery'), 'blog' => __('Blog') ] ], 'show_on_nav' => [ 'label' => __('Display this page on navigation'), 'type' => Mystique::CHECKBOX ] ] ]; Searching data on Mystique field is limited. Because, Mystique saving data to database in json format. When you make search for Mystique field, operator not important. Operator will be changed with %= operator. Search example $navigationPages = pages()->find('my_mystique_field.show_on_nav=1'); $navigationPages = pages()->find('my_mystique_field.page_tpye=gallery');
  19. 21 points
    I've been working remotely this week and haven't had a good place to sit or very particularly reliable internet, so I've put my attention towards things that I could make progress with in small and inconsistent chunks of time. As a result, it worked well to focus on resolving issue reports this week. In addition to updates mentioned last week, 3.0.134 resolves 18+ issues and contains roughly 25 commits relative to 3.0.133. Since most of the commits since last week are focused on resolving issue reports, I don't have much to write here beyond what's in the commit log, but do want to thank everyone for their reports and hope that you have a great weekend!
  20. 20 points
    In this tutorial I want to write about handling special cases and change requests by clients gracefully without introducing code bloat or degrading code quality and maintainability. I'll use a site's navigation menu as an example, as it's relatable and pretty much every site has one. I'll give some examples of real situations and change requests I encountered during projects, and describe multiple approaches to handling them. However, this post is also about the general mindset I find useful for ProcessWire development, which is more about how to handle special cases and still keep your code clean by making the special case a normal one. The problem: Special cases everywhere Since ProcessWire has a hierarchical page tree by default, as a developer you'll usually write a function or loop that iterates over all children of the homepage and displays a list of titles with links. If the site is a bit more complex, maybe you additionally loop over all grandchildren and display those in drop-down menus as well, or you even use a recursive function to iterate over an arbitrary amount of nested child pages. Something like this: function buildRecursiveMenu(Page $root): string { $markup = ['<ul class="navigation">']; foreach ($root->children() as $child) { $link = '<a class="navigation__link" href="' . $child->url() . '">' . $child->title . '</a>'; $children = $child->hasChildren() ? buildRecursiveMenu($child) : ''; $markup[] = "<li class="navigation__item">{$link}{$children}</li>"; } $markup[] = '</ul>'; return implode(PHP_EOL, $markup); } But then the requests for special cases come rolling in. For example, those are some of the requests I've gotten from clients on my projects (by the way, I'm not saying the clients were wrong or unreasonable in any of those cases - it's simply something I needed to handle in a sensible way): The homepage has the company's name as it's title, but the menu link in the navigation should just say "Home". The first page in a drop-down menu should be the top-level page containing the drop-down menu. This was requested because the first click on the top-level item opens the sub-navigation instead of navigating to that page (espcially on touch devices, such as iPads, where you don't have a hover state!), so some visitors might not realize it's a page itself. Some top-level pages should be displayed in a drop-down menu of another top-level page, but the position in the page tree can't change because of the template family settings. The menu needs to contain some special links to external URLs. For one especially long drop-down menu, the items should be sorted into categories with subheadings based on a taxonomy field. In general, my solutions to those requests fall into three categories, which I'll try to elaborate on, including their respective benefits and downsides: Checking for the special case / condition in the code and changing the output accordingly (usually with hard-coded values). Separating the navigation menu from the page tree completely and building a custom solution. Utilizing the Content Management Framework by adding fields, templates and pages that represent special states or settings. Handling it in the code This is the simplest solution, and often the first thing that comes to mind. For example, the first request (listing the homepage as "Home" instead of it's title in the navigation) can be solved by simply checking the template or ID of the current page inside the menu builder function, and changing the output accordingly: // ... $title = $child->template->name === 'home' ? 'Home' : $child->title; $link = '<a class="navigation__link" href="' . $child->url() . '">' . $title . '</a>'; // ... This is definitely the fastest solution. However, there are multiple downsides. Most notably, it's harder to maintain, as each of those special cases increases the complexity of the menu builder function, and makes it harder to change. As you add more special conditions, it becomes exponentially harder to keep changing it. This is the breeding ground for bugs. And it's much harder to read, so it takes longer for another developer to pick up where you left (or, as is often cited, for yourself in six months). Also, now we have a hard-coded value inside the template, that only someone with access to and knowledge of the template files can change. If the client want's the link to say "Homepage" instead of "Home" at some point, they won't be able to change it without the developer. Also, each special case that is hidden in the code makes it harder for the client to understand what's going on in terms of template logic - thus increasing your workload in editorial support. That said, there are definitely some times where I would go with this approach. Specifically: For smaller projects that you know won't need to scale or be maintained long-term. If you are the only developer, and/or only developers will edit the site, with no "non-technical" folk involved. For rapid prototyping ("We'll change it later") Building a custom solution My initial assumption was that the main navigation is generated based on the page tree inside ProcessWire. But of course this isn't set in stone. You can just as easily forgo using the page tree hierarchy at all, and instead build a custom menu system. For example, you could add a nested repeater where you can add pages or links on a general settings page, and generate the menu based on that. There are also modules for this approach, such as the Menu Builder by @kongondo. This approach is not the quickest, but gives the most power to the editors of your site. They have full control over which pages to show and where. However, with great power comes great responsibility, as now each change to the menu must be performed manually. For example, when a new page is added, it won't be visible in the menu automatically. This is very likely to create a disconnect between the page tree and the menu (which may be what you want, after all). You may get ghost pages that are not accessible from the homepage at all, or the client may forgot to unpublish pages they don't want to have any more after they've removed them from the menu. I would only go with this approach if there are so many special cases that there hardly is a "normal case". However, even then it might not be the best solution. The direct relationship between the page tree, the menu structure and page paths are one of the strongest features of ProcessWire in my opinion. If many pages need to be placed in special locations without much structure in regards to what templates go where, maybe you only need to loosen up the template family settings. I have built one site without any template family restrictions at all - any page of any template can go anywhere. It's definitely a different mindset, but in this case it worked well, because it allowed the client to build custom sections with different page types grouped together. It's a trade-off, as it is so often, between flexibility and workload. Weigh those options carefully before you choose this solution! Utilizing the CMF This is the middle ground between the two options above. Instead of building a completely custom solution, you keep with the basic idea of generating a hierarchical menu based on the page tree, but add fields and templates that allow the editor to adjust how and where individual pages are displayed, or to add custom content to the menu. of course, you will still write some additional code, but instead of having hard-coded values or conditions in the template, you expose those to the client, thereby making the special case one of the normal cases. The resulting code is often more resilient to changing requirements, as it can not one handle that specific case that the client requested, but also every future change request of the same type. The key is to add fields that enable the client to overwrite the default behaviour, while still having sensible defaults that don't require special attention from the editor in most cases. I'll give some more examples for this one, as I think it's usually the best option. Example 1: Menu display options This is probably the first thing you thought of for the very first change request I mentioned (displaying the homepage with a different title). Instead of hard-coding the title "Home" in the template, you add a field menu_title that will overwrite the normal title, if set. This is definitely cleaner than the hard-coded value, since it allows the client to overwrite the title of any page in the menu. I'll only say this much in terms of downsides: Maybe the menu title isn't really what the client wanted - instead, perhaps they feel limited because the title is also displayed as the headline (h1) of the page. In this case, the sensible solution would be an additional headline field that will overwrite the h1, instead of the menu_title field. Which fields are really needed is an important consideration, because you don't want to end up with too many. If each page has fields for the title, a headline, a menu title and an SEO-title, it's much more complicated than it needs to be, and you will have a hard time explaining to the client what each field is used for. Another example in this category would be an option to "Hide this page in the menu". This could be accomplished by hiding the page using the inbuilt "hidden" status as well, but if it's hidden it won't show up in other listings as well, so separating the menu display from the hidden status might be a good idea if your site has lots of page listings. Example 2: "Menu link" template One solution that is quite flexible in allowing for custom links to pages or external URLs is creating a menu-link template that can be placed anywhere in the page tree. This templates can have fields for the menu title, target page and/or external target URL. This way, you can link to another top-level page or an external service inside a drop-down menu, by placing a Menu Link page at the appropriate position. This is also a clean solution, because the navigation menu will still reflect the page tree, making the custom links visible and easily editable by the editors. A minor downside is that those templates are non-semantical in the sense that they aren't pages with content of their own. You'll need to make sure not to display them in listings or in other places, as they aren't viewable. It may also require loosening up strict family rules - for example, allowing for Menu Link pages to be placed below the news index page, which normally can only hold news pages. Example 3: Drop-down menu override This one is a more radical solution to override drop-down menus. You add a repeater field to top-level pages, similar to the one mentioned as a custom solution, where you can add multiple links to internal pages or URLs. If the repeater is empty, the drop-down menu is generated normally, based on the sub-pages in the page tree. But if the repeater contains some links, it completely overrides the drop-down menu. It's similar to the fully custom solution in that as soon as you override a sub-menu for a top-level page, you have to manually manage it in case the page structure changes. But you can make that decision for each top-level page individually, so you can leave some of them as is and only have to worry about the ones that you have overwritten. Again, this offers sensible defaults with good customizability. A downside is that the mixed approach may confuse the client, if some changes to the page tree are reflected in the drop-down menu directly, while others don't seem to have any effect (especially if you have multiple editors working on a site). Finding the right solution So how do you choose between the approaches? It depends on the client, the requirements, and on what special cases you expect and want to handle. Sometimes, a special request can be turned down by explaining how it would complicate editorial workflows or have a negative impact on SEO (for example, if you risk having some pages not accessible from the homepage at all). Also, make sure you understand the actual reason behind a change request, instead of just blindly implementing the suggestion by the client. Often, clients will suggest solutions without telling you what the actual problem is they're trying to solve. For example: In one case, I implemented the drop-down override mentioned in example three. However, what the client really wanted was to have the top-level page as the first item in the drop-down menu (see the example requests mentioned above). So they ended up overwriting every single drop-down menu, making the menu harder to maintain. In this case, it would have been better to go with a more specialized solution, such as adding a checkbox option, or even handling it in the code, since it would have been consistent throughout the menu. Another example was mentioned above: If the client requests an additional "Menu title" field, maybe what they really need is a "Headline" field. I recommend reading Articulating Design Decisions by Tom Greever; it includes some chapters on listening to the client, finding out the real reason behind a change request, and responding appropriately. It's written from a design perspective, but is applicable to development as well, and since UX becomes more important by the day, the lines between the disciplines are blurred anyway. Conclusion I realize now this reads more like a podcast (or worse, a rant) than an actual tutorial, but hopefully I got my point across. ProcessWire is at is greatest if you utilize it as a Content Management Framework, creating options and interfaces that allow for customizability while retaining usability for the client / editor. I usually try to hit a sweet spot where the editors have maximum control over the relevant aspects of their site, while requiring minimal work on their part by providing sensible defaults. Above, I listed some examples of requests I've gotten and different solutions I came up with to handle those with custom fields or templates. Though in some cases the requirements call for a custom solution or a quick hack in the template code as well! What are some of the special requests you got? How did you solve them? I'd love to get some insights and examples from you. Thanks for reading!
  21. 20 points
    Repeater Images Adds options to modify Repeater fields to make them convenient for "page-per-image" usage. Using a page-per-image approach allows for additional fields to be associated with each image, to record things such as photographer, date, license, links, etc. When Repeater Images is enabled for a Repeater field the module changes the appearance of the Repeater inputfield to be similar (but not identical) to an Images field. The collapsed view shows a thumbnail for each Repeater item, and items can be expanded for field editing. Screencast Installation Install the Repeater Images module. Setup Create an image field to use in the Repeater field. Recommended settings for the image field are "Maximum files allowed" set to 1 and "Formatted value" set to "Single item (null if empty)". Create a Repeater field. Add the image field to the Repeater. If you want additional fields in the Repeater create and add these also. Repeater Images configuration Tick the "Activate Repeater Images for this Repeater field" checkbox. In the "Image field within Repeater" dropdown select the single image field. You must save the Repeater field settings to see any newly added Image fields in the dropdown. Adjust the image thumbnail height if you want (unlike the core Images field there is no slider to change thumbnail height within Page Edit). Note: the depth option for Repeater fields is not compatible with the Repeater Images module. Image uploads feature There is a checkbox to activate image uploads. This feature allows users to quickly and easily add images to the Repeater Images field by uploading them to an adjacent "upload" field. To use this feature you must add the image field selected in the Repeater Images config to the template of the page containing the Repeater Images field - immediately above or below the Repeater Images field would be a good position. It's recommended to set the label for this field in template context to "Upload images" or similar, and set the visibility of the field to "Closed" so that it takes up less room when it's not being used. Note that when you drag images to a closed Images field it will automatically open. You don't need to worry about the "Maximum files allowed" setting because the Repeater Images module overrides this for the upload field. New Repeater items will be created from the images uploaded to the upload field when the page is saved. The user can add descriptions and tags to the images while they are still in the upload field and these will be retained in the Repeater items. Images are automatically deleted from the upload field when the page is saved. Tips The "Use accordion mode?" option in the Repeater field settings is useful for keeping the inputfield compact, with only one image item open for editing at a time. The "Repeater item labels" setting determines what is shown in the thumbnail overlay on hover. Example for an image field named "image": {image.basename} ({image.width}x{image.height}) https://github.com/Toutouwai/RepeaterImages https://modules.processwire.com/modules/repeater-images/
  22. 20 points
    I've been in Minnesota all week for a family reunion and only a few minutes at the computer every day, so I don't have a core update or anything worthwhile to write about this week. But now I'm headed back home so will be back to a regular schedule next week. Hope that you have a great weekend!
  23. 20 points
    A sneak preview of a new page builder concept that I'm close to completing. I'll write more about this in coming weeks, but this video demonstrates a lot of unique things going on:
  24. 20 points
    WIP module (90% done) following this request expression of interest 😉 by @szabesz. A (Process) module that allows the posting of Notes in the ProcessWire admin. Inspired by WP Dashboard Notes (see video in link above). The module is almost complete. As usual, I hit a snag with the CSS! PRs highly welcome, please! (see below). Setting note sizes and display was a bit tricky. Module is now available for alpha testing here. https://github.com/kongondo/DashboardNotes Contributing I should have mentioned this earlier and done it properly but I am lazy, so this is the rough guide. I know we all have our preferences but please note: No heredoc syntax No alternative syntax for control structures (i.e. endif, etc) Indent using tabs (4) Doesn't matter in this case, but no PHP short tags For methods, opening curly bracket on same line as the method name (there's a technical wording for this, I can't remember now) Features Set Notes priority (low/normal/high) Note text and background colours Enable/disable replies to Notes Lock Notes for editing Viewing of Notes can be controlled using users IDs, roles or permissions. Default is all Notes can be viewed by all who have access to the module Edit Note after posting Global note settings (accessible only to those with dashboard-notes-settings permission) - default colours, date format, if users can delete notes they did not create, if users can edit notes they did not create, note display dimensions, maximum depth of (nested) replies, maximum characters of note preview before truncate, etc.) Sort notes by date, title or priority Pending Bulk actions (delete, lock, change priority, etc) Reply/commenting on notes More testing on visibility Requests/Ideas Mine is: PRs are welcome! Especially with the CSS and/or Design (Use the Dev Branch please) Display Note author title (if present, or any other named author title field) rather than their (user)name? Other? Screenshots Thanks!
  25. 20 points
    For the last couple months, I've been working on a module that does exactly this. It's not a site profile, it's not a theme. I don't know what term would accurately describe it, but its a ProcessWire module that's an opinionated, update-able starting point, oriented towards developers, and brings in a bunch of boilerplate like: an installer that will create fields, templates, pages, hannacodes; it runs through a thorough check before doing anything that may result in an error (module installation errors are aggravating; i'm testing it very thoroughly) the installer will rename your 'templates' dir to something temporary, and then copy a starting 'templates' folder that's prepped for the module (you should only do this on dev) if you try to add it to an existing site with a bunch of data, it will work as long as there are not collisions in some fields and templates; if there are, the module won't install and tell you what you need to change around to allow it to install establishes some new $config variables ('env', 'disableTemplateCache', a few others) built with UIkit 3 in mind, but not hardcoded to it a menu builder based on Repeaters with its own Process Module has its own seo+og+twitter+sitemap metadata fields and uses Profields FieldGroup since that is the best module for handling such a grouping has it's own templates inside the module which can be used, or overridden in /site/templates/; this includes blog sitemap.xml maintenance search in addition to template files being able to be overridden, partial files can be overridden too! some module configuration fields (site_name, maintenance, etc.) the module has documentation and other statistics built into it for easy reference takes full advantage of setting() and markup regions; applies attributes like UIkit 'uk-grid' and other data attributes without "touching" the html; keeps the module flexible and easily allows you to rip out UIkit and swap it for another CSS framework (Bootstrap 4); you'll never need to touch edit the _main.php file because of how regions has been set up has it's on RepeaterMatrix fields with boilerplate matrix-types (headline, text, slideshow, etc. etc.); if the user makes new custom matrix types and a later version of my module brings in a new matrix-type, it will update the RepeaterMatrix field and merge it correctly (tricky to do!); the matrix types use many of the same base fields, thereby allowing you to switch from one matrix type to another without data being destroyed (this was only possible as of 2 weeks ago with the new matrix update) to avoid creating a bunch of 1-off fields for the matrix field for block configuration, it uses the new and quite amazing Mystique fieldtype in a unique way (this was tricky to do); this module is critical to establishing a page-builder that is clean (this was only possible as of April 2019 since the module is brand new) brings in PW's debugger to the frontend (brings in jQuery UI); can be disabled all field and template names don't use any prefixes; this would allow you to dump the module one day in the future if you don't like it, without having a bunch of field and template names that sound too specific to the module Laravel Mix based asset compiler pre-configured with UIkit works with FormBuilder and other modules I often use; works and may require certain Pro modules; eliminates the need for any modules that do blogging, menu building, sitemap, maintenance or seo since this module does it using native ProcessWire login/logout/account/register templates it may include a 'collection' generator for common things like events, products, people, properties, along with some templates for those. don't like the templates my module provides? then just create your own template file in /site/templates/the-template-file.php which will override /site/modules/my-module-name/templates/the-template-file.php Right now I just started building a few sites with it (spent the last 2 months developing it) which will hammer it out further. I will release it late summer, early fall.
  26. 20 points
    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 a repeater item 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 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 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 > Github: https://github.com/FlipZoomMedia/InputfieldRepeaterMatrixDuplicate > PW module directory: – soon –
  27. 20 points
    In addition to Ryan's work in the codebase, I'd like to mention @matjazp, @Robin S and @adrian for their activity in the issue repo! (I know there are others - but these three stand out to me.) Six weeks ago there were 230+ open issues, we just dipped under 100.
  28. 19 points
    I've just upgraded the forums to the latest version 4.4.x as there was a critical security patch that warranted it. As usual, there is some pain in upgrading from a 4.x to 4.x branch due to template changes and feature changes/additions so you may find things have moved around a bit. There is still work to do on the template as this was a little rushed (security update forced my hand) but it should be functional at the very least. If you spot anything drastically broken that I may have missed, please let me know here. Minor template tweaks (fonts, alignment etc) will be updated in the next few days.
  29. 19 points
    Core version 3.0.137 on the dev branch adds the ability to hook multiple methods at once, in a single call. This post details how it works and provides a useful example of how you might put it to use in your development environment. This version also refactors and improves upon several core classes— https://processwire.com/blog/posts/pw-3.0.137/
  30. 19 points
    MarkupMenu is a markup module for generating menu trees. When provided a root page as a starting point, it generates a navigation tree (by default as a HTML "<ul>" element wrapped by a "<nav>" element) from that point onwards. If you've also provided it with current (active) page, the menu will be rendered accordingly, with current item highlighted and items rendered up to that item and its children (unless you disable the "collapsed" option, in which case the full page tree will be rendered instead). Modules directory: https://modules.processwire.com/modules/markup-menu/ GitHub repository: https://github.com/teppokoivula/MarkupMenu Usage As a markup module, MarkupMenu is intended for front-end use, but you can of course use it in a module as well. Typically you'll only need the render() method, which takes an array of options as its only argument: echo $modules->get('MarkupMenu')->render([ 'root_page' => $pages->get(1), 'current_page' => $page, ]); Note: if you omit root_page, site root page is used by default. If you omit current_page, the menu will be rendered, but current (active) page won't be highlighted etc. A slightly more complex example, based on what I'm using on one of my own sites to render a (single-level) top menu: echo $modules->get('MarkupMenu')->render([ 'current_page' => $page, 'templates' => [ 'nav' => '<nav class="{classes} menu--{menu_class_modifier}" aria-label="{aria_label}">%s</nav>', 'item_current' => '<a class="menu__item menu__item--current" href="{item.url}" tabindex="0" aria-label="Current page: {item.title}">{item.title}</a>', ], 'placeholders' => [ 'menu_class_modifier' => 'top', 'aria_label' => 'Main navigation', ], 'include' => [ 'root_page' => true, ], 'exclude' => [ 'level_greater_than' => 1, ], ]); Note: some things you see above may not be entirely sensible, such as the use of {menu_class_modifier} and {aria_label} placeholders. On the actual site the "nav" template is defined in site config, so I can define just these parts on a case-by-case basis while actual nav markup is maintained in one place. Please check out the README file for available render options. I'd very much prefer not to keep this list up to date in multiple places. Basically there are settings for defining "templates" for different parts of the menu (list, item, etc.), include array for defining rules for including in the menu and exclude array for the opposite effect, classes and placeholders arrays for overriding default classes and injecting custom placeholders, etc. 🙂 MarkupMenu vs. MarkupSimpleNavigation TL;DR: this is another take on the same concept. There are many similarities, but also some differences – especially when it comes to the supported options and syntax. If you're currently using MarkupSimpleNavigation then there's probably no reason to switch over. I'd be surprised if someone didn't draw lines between this module and Soma's awesome MarkupSimpleNavigation. Simply put I've been using MSN (...) for years, and it's been great – but there are some issues with it, particularly in the markup generation area, and it also does some things in a way that doesn't quite work for me – the xtemplates thing being one of these. In some ways less about features, and more about style, I guess 🙂 Anyhow, in MarkupMenu I've tried to correct those little hiccups, modernise the default markup, and allow for more flexibility with placeholder variables and additional / different options. MarkupMenu was built for ProcessWire 3.0.112+ and with PHP 7.1+ in mind, it's installable with Composer, and I have a few additional ideas (such as conditional placeholders) still on my todo list. One more small(ish) difference is that MarkupMenu supports overriding default options via $config->MarkupMenu. I find myself redefining the default markup for every site, which until now meant that each site had a wrapper function for MarkupSimpleNavigation (to avoid code / config repetition), and this way I've been able to leave that out 🙂 Requirements ProcessWire >= 3.0.112 PHP >= 7.1.0 If you're working on an earlier version of ProcessWire or PHP, use MarkupSimpleNavigation instead.
  31. 19 points
    After forgetting the class name of the wonderful AdminPageFieldEditLinks module for what feels like the 100th time I decided I needed to give my failing memory a helping hand... Autocomplete Module Class Name Provides class name autocomplete suggestions for the "Add Module From Directory" and "Add Module From URL" fields at Modules > New. Requires ProcessWire >= v3.0.16. Screencast Installation Install the Autocomplete Module Class Name module. Configuration Add Module From Directory Choose the type of autocomplete suggestions list: "Module class names from directory" or "Custom list of module class names". The latter could be useful if you regularly install some modules and would prefer a shorter list of autocomplete suggestions. The list of class names in the modules directory is generated when the Autocomplete Module Class Name module is installed. It doesn't update automatically (because the retrieval of the class names is quite slow), but you can use the button underneath when you want to retrieve an updated list of class names from the directory. Add Module From URL If you want to see autocomplete suggestions for the "Add Module From URL" field then enter them in the following format: [autocomplete suggestion] > [module ZIP url] Example: RepeaterImages > https://github.com/Toutouwai/RepeaterImages/archive/master.zip Awesomplete options The "fuzzy search" option uses custom filter and item functions for Awesomplete so that the characters you type just have to exist in the autocomplete suggestion item and occur after preceding matches but do not need to be contiguous. Uncheck this option if you prefer the standard Awesomplete matching. Custom settings for Awesomplete can be entered in the "Awesomplete options" field if needed. See the Awesomplete documentation for more information. https://github.com/Toutouwai/AutocompleteModuleClassName https://modules.processwire.com/modules/autocomplete-module-class-name/
  32. 19 points
    Quietly and without interruption this week, our whole website (and all subdomains) moved from a single static server to a load-balanced multi-server environment, giving us even more horsepower and redundancy than before— https://processwire.com/blog/posts/processwire-hosting-upgrades/
  33. 19 points
    Work continued in closing out issue reports this week. We’re down to about 60 of them now, though if we subtract issues that aren’t reproducible, are already marked as resolved (close pending), may be moved to the request repo, or are a discussion (rather than something to fix), then we’re closer to half that number. Over these last few weeks we’ve been working on issue reports, but I’ve also been enhancing the core in small ways as well. This post will cover a few of the useful enhancements that have been made in recent weeks— https://processwire.com/blog/posts/pw-3.0.130/
  34. 18 points
    ProcessWire 3.0.136 upgrades the version of CKEditor from 4.10.1 to 4.12.1. While that might look like a minor version bump, it’s actually 5 versions ahead and includes quite a lot of new features, changes and fixes. See the CKEditor release notes for more details on all that's been added and changed in the last 5 versions. It was a year or two ago where it seemed like CKEditor was going to be phasing out CKE 4 in favor of CKE 5. But interestingly it now seems like there is a new focus in CKE 4 from the CKEditor folks, so I’m going to have to start watching the version updates more often. Of course, I remain interested in CKE 5 too, but it’s nice to see CKE 4 (my favorite editor for a long time) going so strong and getting new features and attention, which is also a nice benefit for all of us PW users. I’m looking forward to working with some of the new stuff they’ve added in recent versions as well. For instance, the autocomplete feature sounds like it has nice potential for inserting Hanna codes or links to other PW pages, among other things. Also new in 3.0.136 is a new Debug::backtrace() static method in the core. I often use PHP’s debug_backtrace() method when debugging (and it appears in PW’s fatal exceptions), but the reality is it gives me a lot of stuff I just don’t want… all the hook method calls and such that aren’t usually relevant to what I’m trying to find. So the new built in Debug::backtrace() method returns a much simpler array than PHP does, and it also excludes all of the [likely] irrelevant internal hook method calls, and is just generally more focused on what you are likely to need from a backtrace in ProcessWire. It’s very convenient to plug into a ProcessWire $wire->message(Debug::backtrace()), or a Tracy Debugger bd(Debug::backtrace()); or even an echo '<pre>' . print_r(Debug::backtrace(), true); call. Though please consider this new method a work in progress, as it’s just a start at the moment and is likely to get additional updates. At some point, PW’s fatal exceptions will likely use the output from this method as well. Since this is kind of a short post, I’m just posting in the forums rather than creating a new blog post. More core updates on the way next week. Hope you all have a great weekend!
  35. 18 points
    I have sent a pull request on github for webP support in the core: https://github.com/processwire/processwire/pull/141 Explanation of its usage: I implemented two new options for the imagesizer that can be set globally in the site/config.php or can be passed within an individual options array to any size-method: $options = [ "webpAdd" => true, // boolean, if true, an additional webp variation will be created "webpQuality" => 80 // integer range 0 - 100, 100 is best ]; This creates an additional webp variation file besides the regular JPEG, PNG or GIF variations. In the template files you have two new image properties to work with the webp variation: $image->hasWebp; // boolean, true indicates that a webp variation is available for that image variation ?> <img src="<?= $image->srcWebp ?>" alt="" /> So we can create conditional markup like in this example: $image = $page->images->first()->size(300, 300); ?> <picture> <?php if($image->hasWebp) { ?> <source srcset="<?=$image->srcWebp?>" type="image/webp" /> <?php } ?> <source srcset="<?=$image->src?>" type="image/jpeg" /> <img src="<?=$image->url?>" alt="Alt Text!" /> </picture> The pull request and my test branch are based on this weeks pw dev branch. So if someone want to test it, please grab a copy, play with it and report back here. I don't know what timeline @ryan has and what parts need to be modified / rearanged, etc. Maybe the property names or the option names will be changed, but I think the main functionality will be close to that in the current test branch. ----- And here are a filesize comparision with different quality settings and with both engines, GD-Lib and IMagick: EDIT: An approach without conditional markup for webp comes from @arjen see lazyload. ...
  36. 18 points
    Glad you like the updates! Hope I didn't give the wrong impression, as I didn't intend to communicate anything about a "feature freeze" (as was stated in one of the messages above). At least nothing like that was, is, or ever will be planned, except maybe for a few days prior to a master version release. This is a stable project, but not a static one. There is no freezing or thawing, just the flow—I'll try to clarify... ProcessWire was originally built out of the needs of web development projects here, and that has always been a significant driver of what and when features are focused on at any point in time. When I add or improve something, it's usually because I'm going to be using it now and always going forward in actual projects, and by extension, can also support it in this project for everyone else. Of course, I only add/improve stuff that I know has significant benefit for all PW users, regardless of whether it's recognized in the short term or not. The other major part is features that arise from needs or contributions in the community here and on GitHub. My client projects are pretty similar to those of most PW users, which is good for the project. I'm always looking for ways to optimize and improve PW and its API, especially things that will save time in my and your projects, and this has always been the case. I'm driven by it. The feature focus is always holistic and never sacrifices backwards compatibility. And the product focus is on long term quality and sustainability, being the best tool for the job, not on being popular. The focus may largely be on issue reports right now, but this should not be interpreted to mean anything beyond resolving issue reports. I'm making continuous improvements and additions where appropriate along the way, as always. Perhaps they aren't big enough things to warrant blog posts now, but stay tuned — there is lots of good stuff on the way and currently in development. Every year there are a couple of important periods of good momentum in the issues repo, especially this time around, and so I'd like to continue that as long as possible and hopefully cover everything there. The difference this time is that we've got Netcarver expertly leading the effort as well as intelligently identifying which reports are still relevant. Plus there are a whole lot more "includes suggested fix" reports this time, thanks to people like Toutouwai and many others that know their way around the core extremely well, and often figure out how to resolve issues well before I do. It's a great community collaboration.
  37. 18 points
    Version 3.0.127 contains almost 30 new commits, the majority of which are focused on resolving older issue reports. For more details on those commits, see the commit log. This latest version on the dev branch also adds a couple of new features that you might find useful. Specifically, two new Page status flags: “unique” and “flagged”. Below we’ll go into more detail about what these are and how to use them. https://processwire.com/pw-3.0.127/
  38. 17 points
    No blog post this week because I don’t have anything new or interesting to write about just yet (unless you like to hear about repairing fridges and clothes dryers). But I’ve been focused primarily on completing the FormBuilder updates that I mentioned in last week’s blog post, and it’s looking very good, though I’ve still got a little further to go with it. When it comes to multi-page forms, I’m trying to cover all of the exceptional cases where sessions expire, cookies clear, etc., and want to make sure a form-in-progress continues to work through all these situations. Multi-page forms can be potentially long and people can invest lots of time in them (relative to regular forms), so trying to make it all as resilient as possible. This takes lots of time developing and testing, so that’s what I’ve been doing. I’ll be doing some of that next week too, though also have been planning to dig back into the core issues repo and start working through some of those in preparation for a new master version this Fall. Hope you all have a great weekend!
  39. 17 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.
  40. 17 points
    Just a quick update this week. I’ve got a good post in the works that I thought I’d have ready for today, but didn’t have quite enough time to finish it, so going to save it for next week. Though there's a module that's part of the post, and since it is ready, I've posted it below. We’ll look at ProcessWire 3.0.138 next week as well. I do have a couple of non-core updates to mention this week though. First is that I’ve released a new Textformatter module that converts any image references in your CKEditor/textarea fields to WEBP images on-the-fly as pages are rendered. If you are implementing WEBP on your site, you’ll find that the images placed in rich text fields are the most tricky ones to serve as WEBP, so this module takes care of that task for you. It's in the modules directory or at GitHub: https://github.com/ryancramerdesign/TextformatterWebpImages I’ve also released new development versions of the ListerPro and Export CSV modules, both of which are available to subscribers in the ListerPro support board. Some of the new features are actually built into the core, but currently only utilized by ListerPro. There’s quite a bit of new stuff, so there’s also an ~18 minute screencast that walks you through them, which can also be found in the ListerPro board.
  41. 17 points
    Version 3.0.135 of ProcessWire on the dev branch focuses on adding additional layers of security via .htaccess updates, adds clarity to debug mode, and improves upon the installer— https://processwire.com/blog/posts/pw-3.0.135/
  42. 17 points
    @ryan, may I point you to a WebP pull request? https://github.com/processwire/processwire/pull/141 And a ".htaccess only solution" for site wide webp support: https://processwire.com/talk/topic/14236-webp-support/page/2/?tab=comments#comment-184669 😉
  43. 16 points
    In the last few weeks... or almost months... I worked on a project for a restaurant. Sad to say that the company behind the restaurant went out of business before the project could be finished - or was paid or the website ever saw the light of day. As there is kind of a lot of work in it... but yet a lot of customization... I decided to create a site profile of it and make it public as ProcessWire Barebone Site Profile. Right now I'm stripping out every client detail and finish some functions and details that were planned a few weeks back so you can build right on top of it, if you like or want. Maybe it's only a playground for someone or an inspiration for how to f**k up data-mangement... but hey... better than a ZIP file on a backup drive. 😎 As the project was and is super tailor-made to that client, it may not work for a lot of restaurants out there, but nonetheless I don't want miss the opportunity to offer a foundation for upcoming restaurant projects you may face. The project had a huge focus on dishes, beer and wine variations so those templates are kind of feature-rich. You might want to rip out some of it as most restaurants don't focus that much on those details. Important details I want to be honest and clear about: this profile does NOT include a highly polished and usable frontend as the design is paid and therefore can't be made public the frontend will be a collection of re-usable snippets to show every possible detail of each page, item and whatever the whole site profile will be without any support - future updates aren't planned right now the site profile will be released in single-language setup only (english) existing translations (as seen in parts of the screenshots) will be changed to english existing data, for example dishes, will be replaced with demo content if you, one of your clients or anyone else wants to use this profile - feel free to do so Pro Modules were already stripped out of it only public modules were used and are included with the profile itself the full module list will soon be published on Github the full README will soon be published on Github the full LICENSE will soon be published on Github So... yes... that's just a short preview of an upcoming site profile. As mentioned before, the site profile will most likely never ever receive any future updates, so it will be available on Github only. It's not planned to publish this as a full featured site profile, yet. More details, screenshots and the site profile itself (of course) will be available soon. Questions? Please feel free to ask. Github Repository: https://github.com/webmanufaktur/pwbrestaurant
  44. 16 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/
  45. 16 points
    When your blog content is growing to some thousands of pages and you have comments scattered here and there, sometimes you start wondering if placing comments below each post is the best approach. Of course this totally depends on your project and contents. In my case I came to the conclusion I could provide a better user experience switching to a Forum-like solution, where discussions were organized by macro subjects and not below each individual post. Of course there are many products and services providing fully featured forum solutions, but getting only few comments per day I was reluctant to setup a dedicated forum and to deal with users' profiles. A nice thing of the comments system is that users do not need to create account and password, but simply use their email address. And here we are ... why not to setup a very basic Forum-like solution using PW Comments? But please do not get too excited… we will just use comments in a way that looks-like-a-forum. I think this solution makes sense if you have a limited number of comments per day spread on some topics. If you need to deal with high discussions traffic with several users ... do it with a fully featured forum solution !! To implement this Forum-like solution we will take benefits of (1) PW pages/templates flexibility (why you should be here otherwise…), (2) core module FieldtypeComments, (3) Uikit 3 Site/Blog Profile, (4) some of the tutorials I recently released about PW Comments (listed at the end). OK, let's start. Login into the Admin panel, select Setup, and then Fields. Let's create a checkbox field named "sticky" that we can use to keep some forum subjects on top of the communities. Now let's move to Setup, Template. We will create a new template with name "communities'. In addition to "title" field, we will add also "body" and "sidebarRight" fields (already available in the profile): Then we create a template, that we will use for individual communities, with name "community". In addition to "title" field, we will add "date", "body", "images", "comments" fields (already available in the profile) and the "sticky" field we have just created. If you wish, as I did, you can also associate some category fields. If you use Multi-Language is a good idea to use the field "date", as ,differently from createdStr, it will automatically return a locale-formatted date as you defined in the field. Now that we have created the templates, we need to customize them. Reopen the "communities" template. In the Family tab: allow the template to have children, allow only one page with this template, select "community" as only allowed template for CHILDREN. Then in the URLs tab: select allow page numbers. This will return a paginated list of communities. We reopen the "community" template. In the Family tab: do not allow the template to have children, allow to create new pages, select "communities" as only allowed template for PARENT. Now in the URLs tab: select allow page numbers. This will be necessary to create paginated comments. Let's go to the page-tree, under Home we will create a new page named "Community" using the templates "communities" (note the final s), this will be the page listing all the communities. Under the Community page, we will create the individual communities. Give the pages the name you wish and use the template "community" (note w/o the final s). It may be good creating one with the name "New Forum Requests" checking its "sticky" field so that it remains on top. As to implement this Forum-like solution, the comments pagination is a must, at this stage you will have to implement it as described in this tutorial: Now we are ready for coding (very little!) the php templates. We need to associate php files to the two templates we have created. In site/templates create two new php files communities.php and community.php. Open the template blog.php and copy its content to communities.php, then repeat the same operation copying the content of template blog-post.php to community.php. Great! We are few steps away from our Forum-like solution. Modify communities.php as follows: ... echo ukHeading1(page()->title, 'divider'); echo page()->body . '<br><hr>'; //>>>>> ADD THIS LINE //$posts = page()->children('limit=10'); //echo ukBlogPosts($posts); $posts = page()->children('sort=-sticky, sort=title, limit=10'); //>>>>> ADD THIS LINE echo ukBlogPosts($posts, ['moreText' => '', 'moreIcon' => '']); //>>>>> ADD THIS LINE ... Then modify community.php as follows: // blog post content echo ukBlogPost(page()); // comments if($page->hasField('comments')) { //>>>>> ADD THIS LINE $comments = page()->comments; // comment list if(count($comments)) { //echo ukHeading3("Comments", "icon=comments"); echo ukComments($comments->find("sort=-created"), ['paginate' => true]); //>>>>> ADD THIS LINE - READ PAGINATION TUTORIAL (NEEDED) echo '<hr>'; } // comment form $gdpr = __('I agree with the processing of my personal data. I have read and accept the Privacy Policy.'); //>>>>> ADD THIS LINE - READ GDPR TUTORIAL (OPTIONAL) echo ukHeading3(__('Join the discussion'), "icon=comment"); echo ukCommentForm($comments, ['labels' => ['gdpr' => $gdpr]]); //>>>>> ADD THIS LINE - READ GDPR TUTORIAL (OPTIONAL) } //>>>>> ADD THIS LINE Very good (hope so...). Now let's see the result. When browsing to the Community page we will get the list of the communities. In my example I decided to keep sticky the one where users can submit suggestions for new forum subjects. Selecting one of the communities we have created, we are going to see (1) a description of the community, (2) a paginated list of comments, (3) and the comment form at the bottom. Please note that in this picture pagination is kept with a limit of three items just to fit the image … It makes sense to have 10-15-20 comments per page depending on your preferences. And we are done, here it is. If you wish you can implement some additional features as described in the tutorials below. Not mandatory but probably makes good sense to enable the honeypot field as described in this tutorial as anti-spam measure: If you have the "pleasure" to deal with GDPR matters, here is described how to add a privacy checkbox to your comment form: and finally if you wish your Forum-like solution to be Multi-Language here it is what to do: I hope you enjoyed and wish you a nice week-end ! PS: it's a couple of tutorials I miss the emoj … hope they will come back in this forum soon !!
  46. 16 points
    This week I've been working on core 3.0.134 but am going to keep the version number at 3.0.133 for another week while I continue with updates there. Commit log. One of the updates already present that I'm finding quite useful is a nice upgrade to InputfieldSelector (like used by Lister and ListerPro) which simplifies the field selection process as there are no longer separate "Field" and "Field…" selections for fields that have subfields, and they are now bundled into one. This reduces the number of selectable fields and likewise speeds up the selecting/filtering process. I'll have more details on that next week, along with other updates. I'm going to be working remotely next week (not vacation) and do not yet know what the internet situation is going to be yet, so on the chance that I don't have good internet access, I may not have an update next week, but hopefully will. Have a great weekend!
  47. 16 points
    ProcessWire 3.0.133 adds a useful new $page->meta() method for a new type of page-specific persistent data storage, adds the ability for users to create their own bookmarks in Lister, and has a handy and time saving update for the asmSelect input type. Read on for all the details, examples and screenshots— https://processwire.com/blog/posts/pw-3.0.133/
  48. 16 points
    News Update - 3 May 2019 - Part One The little speckled fella has been very busy on the trail. Despite being the smallest of its kind, she has lofty dreams. We've been working on the API and the Products GUI. In the next post, I'll tell you more about the API. Products Features and GUI Though there are a few issues still pending (aren't there always? sigh), I am relatively pleased with the results. Of course, during beta testing we'll received and incorporate feedback as best as we can. Only UI-Kit theme will be officially supported. Multilingual fields if site is multilingual Ajax powered inputs for fast and convenient editing Four types of products Physical product requiring shipping Physical product not requiring shipping (for collection) Digital product Service/Event (etc) products - e.g. Swimming lessons, Consultancy services, Hotel booking, etc Product Classification (ajax powered) by: Type: e.g. Belt, trousers, etc Brand: Puma, Sanyo, whatever (editors can type in or import brand names + planning to support logos) Categories (aka Collections): Multiple categories, e.g. Men, Girls, Hospitality Tags: Multiple tags can be entered, e.g. sale, amazing, etc Product Variants (consists of an Option (e.g. Colour) and an Option Value (e.g. Red) Add zero or n variants as you wish Live preview as you build variants Each created product variant can be enabled/disabled. Devs can then decide to either show that variant as unavailable or not show them at all. That's up to you :-). Apart from classifications, shipping class, inventory policy, weight and dimensions units, title and description (and this latter one may change), almost all product properties will vary by variant if variants are used Product properties include: Images Colour (more on this below) Downloads (centralised and reusable) Price and Compare Price (aka former price) Inventory policy (whether to track or not) Charge taxes SKU (stock keeping unit) Inventory (quantity) Allow back orders (aka overselling) - @note: this can be set per variant. This is useful if one variant can be restocked faster than others Weight Length Width Height Weight Unit (mg, g, kg, oz, lb, t) Dimensions Unit (mm, cm, m, in, ft ) Shipping Class - can be used for product-based shipping if needed (e.g. bulky goods, light, fragile, small items, perishable, etc) Images (more on this below) Downloads (more on this below) Images Multiple images can be added to both a product and its variants (in case its has some). Images add to the product itself can be used with all variants Images added to a variant are tracked/tagged as belonging to only that variant In some cases, it may not make much sense to add different images for similar variants. For instance, a small red hat and a large red hat could probably share the same images. Although we do not currently support specifying an already uploaded image as belonging to a group of variants, this may change in the future Colour Similar to images, can be set at both product and its variants level Colour saved in RGBA format Downloads Also similar to images, can be populated for both both product and/or its variants Multiple files can be added to a product A file designated for 'whole' product will be available to download irrespective which variant of the product was purchased Conversely, a file or files saved for a variant will only be available to the buyer if they buy that variant of the product The above is useful if you want buyers to be able to download different files of the same product. For instance, recently someone needed to sell two versions of a font as part of one product. This is a solution for such cases. TODO List Lots! e.g. default settings for some properties, e.g. weight unit, shop currency, etc. For the frontend, we are creating a rich language-aware API that you can use to build your shop however you want. There will be no rendering of markup (but see first post in this thread about a separate fully functional frontend shop). In the next post, we talk a bit about the API. Before that, here are some screenshots and a video demo (if you can spare some 20 minutes away from watching, er..., cat videos? 😁) Screenshots Video Demo Thanks 🙂
  49. 16 points
    This week we take a look at what’s in ProcessWire 3.0.126 which focuses largely on resolving issue reports, but also includes a handy new $page->if() method— https://processwire.com/blog/posts/pw-3.0.126/
  50. 15 points
    This module is (or will be) the successor of RockGrid. It uses http://tabulator.info/ as grid library that is completely open sourced (MIT, no commercial extensions) and as far as I've seen so far at least as powerful as ag-grid, which RockGrid is using. GOALS: Support various data sources (RockFinder, JS, PHP, SQL) Supported only in PW Backend + Uikit Easy setup of new fields INSTALLATION: Just install the main module. RockMarkup is a required dependency. Please also have a look at the RockMarkup examples before jumping into RockTabulator! DEMO: STATUS: The module is early alpha and can be downloaded from github: https://github.com/BernhardBaumrock/RockTabulator It took me two weeks of rewriting RockMarkup/RockTabulator to get where I am now and I think I'm quite happy with the setup. There might be some breaking changes though in the near future. At the moment the main features that should be working properly are: Data sources: SQL, PHP, JS Sandbox for easy setup Multilang This means basically everything that is possible with Tabulator is also possible with RockTabulator. Though, there are no custom helpers/plugins yet. That's the next step and whoever is willing to help, please give me a shout 🙂 If you have any questions or ideas please let me know 🙂
×
×
  • Create New...