Jump to content

MarkE

Members
  • Posts

    931
  • Joined

  • Last visited

  • Days Won

    10

Everything posted by MarkE

  1. This is a s lightly obscure issue, but hopefully very easy to deal with. If a page only has one child, then the child doesn't necessarily have a sort attribute. In this case, BatchChildEditor will add a sort attribute and save the page. This seems to me to be unnecessary (and is causing a small problem with a module of mine). Is it possible and reasonable to not set the sort if there is only one child? The relevant code is at the end of the saveChildren() method: $cp->sort = $i; if($cp->isChanged()) { $cp->of(false); $cp->save(); } I think it would need something like: if($this->wire('input')->post->individualChildTitles->count() > 1) { $cp->sort = $i; } if($cp->isChanged()) { $cp->of(false); $cp->save(); } but maybe there is a better solution?
  2. Start by putting your html inside the foreaches. As coded you will only pick up the last item in each loop.
  3. FWIW I have made a little work-round that saves $template->getExportData() as a session var on 'ready' then compares it with the changed value, hooked in 'saved'. It seems to work, but there must be a less clumsy way. trackChanges etc is not very helpful.
  4. Thanks @Jan Romero, but that deals with pages (and the values of their fields). What I am after are the field and template objects themselves.
  5. A simple question: Is there any way, when a template or field is saved of getting the previous properties (i.e. before the save)?
  6. Probably because ProcessWire has such a nice well-documented API 😀. I played with it a bit and it knows how to build modules, but when I asked it to build an inputfield module, the code was what you might use for an inputfield on a page. I am trying to think of how to educate it with the correct context 🤔.
  7. Yes. I realised after my last update that was probably the cause and that there is no delay in setting up. Maybe a small update to the module documentation? Anyway a really helpful module and very easy to install in Formbuilder. Thanks a lot!
  8. Hi @MoritzLost. I just installed this and added a field to my form in Formbuilder as per instructions with secret and site keys from hCaptcha, but nothing shows in the form. Any idea what might be wrong? UPDATE It seems to be working now. Maybe it just takes time for a new site to be recognised.
  9. I have a little home-made pagebuilder that is based on RockFrontend and Tailwind and have a few observations that might (or not) be of interest. Tailwind works really well with Latte. The result is (to my mind) concise and understandable code that is easily encapsulated. I tried some of the plugin components etc. but was generally disappointed. As is usually the case with these things, you get a load of baggage you didn't really want and then you try and customise it slightly and it is not easy. I ended up just building my own components with Latte, Tailwind and a bit of custom vanilla js (with a bit of help from various examples on the www). For example, I built a general-pupose carousel template that can be called via a Latte {include file} with options, e.g.: {include $config->paths->templates . 'motif_layouts/latte_blocks/motif_carousel.latte', imagePages: $page->motif_image_page, modal: true, } and {include $config->paths->templates . 'motif_layouts/latte_blocks/motif_carousel.latte', imagePages: $page->motif_image_page, start: $page->motif_image_page->first, autoCycle: ['speed' => 5000] } My pagebuilder makes extensive use of css grid-area-templates which are not present in Tailwind. I thought this might be a bit of a problem, but was pleasantly surprised that the css file reduced from this: .image-text .has-image { /*grid-area: content;*/ display: grid; grid-template-columns: auto; gap: 20px; grid-template-areas: "image" "text"; } @media (min-width: 500px) { .image-text .has-image:not(.image-right) { /*grid-area: content;*/ display: grid; grid-template-columns: 1fr 5fr; gap: 20px; grid-template-areas: "image text" ".... text"; } .image-text .has-image.image-right { /*grid-area: content;*/ display: grid; grid-template-columns: 5fr 1fr; gap: 20px; grid-template-areas: "text image" "text ...."; } } .image-text .no-image{ /*grid-area: content;*/ display: grid; grid-template-columns: auto; grid-template-areas: "text"; } .image-text img{ grid-area: image; } .image-text div#body{ grid-area: text; } to this: .image-text { --stacked: "image" "text"; --image-left: "image text" ".... text"; --image-right: "text image" "text ...."; --text-only: "text"; } .image-text img{ grid-area: image; } .image-text div[id*='body']{ grid-area: text; } with only a marginal increase in the html (using arbitrary properties and values) and (I think) an increase in clarity: <div n:class= "$imgs > 0 ? '[grid-template-areas:var(--stacked)]' : '[grid-template-areas:var(--text-only)]', ($imgs > 0 && $page->motif_toggle == 0) ? 'sm:[grid-template-areas:var(--image-right)] sm:grid-cols-[5fr_1fr]', ($imgs > 0 && $page->motif_toggle == 1) ? 'sm:[grid-template-areas:var(--image-left)] sm:grid-cols-[1fr_5fr]', grid, gap-5"> Note that you need to include these type of class names in quote marks or Latte gets confused. The bit that worried me most was where I needed styling to be dependent on php variables. Some commentators have said that this presents a problem for Tailwind because it creates the stylesheet before the variables are known. However, the work-round is quite simple, with an in-line style tag to create css vars like this: <style> #gallery-item-{$imgPage->id} { --w: {$imgDisplayWidth|noescape}{$heightArray[1]}; --w2: {$expandWidth|noescape}{$heightArray[1]}; --wh: {$halfWidth|noescape}{$heightArray[1]}; --wq: {$quarterWidth|noescape}{$heightArray[1]}; --h: {$height|noescape}; --h2: {$expandHeight|noescape}; } </style> which then can be used directly: class="w-[var(--w)] hover:w-[var(--w2)]" It may be that there are better ways of doing some of this, but I was pleasantly surprised that each time I looked at a bit of slightly involved css and html and thought 'how the hell am I going to do that in Tailwind?', the answer was much shorter and clearer code. In particular, Latte works well with Tailwind throught the power of the n:class tag.
  10. Yes thanks. I think those elements must have dated from the early days of RockFrontend and I never updated that _main.php. So I've re-done it all now as per the latest readme and it all seems fine.
  11. Aha! I have <script src="<?= urls()->siteModules?>RockFrontend/Alfred.js?m=1660123300"></script> <script src="<?= urls()->siteModules?>RockFrontend/livereload.js?m=1660123300"></script> in my head. I think that was maybe the requirement with an earlier version but no longer needed?
  12. Thanks @bernhard. I can see in the dev tools elements that (for example) <script>let RockFrontend = {"rootUrl":"\/","defaultVspaceScale":0.66000000000000003}</script> is added, but the error persists. Also, I note that this script is not added if there is no Alfred tag on the page, so will that not always cause an error in Alfred.js (albeit not important)?
  13. The hook seems to be working OK. RockFrontend is a js variable. Where is it supposed to be set?
  14. Thanks @bernhard. I did that, but I still get this: Alfred.js?m=1660123300:179 Uncaught ReferenceError: RockFrontend is not defined at Alfred.js?m=1660123300:179:3 at Alfred.js?m=1660123300:282:3 livereload.js?m=1660123300:11 Uncaught ReferenceError: RockFrontend is not defined at startStream (livereload.js?m=1660123300:11:14) at livereload.js?m=1660123300:47:3
  15. Hi @bernhard, Any idea why I am getting this error in the dev tools console after installing the latest version? Uncaught ReferenceError: RockFrontend is not defined at RockFrontend.js?m=1660203134:11:12 at RockFrontend.js?m=1660203134:48:3 I updated from an earlier version (I forget which, but about 2 months ago) because font-awsome was not loading properly - I was getting <link rel="stylesheet" href="undefinedwire/templates-admin/styles/font-awesome/css/font-awesome.min.css" type="text/css"> rather than the correct url. Now I don't even get that link. Looks like a similar issue though as the url is given by RockFrontend.rootUrl
  16. Preventing a page from being moved is not necessarily a straightforward matter of trapping the change in a save hook in the same way as a page edit. A problem occurs if the page is only to be 'blocked' conditionally - when the page path is in some given array, for example. In hooking before page save, the page path is the new page path after the move, rather than before it, so you need to do something like this: // .... In the before page:saveReady hook // $page is the page :) The code below operates when (isset($page->parentPrevious) && $object->parentPrevious != $object->parent) $name = $page->parentPrevious->path . $page->name . '/'; // need the path before it was moved if(in_array($name, $blockedNames)) { // $blockedNames are the ones where we don't want moves // Because this hook operates after the move, we need to reverse the move $page->parent = $page->parentPrevious; // Alternatively, to completely stop the save //$event->replace = true; //$event->return = false; } //... rest of hook This prevents the page being moved, both in the page hierarchy (by dragging) or in the page editor by changing the parent in the settings tab. It is also possible to hook before Page:moveable with something like this /** @var Page $page */ $page = $event->object; $moveable = $event->return; // ... code to set $moveable to false if conditions met $event->return = $moveable; Interestingly, the (not documented?) moveable method is created as a hook by PagePermissions and so is hookable. However, this method appears to catch only the situation where the move is effected by dragging the page in the tree, not when the parent is changed in the settings.
  17. Thanks @gebeer. In reality it's not quite as simple as that because my code is inside a method that is called by six different hooks, rather than in a single hook. However, passing the object argument to that method by reference, rather than by value, means that I can then avoid the unnecessary saves, as you suggest. I'll post an amended version in the tutorials thread.
  18. I have been trying to add some hooks to prevent pages from being moved in certain circumstances. It seems (to me) that this is not entirely straightforward. First off, just a simple hook before the page save does not always work. In my use case, the 'circumstances' are when the page path is in some given array. In hooking before page save, the page path is the new page path after the move, rather than before it, so I need to do something like this: // .... In the before page:saveReady hook // $page is the page :) The code below operates when (isset($page->parentPrevious) && $object->parentPrevious != $object->parent) $name = $page->parentPrevious->path . $page->name . '/'; // need the path before it was moved // Because this hook operates after the move, we need to reverse the move if(in_array($name, $blockedNames)) { // $blockedNames are the ones where we don't want moves $page->parent = $page->parentPrevious; $page->of(false); $this->wire()->session->set('bypassSaveHook', true); // to prevent loops $page->save(); $this->wire()->session->remove('bypassSaveHook'); } //... rest of hook This prevents the page being moved, both in the page hierarchy (by dragging) or in the page editor by changing the parent in the settings tab. I also tried hooking before Page:moveable with something like this /** @var Page $page */ $page = $event->object; $moveable = $event->return; // ... code to set $moveable to false if conditions met $event->return = $moveable; Interestingly, the (not documented?) moveable method is created as a hook by PagePermissions and so is hookable. However, this appears to catch only the situation where the move is effected by dragging the page in the tree, not when the parent is changed in the settings. If anyone knows of any smarter way of doing this stuff, I would be interested, otherwise maybe this could be moved to a tutorial?
  19. But then why not use a fieldset, in which case it doesn’t depend on the screen layout?
  20. I agree. I always considered the behaviour slightly odd as the inputfields are not necessarily related and even differ depending on the screen size.
  21. That's exactly what it is. It is because the repeater page is a child of admin, not of its ’get for' page. per a response from @ryan in another post:
  22. Many many thanks @kongondo! It's still a bit of a hack, as it seems I have to add it in the module ready() like this: public function ready() { /* * Make sure all the assets are there for a page with repeaters */ $page = $this->page(); if($page and $page->template == 'admin') { $pId = $this->wire()->input->get('id'); $pId = $this->wire('sanitizer')->int($pId); if(is_int($pId) && $pId > 0) { $p = $this->wire('pages')->get($pId); $this->getInputfieldAssets($p); } } } protected function getInputfieldAssets($p) { foreach($p->getFields() as $field) { $inputfield = $field->getInputfield($p); $type = $inputfield->className; $name = $inputfield->attr('name'); if($type == 'InputfieldRepeaterMatrix' || $type == 'InputfieldRepeater') { foreach($p->$name as $repeaterItem) { $this->getInputfieldAssets($repeaterItem); } } else { $inputfield->renderReady(); } } } Ideally, I would add it as part of the migration process, rather than have it execute on each ready(), but I haven't found a way of doing that and at least the code above is a lot simpler than what I was trying (and it seems to work fully). EDIT: To avoid complications, the first part of the above code was moved to a before hook on ProcessPageEdit::execute
  23. Additional info: This is only a problem with fields inside repeaters and repeater matrix fields. In fact, if field types inside repeaters also exist in the page outside repeaters then they will load the assets automatically and the fields will look fine inside and outside the repeaters. More context: The problem is occurring with my ProcessDbMigrate module, which I am enhancing to handle repeater matrix fields and nested repeaters, but so far I have not tested the nested feature. I'm not sure where @bernhard's RockMigrations has got to with these features or whether similar problems occur there, but I'll take a look. PS. Don't download the current version of my module, it has some bugs which I hope to fix in this new version (once it works fully!).
  24. I have a strange situation in which the required js and css for the inputfields on an admin page are not being loaded. The main field in question is called 'motif_layout_components' and its matrix items are updated via the API. The image below shows an example of what the page should look like: However, the image below is what I get: As you can see, the toggle field, page ref and CKE fields have not been styled. On inspecting with the browser dev tools, it is clear that this is because the files InputfieldToggle.css etc. have not been loaded. Saving the page has no effect. However, if I go to the field/edit page for the motif_laout_components field and save that then, on reloading the illustrated page, the required sources appear and the page is rendered correctly as shown in the first image. Any ideas? Why are the assets not loaded? How can I ensure that they are loaded (i.e. via the API rather than manually saving the related edit/field page)? Any insights gracefully received!
  25. Any more context and documentation for that teaser? I had problems with laragon and the support is not great. Ddev works fine (and much faster with mutagen on my windows setup).
×
×
  • Create New...