Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery plugin create custom event

I'm starting doing jQuery plugins so I don't have much experience doing it, the thing what I want to have done today is to create a custom event for the plugin I'm working on.

I thing a good example to show you exact what I want to do is the bootstrap tooltip plugin, with this plugin I can do something like that:

$('.my-tooltip').tooltip('show');

Forcing the plugin to do an action, in this case execute show() plugin function

For my specific case I'm doing a plugin to custom validate forms around a website using jQuery validate plugin and I wan't to do something like:

$('form#whatever').validateForm('showInlineChecks');

To force the plugin to run a validation for some specific fields.

Let's take a look of my code:

/*
* jQuery plugin to validate forms around segurosdigitales
* requires jquery validate plugin
* */


if( typeof Object.create !== 'function' ){
    Object.create = function( obj ) {
        function F(){};
        F.prototype = obj;
        return new F();
    }
}


(function($){
    var validator = {

        // init the plugin
        init: function(options, element){
            var self = this;

            self.options = $.extend( {}, $.fn.validateForm.options, options );

            self.elem = element;
            self.$elem = $(element);

            self.validateTheForm();
        },


        // Set default options for jQuery validate plugin
        setValidationOptions: function(){
            var self = this;

            // Default options for all forms around the app
            // These are the default options for jquery validate plugin
            var jQueryValidatePluginOptions = {
                onfocusout: function(e){
                    // Validate all elements when 'blur' event happens, except if it has a 'datepicker-open' class, I'm adding this class because datepicker causes that the input element loses focus and validation error is triggered
                    if(!$(e).hasClass('datepicker-open')){
                        this.element(e);
                    }
                },
                errorElement: 'span',
                errorClass: 'error help-block',
                errorPlacement: function(error, element){
                    if(element.is('input[type="checkbox"]')){
                        error.insertAfter(element.parent());
                    } else {
                        error.insertAfter(element);
                    }
                },

                // Highlight occurs when element has erros
                highlight: function(element, errorClass, validClass){
                    $(element).addClass(errorClass).removeClass(validClass);

                    var control_group = $(element).closest('.control-group, .controls-row');
                    control_group.addClass(errorClass).removeClass(validClass);

                    // Remove any valid icon
                    control_group.find('i.icon-ok').remove();
                },

                // Unhighlight occurs when element is valid
                unhighlight: function(element, errorClass, validClass){

                    $(element).removeClass(errorClass).addClass(validClass);

                    // get the parent of the field
                    var control_group = $(element).closest('.control-group, .controls-row');

                    // is field empty?
                    var element_is_empty = ( $(element).val() === '' );


                    if (!element_is_empty && !control_group.find('i.icon-ok').length) {
                        var label = control_group.find('label');

                        // Prevent to add more than one icon if control group contains more than one label (ie. when we have checkboxes and radio buttons)
                        $.each(label, function () {
                            $(this).prepend('<i class="icon-ok green"></i>');
                            return false;
                        });

                        // add class only if element is valid and not empty
                        control_group.removeClass(errorClass).addClass(validClass);
                    }
                }
            };

            // add other options depending of validateForm plugin options
            if( self.options.errorMessages ){
                jQueryValidatePluginOptions.messages = self.options.errorMessages;
            }

            if( self.options.rules ){
                jQueryValidatePluginOptions.rules = self.options.rules;
            }

            if( self.options.showNotification ){
                jQueryValidatePluginOptions.invalidHandler = function(event, validator){
                    var errors = validator.numberOfInvalids();
                    if(errors){
                        generateNotification('error', false, 'Por favor corrige los errores en los campos resaltados en rojo para poder continuar.');
                    }
                }
            }

            return jQueryValidatePluginOptions;

        },


        // Validate form
        validateTheForm: function(){
            var self = this;

            var validateOpts = self.setValidationOptions();

            self.$elem.validate(validateOpts);
        }

    };

    $.fn.validateForm = function(options){
        return this.each(function(){
            var validate = Object.create(validator);
            validate.init(options, this);
        });
    };

    $.fn.validateForm.options = {
        errorMessages: null,
        rules: null,
        showNotification: true
    }

})(jQuery);

How can I do it?

like image 910
Cristian Rojas Avatar asked May 21 '13 14:05

Cristian Rojas


1 Answers

Creating, emitting and subscribing to custom events are quite simple with jquery.

In order to emit custom event you simply call trigger

 $(elem).trigger('myCustomEvent.myNS')

I would recommend always useing namespaces, for easier managing custom events

Then you subscribe to your event like you do to regular event

 $(elem).on('myCustomEvent.myNS', function(event) {

 })

You can also add additional parameters passed to your event handler, like that

 $(elem).trigger('myCustomEvent.myNS', ['p1', 'p2'])

 $(elem).on('myCustomEvent.myNS', function(event, param1, param2) {
     console.log(param1) // outputs p1
     console.log(param2) // outputs p2
 })

So overall , on some user actions , say clicking a button, you'll emit your custom event, like this

$(elem).on('click', 'button.save', function (e) {
     $(elem).trigger('validate.myCtrl', [e, this])
})

Also note that in case your event has the same name as some method on the object you are defining events on, jquery will try to call this method when calling trigger. To avoid that behavior use triggerHandler jquery method.

UPDATE: @cristiangrojas, I would recomend you check different "standard" ways of setting up jquery plugin here https://github.com/shichuan/javascript-patterns/tree/master/jquery-plugin-patterns'

like image 57
vittore Avatar answered Oct 03 '22 02:10

vittore