Jump to content

Robin S

Members
  • Posts

    5,039
  • Joined

  • Days Won

    340

Everything posted by Robin S

  1. Also, there is a counter option built into PW for all textarea fields:
  2. Thanks for the replies. It's no problem to me to use the built-in PHP functions - just wanted to check I wasn't overlooking something.
  3. I was looking at the API docs for $session and couldn't see any way to get a unique identifier for the current session. I want to use this to create a name for a temp directory so that paths for files stored there for each visitor do not clash with each other. I can use PHP's session_id() function but I'm surprised there's no ProcessWire $session method for this. Does anyone know if there is a PW way to get an identifier for the current session that I'm missing?
  4. Not meaning to hijack this thread, but just curious what advantage you see to using an array that you later implode versus the more typical approach of using .= to concatenate to a selector string. Are you doing things like using an associative array that so that you can conditionally modify parts of the selector by key before you implode, or something like that? Or you just like to be able to more clearly see the different parts of the selector in a Tracy dump?
  5. Just my opinion: I'm not sure there's much advantage to doing that - selector arrays seem more trouble than they are worth. When you start needing things like OR groups and nested selectors (which you inevitably do) the array syntax gets quite verbose and frankly less readable than the string syntax (especially if you are already familiar with the string syntax). I can't locate the topic now but I remember @adrian working with selector arrays for a while and I think he ended up reverting back to selector strings because there were too many issues/hassles with the array syntax. Maybe he will correct me on that.
  6. 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.
  7. 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.
  8. 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
  9. 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); });
  10. @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.
  11. 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.
  12. Maybe you have some other setting that's interfering - something in /site/modules/InputfieldCKEditor/config.js? It's working for me...
  13. 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}
  14. 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/
  15. 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.
  16. 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.
  17. 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); } }); });
  18. 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...
  19. 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]");
  20. You can use my Custom Inputfield Dependencies module to do this.
  21. 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
  22. I use this plugin and it works nicely: https://plugins.jetbrains.com/plugin/7448-zero-width-characters-locator
  23. 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");
  24. 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.
  25. 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); } });
×
×
  • Create New...