<commit_before>define(function (require) {
    var $ = require('jquery'),
        _ = require('underscore'),
        Backbone = require('backbone'),
        Templates = require('./templates'),
        Utils = require('./utils'),
        Forms = {};

    Forms.Model = Backbone.Model.extend({
        initialize: function (options) {
            Backbone.Model.prototype.initialize.call(this, options);

            _.bindAll(this, 'transform', 'is_successfully_synced');

            options = options || {};
            this.name = options.name;
            this.title = options.title;
            this.allow_buttons = options.allow_buttons;

            if (this.allow_buttons !== false) {
                this.allow_buttons = true;
            }

            this.buttons = options.buttons || [];
            this.bind('fetched', this.transform);
        },

        url: function () {
            return '';
        },

        fetch: function (options) {
            options = options || {};
            options.success = function (model, resp) {
                model.trigger('fetched');
            };

            Backbone.Model.prototype.fetch.call(this, options);
        },

        transform: function () {
            this.attributes.title = this.title || '';
            var fields = this.attributes.fields;
            for (var field_name in fields) {
                var field = fields[field_name];

                // Load field name
                if (!field.name) {
                    field.name = field_name;
                }

                // Load field labels if not present
                if (!field.label) {
                    var field_name_components = field_name.split('_');
                    var normalized_field_name_components = [];

                    var index;
                    for (index = 0; index < field_name_components.length; index += 1) {
                        field_name_component = field_name_components[index];
                        normalized_field_name_components.push(
                            Utils.Strings.capitalize(field_name_component)
                        );
                    }

                    field.label = normalized_field_name_components.join(' ');
                }

                // Override fields maximum length with widgets maximum length if present
                if (field.widget && field.widget.attrs && field.widget.attrs.max_length) {
                    field.max_length = field.widget.attrs.max_length;
                }

                // Set field renderer
                if (field.widget) {
                    field.renderer = Templates.Form.Fields[field.widget.title];
                } else {
                    field.renderer = null;
                }
            }

            if (this.attributes.meta) {
                this.meta = this.attributes.meta;
            }

            if (this.allow_buttons && this.buttons.length === 0) {
                this.attributes.buttons = [];
                this.attributes.buttons.push({
                    'class': 'submit',
                    'name': 'submit',
                    'display_text': 'Submit'
                });
            }

            this.trigger('ready');
            this.is_synced = true;
        },

        save: function (options) {
            this.attributes.meta = this.meta || {};
            // For backbone save, seconds parameter is considered options if first parameter is null
            Backbone.Model.prototype.save.call(this, null, options);
        },

        is_successfully_synced: function () {
            if (this.is_synced) {
                if (this.meta && this.meta.errors) {
                    return false;
                } else {
                    return true;
                }
            } else {
                return false;
            }
        }
    });

    Forms.View = Backbone.View.extend({
        className: 'form_container',

        events: {
            'click input.submit': 'submit',
            'change input': 'update_field_display',
            'change select': 'update_field_display',
            'change textarea': 'update_field_display',
            'focusin label': 'update_field_display',
            'focusout label': 'update_field_display',
            'keypress input': 'submit_on_enter'
        },

        initialize: function (options) {
            Backbone.View.prototype.initialize.call(this, options);
            _.bindAll(
                this,
                'hide_inputs',
                'load_values',
                'render',
                'render_errors',
                'restore_values',
                'save',
                'submit',
                'submit_on_enter',
                'update_field_display',
                'validate',
                'validate_all'
            );

            options = options || {};

            this.is_valid = false;
            this.prefill = options.prefill || false;

            // Use this options to make the form hidden on sumission, effectively allowing the user
            // to submit only once
            this.hide_on_submit = options.hide_on_submit || false;

            // Use this options to reload the page on form submission
            this.reload_on_save = options.reload_on_save || false;

            // Use this option to redirect users to a particular URL upon save
            this.redirect_url = options.redirect_url;

            // Use this option to effectively make the form readonly
            this.editable = options.editable;
            if (this.editable !== true && this.editable !== false) {
                this.editable = true;
            }

            this.spotcheck = options.spotcheck || false;
            this.spotcheck_fields = [];

            // Use this option to disable spotcheck entirely or within code scope
            this.force_disable_spotcheck = false;

            if (!this.model.meta) {
                this.model.meta = {};
            }

            this.model.bind('ready', this.render);
        },

        render: function (options) {
            options = options || {};
            var messages = options.messages || [];
            var field_name, field, map_errors;

            $(this.el).html(Templates.Form.Base({form: this.model.attributes, messages: messages}));
            // Render field
            this.$('.fieldsets').empty();

            for (field_name in this.model.attributes.fields) {
                if (this.model.attributes.fields.hasOwnProperty(field_name)) {
                    field = this.model.attributes.fields[field_name];
                    map_errors = _.indexOf(this.spotcheck_fields, field_name) >= 0;
                    this.$('.fieldsets').append(field.renderer({field: field, map_errors: map_errors}));
                }
            }

            // Unescape labels
            this.$('p.label-text').each(function (index, el) {
                el.innerHTML = $(el).text();
            });

            // Unescape help text
            this.$('p.help').each(function (index, el) {
                el.innerHTML = $(el).text();
            });

            if (this.prefill) {
                this.restore_values();
            }

            this.delegateEvents();

            var readonly_fields = [];

            if (!this.editable) {
                // All fields are readonly
                readonly_fields = this.$('input, select, textarea').not('input[type=button]');
            }

            if (readonly_fields.length) {
                readonly_fields.off();
                readonly_fields.on('click focus mousedown mouseenter', function (event) {
                    event.preventDefault();
                    return false;
                });
                readonly_fields.fadeTo('fast', 0.8);
            }

            return this;
        },

        update_field_display: function (event) {
            if (this.force_disable_spotcheck) {<commit_msg>Added support for readonly field rendering.<commit_after>define(function (require) {
    var $ = require('jquery'),
        _ = require('underscore'),
        Backbone = require('backbone'),
        Templates = require('./templates'),
        Utils = require('./utils'),
        Forms = {};

    Forms.Model = Backbone.Model.extend({
        initialize: function (options) {
            Backbone.Model.prototype.initialize.call(this, options);

            _.bindAll(this, 'transform', 'is_successfully_synced');

            options = options || {};
            this.name = options.name;
            this.title = options.title;
            this.allow_buttons = options.allow_buttons;

            if (this.allow_buttons !== false) {
                this.allow_buttons = true;
            }

            this.buttons = options.buttons || [];
            this.bind('fetched', this.transform);
        },

        url: function () {
            return '';
        },

        fetch: function (options) {
            options = options || {};
            options.success = function (model, resp) {
                model.trigger('fetched');
            };

            Backbone.Model.prototype.fetch.call(this, options);
        },

        transform: function () {
            this.attributes.title = this.title || '';
            var fields = this.attributes.fields;
            for (var field_name in fields) {
                var field = fields[field_name];

                // Load field name
                if (!field.name) {
                    field.name = field_name;
                }

                // Load field labels if not present
                if (!field.label) {
                    var field_name_components = field_name.split('_');
                    var normalized_field_name_components = [];

                    var index;
                    for (index = 0; index < field_name_components.length; index += 1) {
                        field_name_component = field_name_components[index];
                        normalized_field_name_components.push(
                            Utils.Strings.capitalize(field_name_component)
                        );
                    }

                    field.label = normalized_field_name_components.join(' ');
                }

                // Override fields maximum length with widgets maximum length if present
                if (field.widget && field.widget.attrs && field.widget.attrs.max_length) {
                    field.max_length = field.widget.attrs.max_length;
                }

                // Set field renderer
                if (field.widget) {
                    field.renderer = Templates.Form.Fields[field.widget.title];
                } else {
                    field.renderer = null;
                }
            }

            if (this.attributes.meta) {
                this.meta = this.attributes.meta;
            }

            if (this.allow_buttons && this.buttons.length === 0) {
                this.attributes.buttons = [];
                this.attributes.buttons.push({
                    'class': 'submit',
                    'name': 'submit',
                    'display_text': 'Submit'
                });
            }

            this.trigger('ready');
            this.is_synced = true;
        },

        save: function (options) {
            this.attributes.meta = this.meta || {};
            // For backbone save, seconds parameter is considered options if first parameter is null
            Backbone.Model.prototype.save.call(this, null, options);
        },

        is_successfully_synced: function () {
            if (this.is_synced) {
                if (this.meta && this.meta.errors) {
                    return false;
                } else {
                    return true;
                }
            } else {
                return false;
            }
        }
    });

    Forms.View = Backbone.View.extend({
        className: 'form_container',

        events: {
            'click input.submit': 'submit',
            'change input': 'update_field_display',
            'change select': 'update_field_display',
            'change textarea': 'update_field_display',
            'focusin label': 'update_field_display',
            'focusout label': 'update_field_display',
            'keypress input': 'submit_on_enter'
        },

        initialize: function (options) {
            Backbone.View.prototype.initialize.call(this, options);
            _.bindAll(
                this,
                'hide_inputs',
                'load_values',
                'render',
                'render_errors',
                'restore_values',
                'save',
                'submit',
                'submit_on_enter',
                'update_field_display',
                'validate',
                'validate_all'
            );

            options = options || {};

            this.is_valid = false;
            this.prefill = options.prefill || false;

            // Use this options to make the form hidden on sumission, effectively allowing the user
            // to submit only once
            this.hide_on_submit = options.hide_on_submit || false;

            // Use this options to reload the page on form submission
            this.reload_on_save = options.reload_on_save || false;

            // Use this option to redirect users to a particular URL upon save
            this.redirect_url = options.redirect_url;

            // Use this option to effectively make the form readonly
            this.editable = options.editable;
            if (this.editable !== true && this.editable !== false) {
                this.editable = true;
            }

            this.spotcheck = options.spotcheck || false;
            this.spotcheck_fields = [];

            // Use this option to disable spotcheck entirely or within code scope
            this.force_disable_spotcheck = false;

            if (!this.model.meta) {
                this.model.meta = {};
            }

            this.model.bind('ready', this.render);
        },

        render: function (options) {
            options = options || {};
            var messages = options.messages || [];
            var field_name, field, map_errors;
            var readonly_fields = [];

            $(this.el).html(Templates.Form.Base({form: this.model.attributes, messages: messages}));
            // Render field
            this.$('.fieldsets').empty();

            for (field_name in this.model.attributes.fields) {
                if (this.model.attributes.fields.hasOwnProperty(field_name)) {
                    field = this.model.attributes.fields[field_name];
                    map_errors = _.indexOf(this.spotcheck_fields, field_name) >= 0;
                    this.$('.fieldsets').append(field.renderer({field: field, map_errors: map_errors}));
                }

                if (!this.editable) {
                    readonly_fields.push(field_name);
                } else if (field.readonly) {
                    readonly_fields.push(field_name);
                }
            }

            // Unescape labels
            this.$('p.label-text').each(function (index, el) {
                el.innerHTML = $(el).text();
            });

            // Unescape help text
            this.$('p.help').each(function (index, el) {
                el.innerHTML = $(el).text();
            });

            if (this.prefill) {
                this.restore_values();
            }

            this.delegateEvents();

            // Construct readonly fields selector and make them immutable
            var readonly_fields_selector, readonly_fields_selector_param = '', index;

            for (index = 0; index < readonly_fields.length; index += 1) {
                field_name = readonly_fields[index];
                readonly_fields_selector_param += '[for=' + field_name + ']';

                if (index < readonly_fields.length - 1) {
                    readonly_fields_selector_param += ', ';
                }
            }

            if (readonly_fields.length) {
                readonly_fields_selector = this.$(readonly_fields_selector_param).find('input, select, textarea');
                readonly_fields_selector.off();
                readonly_fields_selector.on('click focus mousedown mouseenter', function (event) {
                    event.preventDefault();
                    return false;
                });
                readonly_fields_selector.fadeTo('fast', 0.5);
            }

            return this;
        },

        update_field_display: function (event) {
            if (this.force_disable_spotcheck) {
{'fraction_non_alphanumeric': 0.10736526946107784, 'fraction_numerical': 0.0008982035928143712, 'mean_word_length': 1.3865390111460418, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '803524', 'n_tokens_mistral': 4195, 'n_tokens_neox': 3930, 'n_words': 857}