zoukankan      html  css  js  c++  java
  • Composite in Javascript

        本文从简的演示利用Composite Pattern来动态创建form,它支持保存和还原上次输入的数据。

        第一步,定义接口:

    var Composite = new Interface("Composite", ["add", "remove", "getChild"]);
    var FormItem = new Interface("FormItem", ["save", "restore", "getElement"]);

    你懂的,这里是基于single responsibility rule将接口分为2个。


        然后,分别来实现2个接口了: 

    var CompositeForm = function (id, method, action) {
        this.formComponents = [];

        this.element = document.createElement("form");
        this.element.id = id;
        this.element.method = method || "post";
        this.element.action = action || "#";
    };
    CompositeForm.prototype = {
        add: function (child) {
            Interface.ensureImplements(child, [Composite, FormItem]);
            this.formComponents.push(child);
            this.element.appendChild(child.getElement());
        },
        remove: function (child) {
            for (var i = 0; i < this.formComponents.length; i++) {
                if (this.formComponents[i] == child) {
                    this.formComponents.splice(i, 1);
                    this.element.removeChild(child.getElement());
                    break;
                }
            }
        },
        getChild: function (i) {
            if (i >= this.formComponents.length) {
                throw new Error("i is out of range.");
            }
            return this.fromComponents[i];
        },
        save: function () {
            for (index in formComponents) {
                this.formComponents[index].save();
            }
        },
        restore: function () {
            for (index in formComponents) {
                this.formComponents[index].resotre();
            }
        },
        getElement: function () {
            return this.element;
        }
    };
    CompositeForm.prototype.constructor = CompositeForm;

    // composite fieldset
    var CompositeFieldset = function (id, legendText) {
        this.components = {};

        this.element = document.createElement("fieldset");
        this.element.id = id;
        if (legendText) {
            this.legend = document.createElement("legend");
            this.legend.appendChild(document.createTextNode(legendText));
            this.element.appendChild(this.legend);
        }
    };
    CompositeFieldset.prototype = {
        add: function (child) {
            Interface.ensureImplements(child, [Composite, FormItem]);
            this.components[child.getElement().id] = child;
            this.element.appendChild(child.getElement());
        },
        remove: function (child) {
            delete this.components[child.getElement().id];
            this.element.removeChild(child.getElement());
        },
        getChild: function (id) {
            return this.components[id];
        },
        save: function () {
            for (index in components) {
                if (components.hasOwnProperty(index)) {
                    this.fieldset[index].save();
                }
            }
        },
        restore: function () {
            for (index in components) {
                if (components.hasOwnProperty(index)) {
                    this.fieldset[index].resotre();
                }
            }
        },
        getElement: function () {
            return this.element;
        }
    };
    CompositeFieldset.prototype.constructor = CompositeFieldset;


    // field abstract class
    var Field = function (id) {
        this.element = document.createElement('div');
        this.element.id = id;
        this.element.className = 'input-field';
    };
    Field.prototype = {
        add: function (child) {
        },
        remove: function (i) {
        },
        getChild: function (i) {
        },
        save: function () {
            setCookie(this.id, this.getValue());
        },
        resotre: function () {
            var value = getCookie(this.id);
            setValue(value);
        },
        getElement: function () {
            return this.element;
        },
        getValue: function () {
            throw new Error("Unimplemented on the class Field.");
        },
        setValue: function () {
            throw new Error("Unimplemented on the class Field.");
        }
    };
    Field.prototype.constructor = Field;

    // input field class
    var InputField = function (id, label) {
        this.superClass.constructor.call(this, id);

        this.input = document.createElement('input');
        this.input.id = id + "_input";
        this.label = document.createElement('label');
        this.label.id = id + "_label";
        var labelTextNode = document.createTextNode(label);
        this.label.appendChild(labelTextNode);

        this.element.appendChild(this.label);
        this.element.appendChild(this.input);
    };
    extend(InputField, Field);
    InputField.prototype.getValue = function () {
        return this.input.value;
    };
    InputField.prototype.getValue = function (value) {
        this.input.value = value;
    };

    // textarea field class
    var TextAreaField = function (id, label) {
        this.superClass.constructor.call(this, id);

        this.textArea = document.createElement('textarea');
        this.textArea.id = id + "_textarea";
        this.label = document.createElement('label');
        this.label.id = id + "_label";
        var labelTextNode = document.createTextNode(label);
        this.label.appendChild(labelTextNode);

        this.element.appendChild(this.label);
        this.element.appendChild(this.textArea);
    };
    extend(TextAreaField, Field);
    TextAreaField.prototype.getValue = function () {
        return this.textArea.value;
    };
    TextAreaField.prototype.getValue = function (value) {
        this.textArea.value = value;
    };

    // select field class
    var SelectField = function (id, label, options) {
        this.superClass.constructor.call(this, id);

        this.select = document.createElement('select');
        this.select.id = id + "_select";
        for(var i = 0;i<options.length;i++){
            var option = document.createElement("option");
            option.text = options[i].text;
            option.value = options[i].value;
            try{
                this.select.add(option, this.select.options[null]);
            }
            catch(e){
                this.select.add(option, null);
            }
        }
        this.label = document.createElement('label');
        this.label.id = id + "_label";
        var labelTextNode = document.createTextNode(label);
        this.label.appendChild(labelTextNode);

        this.element.appendChild(this.label);
        this.element.appendChild(this.select);
    };
    extend(SelectField, Field);
    SelectField.prototype.getValue = function () {
        return this.select.options[this.select.selectedIndex].value;
    };
    SelectField.prototype.getValue = function (value) {
        for (index in this.select.options) {
            if (this.select.options[index].value == value) {
                this.select.selectedIndex = index;
                break;
            }
        }
    };

    测试代码如下: 

        var contactForm = new CompositeForm("contactForm", "post", "contact.php"); 
        var nameFieldset = new CompositeFieldset('nameFieldset', "Name");
        nameFieldset.add(new InputField("firstName", "First Name"));
        nameFieldset.add(new InputField("lastName", "Last Name"));
        contactForm.add(nameFieldset);

        var addressFieldset = new CompositeFieldset('addressFieldset', "Address");
        addressFieldset.add(new InputField("address", "Address"));
        addressFieldset.add(new SelectField("state", "State", [{"text": "Alabama", "value": "Alabama"}, {"text": "Seattle", "value": "Seattle"}]));
        addressFieldset.add(new InputField('zip', 'Zip'));    
        contactForm.add(addressFieldset);

        contactForm.add(new TextAreaField('comments', 'Comments'));

        body.appendChild(contactForm.getElement());
        addEvent(window, "load", contactForm.restore);
        addEvent(window, "unload", contactForm.save);

    这里不再详细解释了,注意Field类是abstract的即可。 download

  • 相关阅读:
    xshell 使用命令上传、下载文件
    linux extglob模式 和rm反选,除了某个文件外的其他文件全部删除的命令
    vscode
    win10文件夹共享
    jquery-自适应全屏背景轮播动画
    jquery-抖动图组轮播动画
    jquery-leonaScroll-1.2-自定义滚动条插件
    jquery-leonaScroll-1.1-自定义滚动条插件
    JavaScript-JQ实现自定义滚动条插件1.0
    JavaScript-JQ初探实现自定义滚动条
  • 原文地址:https://www.cnblogs.com/Langzi127/p/2701271.html
Copyright © 2011-2022 走看看