let Forms = function () {
    let _ = Object.create (Bedrock.Base);

    let forms = {};

    // strings used internally
    const DATALIST = "datalist-";
    const INPUT = "-input-";
    const ERROR = "-error-";

    // strings for input types
    _.LIST = "list";
    _.SELECT = "select";
    _.TEXT = "text";
    _.CHECKBOX = "checkbox";

    _.init = function (parameters) {
        // parameters.name - name of the form (and the event to use when submitting)
        let formName = this.name = parameters.name;
        forms[formName] = this;

        // parameters.submit - function to call when the user clicks submit and all the
        //                     input values pass validation
        this.completion = parameters.completion;

        // parameters.div - where to put the form
        let divElement = document.getElementById(parameters.div);
        divElement = addElement(divElement, "div", { class : "form-container" });

        // parameters.inputs - array of input names, with prompt, type, default value, template, and required flag
        // input = { name: "nm", type: "text|checkbox|select", label: "blah", required: true, (...values appropriate for input type...) }
        let inputs = this.inputs = {};
        for (let input of parameters.inputs) {
            // create the div and set the title
            let formDivElement = addElement (divElement, "div", { class: "form-div" });
            addElement (formDivElement, "div", { class: "form-title-div", innerHTML: input.label });

            // now add the actual input
            let inputObject = inputs[input.name] = {
                name: input.name,
                type: input.type,
                required: ("required" in input) ? input.required : false,
            };

            // and the input element depending on the type
            let inputElementId = formName + INPUT + input.name;
            switch (input.type) {
                case _.TEXT: {
                    let value = ("value" in input) ? input.value : "";
                    inputObject.inputElement = addElement (formDivElement, "input", { id: inputElementId, type: _.TEXT, class: "form-input", placeholder: input.placeholder, value: value });
                    inputObject.value = value;
                    if ("pattern" in input) {
                        inputObject.pattern = input.pattern;
                    }
                    break;
                }
                case _.CHECKBOX: {
                    let checked = ("checked" in input) ? input.checked : false;
                    inputObject.inputElement = addElement (formDivElement, "input", { id: inputElementId, type: _.CHECKBOX, class: "form-input", checked: checked });
                    inputObject.checked = checked;
                    break;
                }
                case _.SELECT: {
                    let inputElement = inputObject.inputElement = addElement (formDivElement, _.SELECT, { id: inputElementId, class: "form-input" });
                    for (let option of input.options) {
                        let value = (option === Object (option)) ? option.value : option;
                        let label = ((option === Object (option)) && ("label" in option)) ? option.label : value;
                        addElement (inputElement, "option", { value: value, innerHTML: label });
                    }
                    let value = ("value" in input) ? input.value : inputObject.inputElement.value;
                    inputObject.value = value;
                    inputObject.inputElement.value = value;
                    break;
                }
                case _.LIST: {
                    let value = ("value" in input) ? input.value : "";

                    inputObject.inputElement = Bedrock.ComboBox.new ({
                        class: "form-input",
                        parentElement: formDivElement,
                        placeholder: input.placeholder,
                        inputElementId: inputElementId,
                        options: input.options,
                        value: value
                    });

                    if ("pattern" in input) {
                        inputObject.pattern = input.pattern;
                    }
                    break;

                    /*
                    inputObject.inputElement = addElement (formDivElement, "input", { id: (formName + INPUT + input.name), type: _.LIST, class: "form-input", placeholder: input.placeholder });
                    if (typeof input.options !== "undefined") {
                        let datalist = document.createElement ("datalist");
                        datalist.id = (DATALIST + formName + INPUT + input.name);
                        for (let option of input.options) {
                            let value = (option === Object (option)) ? option.value : option;
                            let label = ((option === Object (option)) && ("label" in option)) ? option.label : value;
                            addElement (datalist, "option", { value: value, innerHTML: label });
                        }
                        formDivElement.appendChild (datalist);
                        inputObject.inputElement.setAttribute ("list", datalist.id);
                    }
                    inputObject.value = value;
                    inputObject.inputElement.value = value;
                    */
                    break;
                }
            }

            // and now add the error element
            inputObject.errorElement = addElement (formDivElement, "div", { id: (formName + ERROR + input.name), class: "form-error", innerHTML: inputObject.required ? "REQUIRED" : "" });
        }

        // now add the submit button
        let formDivElement = addElement (divElement, "div", { classes: ["form-div", "form-button-wrapper"] });
        addElement (formDivElement, "input", { type: "button", value: "SUBMIT", class: "form-submit-button", onclick: function () { forms[formName].handleClickSubmit (); }  });

        return this;
    };

    _.handleClickSubmit = function () {
        // define the error condition
        let allValid = true;

        // check if all the required inputs are set correctly
        let inputNames = Object.keys(this.inputs);
        for (let inputName of inputNames) {
            let input = this.inputs[inputName];
            if (input.required) {
                let valid = true;
                switch (input.type) {
                    case _.TEXT:
                    case _.SELECT:
                    case _.LIST: {
                        if ("pattern" in input) {
                            valid = (input.inputElement.value.match (input.pattern) !== null);
                        } else  {
                            valid = (input.inputElement.value.length > 0);
                        }
                        break;
                    }
                    case _.CHECKBOX: {
                        valid = input.inputElement.checked;
                        break;
                    }
                }
                input.errorElement.style.visibility = valid ? "hidden" : "visible";
                allValid = allValid && valid;
            }
        }

        // call completion if everything passes
        if (allValid === true) {
            this.completion (this);
        }
    };

    _.reset = function () {
        let inputNames = Object.keys (this.inputs);
        for (let inputName of inputNames) {
            let input = this.inputs[inputName];
            switch (input.type) {
                case _.CHECKBOX:
                    input.inputElement.checked = input.checked;
                    break;
                case _.TEXT:
                case _.SELECT:
                case _.LIST:
                    input.inputElement.value = input.value;
                    break;
            }
        }
    };

    _.getInputValues = function () {
        let now = new Date ().getTime ();
        let result = "api?event=" + this.name + "&timestamp=" + now;
        let keys = Object.keys (this.inputs);
        for (let key of keys) {
            let input = this.inputs[key];
            result += "&" + input.name + "=";
            switch (input.type) {
                case _.CHECKBOX:
                    result += input.inputElement.checked;
                    break;
                case _.TEXT:
                case _.SELECT:
                case _.LIST:
                    result += input.inputElement.value;
                    break;
            }
        }
        return result;
    };


    return _;
} ();


@@ -4282,1169 +4282,8 @@
 eak;
-%0A%0A                    /*%0A                    inputObject.inputElement = addElement (formDivElement, %22input%22, %7B id: (formName + INPUT + input.name), type: _.LIST, class: %22form-input%22, placeholder: input.placeholder %7D);%0A                    if (typeof input.options !== %22undefined%22) %7B%0A                        let datalist = document.createElement (%22datalist%22);%0A                        datalist.id = (DATALIST + formName + INPUT + input.name);%0A                        for (let option of input.options) %7B%0A                            let value = (option === Object (option)) ? option.value : option;%0A                            let label = ((option === Object (option)) && (%22label%22 in option)) ? option.label : value;%0A                            addElement (datalist, %22option%22, %7B value: value, innerHTML: label %7D);%0A                        %7D%0A                        formDivElement.appendChild (datalist);%0A                        inputObject.inputElement.setAttribute (%22list%22, datalist.id);%0A                    %7D%0A                    inputObject.value = value;%0A                    inputObject.inputElement.value = value;%0A                    */%0A                    break;
 %0A   

remove unneeded code