Jump to content

Chris Bennett

  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by Chris Bennett

  1. Nice one! Will keep that in mind for future as well. if($inputfield.hasClass('InputfieldIgnoreChanges')) return false; That said, it wouldn't have quite fitted my needs as I wanted it to be saved after the first ignore, so I would have had to remove the class anyway. Would definitely come in handy elsewhere.
  2. Reminder to myself to occasionally step back and think about what I am trying to do. Background: Working on an autocomplete function using google places. Allows clients or me to fill out boring address block and accurately geocode all at once from single input. No repetition, no fuss, for single business or multiple branches using repeaters. Not at all necessary, but figured why not, feels kinda nice and will not be costing me anything tucked away in the backend. "Problem" and ridiculously easy solution: Was working nicely, except when using enter/return to choose location, as save was getting fired on original input, throwing off the auto-filling. Stupidly, I spent too much time trying to chase down php and api solutions, using many hooks without success attempting to prevent the page and field from saving. Finally, feeling like a dumbarse, I took a step back and cursed my silliness. Yep. If the thing you want to work around is javascript, maybe try javascript to work around it. In the end, much to my embarrassment, the solution I sought was adding a few simple lines of js. Define the form, and preventDefault on the form's submit once. I cringe at how I missed the very simple solution while looking for the complicated workaround. Won't be the last mistake I make, by a long shot, but hopefully the last time I make this particular one :) window.addEventListener('focusin', function (event) { const input = event.target; if (input.classList.contains('autoComplete')) { // Below, the 4 very simple lines I should have thought of much, much sooner const form = document.getElementById('ProcessPageEdit'); form.addEventListener('submit', function(e) { e.preventDefault(); }, { once: true });
  3. Hi wise ones, have been going round in circles for a while, so figured I'd ask it's possible before going down the rabbit hole again. If it is possible, I'd love to maybe get a nudge in the right direction. I'm playing around with multisite using index.config.php and I can't get the usually simple symlink stuff for CSS/JS etc working. Have confirmed that I can access the directories and files and create the symlink. Unlike single site install, which has always been delightfully simple, I can't seem to get it working. Am I missing something really obvious or does it just not work because of the index.config.php symlinks to the site itself? As always, any pointers in the right direction are much appreciated.
  4. No worries Joe, yep Devtools is surely a little confusing at first, but once you get familiar with it, life gets easier. Definitely a very important tool in your webdev toolbelt, so the more you get used to it, the better. It will tell you about your javascript errors, show you what is getting loaded, from where, what is missing, let you know what your CSS is doing and all manner of stuff you need to know. The header problem might have gone away by simply renaming main.css if your page could no longer link to the CSS that was causing the problem. No idea which site profile you started with, but if you, for example, renamed main.css to anythingelse.css and didn't update the link to the css in your page with the renamed file, then the page rules set in main.css would no longer apply because they wouldn't be found. So something along the lines of: #masthead-logo img { /* image for masthead logo */ width: 100px; } would simply disappear removing the width restriction on that element.
  5. Hi @Joe_H. You can make whatever CSS changes you want to main.css, it is very much a starting point. Devtools in your browser of choice is really useful when troubleshooting why something isn't behaving how you want. Right-click on the culprit, inspect element, and the CSS involved is all there, which you can alter at will to test possible solutions You can also add as many links to your own CSS as you want by following the general method set out in _main.php. <link rel="stylesheet" type="text/css" href="<?php echo $config->urls->templates?>styles/whetevernameyouchooseasyourdefault.css" /> Processwire is not very opinionated at all on what you do with the data, so frontend styling is not something dealt with in the admin console by default. Basically, all you need to do is tell processwire what file to get and it will get it for you, but what you put in there is gloriously and flexibly up to you. All the fun stuff is up to you, processwire will just throw in data where you tell it to.
  6. Thank you to both @Zeka and @Robin S. I finally troubleshot my own head-scratcher to the point I was able to search for the right thing and, of course, was not surprised to find Robin involved in the exact answer I was looking for. You are both legends.
  7. Yes, you are absolutely correct that the nonce should be unique for each HTTP request. The nonce is basically just a handy way to load a number of scripts from different domains and have those permissions filter through to other scripts that might be loaded by the allowed scripts. So for a static page you'd probably want to go with the url allowlist method instead, similar to the $hasMapStyles / $cspStyleSrc combo.
  8. Sorry @DV-JF I can't be sure as I don't use ProCache. I can't imagine why it would, but I just can't say for sure. If there was a problem, I guess nonces could be replaced by URLs instead. Naturally, you'd want to make sure your CSP settings are suitable for your site or the devtools will quickly fill with lots of red :)
  9. 2021 update: bit easier, better security, no warnings about using <meta http-equiv="Content-Security-Policy">. Rather than rely on <meta http-equiv="Content-Security-Policy"> I have tweaked things a little. Bit more secure, bit easier to do and added nonce function as well to further lock down script-src. If we remove all CSP from htaccess we can define everything in one place and set header() with php instead, right before <!DOCTYPE html> I find it cleaner and easier to customize that way. Allows as much logic and conditional loading as you need. For example: <?php if ($user->isGuest()): $loadMap = $page->name === "map"; $hasMapImgs = ($loadMap) ? " https://*.googleapis.com https://maps.gstatic.com https://*.ggpht.com" : ""; $hasMapStyles = ($loadMap) ? " 'unsafe-inline' https://fonts.googleapis.com" : ""; $cspImgSrc = " img-src 'self' https://www.google-analytics.com data: 'self'" . $hasMapImgs . ";"; $cspStyleSrc = " style-src 'self'" . $hasMapStyles . ";"; $cspCond = $cspImgSrc.$cspStyleSrc; function generateRandomString($length = 25) { $characters = '0123456789'; $charactersLength = strlen($characters); $randomString = ''; for ($i = 0; $i < $length; $i++) { $randomString .= $characters[rand(0, $charactersLength - 1)]; } return $randomString; } $nonce = generateRandomString(35); $csp = "Content-Security-Policy: base-uri 'self'; frame-ancestors 'self'; default-src 'none'; child-src 'self'; manifest-src 'self'; form-action 'self'; connect-src 'self' https://www.google-analytics.com https://maps.googleapis.com; font-src 'self' data: https://fonts.gstatic.com; frame-src 'self' https://www.youtube.com; script-src 'self' https: 'unsafe-inline' 'nonce-" . $nonce . "' 'strict-dynamic';" . $cspCond ; header($csp); ?> <?php endif; ?> <!DOCTYPE html> https://observatory.mozilla.org/analyze/www.alfresco-bar-bistro.com.au
  10. Sweet! ? I love your work and many, many thanks! Although I am disappointed not to be able to use Option B: Percentage based, this at least got rid of the plethora of inline width declarations and the very unwanted maxColHeightSpacer div. Also helps narrow down where the issue might lie. Maybe something about the upgrade has 'reverted' the B option to use the older js inline width and height declarations? Or perhaps a newly added feature to deal with some use-case. Either way, I am stoked for your help and mightily relieved. Love your work, you are a legend!
  11. Thanks Robin, I will have a play with that. Anything to help me avoid the pain and unnecessary layout shift is welcome. That said, I was definitely previously using the Percentage based widths option.
  12. Thanks Robin, I appreciate your comments. I have never used any theme apart from AdminThemeUiKit and 100%, the inline styles are injected by js. My confusion comes from them not being injected in this way in the previous master dev. It's why I was surprised both the inline styles that hadn't been there previously and maxColHeightSpacer suddenly appeared after upgrading from 3.0.165. In fact, looking again, both maxColHeightSpacer and style="width: 35%;" data-original-width="33" are being added on the same custom module. Previously it had been a perfectly horizontally aligned radio inputfield, with a simple data-colwidth="width: 33%", which could be over-ridden easily allowing margins and borders and fun stuff. On upgrade, it suddenly had a 24px vertical spacer div inserted underneath, flex alignment was thrown out, and the style="33%" meant it wouldn't flex properly any more. Examples shown using my tweaked AdminThemeUiKit theme. Admittedly, I have played around with AdminThemeUiKit for probably way too many hours. I guess it has to be in the 1000's by now ...sheesh... That means very little, except to say I am pretty familiar with how it works, what it does and how it does/did it. Results are the same in default AdminThemeUIKit. Example: Post upgrade, pre addition of formerly unnecessary !important overrides. Example: Post upgrade, after a long string of formerly unneeded !important declarations applied, back to what it had previously looked like. But throughout the admin, wherever there was formerly a simple data-colwidth, there is now a new inline style declaration. It's the new bit that I don't get. I don't understand why the js injection wasn't necessary for 3.0.165 but needs to be there for 3.0.184.
  13. Hi all, have just upgraded to 3.0.184, a little late to the party. Not sure about a few things and would love to understand better. It seems to me like there is now an increased over-reliance on inline style width declarations on Inputfields. To me, they seem like extra bits of unnecessarily specific css that impede easily customisable CSS. I can't wrap my head around why they are needed. Surely CSS and flexbox can do this better, easier, with much greater flexibility, less javascript, less thread work, less bytes and less layout shifts? In previous versions, data-colwidth on everything with a width worked just fine. Was very easy to target li[data-colwidth] and use calc to add a margin if desired and use flexbox to flex like a champion, taking up available space. Lovely, simple, flexible and lightweight. Now it seems some wrappers have a style="width: ..." where once they had data-colwidth and some Inputfields have data-original-width. Each can technically be over-ridden using ...sigh... a multitude of repetitive !important declarations, but that is not ideal. Is there something I am missing? Is there a reason the inline width styles were needed? Is there a benefit I am unaware of? Can I help provide possible alternate solutions to whatever use case necessitated it? In a similar vein, I also got to see maxColHeightSpacer for the first time. Can't say it was a pleasure for it to appear. Similar to the use of inline style="width:..." on Inputfields, in the age of flexbox I don't understand why a spacer div with inline height is needed. Is there a need for it I just don't get? Hadn't seen it before but found some info from a few years ago here: Anyway, I would honestly love any insight on any of this. Would love to understand the 'why' and, if possible, help.
  14. Thanks to the excellent feedback from @matjazp , have re-vamped way the whole module works. Minimizes potential conflicts and was just a better idea. Now draws CSS variables, conditionally loaded source CSS and framework CSS together to generate single minified CSS file, with version control link to refresh cache for other pages. Only occurs when the module is visited, as it should, and after that other pages draw the minifed CSS straight from cache. Now loads in parallel with other CSS. at somewhere around 30ms, same as other CSS files. First load (in the module itself, not subsequent pages) comes in around 17 kB compressed (somewhere around 96kB uncompressed and with all options selected), so considerable improvement, especially given the elimination of almost all processing overhead. Very happy I was prodded into action. Took a little time, but I am much happier going forward. As part of the re-working, I am in the process of splitting up CSS for conditional loading according to user selections. Opens up a far greater range of user options, which I am rolling out to module as I go. As a bonus, splitting the source CSS up is making it easier for me to track and alter, allowing me to simplify the CSS and balance specificity better. Always nice when file sizes are going down, not up even though you are adding new stuff :)
  15. https://github.com/chrisbennett-Bene/AdminThemeTweaker Inspired by @bernhard's excellent work on the new customisable LESS CSS getting rolled into the core soon, I thought I would offer up the module for beta testing, if it is of interest to anyone. It takes a different approach to admin styling, basically using the Cascade part of CSS to over-ride default UiKit values. Values are stored in ModuleConfig Module creates a separate AdminThemeTweaker Folder at root, so it can link to AdminThemeTweaker.php as CSS AdminThemeTweaker.php reads the module values, constructs the CSS variables then includes the CSS framework Can be switched on and off with a click. Uninstall removes everything, thanks to bernhard's wonderful remove dir & contents function. It won't touch your core. It won't care if stuff is upgraded. You won't need to compile anything and you don't need to touch CSS unless you want to. It won't do much at all apart from read some values from your module config, work out the right CSS variables to use (auto contrast based on selected backgrounds) and throw it on your screen. You can configure a lot of stuff, leave it as it comes (dark and curvy), change two main colors (background and content background) or delve deep to configure custom margins, height of mastheads, and all manner of silly stuff I never use. Have been developing it for somewhere around 2 years now. It has been (and will continue to be) constantly tweaked over that time, as I click on something and find something else to do. That said, it is pretty solid and has been in constant use as my sole Admin styling option for all of those 2 years. If nothing else, it would be great if it can provide any assistance to @bernhard or other contributor's who may be looking to solve some of the quirkier UiKit behavior. Has (in my opinion) more robust and predictable handling of hidden Inputfields, data-colwidths and showIf wrappers. I am very keen to help out with that stuff in any way I can, though LESS (and any css frameworks/tools basically) are not my go. I love CSS variables and banging-rocks-together, no-dependency CSS you can write with notepad.
  16. Weird edge case, which has me scratching my head. Background: API-added button to delete selected files exhibits (maybe) weird behavior when save is triggered by custom js. As soon as the InputfieldSubmit field is there, it intercepts/captures the javascript trigger instead. Almost like validation or as if it's acting as an anchor. It definitely seems like the inclusion of that InputfieldSubmit causes the unexpected (by me) behavior. Have tried multiple different workarounds to troubleshoot: deleting trigger does nothing deleting hook does nothing moving InputfieldSubmit outside MarkupAdminDataTable does nothing changing name and/or id of InputfieldSubmit does nothing If the new InputfieldSubmit is there, it 'catches' the custom js save trigger. If the field is not added (or hidden then loaded by AJAX), then the custom js trigger happily clicks the save_submit id, and page save happens, as expected. console.log confirms 'submit_save' is the element' the js was targeting. The js save hangs, and window.parent.document.activeElement (and your eyes) confirm the new InputfieldSubmit button is now the active element. Setting InputfieldSubmit as button prevents the weirdness, but doesn't provide the desired functionality. As type=submit, the files are deleted snappily, and the refreshed page is displayed showing they are gone. So it's very much a weird edge case, but I'd love to know what is happening behind the scene if anyone has any ideas or experience with similar issues. Simple custom js is below: if (input.classList.contains('autoSaveOnChange')){ if (input.classList.contains('autoGenerateNew')){ var generateCheckbox = getById('Inputfield_generateNewFavicons'); var showAdvanced = getById('Inputfield_showAdvanced'); generateCheckbox.checked = true; showAdvanced.checked = false; }; input.closest('.InputfieldContent').classList.add('saveLoading'); var saveSubmit = getById('submit_save') || getById('Inputfield_submit_save_module'); //console.log(saveSubmit) saveSubmit.click(); } InputfieldSubmit is added as follows: // Add in button to delete fields $button = $this->modules->get('InputfieldSubmit'); $button->attr('id+name', 'deleteSelectedFolders'); $button->value = 'Delete selected folders'; //button->type = 'button'; auto save works with this, but hook does not $field->add($button);
  17. Hi Kaz, I am by no means an expert. It *could* be a problem with the actual server variables, had a little "fun" with that end, working out what had changed when Siteground made some changes. In my case, setting the timezone properly (again) solved my server problem. Re: config my locale mirrors yours with the exception of setting $config->timezone as well. $config->timezone = 'Australia/Brisbane'; setlocale(LC_ALL,'en_AU.UTF-8'); Hope you get it sorted, sorry I can't be of more assistance.
  18. Thanks Bernard! The mobile preview bit is from the first pw module I am preparing to release into the wild, very shortly, FaviconMagic. Been using it for many months now, but wanted to make it shinier and stress test it before offering it up. Was complicated a little by the background admin styling, which is from another module I plan to release into the wild shortly ...have been using and tweaking it for around 2 years now, since we discussed admin theme tweaking strategies. Just tweaking FaviconMagic now, adding features and trying to break it so I can make it better. Planning to throw it up on Github soon - probably within the week - depending on how much stuff I keep adding ? FaviconMagic is kinda like realfavicongenerator, but I am aiming to take that up a notch (or two) for the processwire community. I have learned much and the processwire community have always been very gracious with their time and advice. Adds support for svg favicons (cutting out unnecessary downloads), autogenerates a maskable favicon, generates webmanifest and browserconfig etc. Basically a shortcut to full PWA requirements, minus the service Worker stuff. You can generate new favicons and play around with a whole heap of stuff without leaving pw admin. Also uses "smarter" options. For example, short_name is apple app name, unless you choose to over-ride it. Theme color is similar, you don't need to cut and paste the same stuff multiple times, but advanced config is always available if you desire it. Apart from a one-off include in the head of the target doc, there is no copy/paste of markup. Always up to date with your latest tweaks. No unzipping either. Generation of all png variations from svg resizing for crispy goodness. More than happy to give you a yell when the beta is up on Github if you'd like, I would love to hear what you think.
  19. Many thanks Horst, confirmed my thinking. After happily and messily playing around, a tiny voice deep in my memory whispered "sandbox" ...sheesh. Been a while since I played around with sandboxed iframes, but the little voice from the past was right. Simple addition of sandbox to the iframe automatically prevents get/set of cookies. So I could get it doing what I wanted by adding: <iframe sandbox="allow-same-origin" src="..."> Apologies for not remembering sooner, I will be busily head-desking over in the corner now ?
  20. Edit: Belated memory that iframe sandbox exists, so there is a simple way to provide page preview as guest. <iframe sandbox="allow-same-origin" src="..."> Prevents get/set of cookies and scripts by default, so simple workaround. Drawback is that little things like your js dark mode etc won't be active either, but for simple preview needs bit easier than the other things I unsuccessfully tried. Page preview as guest from within admin... is there an easy strategy? If any wise heads have any ideas for how I can "log out" only from the iframed link or if there is a query I can pass with the iframe url, I would be very grateful. Can access the iframed url via js to change things, like successfully getting rid of scrollbars etc, but before I delve further along that route was wondering if there is an easier way. Making a little mobile preview for favicon generator/webmanifest thing I'm working on. Not really important (or necessary) - pretty much editor bling to provide instant feedback in a non-new, mid-range android. Working pretty well, with lots of irrelevant silliness like swapping colors of mobile top icons based on contrast. Frivolous but kinda fun. Homescreen / clickable app icon and short_name based on generated favicons and values. Click homescreen icon to start screen with theme color, app start icon and long name. Figured I'd throw in iframe of the site to round things out preview-wise. No problems there, but session remains as admin, so not really a "guest preview" with front-end editing styling, Tracy and various admin stuff.
  21. Slight adjustments to enhance use for 2021 and to remind me how I can make it work when I forget and need to use Google as my offline memory
  22. Very much appreciate the tip. Had taken a look with code inspector, but must have stuffed up my typing, then tried way too many other potential options. Next time, if in doubt I will use Tracy to confirm. Can't believe I didn't think of that, Saturday afternoon brain is not working as well as I would like. Many thanks again!
  23. Thank you Adrian, I love your work. Tried variations similar, but obviously not the right combo. You rock!
  24. Having no joy trying to find out how to trigger InputfieldRadiosFloated on InputfieldRadios via api for module. Basically just want same as Radio Button Column options on "normal" field. Guessing at what the magic words might be has not got me far ? Figure it has to be do-able, and is probably easy, just can't work out how. Any help pointing me in the right direction, or at a good run down of the options in general would be very gratefully accepted.
  25. 2021 update These things change and get tweaked over time, as stuff always does. We can make the size declaration a little more relevant. Declare a selection of sizes for your svg to "encourage" chromium-based browsers to use it instead of the larger bitmapped 192x192 and other assorted icons. We also need to thread the needle to ensure app start icons don't get confused and end up with an icon that is smaller than desired. Declare it last, after your png fallbacks - last one that is suitable size *must* get the nod. Counter-intuitively, declare that your svg is 150x150. (adjusted for 2021) ? "sizes": "48x48 72x72 96x96 128x128 150x150 256x256 512x512 1024x1024", { "name": "Alfresco bar + bistro, Eumundi", "short_name": "Alfresco", "description": "Relaxed outdoor dining on our spacious deck in Eumundi", "start_url": "/", "display": "standalone", "background_color": "#acbd72", "theme_color": "#acbd72", "icons": [ { "src": "https://www.alfresco-bar-bistro.com.au/site/assets/files/favicons/favicon-48x48.png", "sizes": "48x48", "type": "image/png", "purpose": "any" }, { "src": "https://www.alfresco-bar-bistro.com.au/site/assets/files/favicons/favicon-192x192.png", "sizes": "192x192", "type": "image/png", "purpose": "any" }, { "src": "https://www.alfresco-bar-bistro.com.au/site/assets/files/favicons/favicon-512x512.png", "sizes": "512x512", "type": "image/png", "purpose": "any" }, { "src": "https://www.alfresco-bar-bistro.com.au/site/assets/files/favicons/maskable-512x512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }, { "src": "https://www.alfresco-bar-bistro.com.au/site/assets/files/favicons/favicon.svg", "sizes": "48x48 72x72 96x96 128x128 150x150 256x256 512x512 1024x1024", "type": "image/svg+xml", "purpose": "any" } ] } Cross-Origin-Resource-Policy (CORP) manifest/icon bug A slightly-related testing note, if you are incorporating Cross-Origin-Resource-Policy (CORP) to enhance site security. Please note there is a chromium bug which affects chromium dev tools ability to properly display your manifest icons: Chromium DevTools bug: Cross-Origin-Resource-Policy prevents manifest icons from loading This long-term bug doesn't seem to affect the way the manifest itself works or the icons, just their display in Dev tools > Application > Manifest in Chrome, Edge, Brave, Opera... sheesh. Firefox Dev tools continues to happily display them without a problem. ------------------------------------------------------------------------------------ Quick tip for 2020 web manifests, which I couldn't find anywhere else. Wanted web manifest on Chrome/Edge to download the tiny favicon svg, instead of the larger 192x192 png it wanted to by default. Not a big deal, but mildly annoying: 15kb (non-scalable) png vs 1.5kb (infinitely scalable) svg. After a little head-scratching and fiddling around, came up with a solution that seems to do the trick. Declare it last, after your png fallbacks - last one that is suitable size *must* get the nod. Counter-intuitively, declare that your svg is 150x150. (adjusted for 2021) Mine isn't. Never has been, it's a scalable vector graphic. Simply declaring it is 150x150 in the manifest is enough to get the job done. Suspect the Chrome/Edge engine declares that any non-specified svgs are given that 150x150 size and anything else returns as a "fail". Without declaring a size on it, or declaring it as anything other than 150x150, it just wouldn't load. Weird, but works, so I'm happy ? { "name": "Longer App/Business Name", "short_name": "Short Name", "description": "Description of App/Business", "start_url": "/", "display": "standalone", "background_color": "#880000", "theme_color": "#880000", "icons": [ { "src": "favicon-192x192.png", "sizes": "192x192", "type": "image/png", "purpose": "any" }, { "src": "favicon-512x512.png", "sizes": "512x512", "type": "image/png", "purpose": "any" }, { "src": "maskable-512x512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }, { "src": "favicon.svg", "sizes": "150x150", "type": "image/svg+xml", "purpose": "any" } ] }
  • Create New...