Jump to content

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


BrendonKoz
 Share

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).

.../wire/modules/Jquery/JqueryUI/panel.js:

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

 

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) {
	console.log('opened').
});

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. 

image.thumb.png.7f4e32a6ff1d808b5e0dfec9e077dbf6.png

  • 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

@BrendonKoz

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
 Share

×
×
  • Create New...