Robin S Posted February 20 Share Posted February 20 I was browsing the requests repo and saw a request from @adrian that reminded me of a PW feature I had forgotten existed: from Page List you can open a page for editing in a modal window by long-clicking on the Edit button. This is quite handy for when you want to make a quick edit to a page. But as the request notes, it would speed things up if there was a "Save + Close" button in the modal. Until the request is actioned in the core I thought I'd try implementing it in some custom code, and it's also an opportunity to show an easy way you can add custom JS and CSS to the ProcessWire admin. The first step is to create the following files at /site/templates/admin-assets/admin-custom.js and /site/templates/admin-assets/admin-custom.css. The CSS is optional. admin-custom.js $(document).ready(function() { const $body = $('body'); const is_modal = $body.hasClass('modal') || $body.hasClass('pw-iframe'); if($body.hasClass('ProcessPageEdit') && is_modal) { const params = new URLSearchParams(window.location.search); const $save_button = $('#submit_save'); if(params.has('quick_edit') && $save_button.length) { $save_button.parent().append('<button type="submit" name="submit_save" value="Save" class="ui-button uk-hidden" id="save-and-close">Save + Close</button>'); } } if($body.hasClass('ProcessPageList') && !is_modal) { $(document).on('ajaxComplete', function() { $('.PageListActionEdit a:not([data-autoclose])').each(function() { $(this).attr('data-autoclose', '#save-and-close').attr('href', $(this).attr('href') + '&quick_edit=1'); }); }); } }); admin-custom.css /* Avoid Tracy debugbar appearing on top of modal */ .ui-widget-overlay.ui-front { z-index:40000; } .ui-dialog { z-index:40001; } /* Place modal buttons on the left rather than the right */ .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float:none; } The second step is to add the following hook to /site/ready.php One good thing about using a hook to AdminTheme::getExtraMarkup to add custom CSS is that the file gets loaded after any CSS files that are loaded by modules or the PW core, so you can override any CSS rules without needing to add extra specificity. // Add custom JS and CSS to admin $wire->addHookAfter('AdminTheme::getExtraMarkup', function(HookEvent $event) { $parts = $event->return; $config = $event->wire()->config; // JS file should exist at /site/templates/admin-assets/admin-custom.js $js_url = $config->urls->templates . 'admin-assets/admin-custom.js'; $modified = filemtime(rtrim($config->paths->root, '/') . $js_url); $parts['head'] .= "<script type='text/javascript' src='$js_url?m=$modified'></script>"; // CSS file should exist at /site/templates/admin-assets/admin-custom.css $css_url = $config->urls->templates . 'admin-assets/admin-custom.css'; $modified = filemtime(rtrim($config->paths->root, '/') . $css_url); $parts['head'] .= "<link rel='stylesheet' href='$css_url?m=$modified'>"; $event->return = $parts; }); The end result: 12 Link to comment Share on other sites More sharing options...
monollonom Posted February 21 Share Posted February 21 10 hours ago, Robin S said: One good thing about using a hook to AdminTheme::getExtraMarkup to add custom CSS is that the file gets loaded after any CSS files that are loaded by modules or the PW core, so you can override any CSS rules without needing to add extra specificity. This is pretty neat, thanks for sharing! Until now I was adding these admin css tweaks through $config->styles in admin.php and thus I had a plethora of “!important” in my CSS... 2 Link to comment Share on other sites More sharing options...
matjazp Posted February 21 Share Posted February 21 Hey Robin! Thanks for this. I haven't had time to test this, but looking the code I see uk-hidden class on button. Would button even show? (and I know it's there for a reason) 1 Link to comment Share on other sites More sharing options...
Robin S Posted February 21 Author Share Posted February 21 3 hours ago, matjazp said: looking the code I see uk-hidden class on button. Would button even show? Yes, it does show, but only in the modal and not in Page Edit itself, which is the intention. The way that modal buttons work is that the modal script looks for buttons that are actually within the page that is being displayed in the modal iframe and then it constructs new buttons for the bottom of the modal. The newly constructed buttons don't carry over things like the uk-hidden class so they are not hidden. But because the button I'm adding is actually within the Page Edit interface (right next to the normal Save button) I never want that button to be shown in normal page editing because "close" wouldn't make sense there. The check for is_modal should also prevent the Save + Close button being displayed when it isn't wanted so the uk-hidden is really just optional but it's a sort of "belt and suspenders" approach just to be on the safe side. ? Link to comment Share on other sites More sharing options...
matjazp Posted February 21 Share Posted February 21 Now that you explain it, I remember this behavior of modal.js. But, unfortunately, it doesn't work here, only the Save button is cloned. Looking at the modal.js line 417, $icontents.find(buttonSelector) only returns one button, not two as expected. It seems like the Save+Close button is added too late, after the modal has already cloned the Save button. While debugging, I added the button unconditionally and also removed the uk-hidden class, and then edited the page in a new tab with modal=1, and both buttons were there, as expected. But not in modal. I guess if I add the button directly to the ProcessPageEdit.module (or via hook), it would work. But it's working for you, so there must be something with my installation. It's a bit late here, so I'll continue testing tomorrow. Link to comment Share on other sites More sharing options...
Robin S Posted February 22 Author Share Posted February 22 On 2/22/2024 at 10:48 AM, matjazp said: It seems like the Save+Close button is added too late, after the modal has already cloned the Save button. It's working reliably on a few sites I've tested on but what you're saying makes sense. So you could add the button with PHP in a hook and not in the JS as demonstrated below. I also had a thought that Page Edit might be opened in a modal in some other circumstances (I think ListerPro has an option for this) where the "Save + Close" button wouldn't work or wouldn't be wanted. So I've updated the code in the first post and in the code below so that a "quick_edit" URL parameter is added for identification purposes. admin-custom.js $(document).ready(function() { const $body = $('body'); const is_modal = $body.hasClass('modal') || $body.hasClass('pw-iframe'); if($body.hasClass('ProcessPageList') && !is_modal) { $(document).on('ajaxComplete', function() { $('.PageListActionEdit a:not([data-autoclose])').each(function() { $(this).attr('data-autoclose', '#save-and-close').attr('href', $(this).attr('href') + '&quick_edit=1'); }); }); } }); Additional hook for /site/ready.php $wire->addHookAfter('ProcessPageEdit::buildForm', function(HookEvent $event) { /* @var InputfieldWrapper $form */ $form = $event->return; // Return if Page Edit is not in a modal window if(!$event->wire()->config->modal) return; // Return if quick_edit GET parameter is not present if(!$this->wire()->input->get('quick_edit')) return; $save_button = $form->getChildByName('submit_save'); if(!$save_button) return; /** @var InputfieldSubmit $f */ $f = $event->wire()->modules->get('InputfieldSubmit'); $f->id = 'save-and-close'; $f->name = 'submit_save'; $f->value = 'Save'; $f->text = 'Save + Close'; $f->addClass('uk-hidden', 'wrapClass'); $form->insertAfter($f, $save_button); }); 1 Link to comment Share on other sites More sharing options...
matjazp Posted February 24 Share Posted February 24 Thx Robin! While the Save + Close button is there (as expected), the js part makes the edit links all open home page, eg. they all have the link /processwire/page/edit/?id=1&quick_edit=1 I fixed that with: const $links = $('.PageListActionEdit a:not([data-autoclose])'); $links.each(function() { $link = $(this); $link.attr('data-autoclose', '#save-and-close').attr('href', $link.attr('href') + '&quick_edit=1'); }); Just to mention that using uk-hidden class (as a "belt and suspender" approach) would only work in AdminThemeUIkit, leaving out newer (and older) admin themes. 3 Link to comment Share on other sites More sharing options...
Robin S Posted February 24 Author Share Posted February 24 5 hours ago, matjazp said: While the Save + Close button is there (as expected), the js part makes the edit links all open home page, Oh, good spotting, thanks! I updated my earlier posts. 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now