/*
jQuery.addRecaptcha() plugin for Ellington CMS
==============================================

Requirements
------------

- jQuery 1.3 or newer
- A global dictionary called `wol` with a `recaptcha` key, whose value is a
  dictionary containing `api_key` and `enable_mailforms` keys.

Usage
-----

Basic usage requires only that you select the forms needing reCAPTCHA (if it is
enabled; if it is not, it noops). ::

    $('form[action^="/mailform/"]').addRecaptcha();

Location of insertion can be changed by passing the option in a dictionary::

    $('form[action^="/mailform/"]').addRecaptcha({insertSelector: '.submit'});

Options
-------

``addWidget``
~~~~~~~~~~~~~

Default:
    ``wol.recaptcha.enable_mailforms``
Purpose:
    If this evaluates to ``true``, the reCAPTCHA widget will be added to the
    selected forms; if ``false`` the plugin does nothing. This allows the plugin
    to be installed site(s)-wide, even if reCAPTCHA is not on all for all sites.
    This also allows the plugin to be used multiple times to target different
    forms under different conditions.

``apiKey``
~~~~~~~~~~

Default:
    ``wol.recaptcha.api_key``
Purpose:
    The reCAPTCHA public API key to use.

``container``
~~~~~~~~~~~~~

Default:
    ``'<div class="recaptcha"></div>'``
Purpose:
    The markup for the element that will contain the reCAPTCHA widget.

``wrapperIdPrefix``
~~~~~~~~~~~~~~~~~~~

Default:
    ``'recaptcha_hole_'``
Purpose:
    The first part of the ``id`` attribute that will be set on ``container``.
    For example, a value of ``'recaptcha_hole_'`` will result in the ``id``
    being set to ``recaptcha_hole_0`` for the first widget on the page.

``insertSelector``
~~~~~~~~~~~~~~~~~~

Default:
    ``'input[type="submit"]'``
Purpose:
    The widget will be inserted before the first object returned by this
    selector within the given form.

``recaptchaOptions``
~~~~~~~~~~~~~~~~~~~~

Default:
    ``{ theme: 'white' }``
Purpose:
    These options are passed to the ``Recaptcha.create()`` method. See available
    options under the "RecaptchaOptions Reference" header at
    http://code.google.com/apis/recaptcha/docs/customization.html.

*/

(function($) {
    $.fn.addRecaptcha = function(options) {

        // Settings
        var settings = $.extend({
            addWidget: wol.recaptcha.enable_mailforms,
            apiKey: wol.recaptcha.api_key,
            container: '<div class="recaptcha"></div>',
            wrapperIdPrefix: 'recaptcha_hole_',
            insertSelector: 'input[type="submit"]',
            recaptchaOptions: {} // Empty because defaults are defined later.
        }, options);

        if (settings.addWidget) {

            var recaptcha_forms = $(this);

            // This function is called once the reCAPTCHA AJAX API script has loaded.
            function ready () {
                // Iterate over and return each form selected for adding reCAPTCHA.
                return recaptcha_forms.each(function (index) {

                    var form = $(this);

                    // Create a container for the reCAPTCHA widget.
                    // TODO: Consider adding code to handle if settings.container
                    // is a selector, rather than markup, and returns an item.
                    // This would allow us to skip setting the id and inserting
                    // the element.
                    var recaptcha_hole = $(settings.container);

                    // Add the index to the id so that we don't clobber
                    // other forms' reCAPTCHAs. (It is true, the reCAPTCHA
                    // widget  itself does not currently handle multiple widgets
                    // per page; but we do by loading them as needed.)
                    recaptcha_hole.attr('id', settings.wrapperIdPrefix + index);

                    // Now insert the container before the first submit input
                    // element in the form.
                    // TODO: This could be more flexible by not demanding that the
                    // insertBefore method be used, but use a configurable method.
                    // TODO: This could be more flexible by not demanding that
                    // the  container be inserted before the first returned item
                    // ([0]),  but rather letting that be a configurable thing.
                    // TODO: Handle case when selector returns no items.
                    recaptcha_hole.insertBefore(form.find(settings.insertSelector)[0]);

                    // Now set up the reCAPTCHA widget options.
                    // The Recaptcha.create() method accepts an options dictionary
                    // as a third argument. See available options at
                    // http://code.google.com/apis/recaptcha/docs/customization.html
                    // (The RecaptchaOptions global dictionary is created as part
                    // of  the Recaptcha.create() method.)
                    // Note that we define defaults for settings.recaptchaOptions
                    // here, so the user can define something like `lang` without
                    // losing the default values (only `theme` currently).
                    var recaptchaOptions = $.extend({
                        theme: 'white'
                    }, settings.recaptchaOptions);

                    // Finally, bind a function to the focus event for any
                    // element inside the given form, which will add the
                    // reCAPTCHA widget to the form. We do this rather than add
                    // the widget immediately to handle the case of multiple
                    // reCAPTHCA-needing forms on a single page. (Recaptcha only
                    // allows one widget per page. So adding on focus will
                    // ensure that the form being used has a widget.)
                    form.find('*').focus(function () {
                        // If there is not already a widget, create one.
                        if ($('#recaptcha_area', recaptcha_hole).length == 0) {
                            Recaptcha.create(settings.apiKey,
                                recaptcha_hole.attr('id'), recaptchaOptions);
                        }
                    });

                }); // END each.
            } // END ready.

            // Verify that there are forms needing reCAPTCHA before loading the
            // API script and calling the workhorse function.
            if (recaptcha_forms.length) {
                // We use the AJAX reCAPTCHA API. See
                // http://code.google.com/apis/recaptcha/docs/display.html#AJAX
                $.getScript('//www.google.com/recaptcha/api/js/recaptcha_ajax.js', ready);
            }
        } // END if wol.recaptcha.enable_mailforms.

    }; // end addRecaptcha function.
})(jQuery);

