Additional Manager customization with stylesheets

I like to customize the Manager to help guide my clients and to amuse myself.

Manager Customization is a great tool, but there are some things only a stylesheet can do, so I wrote a plugin that sets data-attributes on the body tag, so they can be styled by CSS.

The attributes set are data-resource-id and data-resource-template. This is done in a script that the plugin loads. For demonstration purposes, the plugin also loads a stylesheet.

Note that the script is a chunk so I can set values from the plugin. The stylesheet is a chunk here, but could be a file or generated Sass.

Here’s the plugin:

<?php
/* SetBodyAttributes 1.00 */

if ( $modx->event->name == 'OnManagerPageBeforeRender') {
  
  parse_str(parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY), $query_array);
  
  if ($query_array['a'] == 'resource/update') {
    $id = $query_array['id'];
    $resource = $modx->getObject('modResource',$id);
    $template = $resource->get('template'); 
    $params = ['id' => $id, 
              'template' => $template
              ];
    $js = $modx->getChunk('setBodyDataAttributes',$params);
    $modx->regClientStartupHTMLBlock($js);
   
    $css = $modx->getChunk('managerStylesheet');
    $modx->regClientStartupHTMLBlock($css);
  }
}

return;

The javascript chunk:

<script>
  document.addEventListener('DOMContentLoaded', function () {
    let body = document.querySelector('body');
    body.dataset.resourceId = [[+id]];
    body.dataset.resourceTemplate = [[+template]];
  });
</script>

And the demo stylesheet. Use your own template and resource ids.

<style>
  /* make the pagetitle blue for this template */
  body[data-resource-template="105"] #modx-resource-header {
    color: blue;
  }
  /* except this one, which will be red */
  body[data-resource-template="105"][data-resource-id="820"] #modx-resource-header {
    color: red;
  }
</style>
2 Likes

Hey John,

Thanks for posting this. Do you by chance have an example screenshot of what the results look like for the user in this case?

1 Like

I guess the demo stylesheet is just an example on how to target the elements you want to change via CSS.

So this example just turns the h2 red. Well… to be more precise: it does not really do that, bc the h2 wraps another h2 which you should target in your styles. And prepare yourself to use the !important rule a lot, as overriding the default styles often not works without doing so.

Setting those data-attributes is a neat idea imho!

Where is the nested H2 tag coming from? That doesn’t seem like a good idea. I would wager that it’s not allowed according to HTML5 standards. According to W3C, heading tags should include only phrasing content (3 Semantics, structure, and APIs of HTML documents — HTML5), not flow content like other heading tags.

Here’s an updated version that adds the context_key and user groups. (Beware of changed variable names.)

I use the context_key for modifying text editors for different sites in a multi-site. I use the user groups to augment Form Customization.

Tested with MODX 2.8.4 and MODX 3.0.1

/* SetBodyAttributes 1.01 */

if ( $modx->event->name == 'OnManagerPageBeforeRender') {
  
  parse_str(parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY), $query_array);
  
  if ($query_array['a'] == 'resource/update') {
    $resourceId = $query_array['id'];
    $resource = $modx->getObject('modResource',$resourceId);
    $template = $resource->get('template'); 
    $context = $resource->get('context_key'); 
    
    $user = $modx->getUser();
    
    $userGroupNames = $user->getUserGroupNames();
    $userGroups = implode(" ", $userGroupNames);

    $params = ['resourceId' => $resourceId, 
            'resourceTemplate' => $template,
            'resourceContext' => $context,
            'userGroups' => $userGroups,
            ];
    $js = $modx->getChunk('setBodyDataAttributes',$params);
    $modx->regClientStartupHTMLBlock($js);
   
    $css = $modx->getChunk('managerStylesheet');
    $modx->regClientStartupHTMLBlock($css);
  }
}

return;

Here’s the new javascript chunk:

<script>
  document.addEventListener('DOMContentLoaded', function () {
    let body = document.querySelector('body');
    body.dataset.resourceId = "[[+resourceId]]";
    body.dataset.resourceTemplate = "[[+resourceTemplate]]";
    body.dataset.resourceContext = "[[+resourceContext]]";
    body.dataset.userGroups = "[[+userGroups]]";
  });
</script>

The additions to my body tag:

 data-resource-id="1" data-resource-template="1" data-resource-context="web" data-user-groups="Administrator"

And the photoshoot:
image
image

You’re on your own for the stylesheet. Note that the versions I tested didn’t have the wrapped H2, but I’ve seen things like that before.