It seems if i define an extra element like:

                infoTab.add( {
                  id: 'myCheckbox',
                  type: 'checkbox',
                  label: 'myCheckbox',
                  onLoad: function() {
                    Drupal.dndck4.registeredOptions.push({id: this.id, type: 'image', mode: 'atom', name: 'scald_image'});
                  },
                  setup: function(widget) {
                    var options = JSON.parse(widget.data.options);
                    this.setValue(options.my_checkbox);
                  },
                  commit: function(widget) {
                    // Copy the current options into a new object,
                    var options = JSON.parse(widget.data.options);
                    var value = this.getValue();
                    if (value != '') {
                      options.my_checkbox = value;
                    }
                    else {
                      delete options.my_checkbox;
                    }
                    widget.setData('options', JSON.stringify(options));
                  }
                });

Then the onLoad function is not called (neither the onShow). However if all i do is change the type to text, then onLoad works fine.
I suspect it is a ckeditor bug. However this prevents me for making this work properly.

ckeditor version 4.4.6

Comments

nagy.balint’s picture

StatusFileSize
new1.87 KB

The workaround i found is to make the showHideOptions function available globally by the patch attached.

And then to add in the setup:

                 setup: function(widget) {
                    Drupal.dndck4.registeredOptions.push({id: this.id, type: 'image', mode: 'atom', name: 'scald_image'});
                    Drupal.dndck4.showHideOptions(this);

Then it works fine. (Though in certain cases then the showHideOptions will be called twice.

@gifad : can you check if you see the same thing? If we can do this workaround, or rather should do something else?

gifad’s picture

@nagy.balint :
1 - Your code would not work, because the argument of showHideOptions() must be the context field...
2 - the registration code is not required to be located inside the element description; you can issue

  Drupal.dndck4.registeredOptions = Drupal.dndck4.registeredOptions || [];
  Drupal.dndck4.registeredOptions.push({id: 'myCheckbox', type: 'image', mode: 'atom', name: 'scald_image'});

- if you are injecting the element dynamically : in the script where you do the on('dialogDefinition',...
- if you are building a custom dialog : in the onLoad of a regular control, or in the onLoad of the dialog itself.

BTW, the ckeditor "bug" is still present in ckeditor-dev 4.4.8 and 4.5.0; so it could be a feature ?

[Edit] : This works, because the registeredOptions array stores only the string representation of the element id, not requiring that the element is actually created.

gifad’s picture

Status: Active » Needs review
StatusFileSize
new1.1 KB

As a proof of concept, and/or for sample code, I tested this on scald_image module.

gifad’s picture

StatusFileSize
new1.69 KB

Correction : the initialisation of registeredOptions in atomProperties.js must be made compliant...

nagy.balint’s picture

@gifad thats not going to work on pages where you have more than one wysiwyg.
The dialog add runs when you click on the edit atom properties (and thats when all the other js runs that adds new items).
So clicking edit atom properties in the first field will add correctly the 2 items (scald_image, and my custom), and then if you do the same in the second wysiwyg, it will add them too, and you end up having 4 items in the Drupal.dndck4.registeredOptions

nagy.balint’s picture

So in fact the current version of the code works fine, cause even though it always replaces the array with an empty one and fills it up again in each wysiwyg, but since we dont have the capability to add something different for a specific wysiwyg it wont cause a problem.

nagy.balint’s picture

Status: Needs review » Fixed
gifad’s picture

Status: Fixed » Needs review
StatusFileSize
new2.37 KB

I was never satisfied with the public use of registeredOptions array;
So I made a registerOptions function(id, type, mode, name), which is cleaner, and solves problems.
Sample usage (in scald_image.js)
Drupal.dndck4.registerOptions('txtLink', 'image', 'atom', 'scald_image');

I don't think there are so many uses of this for now, so API change it not a hard inconvenience...

[Edit]
Sorry, issue was fixed while I was building the patch
Leaving status as is, as this is better (at least less bad) code...

nagy.balint’s picture

a) I think that at this point:
+ if (found = (this.id == id && this.type == type && this.mode == mode && this.name == name)) {
Checking the id would be enough, as likely you would not give the same id to two different items.

b)
$.merge(Drupal.dndck4.registeredOptions, [item]);
I dont see why we need merge as we will never add more than one item at the same time, so the previous push is enough.

gifad’s picture

StatusFileSize
new2.36 KB

@nagy.balint :
a) Of course I "would not give the same id to two different items", but I have two custom image providers, and some of them implement the same item (including the "txtLink")
b) You're right...

nagy.balint’s picture

a) Hmm well since here we only add to the list to have a list to consider when doing a cycle.
So if the field is the same on another provider, then that provider does not need to add the option, as it will be added by the other provider for the image already.
Or even if the other provider adds it to the list, comparing the id would be enough, as then one of the providers will add the item to the list.
If both provider is supposed to display its field on the atom properties, then they should not have the same id anyways, so that case would be fine as well.

So can you provide a use case where comparing only with the id would be bad?

gifad’s picture

Use case : two image providers implementing he same "txtLink" option;
If we added in the list only the first referencing "txtLink", the atoms provided by the second provider would not have the option available !
This is because the test is :

    $.each(registeredOptions, function(){
      // Check provider
      if (this.mode == 'atom' && this.name == provider) {
        states[this.id] = true;

which is necessary for the case of the second provider not implementing the option.
[Edit] such as scald_flickr module...

nagy.balint’s picture

Okey.

Another question. In showHideOptions it seems unnecessary to do $.each 3 times. Seems to me that what the function does could be done with a single $.each, as you are not accessing any other items in an iteration.
Also lets delete the commented console logs at the end.

gifad’s picture

StatusFileSize
new4.02 KB

Well, I'm used to optimizing compilers, and I'm a javascript beginner, so this code was written with debugging in mind...
This is a "minified" version...

  • nagy.balint committed b168213 on 7.x-1.x authored by gifad
    Issue #2468313 by gifad, nagy.balint: Unable to trigger onLoad on...
nagy.balint’s picture

Status: Needs review » Fixed

Thanks!

Committed.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.