Jump to content

Chris Bennett

  • Content Count

  • Joined

  • Last visited

  • Days Won


Chris Bennett last won the day on February 22 2020

Chris Bennett had the most liked content!

Community Reputation

56 Excellent

About Chris Bennett

  • Rank
    Jr. Member

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. 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!
  2. Thank you Adrian, I love your work. Tried variations similar, but obviously not the right combo. You rock!
  3. 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.
  4. 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. 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" } ] }
  5. Many thanks @BillH, I will certainly investigate that thread further, it expands on some of the snippets I tried unsuccessfully along the way. In the meantime, I lucked upon the thread below, thanks to Bernard posting, which got me a lot further along the path. Still experimenting, with a fair degree of success so far, but not yet ready to claim it is "solved". Enjoying learning more as I go. Module I am playing around with - mainly to force myself to learn more about how everything really works - is an attempt to recreate what I am already using (via normal admin page, a couple of fields with a nifty preview/review using RuntimeMarkup and a couple of php templates). It generates favicons from svg right the way through (unlike realfavicongenerator), with a fallback for pngs and all the necessary markup, manifest, browserconfig etc. Similar to realfavicongenerator (which I have long loved), but tweaked according to my personal wishlist. Could accomplish what is *needed* pretty easily, but would really like to add some polish for clients. Also so they can easily see what we have done and/or do that stuff themselves πŸ˜‰ The php templates I am currently using simply by accessing the normal hidden admin page automatically generate: svg favicons for current gen browsers (if svg source provided) black safari pinned tab mask icon and white mstiles (if svg silhouette provided) automatic mask icon with required safe space for webmanifest automatic cropping of svgs/pngs so small icons can use the whole 16x16 or 32 x32 - because 3 or 4 px makes a big difference when you only start with 16 generation of webmanifest and browserconfig frontend markup for inclusion that basically just checks if the right file exists and plonks in the correct markup if it does Was a little surprised it seemed to work well. No zip files, no code, no third parties, plonk new sources in, click generate new, check results and done. Lots more previews/config options I could/will add but figured it might be wise to work out any inevitable kinks with implementation of a module along these lines within the api before I got carried away too much more.
  6. Thank you @bernhard, @adrian and @kixe for this thread and the very timely thank-you note from Bernard that pointed my in a far more productive direction with regards to my question from yesterday: Had been playing around with hooks to try to achieve my goals but this has made things a whole lot better and a whole lot easier. I kinda figured there had to be a way to hook into the form build process, but without this thread I would have remained lost for much longer as I played around the edges. My very grateful appreciation to all!
  7. Hi all, I am going round and round in circles and would greatly appreciate if anyone can point me in the right direction. I am sure I am doing something dumb, or missing something I should know, but don't. Story of my life πŸ˜‰ Playing round with a module and my basic problem is I want to upload an image and also use InputfieldMarkup and other Inputfields. Going back and forth between trying an api generated page defining Fieldgroup, Template, Fields, Page and the InputfieldWrapper method. InputfieldWrapper method works great for all the markup stuff, but I just can't wrap my head around what I need to do to save the image to the database. Can generate a Field for it (thanks to the api investigations) but not sure what I need to do to link the Inputfield to that. Tried a lot of stuff from various threads, of varying dates without luck. Undoubtedly not helped by me not knowing enough. Defining Fieldgroup etc through the api seems nice and clean and works great for the images but I can't wrap my head around how/if I can add/append/hook the InputfieldWrapper/InputfieldMarkup stuff I'd like to include on that template as well. Not even sure if it should be where it is on ___install with the Fieldtype stuff or later on . Not getting Tracy errors, just nothing seems to happen. If anyone has any ideas or can point me in the right direction, that would be great because at the moment I am stumbling round in the dark. public function ___install() { parent::___install(); $page = $this->pages->get('name='.self::PAGE_NAME); if (!$page->id) { // Create fieldgroup, template, fields and page // Create new fieldgroup $fmFieldgroup = new Fieldgroup(); $fmFieldgroup->name = MODULE_NAME.'-fieldgroup'; $fmFieldgroup->add($this->fields->get('title')); // needed title field $fmFieldgroup->save(); // Create new template using the fieldgroup $fmTemplate = new Template(); $fmTemplate->name = MODULE_NAME; $fmTemplate->fieldgroup = $fmFieldgroup; $fmTemplate->noSettings = 1; $fmTemplate->noChildren = 1; $fmTemplate->allowNewPages = 0; $fmTemplate->tabContent = MODULE_NAME; $fmTemplate->noChangeTemplate = 1; $fmTemplate->setIcon(ICON); $fmTemplate->save(); // Favicon source $fmField = new Field(); $fmField->type = $this->modules->get("FieldtypeImage"); $fmField->name = 'fmFavicon'; $fmField->label = 'Favicon'; $fmField->focusMode = 'off'; $fmField->gridMode = 'grid'; $fmField->extensions = 'svg png'; $fmField->columnWidth = 50; $fmField->collapsed = Inputfield::collapsedNever; $fmField->setIcon(ICON); $fmField->addTag(MODULE_NAME); $fmField->save(); $fmFieldgroup->add($fmField); // Favicon Silhouette source $fmField = new Field(); $fmField->type = $this->modules->get("FieldtypeImage"); $fmField->name = 'fmFaviconSilhouette'; $fmField->label = 'SVG Silhouette'; $fmField->notes = 'When creating a silhouette/mask svg version for Safari Pinned Tabs and Windows Tiles, we recommend setting your viewbox for 0 0 16 16, as this is what Apple requires. In many cases, the easiest way to do this in something like illustrator is a sacrificial rectangle with no fill, and no stroke at 16 x 16. This forces the desired viewbox and can then be discarded easily using something as simple as notepad. Easy is good, especially when you get the result you want without a lot of hassle.'; $fmField->focusMode = 'off'; $fmField->extensions = 'svg'; $fmField->columnWidth = 50; $fmField->collapsed = Inputfield::collapsedNever; $fmField->setIcon(ICON); $fmField->addTag(MODULE_NAME); $fmField->save(); $fmFieldgroup->add($fmField); // Create: Open Settings Tab $tabOpener = new Field(); $tabOpener->type = new FieldtypeFieldsetTabOpen(); $tabOpener->name = 'fmTab1'; $tabOpener->label = "Favicon Settings"; $tabOpener->collapsed = Inputfield::collapsedNever; $tabOpener->addTag(MODULE_NAME); $tabOpener->save(); // Create: Close Settings Tab $tabCloser = new Field(); $tabCloser->type = new FieldtypeFieldsetClose; $tabCloser->name = 'fmTab1' . FieldtypeFieldsetTabOpen::fieldsetCloseIdentifier; $tabCloser->label = "Close open tab"; $tabCloser->addTag(MODULE_NAME); $tabCloser->save(); // Create: Opens wrapper for Favicon Folder Name $filesOpener = new Field(); $filesOpener->type = new FieldtypeFieldsetOpen(); $filesOpener->name = 'fmOpenFolderName'; $filesOpener->label = 'Wrap Folder Name'; $filesOpener->class = 'inline'; $filesOpener->collapsed = Inputfield::collapsedNever; $filesOpener->addTag(MODULE_NAME); $filesOpener->save(); // Create: Close wrapper for Favicon Folder Name $filesCloser = new Field(); $filesCloser->type = new FieldtypeFieldsetClose(); $filesCloser->name = 'fmOpenFolderName' . FieldtypeFieldsetOpen::fieldsetCloseIdentifier; $filesCloser->label = "Close open fieldset"; $filesCloser->addTag(MODULE_NAME); $filesCloser->save(); // Create Favicon Folder Name $fmField = new Field(); $fmField->type = $this->modules->get("FieldtypeText"); $fmField->name = 'folderName'; $fmField->label = 'Favicon Folder:'; $fmField->description = $this->config->urls->files; $fmField->placeholder = 'Destination Folder for your generated favicons, webmanifest and browserconfig'; $fmField->columnWidth = 100; $fmField->collapsed = Inputfield::collapsedNever; $fmField->setIcon('folder'); $fmField->addTag(MODULE_NAME); $fmField->save(); $fmFieldgroup->add($tabOpener); $fmFieldgroup->add($filesOpener); $fmFieldgroup->add($fmField); $fmFieldgroup->add($filesCloser); $fmFieldgroup->add($tabCloser); $fmFieldgroup->save(); /////////////////////////////////////////////////////////////// // Experimental Markup Tests $wrapperFaviconMagic = new InputfieldWrapper(); $wrapperFaviconMagic->attr('id','faviconMagicWrapper'); $wrapperFaviconMagic->attr('title',$this->_('Favicon Magic')); // field show info what $field = $this->modules->get('InputfieldMarkup'); $field->name = 'use'; $field->label = __('How do I use it?'); $field->collapsed = Inputfield::collapsedNever; $field->icon('info'); $field->attr('value', 'Does this even begin to vaguely work?'); $field->columnWidth = 50; $wrapperFaviconMagic->add($field); $fmTemplate->fields->add($wrapperFaviconMagic); $fmTemplate->fields->save(); ///////////////////////////////////////////////////////////// // Create page $page = $this->wire( new Page() ); $page->template = MODULE_NAME; $page->parent = $this->wire('pages')->get('/'); $page->addStatus(Page::statusHidden); $page->title = 'Favicons'; $page->name = self::PAGE_NAME; $page->process = $this; $page->save(); } }
  8. See, more thanks needed :) Love your work Robin
  9. Thank you Robin S, I find myself continually (eventually) finding the answers I am looking for with your name attached. Many thanks! Had gone round and round using the wrong method for the job I wanted. In my case, was just trying to clean up fields added by a module generated page I was playing with. Deleting api generated page, templates and fieldgroups was very easy but kept on bumping up against deleting the fields. Finally realised I could just set a tag on them, but kept using the (very wrong) getTags() method instead of the delightfully easy find('tags=...). Knew I was doing something wrong and when I eventually found your advice was acting as expected in minutes. public function ___uninstall() { parent::___uninstall(); $page = $this->pages->get('name='.self::PAGE_NAME); if ($page->id) { $page->delete(); } $addedTemplate = $this->templates->get(MODULE_NAME); if ($addedTemplate) { $this->templates->delete($addedTemplate); } $addedFieldgroup = $this->fieldgroups->get(MODULE_NAME.'-fieldgroup'); if ($addedFieldgroup) { $this->fieldgroups->delete($addedFieldgroup); } $addedFields = $this->wire->fields->find('tags='.MODULE_NAME.''); foreach($addedFields as $addedField) { $field = $this->wire->fields->get($addedField); $this->wire->fields->delete($field); }
  10. I use this approach for breadcrumbs with built in structured data to help Google etc know what is going on. Could definitely generate separate json to do the same but I kinda like doing it once and not worrying. It's nothing fancy, just building on the default sample function. Mainly adds extra schema stuff and the current page, in an <ol> for semantics and accessibility. Rather than a function, I often just plonk it in my default where I want the breadcrumbs, surrounded by an if to see if I want to display them or not. <nav class="breadcrumbs" aria-labelledby="breadcrumblist"> <h2 id="breadcrumblist" class="visually-hidden">Breadcrumbs</h2> <ol itemscope itemtype="http://schema.org/BreadcrumbList"> <?php // Display breadcrumbs in a Google-friendly aria-compliant microdata format $count = 0; // count link depth foreach($page->parents() as $item) { $count++; // output parent pages, links and schema breadcrumb info echo'<li itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"> <a itemprop="item" href="' . $item->url . '"><span itemprop="name">' . $item->title . '</span></a> <meta itemprop="position" content="' . $count . '"></li>'; } // output the current page as the last item $count = $count+1; echo'<li itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"> <link itemprop="item" href="' . $page->url . '"> <span itemprop="name" aria-current="page">' . $page->title . '</span> <meta itemprop="position" content="' . $count . '"></li>'; ?> </ol> </nav> After that, touch of CSS and you're ready to go. Correct breadcrumb data and order reported with Structured Data Testing Tool and Rich Results Test.
  11. Plenty of posts on the forum relating to Content Security Policy (CSP) and how to integrate it with Processwire. It's not too hard to implement a decent htaccess CSP that will get you a solid B+ at Mozilla Observatory. If you're after A+ it's a little harder because of all the back-end stuff... until you realize it's surprisingly easy. After a lot of testing, the easiest way I found was to specify only what is needed in the htaccess and then add your required CSP as a meta in your page template. Plenty of people have suggested similar. Works very easily for back-end vs front-end, but gets complicated if you want front page editing. Luckily, a little php will preserve back-end and front page editing capabilities while allowing you to lock down the site for anyone not logged in. None of this is rocket science, but CSPs are a bit of a pain the rear, so the easier the better, I reckon πŸ˜‰ The only CSP I'd suggest you include in your site htaccess is: Header set Content-Security-Policy "frame-ancestors 'self'" The reason for this is you can't set "frame-ancestors" via meta tags. In addition, you can only make your CSP more restrictive using meta tags, not less, so leaving the back-end free is a solid plan to avoid frustration. Then in your public front-facing page template/s, add your desired Content Security Policy as a meta tag. Please note: your CSP should be the first meta tag after your <head>. For example: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Security-Policy" content="Your CSP goes here"> <!-- followed by whatever your normal meta tags are --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="format-detection" content="telephone=no"> If you haven't got Front Page Editing enabled, this works fine by itself. Just one extra step is needed to make sure you don't have to worry either way. The easiest way I found to allow both CSP and front page editing capabilities is the addition of a little php, according to whatever your needs are. Basically, if the user is a guest, throw in your CSP, if they're not do nothing. It's so simple I could have kicked myself when it finally dawned on me. I wish it had clicked for me earlier in my testing, but it didn't so I'm here to try to save some other person a little time. Example: <!DOCTYPE html> <html> <head> <?php if ($user->isGuest()): ?> <meta http-equiv="Content-Security-Policy" content="Your CSP goes here"> <?php endif; ?> <!-- followed by whatever your normal meta tags are --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="format-detection" content="telephone=no"> If you want it a bit more involved then you can add additional tests and be as specific as you like about what pages should get which CSP. For example, the following is what I use to expand the scope of the CSP only for my "map" page: <?php $loadMap = $page->name === "map"; ?> <!DOCTYPE html> <html> <head> <?php if ($user->isGuest()): ?> <meta http-equiv="Content-Security-Policy" content="default-src 'none'; base-uri 'self'; manifest-src 'self'; form-action 'self'; font-src 'self' data: https://fonts.gstatic.com; frame-src 'self' https://www.youtube.com; img-src 'self' data:<?php echo ($loadMap) ? " https://maps.googleapis.com https://maps.gstatic.com" : ""; ?> https://www.google-analytics.com; script-src 'self' <?php echo ($loadMap) ? "https://maps.googleapis.com " : ""; ?>https://www.google-analytics.com https://www.googletagmanager.com; style-src 'self' <?php echo ($loadMap) ? "'unsafe-inline' https://fonts.googleapis.com" : ""; ?>"> <?php endif; ?> Hope this saves someone a little time testing. https://observatory.mozilla.org/analyze/bene.net.au
  12. Sorry, I realized after sending that your pen had already done exactly that. My apologies and nice work!
  13. No worries mate. Yep, the label I added was just an addition for resizing the label and to ensure alignment, as I wasn't sure what other CSS was acting on it. You are spot on with needing to over-ride the .uk-checkbox:checked but it should be nice and easy with specificity because the attribute selector [type="checkbox"] should trump the class selector. Just add background-image:none and it should clear up the problem; input[type="checkbox"]:checked { border-color: #3eb998; background-color: #3eb998; background-image:none; }
  14. Sorry about delay, the curse of living in the Southern Hemisphere πŸ™‚ I'm not seeing anything too weird when setting label and checkbox to 0.85em on @LostKobrakai's example but it may be influenced by other CSS. If it's the alignment of the span in relation to the you toggle, you could add a little CSS for the label. Depending on your needs you might want to add a class to the label to limit it to your toggle. Either way, something along the lines of: label {display:flex;align-items:center;font-size:0.85rem;} and input[type="checkbox"] {font-size:0.85em; ...should make it smaller and align the text in the middle.
  15. @flydev's solution should do the trick for you, nice and clean, unlike the uikit one that had to negotiate the specificity issues inherent with uikit. If not I am happy to take a look for you.
  • Create New...