Custom JS in ProcessWire backend

2014/04/02 9:57 PM • ProcessWire Tutorial Comments (4)

We look at how we can quickly add some Javascript magic to the ProcessWire admin, without creating a module or doing anything complicated. This quick tutorial is for people new or already advanced users of PW. Maybe either of you can pick up something new along the way.

There's a lot to discover in PW and once you get to the point where you think of having a javascript loaded in the admin, that interacts with the backend, here's a quick way of doing just that. It may not best suited for all tasks and there for sure are other ways of injecting custom stuff into the admin. This might be the most straight forwards way, letting you experiment with some ideas, or just giving that last edge you ever wanted for your PW admin install.

It's all pages

PW admin pages are in fact also pages. As you may already know and use them. They just use the admin template. This simply means it's a template same as you know and already use. The template php file is located in your site templates folder and is the /site/templates/admin.php. If you open it, you'll se only 1 line of code which is like a remote controller that includes the real admin controller.

<?php
/**
 * Admin template just loads the admin application controller,
 * and admin is just an application built on top of ProcessWire.
 *
 * This demonstrates how you can use ProcessWire as a front-end
 * to another application.
 *
 * Feel free to hook admin-specific functionality from this file,
 * but remember to leave the require() statement below at the end.
 *
 */
require($config->paths->adminTemplates . 'controller.php');

This is nice as it allows us to add small snippets in there that will get executed on every page load. Since it's in the site folder, we don't have to worry about being replaced on updates. As you see this would also be a good place to add PW hooks, but we'll use it to inject a custom JS file in the admin.

Adding our javascript file

Using this template to add a Javascript file. PW uses the $config->scripts and $config->styles config variables to populate an array of files, that then will get iterated and output in the HTML head of any admin page. Modules use this method to add JS to the admin. So what we do is create a new JS file for example under /site/templates/scripts/scroll.js, then let's insert some real cool stuff: ;)

$(function() {
    alert("Hello Worlds!");
}

Ok, no we only need to get PW to load that file we just created. This is where, as earlier mentioned, the $config->scripts file array comes into play. There's an add() method $config->scripts->add(fileURL) we can use, so we add the following lines in the admin.php just before the include line:

$config->scripts->add($config->urls->templates . "scripts/scroll.js");

$config->urls->templates here gives us the path to the /site/templates/ folder. Save the template file and open the PW admin the browser. If it works all out, we should get alerted by the JS we just added. But the script isn't working! Why? 

Turns out that adding the script this way will add out JS before the Jquery.js library, thus our script that uses jQuery syntax isn't working but throwing an error that $ isn't defined. This is simply because we add our script in a place that is before all other scripts will get appended including Jquery core.

We can fix this by either using a simple hook instead to add our script. But there's also a trick we can use to make sure the JqueryCore gets added before ours. We simply load the JqueryCore module before we add our script. To load a module we simply have to call it via $modules API var.

$modules->get('JqueryCore');
$config->scripts->add($config->urls->templates . "scripts/scroll.js");

Test again. Now our script will get added after the jQuery script and we see the JS alert as it should.

Communicating with PHP

Ok, but let's go one step further and add some more. What if you want to have some dynamic variables in your JS? Something that a lot of people ask is "how can I give my JS a value of what I only have easy access to via PHP or in this case PW API?"

Just for sake of having a very simple example, I thought following might be ok. Let's say we want to get the GET parameter ?open=1234, that is added to the admin page url when you click on a parent breadcrumb page to get back to the admin tree. The parameter ?open=ID is used to then fold out the page in the tree with the ID 1234. We could take that ID and add a little jQuery magic to scroll to the opened page in the page tree. At times the page is deep down the page tree and we have to scroll down manually.

We need something to communicate that ID to our JS. PW has something built in and does this already in the admin. If you look at the HTML head source code of an admin page you'll see something like:

<script type="text/javascript">var config = {"ProcessPageList":{"containerID":"PageListContainer","ajaxURL":"\/processwire\/page\/list\/","ajaxMoveURL":"\/processwire\/page\/sort\/","rootPageID":0,"openPageIDs":[1079,2],"openPagination":0,"showRootPage":true,"limit":50,"speed":200,"selectStartLabel":"Change","selectCancelLabel":"Cancel","selectSelectLabel":"Select","selectUnselectLabel":"Unselect","moreLabel":"More","moveInstructionLabel":"Click and drag to move"},"debug":false,"urls":{"root":"\/","admin":"\/processwire\/","modules":"\/wire\/modules\/","core":"\/wire\/core\/","files":"\/site\/assets\/files\/","templates":"\/site\/templates\/","adminTemplates":"\/wire\/modules\/AdminTheme\/AdminThemeDefault\/"}}</script>

This is a JSON array simply printed out before the scripts. This way PW modules can populate and their JS pick up this JS config variable that's in fact a JSON array. We can also use it to add our custom variable containing the opening page ID. Again in the API $config variable there is a $config->js(key, mixed) method we can use. (key would be the name of the variable and the mixed can be either a int, string, or array)

Cool then, we just add another line to our /site/templates/admin.php just before the lines of code already in there.

$config->js("scrollToPage", $input->get->open);

Our admin.php now looks like this:

<?php
/**
 * Admin template just loads the admin application controller,
 * and admin is just an application built on top of ProcessWire.
 *
 * This demonstrates how you can use ProcessWire as a front-end
 * to another application.
 *
 * Feel free to hook admin-specific functionality from this file,
 * but remember to leave the require() statement below at the end.
 *
 */

$config->js("scrollToPage", $input->get->open);
$modules->get('JqueryCore');
$config")->scripts->add($config->urls->templates . "scripts/scroll.js");

require($config->paths->adminTemplates . 'controller.php');

$input->get->openwill get us the ID from the GET parameter. Now if you refresh the admin page, we have a new variable in there config variable scrollToPage: "" .

Let's update and add some jQuery magic to our JS to pick up this new variable.

$(function() {
    setTimeout(scrollToTreeOpen, 1000);
    function scrollToTreeOpen() {
        if (config.scrollToPage) {
            $('html, body').animate({
                scrollTop: ($(".PageListID" + config.scrollToPage).offset().top) + "px"
            }, 500);
        }
    }
});

The JSON variable config.scrollToPage will contain the ID. The page, that PW opens in the tree, is a div and has a class in the format PageListID1234. Since we have the ID the rest is simple. (Don't worry if you don't understand what this script does exactly. Just watch it and at some point you'll get it)

Note: I've added some delay here to execute the scrollToTreeOpen() function, because the admin page tree is loaded via AJAX and takes a little time to start opening the branches. Note that this example is more just for fun and it may not work when the page tree takes longer than one second to load. So, this example taken here may not the best way to implement that feature but that's another story.

There's other ways to add JS to the admin, but this would be something for another toturial.

I hope you learned something new and thanks for reading! Happy PWiring.

2014/04/02 9:57 PM | ProcessWire | Tutorial

Comments

  • Posted by kongondo on Apr 2, 2014 11:20 PM

    Nice one Soma! Thanks for sharing...

  • Posted by mary on Apr 3, 2014 12:19 AM

    This will come in handy. Thank you Soma :)

  • Posted by Martijn Geerts on Apr 3, 2014 8:23 AM

    Thanks for you effort. Good work.

  • Posted by arjen on Apr 6, 2014 8:29 PM

    Great post! Learned some new stuff as usual!

Post Comment