Jump to content

Robin S

  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by Robin S

  1. This is great, thanks! It would be cool if there was a filter option to show only assets that are not in the modules directory.
  2. Not sure if you have in mind a site profile for generally sharing with the community, or something that is made available only to some specific users/clients. If it's the former I would think option 1 would be necessary if you want the profile to be usable by a wide audience. I expect there are many here who are not running Git or Composer. And as you say you would update the profile from time to time (not really different in that regard from a module you have authored). If it's the latter then another option could be @bernhard's Kickstart tool: You would provide users with Kickstart settings that point to a remote profile zip that does not include any third-party modules within it, and then add the third-party modules in the "recipe". That way a user who is installing the profile always gets the latest module versions. I suppose you could use the Kickstart approach for a generally shared site profile too but it comes back to the audience thing again. If PW beginners should also be able to use the profile then it's probably best if the profile can be installed as per the standard procedure without them needing to learn any additional tools.
  3. You must have an old version of FieldtypeTable - it has included Page column types since 2015: https://processwire.com/blog/posts/major-updates-to-profields-table-field/#new-support-for-single-and-multi-page-reference-fields
  4. Here's some JS for that, for a Table field named "table_select_once". Add the JS any way that suits you - with AdminOnSteroids, a hook before Page Edit execute, etc. $(function() { // Disable options already selected in another table row function disableSelectedOptions() { var $selects = $('.Inputfield_table_select_once select'); $selects.find('option').prop('disabled', false); $selects.each(function() { var $selected = $(this).find('option[value!=""]:selected'); if($selected.length) { $selects.not(this).find('option[value="' + $selected.val() + '"]').prop('disabled', true); } }); } // Disable selected options on DOM ready disableSelectedOptions(); // Disable selected options when select changes $(document).on('change', '.Inputfield_table_select_once select', disableSelectedOptions); });
  5. @ryan, thanks for the new features! In the past I've worked on modules that needed to store data for some pages and I had to create a custom DB table for that - the new page meta feature will avoid this and make module development easier. Regarding the Lister bookmarks feature, it would be nice if bookmarks were able to store filter rows where the value is empty. This is so that a bookmark could include rows that don't affect the results until a user enters a value, but are sitting there ready to use when needed. At the moment any rows without a value are not stored in the bookmark. I know that achieving a setup like this is possible with a Lister Pro instance or with a hook for the core Lister but it would be nice to have the option in Lister bookmarks too.
  6. If I understand right you need to use a repeating fieldtype that contains a Page Reference field and a text field for the unique code. You could use any repeating type such as Repeater, PageTable or ProFields Table, but I think ProFields Table would be the optimal interface. You can use some custom JS in Page Edit to disable options in the Page Reference field that have already been selected in another row of the table - just shout if you need advice for doing that.
  7. Maybe you have some other setting that's interfering - something in /site/modules/InputfieldCKEditor/config.js? It's working for me...
  8. For this I think you would not disallow styles in config.disallowedContent but would instead insert the following in the Extra Allowed Content of your CKEditor fields: *{text-align}
  9. Repeater Images Adds options to modify Repeater fields to make them convenient for "page-per-image" usage. Using a page-per-image approach allows for additional fields to be associated with each image, to record things such as photographer, date, license, links, etc. When Repeater Images is enabled for a Repeater field the module changes the appearance of the Repeater inputfield to be similar (but not identical) to an Images field. The collapsed view shows a thumbnail for each Repeater item, and items can be expanded for field editing. Screencast Installation Install the Repeater Images module. Setup Create an image field to use in the Repeater field. Recommended settings for the image field are "Maximum files allowed" set to 1 and "Formatted value" set to "Single item (null if empty)". Create a Repeater field. Add the image field to the Repeater. If you want additional fields in the Repeater create and add these also. Repeater Images configuration Tick the "Activate Repeater Images for this Repeater field" checkbox. In the "Image field within Repeater" dropdown select the single image field. You must save the Repeater field settings to see any newly added Image fields in the dropdown. Adjust the image thumbnail height if you want (unlike the core Images field there is no slider to change thumbnail height within Page Edit). Note: the depth option for Repeater fields is not compatible with the Repeater Images module. Image uploads feature There is a checkbox to activate image uploads. This feature allows users to quickly and easily add images to the Repeater Images field by uploading them to an adjacent "upload" field. To use this feature you must add the image field selected in the Repeater Images config to the template of the page containing the Repeater Images field - immediately above or below the Repeater Images field would be a good position. It's recommended to set the label for this field in template context to "Upload images" or similar, and set the visibility of the field to "Closed" so that it takes up less room when it's not being used. Note that when you drag images to a closed Images field it will automatically open. You don't need to worry about the "Maximum files allowed" setting because the Repeater Images module overrides this for the upload field. New Repeater items will be created from the images uploaded to the upload field when the page is saved. The user can add descriptions and tags to the images while they are still in the upload field and these will be retained in the Repeater items. Images are automatically deleted from the upload field when the page is saved. Tips The "Use accordion mode?" option in the Repeater field settings is useful for keeping the inputfield compact, with only one image item open for editing at a time. The "Repeater item labels" setting determines what is shown in the thumbnail overlay on hover. Example for an image field named "image": {image.basename} ({image.width}x{image.height}) https://github.com/Toutouwai/RepeaterImages https://modules.processwire.com/modules/repeater-images/
  10. Every comma separated clause in the selector string constitutes an AND condition. So in this selector you are saying "find pages where foo is in the title AND foo is in the body of a repeater_element". I think you probably meant to say "find pages where foo is in the title OR foo is in the body of a repeater_element". So you can do this with OR-groups... $result = $pages->find("(repeater_element=[title.data{$user->language}%=foo]), (repeater_element=[body.data{$user->language}%=foo])"); ...or perhaps with an OR condition in the field portion of the selector (try it and see if it works).... $result = $pages->find("repeater_element=[title.data{$user->language}|body.data{$user->language}%=foo]"); This won't work because the search term has to be within the square brackets of the sub-selector.
  11. Welcome to the forums @e0f When you use a datetime string (e.g. 2019-06-08) in a $pages->find() selector, the string gets converted to a timestamp behind the scenes via strtotime(). And if you only supply a date without any hours/minutes/seconds to strtotime() then 00:00:00 (midnight) is assumed. This means that in your selector you are actually searching for pages created between 2019-06-08 00:00:00 and 2019-06-10 00:00:00, so you will not find any events created after 00:00:00 on 10 June. So you can fix this by including a time in the second datetime string: $result = $pages->find("template=test, id>1, sort=myFieldName, sort=-created, status=unpublished, created>='2019-06-08', created<='2019-06-10 23:59:59'"); Also, you don't need parentheses around this portion of the selector.
  12. No, it only allows for the showing or hiding of fields, not setting the render value mode. But if you want to selectively render the value of fields rather than the full inputfield you could use hooks like below: $wire->addHookBefore('ProcessPageEdit::buildForm', function(HookEvent $event) { /* @var ProcessPageEdit $ppe */ $ppe = $event->object; $page = $ppe->getPage(); // Some test on $page here, for example... if($page->template != 'news_item') return; $event->wire()->addHookBefore('InputfieldWrapper::renderInputfield', function(HookEvent $event) { /* @var Inputfield $inputfield */ $inputfield = $event->arguments(0); // Some test on $inputfield here, or on the field object via ->hasField if($inputfield->name === 'text_1') { // Inputfield should have only its value rendered, so set render value mode argument to true $event->arguments(1, true); } }); });
  13. When you want to change a page's url or httpUrl in a hook you do this by hooking Page::path - the URLs are derived from the path. The classic post about this is Ryan's CMSCritic case study: So for a hook like this... $wire->addHookBefore('Page::path', function(HookEvent $event) { $page = $event->object; if($page->template == 'news_item') { $event->replace = true; $event->return = "/my-custom-path/$page->name/"; } }); ...the results are...
  14. I don't have a multi-language installation to test on but it should be possible. You'll have to work out the best way to use conditionals to construct your selector but the default language selector would look like... $result = $pages->find("repeater_element.body%=foo"); ...and the non-default language selector would look like... $result = $pages->find("repeater_element=[body.data{$user->language}%=foo]");
  15. You can use my Custom Inputfield Dependencies module to do this.
  16. Yes, it is true, because all of those settings are handled by the image inputfield and when you add an image via the API the inputfield is not involved. So you have to do you own checks, resizing, etc. For some starting code take a look at my AddImageUrls module: https://github.com/Toutouwai/AddImageUrls/blob/bed9f2a910c3b120756e35e84ff734f345160bfa/AddImageUrls.module#L119-L171
  17. I use this plugin and it works nicely: https://plugins.jetbrains.com/plugin/7448-zero-width-characters-locator
  18. See the selectors documentation for sub-selectors: https://processwire.com/docs/selectors/#sub-selectors There are two syntaxes available: square brackets and dot, with the dot syntax being shorter and arguably easier to read, but having some limitations. It's not quite clear to me how many levels of nesting exist in your case but your selectors would look something like this with two levels of nesting: // Square brackets syntax $results = $pages->find("page_reference_1=[page_reference_2=[text|headline%=pencil]]"); // Dot syntax - probably not as useful in your case because pipe OR conditions are not allowed in the field portion of the selector $results = $pages->find("page_reference_1.page_reference_2.text%=pencil");
  19. This sounds like it relates to change tracking, with changes to the custom fields not being detected. Did you see the API example in the module readme, where track changes is specifically set for the custom field being set? Having said that, when I tested I wasn't able to save changes to ImageExtra custom fields via the API regardless of the trackChange() call or if the description was also set. This question probably belongs in the ImageExtra support topic so the module author might see it, although they haven't been active here lately so not sure how well the module is being supported currently.
  20. v0.2.1 released. This is a fairly major update in that there has been quite a bit of refactoring. Please be alert for and report any issues. ProcessWire >= v3.0.0 is now required. This release adds a new hookable HannaCodeDialog::buildForm() method that lets you build the dialog form in the hook rather than setting inputfield options as pseudo-attributes in the Hanna Code tag settings. From the readme... Build entire dialog form in a hook You can hook after HannaCodeDialog::buildForm to add inputfields to the dialog form. You can define options for the inputfields when you add them. Using a hook like this can be useful if you prefer to configure inputfield type/options/descriptions/notes in your IDE rather than as extra attributes in the Hanna tag settings. It's also useful if you want to use inputfield settings such as showIf. When you add the inputfields you must set both the name and the id of the inputfield to match the attribute name. You only need to set an inputfield value in the hook if you want to force the value - otherwise the current values from the tag are automatically applied. To use this hook you only have to define the essential attributes (the "fields" for the tag) in the Hanna Code settings and then all the other inputfield settings can be set in the hook. Example buildForm() hook The Hanna Code attributes defined for tag "meal" (a default value is defined for "vegetables"): vegetables=Carrot meat cooking_style comments The hook code in /site/ready.php: $wire->addHookAfter('HannaCodeDialog::buildForm', function(HookEvent $event) { // The Hanna tag that is being opened in the dialog $tag_name = $event->arguments(0); // Other arguments if you need them /* @var Page $edited_page */ $edited_page = $event->arguments(1); // The page open in Page Edit $current_attributes = $event->arguments(2); // The current attribute values $default_attributes = $event->arguments(3); // The default attribute values // The form rendered in the dialog /* @var InputfieldForm $form */ $form = $event->return; if($tag_name === 'meal') { $modules = $event->wire('modules'); /* @var InputfieldCheckboxes $f */ $f = $modules->InputfieldCheckboxes; $f->name = 'vegetables'; // Set name to match attribute $f->id = 'vegetables'; // Set id to match attribute $f->label = 'Vegetables'; $f->description = 'Please select some vegetables.'; $f->notes = "If you don't eat your vegetables you can't have any pudding."; $f->addOptions(['Carrot', 'Cabbage', 'Celery'], false); $form->add($f); /* @var InputfieldRadios $f */ $f = $modules->InputfieldRadios; $f->name = 'meat'; $f->id = 'meat'; $f->label = 'Meat'; $f->addOptions(['Pork', 'Beef', 'Chicken', 'Lamb'], false); $form->add($f); /* @var InputfieldSelect $f */ $f = $modules->InputfieldSelect; $f->name = 'cooking_style'; $f->id = 'cooking_style'; $f->label = 'How would you like it cooked?'; $f->addOptions(['Fried', 'Boiled', 'Baked'], false); $form->add($f); /* @var InputfieldText $f */ $f = $modules->InputfieldText; $f->name = 'comments'; $f->id = 'comments'; $f->label = 'Comments for the chef'; $f->showIf = 'cooking_style=Fried'; $form->add($f); } });
  21. I just submitted a pull request with fixes for the overflow positioning, offset when CKEditor is in inline mode, and overrides for the <ul> padding and margin coming from AdminThemeUikit. https://github.com/BitPoet/ProcessCKInlineComplete/pull/4
  22. It's possible, but not as simple as it should be because it seems that the option() method of Datepicker (and Timepicker) is not working for the stepMinute option. Instead it seems you have to destroy and re-init the datepicker if you change stepMinute. In some custom admin JS, for a field named "date"... // For a Datetime field named "date" with time enabled $('#Inputfield_date').on('focus', function() { // Get the existing options for the Datetimepicker var options = $(this).datetimepicker('option', 'all'); // If the picker has the default stepMinute setting... if(options.stepMinute === 1) { // Set custom stepMinute setting options.stepMinute = 15; // Destroy picker $(this).datetimepicker('destroy'); // Re-initialise picker $(this).datetimepicker(options); } });
  23. Here's an example... The page structure: Some pet species have breed child pages and some do not. The selector string for selectable pages for the breed field is "parent=page.species". In ready.php: $wire->addHookAfter('ProcessPageEdit::buildForm', function(HookEvent $event) { /* @var InputfieldForm $form */ $form = $event->return; $breed_field = $form->getChildByName('breed'); if(!$breed_field) return; $species_with_breeds = $event->wire('pages')->find('parent=/selects/pets/, children.count>0'); $breed_field->showIf = 'species=' . $species_with_breeds->implode('|', 'id'); });
  24. See how PW determines $config->ajax here. So you may need to set the X-Requested-With header:
  25. Do you mean you tried to upload a WebP image to an Images field? If so that's not supported - the blog post explains that WebP is an output format only:
  • Create New...