Extra JS in an Admin blueprint triggers a reload which I do not understand

Hello everybody,

I am once again working on my Cloudinary plugin that provides Grav Admin integration for files hosted with Cloudinary. It works so far for displaying stuff on the frontend, but I’d really love to add easy integration of new files in Admin.

Cloudinary offers a javascript upload widget that should make this a simple endeavour. So I created a new field template (named cl-file) by copying the text field template, and added the relevant bits of JS to that, as well as a button:

{% extends "forms/field.html.twig" %}

{% block prepend %}
{% if field.prepend %}
    <div class="form-input-addon form-input-prepend">
        {{- field.prepend|t|raw -}}
    </div>
{% endif %}
{% endblock %}

{% block input_attributes %}
    type="text"
    {% if field.size %}size="{{ field.size }}"{% endif %}
    {% if field.minlength is defined or field.validate.min is defined %}minlength="{{ field.minlength | default(field.validate.min) }}"{% endif %}
    {% if field.maxlength is defined or field.validate.max is defined %}maxlength="{{ field.maxlength | default(field.validate.max) }}"{% endif %}
    {{ parent() }}
{% endblock %}

{% block append %}
    {% if data.header.public_id is not null %}
        <div class="form-input-addon form-input-append">
            {% set thumb_options = {'width': '400'} %}
            <img src="{{ cl_url('thumbnail', data.header.public_id, thumb_options) }}" alt="Vorschau">
        </div>
    {% endif %}
    <button id="upload_widget" class="cloudinary-button">Upload files</button>
{% endblock %}

{% block input %}
{% if field.prepend or field.append %}
    {% set field = field|merge({'wrapper_classes': 'form-input-addon-wrapper'}) %}
{% endif %}
{{ parent() }}

{% do assets.addJs('https://widget.cloudinary.com/v2.0/global/all.js', 101) %}
{% do assets.addInlineJs("
var myWidget = cloudinary.createUploadWidget({
  cloudName: 'netzhexe',
  uploadPreset: 'my_preset'}, (error, result) => {
    if (!error && result && result.event === 'success') {
      //console.log('Done! Here is the image info: ', result.info);
    }
  }
)

document.getElementById('upload_widget').addEventListener('click', function(){
    myWidget.open();
    console.log('test');
  }, true);

", {'group': 'bottom'}) %}
{% endblock %}

The button shows up alright and is clickable. On click the upload widget opens and then vanishes again after half a second or so. I get no errors in the console, and I’m finding this hard to debug. As far as I can see, the problem is that something triggers a page reload, which naturally closes the opened widget again. But… why?? Where does that happen? And of course, how can I prevent this?

I’m wildly guessing that there must be some conflict between this script and at least one of the many others that go into that Admin page… but I just don’t know what or where or how to look. I am very grateful for any and all ideas!

Hey @Netzhexe,

I think I see the problem, the default behavior of a button in a form is to submit the form when clicked.

By preventing the default behavior of the click event, your function body will be executed without the interruption of the default behavior. Also I don’t think you do need the useCapture flag for this.

If that’s not enough you could also try event.stopPropagation(); but I don’t think there’s other events attached to that one element being created by you.

Bear in mind I haven’t tested your code nor Cloudinary, so hopefully I am on the right track. :slight_smile:

Oh man, just like I thought. SO simple really, and I would never have thought of that myself. You have my neverending gratitude!! :smiling_face_with_three_hearts:

What if you just add type="button"?

<button type="button" id="upload_widget" class="cloudinary-button">Upload files</button>

I think most browsers (at least it used to be back in the day) treat buttons with no type defined as a submit buttons (type="submit") and adding type="button" makes it simply a clickable button, but no submit is triggered

Yeah that would probably work too. i just didn’t know about submit being the standard action for a button :upside_down_face: and since I’m javascripting anyway, event.preventDefault() is a very usable solution I think. I was so happy about this breakthrough, I fixed a whole new version of my plugin and had it up in no time at all (and then another one because I forgot some bits and pieces of course :wink: ). I :heartpulse: this forum!