Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC 3 unobtrusive validation, submit and TinyMCE

We have an in-house developed file/image/document manager plugin for TinyMCE that is still being ported over to jQuery. In the mean time, some of our projects that rely on having these features need to use the Prototype-based version of TinyMCE & jQuery.noConflict(). This works fine however with unobtrusive validation in ASP.NET MVC 3 the validation on submit happens before the TinyMCE callback to copy the TinyMCE'ed contents to the form field is triggered. Is it possible to hook into a pre-validation event in the unobtrusive validation?

like image 384
Cymen Avatar asked Feb 05 '11 03:02

Cymen


2 Answers

If you are using submit buttons to post the form, try this:

$("input[type='submit']").click(function () {
    tinyMCE.triggerSave();
});

If you're not using submit buttons, just hook into whatever event happens immediately before form submission and call tinyMCE.triggerSave().

like image 188
ctsears Avatar answered Oct 13 '22 11:10

ctsears


Another way to go about this which gives you more control is in the TinyMCE initialization. This works well except for one case: the last TinyMCE instance you exit does not trigger the onDeactivate event within TinyMCE (it is only trigger when you go to another TinyMCE instance). So here is a way to work around this -- so far it seems to work well but YMMV.

Note: I would use this in conjunction with the accepted answer. This code triggers the validation as content is being edited in TinyMCE.

tinyMCE.init({
    ...
    setup: ValidationTinyMceSetup
});

And our setup method:

function ValidationTinyMceSetup(editor) {
    var $textarea = $('#' + editor.editorId);

    // method to use to save editor contents to backend input field (TinyMCE hides real input and syncs it up
    // with values on form submit) -- we need to sync up the hidden input fields and call the valid()
    // method from jQuery unobtrusive validation if it is present
    function save(editor) {
        if (editor.isDirty) {
            editor.save();
            var $input = $('#' + editor.editorId);
            if (typeof $input.valid === 'function')
                $input.valid();
        }
    }

    // Save tinyMCE contents to input field on key/up down (efficiently so IE-old friendly)
    var typingTimerDown, typingTimerUp;
    var triggerDownSaveInterval = 1000;     // time in ms
    var triggerUpSaveInterval = 500;        // time in ms

    editor.onKeyDown.add(function (editor) {
        clearTimeout(typingTimerDown);
        typingTimerDown = setTimeout(function () { save(editor) }, triggerDownSaveInterval);
    });

    editor.onKeyUp.add(function () {
        clearTimeout(typingTimerUp);
        typingTimerUp = setTimeout(function () { save(editor) }, triggerUpSaveInterval);
    });


    // Save tinyMCE contents to input field on deactivate (when focus leaves editor)
    // this is via TAB
    editor.onKeyDown.add(function (editor, event) {
        if (event.keyCode === 9)
            save(editor);
    });

    // this is when focus goes from one editor to another (however the last one never
    // triggers -- need to enter another TinyMCE for event to trigger!)
    editor.onDeactivate.add(function (editor) {
        save(editor);
    });
}

Finally, a bonus item that is completely unrelated: you can add a character counter by including this function in your JavaScript source:

function CharacterCountDisplay(current, max) {
    if (current <= max) {
        return current + ' of ' + max + ' characters max';
    }
    else {
        return '<span style="color: red;">' + current + '</span> of ' + max + ' characters';
    }
}

And in the above ValidationTinyMceSetup method add:

// check for character count data-val
var character_max = $textarea.attr('data-val-lengthignoretags-max');
if (typeof character_max === 'undefined' || character_max === false) {
    character_max = $textarea.attr('data-val-length-max');
}
if (typeof character_max !== 'undefined' && character_max !== false) {
    var character_count = function (editor) {
        var currentLength = $(editor.getDoc().body).text().length;
        editor.dom.setHTML(tinymce.DOM.get(editor.id + '_path_row'), CharacterCountDisplay(currentLength, character_max));
    };

    // on load show character count
    editor.onInit.add(character_count);

    // while typing update character count
    editor.onKeyUp.add(character_count);
}

To use simply add a data-val-length-max="250" to your textarea tag or whatever it is you're using TinyMCE on!

like image 31
Cymen Avatar answered Oct 13 '22 10:10

Cymen