processwire/processwire-requests

Add attributes to script tags in admin theme.

Opened this issue ยท 4 comments

elabx commented

Short description of the enhancement

Be able to add attributes to script tags in admin theme.

Optional: Steps that explain the enhancement

Hi @ryancramerdesign !

Recently had a conversation with a couple forum members on the topic of being able to add attributes to script tags. This issue came about when talking about using Alpine.js for the development of a ProcessWire Inputfield, and the requirement of Alpine to be installed with the deferred attribute.

I am not sure is this is the right approach to make the tags output configurable but nonetheless decided to give it a shot, as one of the forum members (kongondo) proposed.

processwire/processwire#250

So in the Inputfield modules we could do something like:

public function renderReady(Inputfield $parent = null, $renderValueMode = false){
  $this->config->scripts->add("https://unpkg.com/alpinejs@3.10.2/dist/cdn.min.js", 
    ['defer' => true] 
  );
  parent::renderReady($parent, $renderValueMode);
}

@elabx Sounds like a good idea, maybe we should implement something similar. I wanted to mention that if this is for the admin, this is something you can already do in a different way:

$src = "https://unpkg.com/alpinejs@3.10.2/dist/cdn.min.js";
$this->wire()->adminTheme->addExtraMarkup('head', "<script src='$src' defer></script>");

For an Inputfield that might be used outside the admin, the script can also be included in the output from the ___render() method. But having an attributes option would be nicer, I'll look into it.

@ryancramerdesign if you add this could you please also support string syntax? It's an easy addition (actually I think the array syntax is supposed to be the addition and string is the default) but so much easier to write/read:

$config->scripts->add('myscript.js', 'defer');
// instead of 
$config->scripts->add('myscript.js', ['defer' => true]);

The string syntax would also work for something like this:

$scripts->add("https://code.jquery.com/jquery-3.6.1.min.js", 'integrity="sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=" crossorigin="anonymous"');

This also has the benefit that you can copy&paste everything from the CDN site (eg https://releases.jquery.com/). With array syntax you need to reformat everything after copy&pasting.

I also wanted to create a similar issue for a long time, because I needed to integrate scripts (custom scripts, and alpine or tabulator) in the admin as ES modules (type="module") so I can use imports in them. Didn't had the time to create that issue yet.

Here is my solution, that I used until now:

 $this->addHookAfter('AdminTheme::getExtraMarkup', $this, 'addFieldJs');
function addFieldJs(HookEvent $event) {
    bd("hook addFieldJs");
    $parts = $event->return;
    $file = $this->tabulator->assetUrl($this->files_path . $this->field->name . '.js');
    $out = "<script src='{$file}' type='module'></script>";
    $parts['body'] = $out;
    $event->return = $parts;
  }

I would love to see the string syntax in favor of an array based syntax like @BernhardBaumrock mentioned.

elabx commented

I updated the PR to reflect also the usage of a string syntax, seems nicer imho, I vote for @BernhardBaumrock 's suggestion.