Jump to content

Robin S

  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by Robin S

  1. https://github.com/processwire/processwire-issues/issues/480#issuecomment-382383357 https://processwire.com/blog/posts/pw-3.0.99/ Percentage-based widths should be the default IMO.
  2. The issue of paginating results when sort=random has come up before. Ryan suggested finding all the IDs with a random sort, then loading pages from slices of that array. His example assumes normal pagination but could be adapted for ajax loading. $limit = 10; $start = $limit * ($input->pageNum()-1); $ids = $session->get('ids'); if(!$ids) $ids = $pages->findIDs("template=project, sort=random"); $session->set('ids', $ids); $a = array_slice($ids, $start, $limit); if(!empty($a)) { $items = $pages->getByID($a)->setStart($start)->setLimit($limit)->setTotal(count($ids)); echo $items->implode("<li>{title}</li>") . $items->renderPager(); }
  3. Ryan introduced it at the end of 2016. In my mind it doesn't seem like that long ago. I must be getting old. 😄 https://processwire.com/blog/posts/pw-3.0.44-repeaters/
  4. I just noticed that the topic title mentions field type. The jqTree library you linked to can read/write to/from JSON format, so that data can be stored in a FieldtypeTextarea. For the inputfield you could create a custom inputfield module that extends InputfieldTextarea - in the renderReady() and render() methods you would make use of jqTree. If you are not up for coding that another idea is to use the depth option available for Repeater fields. If you go this route you might also find my Repeater Depth Helper module useful.
  5. This is a module I made as an experiment a while ago and never got around to releasing publicly. At the time it was prompted by discussions around using Repeater fields for "page builder" purposes, where the depth feature could possibly be used for elements that would be nested inside other elements. I thought it would be useful to enforce some depth rules and translate the depth data into a multi-dimensional array structure. I'm not using this module anywhere myself but maybe it's useful to somebody. Repeater Depth Helper This module does two things relating to Repeater fields that have the "Item depth" option enabled: It enforces some depth rules for Repeater fields on save. Those rules are: The first item must have a depth of zero. Each item depth must not be more than one greater than previous item depth. It provides a RepeaterPageArray::getDepthStructure helper method that returns a nested depth structure for a Repeater field value. Helper method The module adds a RepeaterPageArray::getDepthStructure method that returns a multi-dimensional array where the key is the page ID and the value is an array of nested "child" items, or null if there are no nested children. Example The module doesn't make any assumptions about how you might want to use the depth structure array, but here is a way you might use it to output a nested unordered list. // Output a nested unordered list from a depth structure array function outputNestedList($depth_structure, $repeater_items) { $out = "<ul>"; foreach($depth_structure as $page_id => $nested_children) { $out .= "<li>" . $repeater_items->get("id=$page_id")->title; // Go recursive if there are nested children if(is_array($nested_children)) $out .= outputNestedList($nested_children, $repeater_items); $out .= "</li>"; } $out .= "</ul>"; return $out; } $repeater_items = $page->my_repeater; $depth_structure = $repeater_items->getDepthStructure(); echo outputNestedList($depth_structure, $repeater_items); https://github.com/Toutouwai/RepeaterDepthHelper https://modules.processwire.com/modules/repeater-depth-helper/
  6. Not exactly a module, but the page tree emulates a tree, allows drag and drop organisation of elements, and returns results as a (Page)Array. 😉 You could also use exactly that example. If you are talking about the frontend then PW doesn't place any limitations on what JS libraries you can use. And you could use it in the backend too if needed, via RuntimeMarkup for example.
  7. You would strip apostrophes from the search input also. The general idea is you strip out any characters that shouldn't affect the search from both the input and the stored index. There is discussion in this topic: On one site I've implemented a fuzzy search that uses the Levenshtein distance with the approach described here, but it was done with plain SQL and searched only the title field. Using it on multiple fields has the potential to generate a huge number of queries so performance could become an issue.
  8. I took the liberty of opening a GitHub issue for this problem: https://github.com/processwire/processwire-issues/issues/1192 As a workaround for now you could use this hook in /site/ready.php: $pages->addHookBefore('added', function(HookEvent $event) { /** @var Page $page */ $page = $event->arguments(0); /** @var Pages $pages */ $pages = $event->object; // Only for a particular template if($page->template != 'your_template') return; // Check if there is a name clash with an existing sibling page $default_name = $this->wire('sanitizer')->pageName($page->title, true); if($pages->count("parent=$page->parent, id!=$page->id, name=$default_name, include=all")) { // Manually create a proposed name $name = $default_name . '-1'; // Auto-adjust the name when needed $name = $pages->names()->uniquePageName($name, $page); // Set the name $page->setAndSave('name', $name); } });
  9. The normal way to match content in a Repeater is by searching the subfields of the Repeater. Instead of... my_field%=foo, template=repeater_my_repeater_field ...you would do... my_repeater_field.my_field%=foo That way you are matching the pages that contain the repeater field so you don't need getForPage(), plus you don't have to deal with the access restrictions on the Repeater template, unpublished repeater items, sorting of the container pages, etc. Have you considered merging the text of all the fields you want to search into a hidden "index" textarea field? It's not too difficult to do this with a Pages::saveReady hook, but to make it really easy you can use the SearchEngine module which takes this approach. Doing this has the potential to solve the other issues you raised here and here (you could strip apostrophes from text that is saved to the index field).
  10. https://github.com/processwire/processwire-requests/issues/353 I expect that is a Page Reference field and not a Select Options field.
  11. That's the thing that isn't possible due to the circular reference issue with "single" Page Reference fields. My suggestion: make one of your Page Reference fields a "multiple" field, even if you are only going to store a single page in it. That way you can use Connect Page Fields and your job will be a lot simpler. You won't need to use PHP to define the selectable pages so you'll be able to use the Page Autocomplete inputfield. Instead you can use a selector string to define the selectable pages and identify pages that not selected by another user with a string like "selected_by_user.count=0" where selected_by_user is a Page Reference field. If your user pages are only managed by superuser then you don't need to do anything special with the inputfield - it won't matter if it technically allows multiple pages to be selected because you'll know to only select a single page. Or if others need to manage the users and you think they'll be confused if the inputfield allows multiple selections then you can limit the number of selectable pages with a hook: $wire->addHookAfter('InputfieldPageAutocomplete::renderReadyHook', function(HookEvent $event) { /** @var InputfieldPageAutocomplete $inputfield */ $inputfield = $event->object; $field = $inputfield->hasField; if($field && $field->name === 'colour') { $inputfield->maxSelectedItems = 1; } }); And of course the value of this field will be a PageArray but you can get the selected page by using the first() method.
  12. Thanks for the update @ryan! Could you please take a look at what might be causing the main download button for the dev version to be stuck on 3.0.153? It's been this way for several weeks. I know that the button always links to the current state of the dev branch but it's potentially confusing to users having the version number out of sync like this. Thanks 🙂
  13. I couldn't confidently say "impossible" but the front-end is a totally different context to the back-end so it would require substantial changes to the module, and I expect there would need to be changes to PageFrontEdit to allow modules to inject CSS and JS into the frontend. I'm not that motivated to spend a lot of time on it because I never use front-end editing and if I did and needed Hanna Code Dialog I would just use Option D because in my opinion it's no great loss to switch to a modal editor for such cases. So sorry to disappoint but the response for now is "if you need Hanna Code Dialog on the front-end bad enough then use Option D". Of course the module is open-source so you are welcome to experiment with it and modify it as needed.
  14. Only if you use Option D for front-end editing in a dialog. Hanna Code Dialog works by hooking ProcessPageEdit::execute and this method isn't called when using inline front-end editing. PageFrontEdit doesn't even have any hookable methods so there's really no scope for the kind of customisation done by Hanna Code Dialog.
  15. A FieldsetPage field is a kind of Repeater, and conditionally setting the required status of inputfields within a Repeater is difficult. AFAIK you can't do this from a ProcessPageEdit::buildForm hook. And what's worse is that you'd need to hook one method to conditionally show the required asterisk in Page Edit and a different method to actually enforce the required status when the input is processed for each inputfield type within the FieldsetPage. So you'd end up needing to apply your logic in three different places. Long story short, you'll make things much simpler if you have Profields and can change your FieldsetPage to a FieldsetGroup, or failing that a standard Fieldset.
  16. You can also configure your CKEditor field to insert <br> tags instead of <p> tags on Enter. https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html#property-ENTER_BR
  17. Not sure if it will make a big difference but you can avoid loading the categories PageArray (which happens when you do $existing->categories->count) on pages that you don't need to update. $existing = wire('pages')->get("template=supplier, unique_id={$record['Unique ID']}, categories.count=0", ['cache' => false]); if($existing->id) { // ...
  18. For a field named "colour" allowing pages using a template named "colour": $wire->addHookAfter('InputfieldPage::getSelectablePages', function($event) { $page = $event->arguments(0); $pages = $event->wire('pages'); if($event->object->hasField == 'colour') { // Find pages that are already selected on another user page $already_selected = $pages->find("template=colour, colour.owner.template=user, colour.owner.id!=$page->id"); // Selectable pages are those that are not already selected $event->return = $pages->find("template=colour, id!=$already_selected"); } }); Owner selectors: https://processwire.com/blog/posts/processwire-3.0.95-core-updates/
  19. 1. Set the columns to 0 in the Page Reference field settings. 2. Use AdminOnSteroids to add some custom admin CSS that applies columns to the list of checkboxes: #wrap_Inputfield_your_field_name .InputfieldCheckboxesStacked { column-count:2; }
  20. Similar topic: So I guess it's not supported by the core. But it's not difficult to write your own custom JS to show/hide the field: $(document).ready(function() { // Show/hide a field if another field's value is zero function showHideField() { $('#wrap_Inputfield_my_textarea_field').toggle($('input[name="my_integer_field"]').val() === '0'); } // Show/hide on DOM ready showHideField(); // Show/hide on input change $(document).on('change', 'input[name="my_integer_field"]', showHideField); }); You'll need to get clever with the jQuery selectors if you are using fields inside a Repeater.
  21. Sorry, I should have read the thread more carefully. In my world if a live site broke like this it would be a pretty big deal and the imperative would be to get it functioning again as quickly as possible. But it sounds like there's no pressure in this case.
  22. To give another perspective on this topic... This is something that is much easier fixed by changing host than changing the website itself. A statement like that is a clear message that it's time to find a different host. I think it's outrageous for a host to change the PHP version on a live site without warning and then tell their customers that it's their problem to solve. If a host did that to me I would drop them just on principle. Almost all shared cPanel hosting lets you pick the PHP version. So my suggestion would be to open a new account at a shared cPanel host of your choosing. This kind of hosting is as cheap as chips. Hopefully you made a backup of the site files and database before you started changing things. Set the PHP version to 5.4, create/import the database and upload the files and chances are everything will work as it did before. The host might even do the migration for you as a sweetener for new customers. You can use a subdomain (test.vivesport.co.uk) for testing the new hosting and later change the primary domain if everything is working.
  23. Adding some code to expand on my post above. In /site/ready.php: // Forgot password: add verification code as a URL parameter $wire->addHookBefore('ProcessForgotPassword::renderEmailBody', function(HookEvent $event) { $url = $event->arguments(0); $verification_code = urlencode($event->arguments(1)); $url .= "&code=$verification_code"; $event->arguments(0, $url); }); // Forgot password: pre-fill verify field from URL parameter $wire->addHookBefore('ProcessForgotPassword::renderForm', function(HookEvent $event) { $form = $event->arguments(0); $form_name = $event->arguments(1); if($form_name !== 'step3') return; $verify_field = $form->getChildByName('verify'); if(!$verify_field) return; $code = $event->wire('input')->get('code'); if(!$code) return; $verify_field->description = 'Please type or paste in the code you received in your email if it is not already shown below.'; $verify_field->value = urldecode($code); }); I just set this up on a site and it seems to be working well.
  24. A sanitizer is a good idea, but not $sanitizer->selectorValue() because as you say you are not supplying a selector to the method but are supplying a path (you can also supply an ID which is different again). So you'd want $sanitizer->pagePathName(). Yes, in fact you can see in the error message that PW builds a selector using "path=" when you supply a path to $pages->get(). See here: https://github.com/processwire/processwire/blob/88e04129c72c1702926543c8bef555a9f0d1043f/wire/core/PagesLoader.php#L131-L133 else if($selector[0] === '/') { // if selector begins with a slash, it is referring to a path $selector = "path=$selector";
  25. Robin S

    Hanna Code

    @MarkE, if you prefer to edit your Hanna code in your IDE you might find this useful:
  • Create New...