Jump to content

MarkE

Members
  • Posts

    1,035
  • Joined

  • Last visited

  • Days Won

    12

Everything posted by MarkE

  1. I have created a custom admin page which uses InputfieldPageListSelect. It works very nicely (see image), especially with a bit of css to modify the appearance within a MarkupAdminDataTable and some js with AJAX to interactively update each row. However, I would also like to be able to "view" the selected tariffs. When using a normal InputfieldPageListSelect in the admin, you can set "Enable view/edit links on selected pages" (and "Enable link to create new pages"). I can't see how to pass a parameter for that in the API. Any ideas?
  2. As always, it's never simple. When I used the GET method, I linked to the action page via a data-href attribute in the InputfieldButton. It also had class="pw-modal". Now, with the POST method (working!), I have had to remove the data-href and have the action in the form element. That means I can no longer use pw-modal. So how do I get the action page in a modal? Update: I gave up and went back to using GET. I could not find a way of getting POST and pw-modal to work together.
  3. Well that is true, but $this->input->post['param'] is filled correctly! Sorry for the slight red herring. I obviously misunderstood in thinking I could use $_POST (as $_GET was OK) .
  4. Yes Submit on click. No AJAX here (ironically, elsewhere, I got AJAX posts working). The action page is loaded fine on submit. The dev tools show the POST params are there. But the ___execute() function in the module sees nothing. (All in Superuser, BTW).
  5. Sorry if I'm being a bit dim, but I'm struggling with a form submission. I have a form (InputfieldForm) with values, which are set programmatically, in hidden inputfields and a submit button. The action is an admin page with a custom process. Previously, I just had the button (no form) and a data-href with url parameters which the custom admin page picked up via $_GET - this worked fine. Then I wanted to add a load more parameters and decided to change to the post method. However, the POST parameters do not seem to be available to the custom page ($_POST is empty and $this->input->post->submit is null too). I can see from the developer tools that the POST has worked and that the parameters are there. Any ideas what I might be doing wrong?
  6. Updated version here - works with more field types - just make sure you have at least 3.0.148 if you want to use it with autocomplete /* Script to refresh a form content when an element gets changed To work across all admin pages, this script needs to be loaded in admin.php – add the line $config->scripts->add($config->urls->templates . "scripts/form-update.js"); before the final require in templates/admin.php. Typical use is to modify other elements based on a select drop-down change The trigger element can have the following data attributes assigned to it (typically set these with $myInputfield->attr() in a module or hook): * data-action="form-update" : Required to run the script. * data-update-target="#myid1" : Required - the element to change. Note that this should not be the whole form, otherwise .find(target) will not find it. * data-confirm="Some confirmation text": Optional - if you want to show a confirmation before the update, this holds the text to display. If absent, there will be no confirmation dialogue. If the user chooses ‘cancel’, the script will revert the change and terminate. * data-alert="Some alert text": Optional – if you want to warn the user that the update cannot happen for some reason (the script will then revert the change and terminate). * data-cache="#myid2" : Optional - if you want to cache the (changed) value, this element stores it. * data-cache-prefix="Some prefix string" : Optional (requires data-cache) - a prefix to prepend the value stored in the cache This currently works with the following trigger elements: * select options * select page (single and multiple) * page list select (single and multiple) * asm select * page autocomplete (but note that data attributes must be set in the wrapper element - e.g. $myInputfield->wrapAttr() ) Note also that autocomplete only works fully with the latest master 3.0.148 * checkboxes (set attributes in wrapper as above) * checkbox (set attributes in wrapper as above; also, if you need to set or get the value (0 or 1) you may need to use getParent() ) * toggle (but only with 0,1 formatting and 'select' input type; plus see the comments for checkbox above) but not with: * toggle other than as described above * radio buttons NOTE: If you are using this with other js scripts (e.g. in a module) that listen for events in the target, you must use event delegation (e.g. $(document).on("change","#myid", function(){}); NOT $("#myid").onchange(function(){}); ) because #myid is dynamic if it is inside the target) */ $(document).on('change focusin', '[data-action="form-update"]', formUpdate); // need 'change' to catch normal select fields and 'mouseenter' for others function formUpdate(event) { console.log("event type = " + event.type); value = inputVal(this); if (event.type != 'change') { // if the input has not changed, just get the value now so that we can revert if necessary when it is changed console.log("Saving prev value " + value); $(this).data('prevVal', value); return; } console.log("Saving current value " + value); $(this).data('currVal', value); var prev = $(this).data('prevVal'); var current = $(this).data('currVal'); console.log("Prev value " + prev); console.log("New value " + current); // if trigger element has data-confirm attribute, confirm or revert and exit var confirmText = $(this).data('confirm'); if (confirmText) { if (!confirm(confirmText)) { $(this).val(inputVal(this, prev)); return; } } // if trigger element has data-alert attribute, show alert and exit var alertText = $(this).data('alert'); if (alertText) { alert(alertText); $(this).val(inputVal(this, prev)); return; } // cache the value before proceeding (if data-cache set) var cache = $(this).data('cache'); var cachePrefix = ($(this).data('cache-prefix')) ? $(this).data('cache-prefix') : ''; $(cache).val(cachePrefix + current); var $form = $(this).closest('form'); var target = $(this).data('update-target'); console.log("Target is " + target); var method = $form.attr('method'); var action = $form.attr('action'); var data = $form.serialize(); var encodedName; // .serialize() will omit select elements that do not have a 'null' option (e.g. asm select, page list select) // or checkboxes with nothing selected // so find them and add empty parameters to the data string, otherwise the page field will not be updated $($form.find('select, input').each(function(index){ console.log('Select element no. ' + index + ' with name ' + $(this).attr("name") + ' has serialize = ' + $(this).serialize()); encodedName = encodeURI($(this).attr("name")); if (data.search(encodedName) === -1) { data += ('&' + encodeURI($(this).attr("name")) + '='); } })); console.log("Submitted data: " + data); if (!method) method = 'get'; if (!action) action = window.location.href; // If you want to fade the affected inputfields then assign the loading class to their wrappers with method wrapClass(loading) $(target).find('.loading').css({ display: 'block', opacity: 0.2 }).animate({ opacity: 1 }, 5000); // then send your request $.ajax(action, { type: method, // type used, not method, for older versions of jquery data: data, // you can also add an error handler here if required, in case the server returns an error on the request success: function (data) { // Initial ajax just returns an array with message. Need to GET the form data. $.ajax(window.location.href, { type: 'GET', cache: false, success: function (data) { // then just take the target, and replace it with the target div from the returned data $(target).html($(data).find(target).html()); console.log("Returned data: " + data); console.log("Updating html with: " + $(data).find(target).html()); } }); } }); } function inputVal(el, val=null) { var value = $(el).val(); var inputfield = $(el); if ($(el).hasClass('InputfieldCheckbox')) { console.log("checkbox"); inputfield = $(el).find("input[type='checkbox'], input[type='radio']").first(); if (val === 1) { $(inputfield).attr('checked', 'checked'); } else if (val === 0) { $(inputfield).removeAttr('checked'); } value = ($(inputfield).attr('checked') === 'checked') ? 1 : 0; } else if ($(el).hasClass('InputfieldToggle')) { console.log("toggle"); inputfield = $(el).find("option[selected='selected']").first(); if (val === '1') { $(inputfield).attr('selected', 'selected'); } else if (val === '0') { $(inputfield).removeAttr('selected'); } value = ($(inputfield).attr('selected') === 'selected') ? '1' : '0'; } else if ($(el).hasClass('InputfieldPage') && $(el).find(".InputfieldPageAutocompleteData")) { console.log("page autocomplete"); inputfield = $(el).find(".InputfieldPageAutocompleteData").first(); value = $(inputfield).val(); } else { console.log("other selector type"); if (val) { $(el).val(val); } value = $(el).val(); } console.log("returning value = " + value); return value; }
  7. I had upgraded to 3.0.148 successfully on my dev machine and used it without problems for a couple of weeks. So I decided to upgrade the production environment. The front end works OK and so does some of the back end. However, on attempting to edit certain pages in the back end, I get the following error message: Fatal error: Uncaught TypeError: Argument 1 passed to ProcessWire\Modules::setModuleConfigData() must implement interface ProcessWire\Module, string given, called in /home/highmoss/public_html/processwire/wire/core/Wire.php on line 383 and defined in /home/highmoss/public_html/processwire/wire/core/Modules.php:3685 Stack trace: #0 /home/highmoss/public_html/processwire/wire/core/Wire.php(383): ProcessWire\Modules->setModuleConfigData('ProcessVersionC...') #1 /home/highmoss/public_html/processwire/wire/core/WireHooks.php(823): ProcessWire\Wire->_callMethod('setModuleConfig...', Array) #2 /home/highmoss/public_html/processwire/wire/core/Wire.php(450): ProcessWire\WireHooks->runHooks(Object(ProcessWire\Modules), 'setModuleConfig...', Array) #3 /home/highmoss/public_html/processwire/site-ncog/modules/VersionControl-2.0/ProcessVersionControl.module(75): ProcessWire\Wire->__call('setModuleConfig...', Array) #4 /home/highmoss/public_html/processwire/wire/core/Modules.php(553): ProcessWire\ProcessVersionControl->__construct() #5 in /home/highmoss/public_html/processwire/wire/core/Modules.php on line 3685 I refreshed the modules and cleared the FileCompiler, but it persists. Any ideas? EDIT: Uninstalled version control and it works OK
  8. Whoops, I was getting tripping myself up. Originally I put the selector in the field admin page, then later added a hook without deleting the original selector. The hook over-rides the selector, so adding a sort to the original selector has no effect. As a matter of practice, I'll try and remember to delete selectors if I add a hook, but it's an easy thing to forget. Then later, you see the selector and think that's where the criteria are applied ? Perhaps it's better to just use hooks in the first place, so everything is consistently in the same place?
  9. How do I get the sort order of a dropdown (in a page reference field using asmselect) to be how I want it. It seems to be the original order of creation, no matter what I specify. Changing the sort order in the pages or using a selector sort= on the field seems to have no effect.
  10. Please note that the updated version of this script and any other associated info is now at https://github.com/MetaTunes/Form-update I had a need to interactively update the page choices in a multi-choice page select field. I chose to do this with a general-purpose piece of jQuery. By combining it with a InputfieldPage::getSelectablePages hook, you can get the trigger field to alter the selectable pages interactively. I have also found this to be useful in a number of other situations - e.g. updating a RuntimeMarkup field for changes on a page. There may be more elegant ways of achieving this (I'm open to suggestions), but in case it is useful to others, I'll post it here. Hopefully the comments in the script are self-explanatory and describe how to use it. Note that there are several console.log statements to help with debugging, which you can remove once happy with its operation. Happy to answer any questions (if I can ? ). Also, if anyone can explain how to get it working fully with checbox/toggle ad radio buttons, I would be grateful. /* Script to refresh a form content when an element gets changed To work across all admin pages, this script needs to be loaded in admin.php – add the line $config->scripts->add($config->urls->templates . "scripts/form-update.js"); before the final require in templates/admin.php. Typical use is to modify other elements based on a select drop-down change The trigger element can have the following data attributes assigned to it (typically set these with $myInputfield->attr() in a module or hook): * data-action="form-update" : Required to run the script. * data-update-target="#myid1" : Required - the element to change. Note that this should not be the whole form, otherwise .find(target) will not find it. * data-confirm="Some confirmation text": Optional - if you want to show a confirmation before the update, this holds the text to display. If absent, there will be no confirmation dialogue. If the user chooses ‘cancel’, the script will revert the change and terminate. * data-alert="Some alert text": Optional – if you want to warn the user that the update cannot happen for some reason (the script will then revert the change and terminate). * data-cache="#myid2" : Optional - if you want to cache the (changed) value, this element stores it. * data-cache-prefix="Some prefix string" : Optional (requires data-cache) - a prefix to prepend the value stored in the cache This currently works with the following trigger elements: * select options * select page (single and multiple) * page list select (single and multiple) * asm select * page autocomplete (but note that data attributes must be set in the wrapper element - e.g. $myInputfield->wrapAttr() ) * checkboxes (set attributes in wrapper as above) but not with: * toggle * checkbox * radio buttons (These partly work - the attributes need to be in the wrapper -, but doesn't work completely as wrapper 'value' attribute is not updated by PW (always 0) ) NOTE: If you are using this with other js scripts (e.g. in a module) that listen for events in the target, you must use event delegation (e.g. $(document).on("change","#myid", function(){}); NOT $("#myid").onchange(function(){}); ) because #myid is dynamic if it is inside the target) */ $(document).on('focusin', '[data-action="form-update"]', function(){ // get the value before the element is changed console.log("Saving value " + $(this).val()); $(this).data('val', $(this).val()); }).on('change','[data-action="form-update"]', function(event){ var prev = $(this).data('val'); var current = $(this).val(); console.log("Prev value " + prev); console.log("New value " + current); // if trigger element has data-confirm attribute, confirm or revert and exit var confirmText = $(this).data('confirm'); if (confirmText) { if (!confirm(confirmText)) { $(this).val(prev); return; } } // if trigger element has data-alert attribute, show alert and exit var alertText = $(this).data('alert'); if (alertText) { alert(alertText); $(this).val(prev); return; } // cache the value before proceeding (if data-cache set) var cache = $(this).data('cache'); var cachePrefix = ($(this).data('cache-prefix')) ? $(this).data('cache-prefix') : ''; $(cache).val(cachePrefix + current); var $form = $(this).closest('form'); var target = $(this).data('update-target'); console.log("Target is " + target); var method = $form.attr('method'); var action = $form.attr('action'); var data = $form.serialize(); var encodedName; // .serialize() will omit select elements that do not have a 'null' option (e.g. asm select, page list select) // or checkboxes with nothing selected // so find them and add empty parameters to the data string, otherwise the page field will not be updated $($form.find('select, input').each(function(index){ console.log('Select element no. ' + index + ' with name ' + $(this).attr("name") + ' has serialize = ' + $(this).serialize()); encodedName = encodeURI($(this).attr("name")) if (data.search(encodedName) === -1) { data += ('&' + encodeURI($(this).attr("name")) + '='); } })); console.log("Submitted data: " + data); if (!method) method = 'get'; if (!action) action = window.location.href; // If you want to fade the affected inputfields then assign the loading class to their wrappers with method wrapClass(loading) $(target).find('.loading').css({ display: 'block', opacity: 0.2 }).animate({ opacity: 1 }, 5000); // then send your request $.ajax(action, { type: method, // type used, not method, for older versions of jquery data: data, // you can also add an error handler here if required, in case the server returns an error on the request success: function (data) { // Initial ajax just returns an array with message. Need to GET the form data. $.ajax(window.location.href, { type: 'GET', cache: false, success: function (data) { // then just take the target, and replace it with the target div from the returned data console.log("Returned data: " + data); console.log("Updating html with: " + $(data).find(target).html()); $(target).html($(data).find(target).html()); } }); } }); });
  11. I have now ? I hadn't realised that I had to install 2 modules separately. Many thanks.
  12. This may seem a really dim question, but here goes: I've just upgraded to 3.0.148 and installed the "Toggle" inputfield. I now want to add a new field with type "Toggle", but it does not appear in the drop-down for type on the new field page. I've checked that it is installed and have logged out and back in, but it's still not there. ???
  13. Solved now - the problem is in the jquery ajax call - using method: with version 1.8.3 - it should be type: prior to 1.9. See
  14. Aha - mostly solved this now - I am using method: in the ajax, but jquery is version 1.8.3, so I should use type: EDIT: Spoke too soon. Needed to modify the success: function(data) as follows success: function (data) { $.ajax(window.location.href, { type: 'GET', cache: false, success: function (data) { // then just take the target, and replace it with the target div from the returned data console.log("Returned data: " + data); // modified below to use .attr('value', ...) rather than .html console.log("Updating value with: " + $(data).find(target).attr('value')); $(target).attr('value', ($(data).find(target).attr('value'))); } }); but the returned data has not been updated by the posted data. EDIT2: Finally solved. I'll post the JS when I've tidied it up, in case it is useful to anyone else.
  15. I have a template with a field 'selector' that stores a selector string built from InputfieldSelect and InputfieldSelector options. The selector field is updated by javascript. When I save the admin page, the selector field in the DB is updated and the page loads with the correct Inputfield options. I am trying to avoid having to manually save the page when the InputfieldSelect value changes, so I have a little js snippet that runs on 'change' to update the value of the selector field. I can see from the console log that see that the data is being submitted and that the post is successful, but the returned data does not have the changed value. What am I doing wrong? The js is below, followed by the html for the InputfieldSelect that triggers it. $(document).on('change', '[data-action="form-update"]', function () { console.log("Executing snippet!"); var $form = $(this).closest('form'); var target = $(this).data('update-target'); console.log("Target is " + target); var method = $form.attr('method'); var action = $form.attr('action'); var data = $form.serialize(); console.log("Submitted data: " + data); console.log("Method: " + method); if (!method) method = 'get'; if (!action) action = window.location.href; // I usually add a loading overlay on the update target here, that might look something like this: $(target).find('.loading').css({ display: 'block', opacity: 0 }).animate({ opacity: 1 }, 5000); // then send your request $.ajax(action, { method: method, data: data, // you can also add an error handler here if required, in case the server returns an error on the request success: function (data) { // then just take the target, and replace it with the target div from the returned data console.log("Returned data: " + data); // modified below to use .attr('value', ...) rather than .html console.log("Updating value with: " + $(data).find(target).attr('value')); $(target).attr('value', ($(data).find(target).attr('value'))); } }) }); <select id="Inputfield_select_template" class="uk-select uk-form-small" name="select_template" data-action="form-update" data-update-target="#Inputfield_selector"><option value="">&nbsp;</option><option value="Booking">Booking</option><option value="Mandate">Mandate</option><option selected="selected" value="Member">Member</option><option value="Membership">Membership</option><option value="MemberShop">MemberShop</option><option value="NewsItem">NewsItem</option><option value="Payment">Payment</option><option value="Profile">Profile</option><option value="Subscription">Subscription</option><option value="user">user</option></select> Console extracts: Target is #Inputfield_selector Submitted data: title=test-users&summary=&select_template=Booking&select_filter__field%5B%5D=&select_filter=&selector=template%3DBooking&edit_mode=edit&childTemplate=&templateId%5Bnew_0%5D=130&idsToDelete=&individualChildTitles%5Bnew_0%5D=&templateId%5Bnew_0%5D=130&_pw_page_name=test-users&template=141&id=8707&TOKEN1616224121X1582934644=BMPaNoSmbHI%2FbXmbxBDyQGtcOHbbYqPK&_after_submit_action= Method: post Updating value with: template=Member I haven't included the full returned data as the last log item shows the value extracted from it. As you can see, template=Booking is submitted, but template=Member is returned.
  16. I have been using this module successfully for some time. Now I have a more complex use case. I want to update the page (in the admin) using ajax, rather than having to manually select "save". However, in this case, the data is submitted OK but the RuntimeMarkup script does not run and so the page is not properly updated. Any ideas? Thanks. Edit. I'm not entirely sure if the problem just lies with this module since, although the ajax is returning 'success' the normal fields don't appear to update either.
  17. MarkE

    Aaron Copland

    I must add my congratulations on a really great site - both the look and feel of the front end and the careful design and ui of the back end. I particularly like the rich content of the site and the dashboards. Complexity made artfully simple! I’m scratching my head about one thing, though. There seem to be a number of situations where many-many relationships exist (e.g. works - events). How did you implement that? I don’t see any use of the ConnectPageFields module.
  18. Having just wasted the best part of a day debugging an access issue because I hadn't realised that page-edit-created negated any related page-edit permissions, could I suggest that a note to this effect is included in the default title. I have amended the title on my system to read: Edit only pages user has created (IMPORTANT: This will negate any related page-edit permission - including permissions granted to a user by other roles) ..although it may be possible to make it briefer while not losing clarity and impact.
  19. SORTED! Tripped up by page-edit-created: "This permission is a bit unique in that it actually reduces access (to roles that have it) rather than adding access. " (my emphasis) You can say that again - it's completely unique and a real gotcha! I blithely went assigning all permissions to my webmaster role without realising that assigning this one actually effectively removed page-edit from most pages. This is really counter-intuitive. Why do it this way? The natural approach seems to me not to assign page-edit permission and then assign page-edit-created as an additional permission. To prevent me forgetting this (as if...), I have added a note to the title of the permission. It might be helpful to add something in the default title.
  20. Additional info: Here's an odd thing. I have a template "Membership" and roles "membership-secretary" and "webmaster" which both have page-edit permissions for that template. If I give a user the webmaster role, or both roles, then they cannot edit a Membership page. If I give the user both roles and REMOVE the page-edit permission for webmaster from the template, then the user CAN edit the page. Uhhh!!? (NB they can't edit it if they only have webmaster with no page-edit!) I have another role "treasurer" which also has page-edit permission for Membership. If I give the user both membership-secretary and treasurer roles but not webmaster, the they can edit a Membership page. If I add webmaster to their roles (with page-edit permission for Membership) then they can no longer edit the page, but they can again if I remove the page-edit permission from webmaster. I do have one or two functions which reference webmaster (to treat it the same as superuser for some purposes). I have double-checked all that code, but just to be certain the problem didn't lie there, I changed the role "webmaster" to "web-master" without amending the php. The problem remained exactly as described. So the issue lies somewhere in the database, but I have no idea where to look. I did the obvious and went through all the webmaster permissions and checked that all the permissions were there and that there were no revocations. In any case, why would adding a page-edit permission have the effect of blocking it? As a final throw of the dice, I created a new role "webmaster" (leaving the old one as web-master) with all page-edit permissions and the problem occurred with that too. Completely stumped at the moment!
  21. I am having a real head-scratch over an access issue. I have defined a role 'webmaster' which has all permissions assigned to it. However, whenever I assign this role to a user, none of the pages in the tree are editable. Users assigned lesser roles (with access to specific templates only) can edit the relevant pages, but if I add 'webmaster' to their roles, they no longer have edit access. Inspecting the templates shows that 'webmaster' has view, edit, create and add rights to all of them. The access overview module shows green ticks for webmaster everywhere. Any ideas how I go about debugging this (or, better still, what might be causing it?)
  22. Many thanks @Robin S. I had previously tried that, but it didn't work - hence my comment about not being able to set it directly. I now realise that the cause of that was that I had previously set initValue, to disable changing the template. After that, setting value with the full selector does not work - it is necessary to first remove the "template=..." from the selector. Thanks for giving me the confidence that I was setting it correctly so that I persisted in hunting down the "feature". So - adding a regex to split the selector into template (for initValue) and non-template (for value) components works a treat.
  23. Thanks, but I don't seem to be able to set that directly.
×
×
  • Create New...