a-ok Posted November 24, 2015 Share Posted November 24, 2015 Hi folks, I have a simple PageField set up, which is being used in this instance as a 'Related Articles' area; they can choose (Multiple Pages) which news articles are related then it does something nice front end. The only issue I have is that I'd like to limit the number of articles they can choose (only allowing three, for example) much like you would have in a File field or Image field (Maximum files allowed). Any thoughts? Link to comment Share on other sites More sharing options...
LostKobrakai Posted November 24, 2015 Share Posted November 24, 2015 This greatly depends on the inputfield you're using as it's javascript which would solve this. The only thing you could do from pw aka php is stripping additional pages when saving the page. Link to comment Share on other sites More sharing options...
a-ok Posted November 24, 2015 Author Share Posted November 24, 2015 I am using the Page field. So I'm guessing there's no option? Seems a little like an oversight, do you think (not to sound as mean as it looks!)? Link to comment Share on other sites More sharing options...
LostKobrakai Posted November 24, 2015 Share Posted November 24, 2015 I'm talking about the inputfield you choose the page field to use, e.g. Select, ASMSelect, PageListSelect and so on. These all work differently in terms of markup and javascript, so it's understandable that there's no central way to limit the number of selections beyond single / multiple. Single and Multiple pagefields are even mostly using different inputfields. Link to comment Share on other sites More sharing options...
a-ok Posted November 24, 2015 Author Share Posted November 24, 2015 Ah right, I understand. I am using the ASMSelect for multiple pages. I thought, above all, if you have multiple pages you should at least be able to limit the amount you choose. Link to comment Share on other sites More sharing options...
LostKobrakai Posted November 24, 2015 Share Posted November 24, 2015 You can always strip off additional pages using php, but that's certainly not the best user experience. For the ASM Select you could create a javascript, which does disable all options from the select box if a certain number of pages was selected (and reset if not). Link to comment Share on other sites More sharing options...
bernhard Posted November 24, 2015 Share Posted November 24, 2015 nice challenge for the evening with a happy end create a javascript file scripts/limitpageselect.js: // my field is called "pageselect" $(window).load(function() { if($('#Inputfield_pageselect :selected').length > 4) $('#Inputfield_pageselect').siblings('select').hide(); $('#Inputfield_pageselect').change(function() { if($('#Inputfield_pageselect :selected').length > 4) { $(this).siblings('select').hide(); } else { $(this).siblings('select').show(); } }); }); and inject this file via hook in /site/ready.php $wire->addHookAfter("ProcessPageEdit::buildForm", function(HookEvent $event){ $process = $event->object; $page = $process->getPage(); if($page->template != 'basic-page') return; // set your template name here $config = wire('config'); $config->scripts->append($config->urls->templates . 'scripts/limitpageselect.js'); }); 7 Link to comment Share on other sites More sharing options...
tpr Posted November 25, 2015 Share Posted November 25, 2015 I wonder if it's better to wrap the whole hook in such a condition: if($page->template === 'basic-page') { $wire->addHookAfter(...) } 2 Link to comment Share on other sites More sharing options...
LostKobrakai Posted November 25, 2015 Share Posted November 25, 2015 The $page variable is only available through the HookEvent, so you cannot dynamically add the hook, besides if you already have the exact instance of the class you want to hook. Link to comment Share on other sites More sharing options...
tpr Posted November 25, 2015 Share Posted November 25, 2015 I see, but in ready.php the $page is already determined, isn't it? This snippet actually works: // content in ready.php if ($page->template != 'admin') { $wire->addHookAfter("Page::render", function (HookEvent $event) { echo <<< HTML <script type="text/javascript">alert('Hello world');</script> HTML; }); } I guess it's because it hooks to Page:: render. Link to comment Share on other sites More sharing options...
LostKobrakai Posted November 25, 2015 Share Posted November 25, 2015 $page is of the admin template for everything you visit in the backend. But most of the time you're interested in the page your editing and not the "admin page" your on. 1 Link to comment Share on other sites More sharing options...
bernhard Posted November 25, 2015 Share Posted November 25, 2015 hi tpr, this method works in frontend but not in admin! try echo $page->id; it will show "10" for all processpageedit pages... /admin/setup/ would be 22 unfortunately there's a bug in my script: when you save a field with 5 pages it will not remove the select-field because its only called on change of the field. the problem is, that the select-field is injected by jquery by the admin so this does not work: // my field is called "pageselect" $(function() { $('#Inputfield_pageselect').siblings('select').hide(); // added this line $('#Inputfield_pageselect').change(function() { if($('#Inputfield_pageselect :selected').length > 4) { $(this).siblings('select').hide(); } else { $(this).siblings('select').show(); } }); }); maybe it would work if the script was loaded at the very last of all scripts? how could i achieve that? Link to comment Share on other sites More sharing options...
gebeer Posted November 25, 2015 Share Posted November 25, 2015 Hi BernhardB, I have a small module that injects a script tag right before </body>. Here's the relevant lines public function init() { $this->addHookAfter('Page::render', $this, 'addInlineScript'); } public function addInlineScript($event) { $page = $event->object; if ($page->template->name !== "admin" && $page->inlineScript) { $event->return = str_replace("</body>", $page->inlineScript . "</body>", $event->return); } } You can adjust that to your situation. Hope it helps. 1 Link to comment Share on other sites More sharing options...
LostKobrakai Posted November 25, 2015 Share Posted November 25, 2015 Just use $(document).ready(function(){ … }); around your code, so it's not executed before the whole dom is loaded. Link to comment Share on other sites More sharing options...
gebeer Posted November 25, 2015 Share Posted November 25, 2015 @LostKobraKai Wouldn't you actually need window.onload or $(window).load for that? $(document).ready fires when the DOM is ready and does not wait for all resources like scripts/images. See here and here. 1 Link to comment Share on other sites More sharing options...
bernhard Posted November 25, 2015 Share Posted November 25, 2015 thank you! i was already using document.ready (short syntax) - gebeer was right, both injecting the JS via str_replace(</body> and loading the script via window.onload worked! i updated the code above so it should be working now. Link to comment Share on other sites More sharing options...
tpr Posted November 25, 2015 Share Posted November 25, 2015 Or use window.load() inside document.ready() to make sure http://stackoverflow.com/questions/5006922/window-load-inside-a-document-ready Link to comment Share on other sites More sharing options...
tpr Posted November 25, 2015 Share Posted November 25, 2015 Some improvements in the JS: $(window).load(function () { var fieldName = 'tags_recipe', // add field name here limit = 5, // set limit here asmSelector = '#Inputfield_' + fieldName; $(asmSelector).on('change limitItems', function () { var obj = $(this).parent().find('.asmSelect'); $(this).find(':selected').length >= limit ? obj.attr('disabled', 1) : obj.removeAttr('disabled'); }); $(asmSelector).trigger('limitItems'); }); What would be nice is to add the "limit" in the backend to the asmSelect using a "data-limit" attribute and then let JavaScript do its part on all asmSelects which have data-limit set. 5 Link to comment Share on other sites More sharing options...
adrian Posted February 21, 2018 Share Posted February 21, 2018 @tpr - have you considered adding this functionality to AOS? Or maybe a @Robin S "limit" special module 2 Link to comment Share on other sites More sharing options...
tpr Posted February 22, 2018 Share Posted February 22, 2018 I haven't yet but I'll give a try. 4 Link to comment Share on other sites More sharing options...
tpr Posted February 22, 2018 Share Posted February 22, 2018 It's done, will be added to the next aos update. I've borrowed some code from @Robin S modules (thanks!) as I haven't added config inputs to fields so far. In fact I totally forgot about this asmSelect snippet of mine, thanks for the reminder 5 1 Link to comment Share on other sites More sharing options...
adrian Posted February 22, 2018 Share Posted February 22, 2018 @tpr - that's what I call service Thank you! 2 Link to comment Share on other sites More sharing options...
Robin S Posted February 22, 2018 Share Posted February 22, 2018 On 2/22/2018 at 10:31 PM, tpr said: It's done, will be added to the next aos update. Expand Awesome! Do you reckon you could do something similar for Page Autocomplete? Link to comment Share on other sites More sharing options...
GhostRider Posted February 22, 2018 Share Posted February 22, 2018 @tpr Fantastic! Great addition. @adrian thanks for suggesting. 2 Link to comment Share on other sites More sharing options...
tpr Posted February 23, 2018 Share Posted February 23, 2018 On 2/22/2018 at 10:54 PM, Robin S said: Do you reckon you could do something similar for Page Autocomplete? Expand I saw this follow-up question coming, ? I think that's also doable, will check that later. I reckon the same question is about to emerge for the rest of the PageField types, isn't it? ? 1 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