Jump to content

MarkE

Members
  • Posts

    921
  • Joined

  • Last visited

  • Days Won

    10

Everything posted by MarkE

  1. Have you tried giving the editor role page-sort permission on the parent template?
  2. One way, if your parent pages have different templates and their children should also have distinct templates, is to use the template family settings. Otherwise I think you may need to hook Pages::moveReady - see https://processwire.com/api/ref/pages/move-ready/
  3. One solution is simply to add {"toolbar_location": "bottom"} to the JSON default overrides in the module config, but I don't really like it.
  4. Sorry to say @bernhard, that I seem to have run out of road on this one. I compared two identical windows, one showing it correctly and the other not. The css was identical and there were no media queries. I compared the html and there are very minor differences in some of the width settings, which you can see being changed by js as the window is dragged between screens. The main one was this div: <div role="application" class="tox tox-tinymce tox-tinymce-inline tox-tinymce--toolbar-sticky-off" aria-disabled="false" style="visibility: hidden; display: flex; position: absolute; left: 10px; top: 826px; width: 591px;"> which is the html on the 'correct' rendering and this: <div role="application" class="tox tox-tinymce tox-tinymce-inline tox-tinymce--toolbar-sticky-off" aria-disabled="false" style="visibility: hidden; display: flex; position: absolute; left: 11px; top: 830px; width: 591px;"> which is the rendering with the drop-down above the icon line (which is what causes the problem). All the other width changes appeared to be fractions of a decimal and there were no other html differences. I manually changed the 'bad' html to be the same as the'good' html using developer tools, but there was no noticeable effect. So I am pretty much stumped. Maybe @ryan, who must have a deeper understanding of what the js is doing (much of it is minimised) could shed some light?
  5. Hi @bernhard. It's really weird. If I move a window from one screen to another, the problem fixes itself. Move it back to the original screen and it reappears. What is happening is that the 'bold' dropdown you can see in the image I posted appears between the menu and icon lines, causing the bottom of the toolbar to drop down. When I move the window to a different screen the 'bold' dropdown is displayed inline with the icons. This is with no interaction other than simply dragging the window, so it looks like maybe a css issue? Still looking....
  6. It seems to only be a problem with TinyMCE. The CKEditor toolbar is positioned correctly. I'm looking into a js fix for now...
  7. Is there any way to adjust the position of the TinyMCE toolbar when using the front end editor? As you can see from the picture, it overlays the text I'm trying to edit.
  8. However, I also had problems using the generated result (e.g. 'template=96, _custom="eventDate>2 months ago"') in the $pages->find() api. It returned all pages matching the template. I had to use regex to turn 'template=96, _custom="eventDate>2 months ago"' into 'template=96, eventDate>2 months ago' which seems a bit clunky. The answer is to set the allowCustom option to true in find().
  9. That works @Robin S. Thanks a lot. However, as you say so it doesn't meet my need for the relative date to be used dynamically, which is why I was wondering if what is really needed is an extension or modification of InputfieldDatetime so that it can store a strtotime-comprehensible text field. Meanwhile the custom row is another option which is less user-friendly, but probably better than just allowing a selector input ion a plain text field.
  10. I've done some searching for an answer on this as I can't believe it has not come up before: My problem is that I would like to use a "selector" field (i.e. the interactive selector builder) to compare, for example, a datetime field with 'today'. The issue is that I want it to operate dynamically, so the comparator needs to be stored as 'today' and only converted when the selector is run. This works fine if I just use a text field instead of the selector field and allow the user to input a selector string - e.g. "myDatetime>today", but in the selector builder the comparison field requires an absolute date - a string entry of a relative date is impossible. However, for many reasons, I would prefer not to have a user attempting to enter a selector string. Has anyone tried something similar? If not, I'm toying with the idea of writing a module to extend InputfieldDatetime. That would permit the storing of a valid string as well as an actual date. The string would be only converted to a date at runtime. This would allow entering a date as, for example, 'last month' such that when the field is formatted it would be displayed as a date one month before the execution date. This contrasts with the present module where, although you can default to 'today', I think that is converted to a timestamp at the time of entry and stored as such. Any thoughts on that?
  11. @titanium I don’t know what the Cargo pagebuilder is like, but the website isn’t great. Did you look at PAGEGRID? I think it offers more flexibility than RockPageBuilder, which is good or bad depending on your point of view. I decided to make my own page builder which offers three levels of access: editor, designer, and developer. It’s still experimental at this stage, even though I started it before the two aforementioned page builders were released, but I might release a proof of concept version later this year. There are some difficult decisions to be made between ease of use / consistency and flexibility. For instance, I have (provisionally) decided that someone with designer access needs a certain level of css skills: enabling lots of GUI options for styles is complex to code and to use as well as inevitably not covering everything.
  12. I use three. Central one 24”, sides 17”. I find that much better than one big one. Typically, the central one for code, one side for displaying the output and the other side for reference. Probably cheaper than one big one as well.
  13. MarkE

    Dynamic CSS

    Thanks for the comments @monollonom and @iank. Very helpful! I have used that approach, but forgot to mention it. It works well but, from a Tailwind point of view, it's pretty much like an inline style (except as noted below and probably with a bit of added overhead). In a typical case, I am setting an image width based on user input, so I can do (in Latte): <style> :root { --cardwidth: {$width}; --cardheight: {$width}; --imgheight: {$imgHeight}; </style> The tag is then: <div class="[width:var(--cardwidth)] [height:var(--cardheight)] ... etc... Although this is a bit messy, it does at least have the advantage of being clear what is being set, as opposed to some arbitrary class name. To quote the Tailwind docs ----------------------------------- I can't get this to work, at least not with the variable width example quoted above. It will correctly generate (say) h-[200px] as the class in the HTML but it is not in Tailwind's output css. Similarly, class="[width:{$width}] ..... doesn't work - it seems it needs to be set as a css var first, although quite why that is, I'm not sure (See EDIT). That's neat! I wasn't aware of that. It works well if there is only going to be a limited set of options which, unfortunately, is not the case for the width/height example. On balance, if I stick with Tailwind, it looks like css vars may be the way to go, but I'll do a bit more hacking about and, if I have any better ideas, will post them here. ---------------------------- PS - see the result here. The site editor can change the card size. It also gives the opprortunity of easily adding responsive variants. ---- EDIT: The reason why using a css custom property as an 'intermediary' for the variable works is that Tailwind can compile that (as var(--whatever)) to its output css, which happens before the php is interpreted to creat the css value which the html can then use.
  14. MarkE

    Dynamic CSS

    What approach do folks use when you want to dynamically set CSS? In particular, is there a preferred method when using Tailwind? As far as I can see, the approaches are: Use in-line styles either in the host tag or in an in-line style tag. This is simple and straightforward to do but seems to be frowned upon by purists and is arguably a bit messy-looking. Use LESS (or similar). But this does not play well with Tailwind. Dynamically create a css file including css variables. But LESS is better at this. Create a php style file. Are there performance issues with the last 2 approaches (or might they be overcome with caching). The problem with Tailwind is that, while you can refer to php variables in your Tailwind class, because the tailwind output is compiled before the php is run, if the php variable value is not already represented by a value in the tailwind output css (perhaps because it has been generated somewhere else by a non-variable input) it will be ignored. This issue is making me think about ditching Tailwind and switching to LESS, but perhaps that is an overreaction.
  15. Not sure I entirely understand the question, but it sounds like you need Hanna code.
  16. I think you’ll find that you can only use “or” when you are referencing the same field.
  17. Maybe there is something for this already in the API, or elsewhere, but I couldn't find it, so here is my suggestion. The problem is that you can't simply copy the repeater using the API in the usual way: $page2->repeater = $page1->repeater; appears to work for page 2 but messes up page1 where the repeaters get duplicated. Instead you have to copy over each of the field values within each repeater item. So I wrote this. It seems to work, at least in my context. I placed it in init.php. (However, it would be better if the core handled this more intuitively 😁) /** * Copies a repeater field to another page * Operates on the RepeaterPageArray object e.g. $page->repeater->copyTo($page2) * * @param HookEvent $event * */ wire()->addHook('RepeaterPageArray::copyTo', function ($event) { $repeater = $event->object; $repeaterField = $repeater->getForField(); $page = $event->arguments(0); if(!$page->hasField($repeaterField)) { $event->error("Field $repeaterField does not exist on page"); return; } $page->of(false); foreach ($repeater as $item) { $newItem = $page->$repeaterField->getNew(); foreach($item->getFields() as $f) { $newItem->$f = $item->$f; } $newItem->save(); $page->$repeaterField->add($newItem); } $page->save(); });
  18. Resurrecting an old post here! The reference above says "Note: we will soon support specification of page references by /path/to/page/ as well." That was a while back, but still seems not to be the case. I like to use page paths wherever possible, as it is so much easier to see what is happening (although to be safe, setting the page to 'system' may be wise as I doubt it could be made to track moves).
  19. Prompted by this, I tried using Unpoly in the back end, to achieve a bit more customisation than with pw-modal. It looks nice but loading a page edit content in an overlay seems to lose all the tabbing.
  20. I considered that, but my use case does not really need it to be configurable. I could allow superuser to configure template and parent in the module settings, but I would then need a more generic title for the setup page (presently it is “Import members from csv” so it refers to the specific context so as to be more meaningful to the user). If others wanted a configurable module, then it would not be too hard to do.
  21. Does anyone have any views on the merits of extending another module when you can't hook the required methods? I came across this recently with ImportPagesCSV. I wanted to restrict the target template and parent and then make the module accessible to a certain role (less than superuser). The buildForm1 and processForm1 methods are not hookable. Even if they were, I would have to re-use most of the code in the hook and replace the $event->return, which seems a bit messy. I guess I could hook the whole execute method, but that would be messier still. Also, the module has no permission set. Alternatively, I could suggest some additional features to @ryan, but that might take a little while to resolve. So my solution was just to extend the module with my own module - 3 methods and done. It also meant I could rename the setup page to something more specific. I've not done this before, but was very easy and seems to work well. Are there any downsides? I guess the obvious one is if some incompatible change was made to the original module and I update it, but that seems unlikely and would also affect the 'messy' hook. It seems better than hacking the original module 🙂
  22. Hi @poljpocket. It also has similarities to https://processwire.com/modules/process-db-migrate/ . That will run snippets before/after migrations. See the docs.
  23. Thanks for raising this issue @donatasand @Robin S. I was just about to consider changing a CKEditor field to TinyMCE, where the field is used in exactly this way, except that the url is inserted via a Hanna code.
  24. Absolutely! I guessed you had come across something similar. So I did an analagous edit to pwimage.js (but not specifically aimed at a repeater - the editable item might be an ordinary page, in my case in a page table). That saves having to mess with PageFrontEdit.module and is a lot simpler. I need to look more closely at the rest of the issue commentary to see what applies...
  25. I have done this by hacking PageFrontEdit.module as follows. There are two parts to the hack. Part 1 puts the id of the page being edited with the inline editor into the (hidden) tag with #Inputfield_id, rather putting the host page id there (this is what is used in the js to pick up the page id). Part 2 then partially suppresses the error that arises because the page being edited is not the host page (there may be a more elegant and safer way of doing this). I'd be grateful for any comments (esp from @bernhard) as to whether you think some change to this effect should be made you have any problems with the suggested changes or have a better idea I should raise an issue for this? Part 1 Line 429 if($hasEditTags) $numEditable += $this->populateEditTags($page, $out); - replace by $editPage = $page; if($hasEditTags) { $editTags = $this->populateEditTags($page, $out); $numEditable += $editTags['num']; $editPage = $editTags['page']; } then in lines 442 & 444 replace $this->renderAssets() by $this->renderAssets($editPage) In populateEditTags() change the return PHPDoc comment to @return array [Number of tags populated, page being edited], change the return in line 510 to if(!preg_match_all('!<' . $tag . '([^>]+)>(.*?)</' . $tag . '>!is', $out, $matches)) return ['num' => 0, 'page' => $page]; and change the return at the end of the method to return ['num' => $numEditable, 'page' => $p]; In renderAssets(), change the top to public function renderAssets($editPage = null) { if(!$editPage) $editPage = $this->page; and add the @param comment @param null|Page $editPage Then change line 853 "<input type='hidden' id='Inputfield_id' class='PageFrontEdit' value='{$this->page->id}' />" . // for CKE plugins to "<input type='hidden' id='Inputfield_id' class='PageFrontEdit' value='{$editPage->id}' />" . // for CKE plugins Part 2 In inlineSaveEdits() change lines 1077-8 from } else if($pageID != $this->page->id) { $data['error'] = "Edited page does not match current page ID ($pageID != {$this->page->id})"; to } else if($pageID != $this->page->id && !$this->pages()->find("id=$pageID, has_parent={$this->page}")) { $data['error'] = "Edited page does not match current page ID (or is not a child) ($pageID != {$this->page->id})";
×
×
  • Create New...