Jump to content

Robin S

Members
  • Posts

    5,008
  • Joined

  • Days Won

    333

Everything posted by Robin S

  1. Anything that can be done with the API can be turned into an executable action with @adrian's Admin Actions module. And you can make an action available to non-superusers too. There's a built-in "Copy Field Content to Other Page" action that you can use as a starting point. This action doesn't work out-of-the-box for Files or Images fields but it wouldn't be difficult to get it working, especially now that you can use Pagefiles::add() with a Pagefile object so that descriptions and tags get copied over automatically. And if you update the action maybe submit a pull request to the module repo with your changes...?
  2. Works great, thanks.
  3. @tpr, would you consider adding an exclude class to the "Autosize textareas according to content" feature? Generally I like this feature but I have some modules with textareas in their config that contain a lot of content and would like to be able to exclude these from being autosized. So I was thinking there could be some special class that can be applied to textareas (e.g. "no-autosize") and the AOS feature when enabled would apply to all textareas without this class. What do you think?
  4. @stuartsa, you can achieve a step setting for InputfieldInteger / InputfieldFloat / InputfieldDecimal by a couple of hooks in /site/ready.php: // Add a step setting to InputfieldInteger / InputfieldFloat / InputfieldDecimal $wire->addHookAfter('Inputfield(className=InputfieldInteger|InputfieldFloat|InputfieldDecimal)::getConfigInputfields', function(HookEvent $event) { $inputfield = $event->object; $field = $inputfield->hasField; if(!$field) return; /* @var InputfieldWrapper $wrapper */ $wrapper = $event->return; /* @var InputfieldText $f */ $f = $event->wire('modules')->InputfieldText; $f->name = 'step'; $f->label = 'Step'; $f->value = $field->step; $f->showIf = 'inputType=number'; $wrapper->add($f); }); // Add step attribute to InputfieldInteger / InputfieldFloat / InputfieldDecimal $wire->addHookBefore('Inputfield(className=InputfieldInteger|InputfieldFloat|InputfieldDecimal)::render', function(HookEvent $event) { /* @var Inputfield $inputfield */ $inputfield = $event->object; $field = $inputfield->hasField; if(!$field || !$field->step || $field->inputType !== 'number') return; $inputfield->attr('step', $field->step); });
  5. This would only be useful for simple, single-value fields like text fields, right? Because how would it work with an Images field or a Repeater field for example? Anyway, here is a proof-of-concept FileCompiler module: https://github.com/Toutouwai/FileCompilerDataAttributes File Compiler Data Attributes A proof of concept module for populating markup elements according to data attributes containing a field name. Created in response to this forum topic. This approach is really only useful for simple, single-value fields such as text fields as far as I can see. Installation Install the File Compiler Data Attributes module. Setup If you follow the practice of starting your template files with the ProcessWire namespace declaration then for every template you want to use this module with you must change the "Use Compiled File?" option in the template settings from the default option. You must choose either of the "Yes" options depending on what suits you best. I find the need to do this annoying and there is an open issue about it. There is an option in the module config to strip the data-field attribute from the markup when the template file is compiled. Usage In your template files, insert HTML elements (probably empty elements although this is not compulsory) with a data-fieldattribute set according the field name you want to populate the element from. Example: <h1 data-field="title"></h1> <div data-field="body"></div>
  6. @stanoliver, yes, I understand the objective. What's not clear is how your blog posts are identified as belonging to a particular category. If there is a blog post titled "My bike" and it is in the category of "bike", how do you connect category "bike" with post "My bike"? Probably it would help if you show a screenshot of your page tree, with both the post pages visible and the category pages visible. Most commonly, developers structure their website so that they have a structure of category pages (using template "category" let's say), and then they have a Page Reference field (named "categories" let's say, with selectable pages "template=category") and they add this Page Reference field to the post template. Then for each post they select one or more category pages. That's what my previous post assumes. So that when you are viewing a category page on the front-end, that category page exists as the $page variable. And so if you want to find posts that have that category page assigned to them you search for them with this: $results = $pages->find("template=templateblogpost, categories=$page, limit=5, sort=-postdate"); Another way that you might be connecting categories to posts is by a parent-child relationship. So the post pages are children of a category page that they belong to. This is okay but less flexible because it means that any post can only belong to one category. So if you found yourself needing to write a blog post "How to fix a bike rack to your car" you would have a problem because the post could only be in the bike category or the car category but not both. But if you are in fact using a parent-child relationship you would use this selector on the category page (note change from $pages->find to $page->children): $results = $page->children("template=templateblogpost, limit=5, sort=-postdate");
  7. @stanoliver, please use the Code button for blocks of code you insert in the forum - your post above is almost unreadable. On to your problem... As I understand it you are rendering a category page (cars, bikes, etc), and you have some posts which are tagged with these same category pages in a Page Reference field (a post is tagged with cars, bikes, etc). Therefore your selector would be: $results = $pages->find("template=templateblogpost, category=$page, limit=5, sort=-postdate"); Note the double-quote marks around the selector string, so that the $page variable will be interpolated. Then foreach() $results to output your markup.
  8. @BitPoet's groupBy() hook is nice for this sort of thing. As with @teppo's suggestion, you'd have to do a bit more to get it working with infinite scroll (the limit might fall in the middle of a day, in which case you wouldn't want the day heading added again on the next pagination).
  9. Also, there is a counter option built into PW for all textarea fields:
  10. 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.
  11. 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?
  12. 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?
  13. 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.
  14. 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.
  15. 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.
  16. 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
  17. 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); });
  18. @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.
  19. 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.
  20. Maybe you have some other setting that's interfering - something in /site/modules/InputfieldCKEditor/config.js? It's working for me...
  21. 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}
  22. 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/
  23. 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.
  24. 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.
  25. 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); } }); });
×
×
  • Create New...