﻿//
// AJAX ReCAPTCHA client side API to be used with ASP.net control
//

// constants required for ReCAPTCHA
var RC_PUBLIC_KEY = "6LfgZgYAAAAAAFL7kWKCEuZYgZ8Xp-fM5XOUVotl";
var RC_RESPONSE_FIELD_ID = "recaptcha_response_field";
var RC_RESPONSE_SUBMIT_EVENT = "keydown";
var RC_SUBMIT_CALLBACK_ATTR = "callback";
var RC_CHALLENGE_ATTR = "challenge";
var RC_RESPONSE_ATTR = "response";

// look & feel of captcha
var RC_THEME = "red";

// custom hidden field selectors
var HF_LOGGED_IN_SELECTOR = "input[id*=hfIsLoggedIn]";
var HF_CAPTURE_REQUIRED_SELECTOR = "input[id*=hfIsCaptchaRequired]";

//
// helpers
//
function generateJQuerySelector(id, type) {
    var prefix = "";
    switch (type) {
        case "id":
            prefix = "#"; break;
        case "class":
            prefix = "."; break;
        default:
            break;
    }
    if (typeof (id) == "string") return prefix + id;
    return null;
}

// 
// initialise captcha
function rc_initialiseCAPTCHA(captcha_id, trigger_class, trigger_event) {
    rc_updateCAPTCHACountdown();
    if ($(HF_LOGGED_IN_SELECTOR)[0].value != "1") {
        trace("rc_initialiseCAPTCHA");
        rc_bindElementToCAPTCHA(trigger_class, captcha_id, trigger_event);
        rc_displayCAPTCHA(captcha_id);
        rc_bindCAPTCHASubmit(RC_RESPONSE_SUBMIT_EVENT);
    }
}

//
// re-initialise captcha -- ONLY USE ON CALLBACK (assumes you've run rc_initialiseCAPTCHA before)
//
function rc_reInitialiseCAPTCHA(captcha_id, trigger_class, trigger_event, button_is_refreshed) {
    rc_updateCAPTCHACountdown();
    if ($(HF_LOGGED_IN_SELECTOR)[0].value != "1") {
        trace("rc_reInitialiseCAPTCHA");
        rc_bindElementToCAPTCHA(trigger_class, captcha_id, trigger_event, button_is_refreshed);
        rc_displayCAPTCHA(captcha_id);
    }
}

//
// bind a given element to open up overlay containing the captcha element
// it will also set the callback function of the captcha element so that
// on captcha submit, the callback is run
//
function rc_bindElementToCAPTCHA(class_name, captcha_id, event, button_is_refreshed) {
    if ($(HF_CAPTURE_REQUIRED_SELECTOR)[0].value == "0") {
        $(class_name).each(function(i) {
            $(this).unbind(event).bind(event, function(e) {
                var challenge_selector = '#' + $(this).attr(RC_CHALLENGE_ATTR); trace(challenge_selector);
                var response_selector = '#' + $(this).attr(RC_RESPONSE_ATTR); trace(response_selector);
                $(generateJQuerySelector(RC_RESPONSE_FIELD_ID, "id")).attr(RC_SUBMIT_CALLBACK_ATTR, $(this).attr("href"));
                $(generateJQuerySelector(RC_RESPONSE_FIELD_ID, "id")).attr(RC_CHALLENGE_ATTR, challenge_selector);
                $(generateJQuerySelector(RC_RESPONSE_FIELD_ID, "id")).attr(RC_RESPONSE_ATTR, response_selector);
            });

            if ($(this).data("overlay")) {
                $(this).unbind("click.overlay");
                var api = $(this).overlay();
                api.dispose();
            }

            if (!$(this).data("overlay")) {
                $(this).overlay({
                    onBeforeLoad: function() {
                        this.getBackgroundImage().expose({ color: '#000' });
                    },
                    onLoad: function() {
                        try { Recaptcha.focus_response_field(); } catch (e) { }
                    },
                    oneInstance: false,
                    onClose: function() {
                        var closeExpose = true;
                        var api = $("a[rel=#image-window]").overlay();
                        if (typeof (api) == "object" && typeof (api.isOpened) == "function") {
                            if (api.isOpened()) {
                                closeExpose = false;
                            }
                        }

                        if (closeExpose)
                            $.expose.close();
                    }
                });
                $(this).bind("unload", function(event) {
                    if ($(this).data("overlay")) {
                        $(this).unbind("click.overlay");
                        var api = $(this).overlay();
                        api.dispose();
                    }
                });
            }
        });
    } else {
        trace('unbinding captcha');
        $(class_name).unbind(event).unbind("click.overlay"); // this is only for buttons that are refreshed again
    }
}

//
// display captcha in a given placeholder
//
function rc_displayCAPTCHA(id) {
    var empty = Recaptcha.get_response() == null;
    var noresponse = empty ? true : Recaptcha.get_response().length == 0;
    if (id) {
        if (empty || !noresponse) {
            Recaptcha.create(RC_PUBLIC_KEY, id, { theme: RC_THEME });
        }
    }
}

function rc_updateCAPTCHACountdown() {
    if (typeof (CAPTCHA_COUNTDOWN) != "undefined") {
        trace(CAPTCHA_COUNTDOWN);
        $(HF_CAPTURE_REQUIRED_SELECTOR)[0].value = CAPTCHA_COUNTDOWN;
        CAPTCHA_COUNTDOWN = undefined;
    }
}

//
// bind captcha's textbox enter event to call the callback attribute
// event paramater is restricted to key events
//
function rc_bindCAPTCHASubmit(event) {
    $(generateJQuerySelector(RC_RESPONSE_FIELD_ID, "id")).live(event, function(e) {
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
            // on enter key
            // close overlays if any
            $("a[rel*=captcha]").each(function(i) {
                $(this).overlay().close();
            });

            if ($(this).attr(RC_SUBMIT_CALLBACK_ATTR)) {
                $($(this).attr(RC_CHALLENGE_ATTR))[0].value = Recaptcha.get_challenge();
                $($(this).attr(RC_RESPONSE_ATTR))[0].value = Recaptcha.get_response();
                eval($(this).attr(RC_SUBMIT_CALLBACK_ATTR));
            }

            return false;
        }
    });
}
