Bob's Blog

Why Subscribe?

As a Subscriber, you will receive access to certain parts
of the site that are hidden from others. You'll also get
email updates when new content is available
on the site or existing content is updated.

When logged in, you'll no longer see this request to
subscribe.

As an added incentive to subscribe, I have a bunch
of new and updated MODX extras I plan to release
as soon as I have a significant number of subscribers
to notify.

Privacy Policy

I'm too lazy to collect any information about you other
than the data you submit when you subscribe, which I will
never intentionally share with anyone.

As usual, Google and other entities may also collect
information about you during your visit.

Updating Manager Pages in a Plugin II

Adding buttons to the Create/Edit Resource Manager page with JavaScript in a plugin attached to OnDocFormRender

This is the second in a series of articles on dealing with issues created by operations performed in plugins that work on the Create/Edit Resource Panel in the MODX Manager. In this one, we'll look at how to insert buttons into the Create/Edit Resource Panel. Will also look at using heredoc syntax for quoted strings in PHP.

Getting a Handle on the Location

The first step in adding buttons to the page is getting the location of the existing buttons in JavaScript ("Save," "View," etc.). The best place for the new buttons was to the left of the existing ones.

The second version is more efficient, but arguably more difficult to understand.

Button Code

Before we can insert the buttons, we have to create code for them. We'll designate them as editDraftButton, deleteDraftButton, and editOriginalButton, and use those for the variable names in both PHP and JavaScript, and a lowercase version with underscores between the words for the IDs of the buttons in HTML. You could put the button code in a chunk. It would slow things down some, but it would let users edit the button content more easily. Because our buttons are fairly simple, we'll just put their HTML content directly in the plugin's JS code. Here's the HTML code for the buttons:

The button code below is designed as a first step to make the buttons functional on their own. When we put everything together in later articles, we'll modify the code to make things more efficient. For example, we only need to get the buttonDiv, buttonRows, and buttonRow elements once.

Inserting the Buttons

Now that we have the buttons defined, here's the full JavaScript code for adding them to the left of the existing buttons:

Using heredoc for Quoted Strings

If you have a complicated quoted string with variables inside it, it's often easier to use PHP's heredoc syntax. Basically you add a variable name at the top of the string, followed by <<< and a token, and put the same token at the end. By convention, the token is in uppercase letters, like this:

The heredoc syntax looks strange at first, but all that's happening in the heredoc section of the code above is assigning a string to the $str variable. Think of the << at the top and the TOKEN at the bottom as super quotation marks.

The nice thing about heredoc syntax is that you can mix in single and double quotes and variable with much less worry. The quotes will always be rendered as written and the variables will be translated into their values. The echo $str code above will display this:

My name is "MyName".
Now, I am printing some 'SomeText'.

Notice that the quotes (both kinds) become part of the string just as written.

If a variable in a heredoc section is complicated, it should be enclosed in curly brackets, like this: {$myArray[0]} or this: {$someFunction->myArray[1]}. When in doubt, you can use the curly brackets, since they will work with any variable.

Using the heredoc syntax makes things a lot easier for our example because it contains both single and double quotes, making it difficult to quote without escaping many of the quotes. Placing the code in a chunk would accomplish the same thing (with slower execution). Any variables in the code would have to be replaced with placeholders and the placeholder values would have to go in an array sent as a second argument to $modx->getChunk(). In StageCoach, most of the heredoc sections contain JavaScript code that no end user would ever edit. If you expect users to edit the string (e.g., the text of a Tpl chunk), you should definitely use a chunk.

Unfortunately, our heredoc code is more complicated than usual because we're creating JavaScript code, especially the part where we construct the links for the editDraft and editOriginal buttons, but we won't worry about that until later articles in the series. For now, we'll just create the buttons.

The Full Code (using heredoc)

Now that we have the JavaScript code for the buttons, we need to get it inserted into the page. We'll only do the two buttons that go on the Original Page — later, we'll introduce the code that determines which pages get which buttons. We'll use the $modx->regClientStartupScript() method, which will put the code in the head section of the page's HTML code. We also need to wrap the code in an Ext.onReady function so it won't execute until the page has been rendered and we can be sure that the HTML code the JavaScript is referencing exists on the page. Since extJS/modExt is loaded along with every Manager page, we might as well use it here. If the MODX Manager were ever re-written without extJS/modExt, we'd have to rewrite our code.

Making sure the page is fully rendered is particularly important with ExtJS/modExt, which creates much of each manager page on the fly. You can see this yourself if you do a "View Source" on a Manager page. You'll find that most of the page code is missing. If you examine the page in Firefox of Chrome Dev. Tools, you'll see a ton of stuff that isn't there in "View Source." The extra HTML code is rendered on the fly by the Manager JavaScript.

modx-action-buttons is the outer div containing the buttons. We get that with the first line. In order to insert the buttons, we need to get the table collection of buttons inside that div. Because the buttons are in a table row with the class x-toolbar-left-row, we can get a collection of rows with that class by calling getElementsByClassName on the buttonDiv element we got in the first line.

There's only one element returned, but getElementsByClassName returns a collection, so we need to refer to it as buttonRows[0]. We want to insert the new buttons to the left of the existing ones so we insert our button with row.insertCell(0).

Notice that we've used the same code for both buttons. Once our first button is inserted, it becomes the leftmost button, so inserting the second button in front of it is done the same way.

Because you can chain functions in JavaScript, the code to get the buttonDiv could also be written as:

The second version is more efficient, but arguably more difficult to understand and to debug.

Coming Up

The code above placed in a plugin attached to OnDocFormRender will add the buttons to the Create/Edit Resource panel, but there are a couple of serious problems. First, the buttons won't do anything. Second, the buttons will appear on every resource of the site. We'll deal with those problems in upcoming articles.

Looking for high-quality, MODX-friendly hosting? As of May 2016, Bob's Guides is hosted at A2 hosting. (More information in the box below.)

Looking for high-quality, MODX-friendly hosting? As of May 2016, Bob's Guides is hosted at A2 hosting. MODX will work fine at most hosting services, but having a MODX-friendly host can prevent a lot of frustration. Better yet, the A2 Solid-State-Drive servers are configured to handle the many Ajax and database calls made by MODX — especially the MODX Manager. My Manager runs about four times as fast as it did on my previous host. I particularly recommend the Swift package with the Performance Plus option.