static/js/forms.js
author Tero Marttila <terom@fixme.fi>
Fri, 07 Jan 2011 03:45:19 +0200
changeset 36 d7a159024912
parent 21 3510b9092bc4
permissions -rw-r--r--
forms: Add a reset/return button to separate-page forms
/**
 * jQuery support code for our forms
 */

(function($) {
    /**
     * Query or set form field disabled state
     */
    $.fn.disabled = function (flag) {
        if (flag == undefined)
            // XXX: jQuery returns `true` here?
            return !!this.attr("disabled");

        if (flag)
            this.attr("disabled", "disabled");
        else
            this.removeAttr("disabled");
    }

    /**
     * Query or set form field checked state
     */
    $.fn.checked = function (flag) {
        if (flag == undefined)
            // XXX: jQuery returns true here?
            return !!this.attr("checked");


        if (flag)
            this.attr("checked", "checked");
        else
            this.removeAttr("checked");
    }

    /**
     * Redirect browser to another URL
     *
     * XXX: Can I do a global function like this?
     */
    $.redirect = function (url) {
        window.location.href = url;

        return false;
    }


    /*
     * The given checkbox acts as an enable/disable toggle for this form control
     */
    $.fn.formEnabledBy = function (checkbox) {
        var target = this;

        checkbox.change(function () {
            target.disabled(!checkbox.checked());
        });
        checkbox.change();
    }

    /*
     * When non-zero <select>/<option> is selected, apply that option as pre-filled values for other form items
     */
    $.fn.formSelectsPreset = function (opts) {
        opts = $.extend({
            // which option value is the "default", i.e. 'create new'
            valueDefault: 0,

            // which element to apply selected option value (id) to
            valueTarget: null,

            // which element to apply selected option text to
            textTarget: null,

            // list of targets from external lookup maps
            mapTargets: null
        }, opts);

        function update () {
            // selected option value (i.e. id)
            value = $(this).val();

            // selected option text (i.e. title/name)
            text = $.trim($(this).find("option:selected").text());

            // fields to set
            field_values = [];

            if (opts.valueTarget)
                field_values.push([opts.valueTarget, value]);

            if (opts.textTarget)
                field_values.push([opts.textTarget, text]);

            if (opts.mapTargets) {
                $.each(opts.mapTargets, function (index, entry) {
                    var field = entry[0], map = entry[1];

                    // entry
                    field_values.push([field, map[value]]);
                });
            }
            
            // apply new value
            if (value == opts.valueDefault) {
                // Re-enable all the fields that we set preset values for earlier
                $.each(field_values, function (index, entry) {
                    var field = entry[0], value = entry[1];

                    if (!field.disabled())
                        // if we didn't lock it down, we shouldn't be resetting it..
                        // this happens mainly at page load
                        return;

                    // reset
                    field.val("");
                    field.disabled(false);
                });

            } else {
                // Set preset value and lock down the target fields
                $.each(field_values, function (index, entry) {
                    var field = entry[0], value = entry[1];

                    // contant value
                    field.disabled(true);
                    
                    // display the read-only value
                    field.val(value);
                });
            }
        }
        
        // update linked field state on update, and startup..
        this.change(update);
        this.change()
    }
})(jQuery);