Jump to content

MarkE

Members
  • Posts

    1,082
  • Joined

  • Last visited

  • Days Won

    12

Everything posted by MarkE

  1. 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()); } }); } }); });
  2. I have now ? I hadn't realised that I had to install 2 modules separately. Many thanks.
  3. 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. ???
  4. 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
  5. 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.
  6. 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.
  7. 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.
  8. 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.
  9. 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.
  10. 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.
  11. 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!
  12. 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?)
  13. 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.
  14. Thanks, but I don't seem to be able to set that directly.
  15. I am using InputfieldSelector in a custom module. I would like to pre-populate it based on a PW selector (e.g. "template=Booking, bookableSlotPage=8527, bookableSlotPage.tickets>0"). Using initValue will pre-select the template, but I would also like to have the initial display show the field filters as well. Is there a way of doing this in PW or do I need to devise some method of doing it with js? By way of context, I am using this for dynamic email lists for my club membership system. The "dynamic" nature of the list is stored as a selector in a field which can then be used by the email function. To date, this has been done by just entering the selector as raw text. I now want to make this easier for 'normal' users by using the InputfieldSelector (in a runtime_markup field) to provide a user-friendly way of creating the selector. But then I need the page to show the initial InputfieldSelector to represent the selector stored in the field, for backwards-compatibility, if nothing else.
  16. It's a shame that this module is no longer supported. I have an app that uses it and it works well. I'm not sure that the use of Flourish is a problem as it only uses a few classes, which presumably could be modified if they cause issues in the future with new PHP versions. I can't find a better alternative at the moment. However, there are a couple of problems I have had with the module: html tags such as <ol> cause problems The additional "notify users" for categories does not work well. Firstly, any additional users in one category are applied to other categories and, secondly, only one set of From, Subject and Body is allowed. I have attempted to fix these at https://github.com/MetaTunes/ProcessEmailToPage. Please feel free to use (and to fix any further bugs!). I'm not promising super support, but will look into any genuine bugs. Another point to note re multiple categories - all the email addresses must use the same password as this is set at an overall level. I have not attempted to fix this. EDIT: updated code to fix the issue reported by @huseyin - let me know if it works.
  17. This doesn't look like a module issue. Try using single quotes around the double asterisks: '**' not ** i.e. (in your example) email='**DialVision**@carsvasite.us' EDIT: Correction - in my off-the-cuff response I hadn't realised that this is in the code, not set in options. See the link in the next post.
  18. Except that, in the 'before' hook, the test is is_null() because the default 'true' value has not been set. The second time, the argument will be 'false', which is not null ?
  19. Aha! So a better way to avoid the hook being called twice would be to test for the 'save' argument. In my case I can't use the trashed hook as I need to access the parent of the page being trashed, which is too late if it has been trashed.
  20. I know it's a long time since the last post, but this still seems to be an issue in 3.0.123. It's easily avoided by setting a flag to prevent repeats (see below), but is it a bug or a side-effect of some intended behaviour? wire()->addHookBefore('Pages::trash', function ($event) { $p = $event->arguments(0); if ($this->skip != $p->id) { $this->skip = $p->id;
  21. OK, I cleared FileCompiler. Any ideas why it would suddenly go awry? (BTW, I should add that it all seems to be working now. Thanks for the quick responses!)
  22. It was set to true - that's how I was able to identify files with the missing namespace statement. Adding namespace ProcessWire; seems to fix the errors, but why is it suddenly a problem??? I have changed no settings. In fact I hadn't touched the site since it was working fine yesterday - a user then alerted me to the problem this afternoon. The hosting service say they haven't changed anything either. The .htaccess is unchanged as is the php config. ?
  23. PW v 3.0.123 I haven't upgraded since the original installation PHP 7.2 I have raised a query with the hosting service Adding namespaces seems to be fixing it (at least partially - still more to do), but I've no idea why it was suddenly a problem (and a lot of modules do not have namespace statements.
  24. One of my sites has just crashed and gives server 500 errors. Looking at the logs, the cause is multiple fatal errors of the type: Fatal Error: Uncaught Error: Class '\ProcessRedirects' not found Inspecting the code, it seems like the namespace ProcessWire; statement is missing in many of the modules and this seems to be causing the error. I'm inserting the statement as I get each error and each time I get a new instance. The odd thing is that the code has not been changed recently (apart from one Hanna code which was working yesterday). The problem only started this afternoon. Is my diagnosis correct and, if so, what might have caused this to suddenly start giving fatal errors.
  25. That's useful to know about, but my tests showed that a simple %20 -> + fix would still have got a 403. Exactly how the rule operates, and therefore what if any replacement might defeat it, is not clear to me.
×
×
  • Create New...