2

I have been pulling my hair out trying to figure this out.

I am running jquery 2.2.2 at the moment with the jquery validation plugin. https://jqueryvalidation.org/ And Trumbowyg WYSIWYG Editor. https://alex-d.github.io/Trumbowyg/

It's great mostly everything works however, every time a use clicks or does anything really. You get the console error Uncaught TypeError: Cannot read property 'nodeName' of undefined. It also creates certain parts of Trumbowyg to not work properly.

So my solution was to use the ignore class on the jquery validation plugin. But it does not work. I have tried ignoring almost every class labeling for different fields and no matter what I do it is never ignored.

So how do I use the jquery validation plugin, with the trumbowyg text editor?

Here is my validation code.

$('form').validate({
    errorPlacement: function (error, element) {
        if ($(element).parent('.input-group').length) {
            error.insertAfter(element.parent().siblings('label'));
            error.addClass('alert alert-danger validate');
        } else {
            error.insertAfter(element.siblings('label'));
            error.addClass('alert alert-danger validate');
        }
    },
    errorElement: 'div',
    highlight: function (element) {
        $(element).parent().addClass("has-error");
    },
    unhighlight: function (element) {
        $(element).parent().removeClass("has-error");
    },
    ignore: '.advanced',
    rules: {
        password_confirm: {
            equalTo: 'input[name=password]'
        },
        user_username: {
            remote: {
                url: 'action/check/',
                type: 'POST',
                data: {
                    id: function () {
                        return $('input[name=id]').val();
                    }
                }
            }
        },
        nav_name: {
            remote: {
                url: 'action/check/',
                type: 'POST',
                data: {
                    id: function () {
                        return $('input[name=id]').val();
                    }
                }
            }
        }
    },
    messages: {
        password_confirm: {
            equalTo: "Passwords must match"
        },
        user_username: {
            remote: "This Username already exists"
        },
        nav_name: {
            remote: "This Nav Item Name already exists"
        }
    },
    submitHandler: function (form) {
        $('button[type="submit"]').addClass('disabled').prop('disabled', true).prepend('<span class="bootstrap-dialog-button-icon glyphicon glyphicon-asterisk icon-spin"></span>');
        form.submit();
    }
});

I did remove the validation plugin and everything with trumbowyg did work. So maybe it's time to find a new validation plugin, I really would like to avoid that.

Update: I did notice that firefox is giving me a different error, so I figured I would share that as well.

TypeError: owner is undefined
owner[ this.expando ] && owner[ this.expando ][ key ];

An example of the problem should be available to demo here: http://develop.chrischampeau.com/admin/test.php

Chris James Champeau
  • 984
  • 2
  • 16
  • 37

2 Answers2

5

This is a known issue with the jQuery Validation plugin where content editable elements in forms would cause exceptions when an event is triggered.

You can find this issue describing the exact same problems:

  • Breaks your WYSIWYG.
  • Undefined errors.
  • All toolbar buttons in your WYSIWYG take two clicks to trigger.

A modification / hack is proposed in this thread to resolve the issue but a pull request fixing this same issue has already been merged into the project in May.

The problem is that the latest release is from February so this merge is not available at the moment. According to this other issue, a maintainer stated 15 hours ago that a release is coming very soon and it includes the fix for your problem.

If you can't wait for the new release, you can always get the latest version from their repository or cherry pick yourself the fix included in this pull request.

Regarding the second issue you described in a comment after applying the fix from the pull request, jQuery Validation check on various events (onfocusout especially in this case) if an element should be ignored or not by checking if it has a class specified in the settings.

You're adding to your textarea class="advanced" to ignore it, unfortunately, when Trumbowyg is initialized, the wrapper created will be the following:

<div class="trumbowyg-editor trumbowyg-reset-css" contenteditable="true" dir="ltr" placeholder="">

It does not propagates the advanced class to the wrapper. A potential fix is to add yourself this class when Trumbowyg is initialized. To do that, you can rely on the tbwinit event by modifying your constructor.

// Setup WYSIWYG
$('textarea.advanced').trumbowyg( {
    resetCss: true,
    removeformatPasted: true,
    autogrow: true,
    btnsDef: {
    // Customizables dropdowns
        image: {
            dropdown: ['insertImage', 'upload', 'base64', 'noEmbed'],
            ico: 'insertImage'
        }
    },
    btns: [
        ['viewHTML'],
        ['undo', 'redo'],
        ['formatting'],
        'btnGrp-design',
        ['link'],
        ['image'],
        'btnGrp-justify',
        'btnGrp-lists',
        ['foreColor', 'backColor'],
        ['preformatted'],
        ['horizontalRule'],
        ['fullscreen']
    ],
    plugins: {
        // Add imagur parameters to upload plugin
        upload: {
            serverPath: 'https://api.imgur.com/3/image',
            fileFieldName: 'image',
            headers: {
                'Authorization': 'Client-ID 9e57cb1c4791cea'
            },
            urlPropertyName: 'data.link'
        }
    }
}).on('tbwinit', function(){
  $('.trumbowyg-editor').addClass('advanced');
});

After initialization, your wrapper will have the advanced class so that jQuery Validation can use it.

<div class="trumbowyg-editor trumbowyg-reset-css advanced" contenteditable="true" dir="ltr" placeholder="">

Regarding the second issue, it's triggered because some libraries like Trumbowyg when they open a popup (like the ones your mentioned in your comment: Insert Link, Insert Image, etc.), they are actually appending a <form> in the DOM but inside another <form> which leads to nested forms.

In the case of nested forms, the second error you mentioned is triggered by jQuery Validation. You can check the comment of the jQuery Validation plugin owner regarding this problem on this message:

Nesting forms is invalid HTML. Either the [...] plugin doesn't generate a form if there is already one, or it has to append it outside the current form.

There is already an issue opened on the Trumbowyg Github regarding this problem, but it's a large modification on the core of the plugin and at this moment, it's moved from milestone to milestone since 2015.

HiDeoo
  • 10,353
  • 8
  • 47
  • 47
  • Ok while this did sort of work I am still getting errors. I updated the file to include the change in the pull request. I am now able to click in my toolbar once and everything seems to work correctly. However I am now getting two errors constantly `jquery.validate.min.js:1000 Uncaught TypeError: Cannot read property 'replace' of undefined` And `jquery.validate.min.js:408 Uncaught TypeError: Cannot read property 'settings' of undefined` – Chris James Champeau Jul 14 '16 at 11:34
  • This is indeed a new issue, I edited my answer to explain it and add a way to fix it. – HiDeoo Jul 14 '16 at 13:06
  • That does fix the first of the two errors, now I am just left with the second `jquery.validate.min.js:408 Uncaught TypeError: Cannot read property 'settings' of undefined` which happens when you click on either insert image or insert link, so it seems to happen when trumbowyg opens a window within itself. I know I may not get rid of all the errors, but my guess is that when trumbowyg creates one of these windows, it wants to validate the inputs in those windows. So I tried to change my ignore rule to this `ignore: '.advanced, .trumbowyg input',` but that did not work – Chris James Champeau Jul 14 '16 at 20:01
  • Added an explanation for the second error which cannot be fixed at the moment using these 2 plugins without rewriting a part of the core of the wysiwyg editor. Some workarounds are described in the issue but are not recommended by the creator of jQuery Validation. – HiDeoo Jul 14 '16 at 20:42
  • Ok cool, I will let that error slide then just wish there was a way to stop it constantly throwing errors. But thank you for your help – Chris James Champeau Jul 14 '16 at 20:45
1

If you're still getting the following error on line jquery.validate.min.js:formatted:490 whenever the jQuery validation tries to kick in on a Trumbowyg element:

Uncaught TypeError: Cannot read properties of undefined (reading 'replace')

Try adding a random value to an id attribute in the trumbowyg-editor div. Something like this will work:

$(".trumbowyg").find(".trumbowyg-editor").attr("id", Math.random());

This may not kick start the actual validation, but it will get rid of the error.

dearsina
  • 4,774
  • 2
  • 28
  • 34