1
\$\begingroup\$

Long story short, I wrote this jQuery form plugin as an exercise to better understand how other form plugins work. If you have any suggestions about how to improve this (or my coding style in general) let me know.

var Form = function(options) {

    options = options || {};

    this.url = options.url;
    this.$fields = $(options.fields);
    this.$status = $(options.status);
    this.$submit = $(options.submit);
    this.$form = options.form || 'form';
    this.rFields = {
        required: /[^.*]/,
        nodigit: /^[^0-9]+$/,
        email: /^[a-z0-9._%-]+@[a-z0-9.-]+\.[a-z]{2,4}$/i,
    };
    this.required = [
        this.rFields.nodigit,
        this.rFields.email,
        this.rFields.required,
        this.rFields.required
    ];
    this.errors = ['Please enter a valid name.', 'Please enter a valid email address.', 'You must enter a subject.', 'No message? But I wanted one :('];

}

Form.prototype.init = function init() {

    this.$submit.click($.proxy(function(e) {
        this.process(e);
    }, this));

};

Form.prototype.process = function process(e) {

    var filled = true;

    e.stopImmediatePropagation();
    e.preventDefault();

    this.$fields.each($.proxy(function(i, element) {

        var $element = $(element);

        if (!$element.val().match(this.required[i])) {

            $element.focus();
            this.update(this.errors[i], true);
            filled = false;
            return false;

        }
    }, this));

    filled && this.submit($(this.$form).serialize());

};

Form.prototype.update = function update(message, isError) {

    if (isError && this.$status.hasClass('error')) {

        this.$status.addClass('error')
            .text(message);

        setTimeout($.proxy(function() {
            this.$status.removeClass('shake');
        }, this), 500);

    }
    else {

        this.$status.fadeOut();

        setTimeout($.proxy(function() {
            this.$status.text(message)
                .fadeIn();

            if (isError) {
                this.$status.removeClass('shake')
                    .addClass('error');
            }
            else {
                this.$status.removeClass('error info')
                    .addClass('success');
            }
        }, this), 500);

    }

    return this;

};

Form.prototype.submit = function submit(data) {

    $.ajax({
        type: 'POST',
        url: this.url,
        data: data,
        success: $.proxy(function(msg) {
            this.$fields.fadeOut();
            this.$status
                .empty()
                .append('<h4 class="">Nice one! The form has been sent to the server...</h4>')

            $(this.$submit)
                .animate({
                left: '-=500px',
                opacity: 0,
            }, 300);

        }, this)
    });
};

Here's how to create a new form:

var exampleForm = new Form({
    url: mailUrl,
    fields: 'form input, form textarea',
    status: '#status',
    submit: '#submit'
})

exampleForm.init()

Pretty simple, just pass in..

  • The url to send the form data too
  • The form fields all encapsulated in one string seperated by commas in the correct order of validation rules.
  • Selector string where you want the status message to go
  • The submit selector. This element will actually submit the form
\$\endgroup\$
0
\$\begingroup\$

From a once over;

  • I would not split statements like

    this.$status.addClass('error')
        .text(message);
    

    over 2 lines, I would reserve that treatment for the longer statements.

  • You seem to cheat with the simpleness of your call, Form knows already the error messages with this.errors and the validation types with this.required. These should have come in as options.
  • I tend to comment all my regular expressions with my intent and an example, that might be overkill for your regular expressions
  • In Form.prototype.process it would have been simpler to have var self = this and use self instead of using $.proxy(. While using closures is not a panacea, it should also not be avoided at all costs.
  • You seem to like shortcuts, consider

    return filled = false;
    

    instead of

    filled = false;
    return false;
    
  • filled && this.submit($(this.$form).serialize()); <-- Too hacky
  • Why is this code removing the shake css class, it never assigns it..
  • On the whole it seems Form.prototype.update could be written in a smarter way, but I would have to see an actual snippet working to get started on that
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy