Jump to content

Targeting pw-panel open with JS (and CSS columns)


Recommended Posts

Hello all! Has anyone with more JavaScript abilities been able to hook into ProcessWire's jQueryUI Panel functionality in order to handle onload events of the panel itself? I'm trying to simply set focus to the first input element of the form after clicking the button that activates the panel, but my click event does not run (I think due to the return false; in the panel.js as shown below).


// delegate events from toggler to pw-panel-button
$toggler.click(function() {
	return false;
}).on('mouseover', function() {
}).on('mouseout', function() {


Link to comment
Share on other sites

I tried taking advantage of the panel.js in the "dev" branch and using an "on" method for "pw-panel-opened" in my module but it also failed.

$(document).ready(function() {
	$(document).on("pw-panel-opened", ".InputfieldBooksAddPanel", function(e) {
		alert('It is open!'); // This never shows up
		$('#isbn').focus();   // This never receives focus


Also, unrelated, but can panels take advantage of the admin theme's columnWidth for rendering core elements? It doesn't seem to behave the way I'd expect (ex: I can get 50% width for the inputs within the panel, but there is never more than a single column).

Link to comment
Share on other sites

Hi @BrendonKoz

Are you developing a custom module? 

$(document).on("pw-panel-opened", function(e) {

This works for me. Where do you place your code? 

As for columns, it works for me, but only when screen larger than 1745 px. In this case, the width of the panel gets larger than 960px 

@media (min-width: 960px)
.uk-width-1-5\@m {
    width: 20%;

Default width of pw-panel is 50%, but you can use ' data-panel-width='60%' or ' $button->attr('data-panel-width', '100%');' to tune the width, so you will get columns on smaller screens. 


  • Like 3
Link to comment
Share on other sites

Hi @Zeka, yes I'm developing (or trying to anyway 😆) a Fieldtype/Inputtype. I'll have to do some more testing with the columns to see what might be the issue I'm having (thanks for showing me your example). I'm also going to upgrade from Master to Dev to see if it makes a difference.

I tried your version of the jQuery call and it worked - the first time the panel opened. Successive opens were not getting logged. So it seems I'm targetting the wrong element in my call (as your code example will run any time any panel is activated), but why it doesn't seem to run on all of the actual events is strange. (Edit: Firefox was kindly aggregating similar console.log results for me and I didn't notice.)

Hopefully the Dev version will show further success. 😉

  • Like 1
Link to comment
Share on other sites

I think my issue with the columns may be because I'm using the panel to load a form that exists (but is hidden via CSS) on the page-edit screen. Essentially my custom Fieldtype is large enough that it made sense to load the add/edit form somewhere else (modal/panel). It's likely that I'm not wrapping the form that I've created on the page (and grabbing via JS using $button->attr('data-panel-id', 'fieldtype-form');) in a particular class, though I've not yet figured out what that class is. I believe most people that use the panel are targeting an AJAX load to another file/form external from the currently edited page.

As for the JS, I'm still trying to figure out how to target only the panel that I just opened and not any panel on the page (i.e.: Page Edit screen's "View" -> "Panel"). I thought I had figured it out with the following, but it only ever runs the ELSE loop. From the panels.js code, it looks like the classes should exist before the custom event trigger is registered, so I'm not sure what's going on.

$(document).ready(function() {
	$(document).on("pw-panel-opened", function(e) {
		if ($('*[data-panel-id="fieldtype-form"]').hasClass('pw-panel-container-open')) {
			console.log('book add opened');
		} else {
			console.log('panel opened');

Running that test ([data-panel-id="fieldtype-form"]) from the browser's console while open or closed manually gives me the result I expect.

Link to comment
Share on other sites


As you develop custom fieldtype you can add custom js file for the page inside iframe via a hook to page render method.

$this->wire()->addHookBefore('Page::render', function ($e) {
	$page = $e->object;
	if ($this->input->get('modal') === 'panel') {
		$this->wire('config')->scripts->add($this->config->urls->YourFieldType . 'your-js-file.js');

Then in 'your-js-file.js' you can directly find doms elements on the loaded page.

Additionally, in hook, you can check whether the template of the current page (the one in the panel) has a field with your Fieldtype and then load you js.

  • Like 2
Link to comment
Share on other sites

That second bit with the hook is extremely useful - just not in this instance: if the field is included, it's going to be used on the page, and therefore the JS will be required no matter what.

However, I'm going to save that bit away for later!!! Thank you!

Your function format (and find() call) apparently was what I needed. Using that worked.

jQuery(document).on('pw-panel-opened', function (eventData, panelNode) {

The iframe, in my case, was not going to work since the form actually exists on the current page. (A semi-unknown/unused aspect of the panel is that you can load content that already exists on the current page using data-panel-id: $button->attr('data-panel-id', 'module-fieldtype-container'); ... when using this method, however, there's no iframe.)

Thank you!!!!!!

Link to comment
Share on other sites

It appears that the issue I'm having with the CSS layout is because I wasn't using AJAX to load a pre-existing template/form, there is no wrapping form field. Even if your module uses InputfieldForm to wrap/render your module's inputs, the form itself is stripped in the page edit admin so that the page template only contains a single form.

So...I either need to dynamically wrap my content in a form (with class "InputfieldForm"), or create a template and use AJAX load with the panel. I'm not sure which is simpler. Probably the AJAX for less future maintenance...in which case, I now need to figure out how to have an external template with my module as I can't think of any public modules that do that to study from.

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Similar Content

    • By phil_s
      Hey folks,
      I am building a new site with PW 2.4 and ran into a strange problem:
      - Image upload via drag and drop is not working (no color change, no upload starting)
      - Image reordering via drag is not working
      - I can't delete images
      Image Field is set to no limit, and resize w/h to 1600, I kept everything else on the default value.
      When I edit the post with said image field, Jquery UI gives me this error: TypeError: i[1] is undefined
      Strangely enough, moving categories and posts in the site tree, and dragging field in the templates works fine, and there is no error..
      Some more specs:
      - The server I'm on uses virtual document root, so uncommented the matching rewrite rule in the htaccess..
      - Mysql version is 5.5.28
      - Php Version is 5.49 (Stable), safe mode is off
      - Assets, and Files, Cache folders are set to 777
      I'm really at a loss at what could cause this :/ It feels like this should be a library not loading, but why would the dragging work in other parts of the admin, but not the images field?
    • By rosieate
      Hello there -
      So I'm migrating an existing yoga studio site that I built into ProcessWire. I created a template for the "teachers" page, which has teacher bios, that uses repeating fields for each teacher & wraps each one in a section tag: 
      <?php foreach($page->Info_Block as $Info_Block) { ?> <section class="bio"> <? echo "<h2>{$Info_Block->Name}</h2>"; echo "<div><img src='{$Info_Block->Image->eq(0)->url}'>"; echo "<p>{$Info_Block->Information}</p></div> "; }?> </section> I would like to make it so that only the teachers' names show, and then the bio section opens when the name is clicked, which I've done with CSS on the existing site: http://saniyoga.com/teachers.php.
      But the pure CSS solution uses modified inputs, which doesn't seem like a viable solution here. I've tried adding the script for the JQuery UI accordion to the template in both its original form (the containing div for the above code is "dropdown_cont")

      $(function() { $( ".dropdown_cont" ).accordion(); });  .... and with a modifier to take the section into account,

      $(function() { $( ".dropdown_cont" ).accordion( { header: '> section.bio > h2' } ); });  but it doesn't work. 
      Still very new to ProcessWire so would appreciate any suggestions. 
  • Create New...