JS设计模式——4.继承(示例)

目的

我们的目的就是编写一个用于创建和管理就地编辑域的可重用的模块化API。它是指网页上的一段普通文本被点击后就变成一个配有一些按钮的表单域,以便用户就地对这段文本进行编辑。

思路

当用户点击时

1.将普通文本域隐藏

2.添加表单元素

3.设置表单元素的value

当用户保存时

ajax通信保存内容

当用户取消时

1.隐藏表单域

2.显示文本域

3.设置文本域的value

类式继承实现就地编辑

superClass的实现(input)

function EditInPlaceField(id, parent, value){
    this.id = id;
    this.value = value || 'default value';
    this.parentElement = parent;

    this.createElements(this.id);
    this.attachEvents();
}
EditInPlaceField.prototype = {
    createElements: function(){
        this.containerElement = document.createElement('div');
        this.parentElement.appendChild(this.containerElement);

        this.staticElement = document.createElement('span');
        this.containerElement.appendChild(this.staticElement);
        this.staticElement.innerHTML = this.value;

        this.fieldElement = document.createElement('input');
        this.fieldElement.type = 'text';
        this.fieldElement.value = this.value;
        this.containerElement.appendChild(this.fieldElement);

        this.saveButton = document.createElement('input');
        this.saveButton.type='button';
        this.saveButton.value="Save";
        this.containerElement.appendChild(this.saveButton);

        this.cancelBtton = document.createElement('input');
        this.cancelBtton.type = 'button';
        this.cancelBtton.value = 'Cancel';
        this.containerElement.appendChild(this.cancelBtton);
        this.convertToText();
    },
    attachEvents: function(){
        var that = this;
        addEvent(this.staticElement, 'click', function(){that.convertToEditable();});
        addEvent(this.saveButton, 'click', function(){ that.save();});
        addEvent(this.cancelBtton, 'click', function(){that.cancel()});
    },
    convertToEditable: function(){
        this.staticElement.style.display = 'none';
        this.fieldElement.style.display = 'inline';
        this.saveButton.style.display = 'inline';
        this.cancelBtton.style.display = 'inline';

        this.setValue(this.value);
    },
    save: function(){
        this.value = this.getValue();
        var that = this;
        var callback = {
            success: function(){that.convertToText();},
            failure: function(){alert('Error saving value.');}
        };
        ajaxRequest('GET', 'save.php?id'+this.id+'&value='+this.value, callback);
    },
    cancel: function(){
        this.convertToText();
    },
    convertToText: function(){
        this.fieldElement.style.display = 'none';
        this.saveButton.style.display = 'none';
        this.cancelBtton.style.display = 'none';
        this.staticElement.style.display = 'inline';

        this.setValue(this.value);
    },
    setValue: function(value){
        this.fieldElement.value = value;
        this.staticElement.innerHTML = value;
    },
    getValue: function(){
        return this.fieldElement.value;
    }
};

subClass的实现(textarea)

function EditInPlaceArea(id, parent, value){
    EditInPlaceArea.superclass.constructor.call(this, id, parent, value);
}
extend(EditInPlaceArea, EditInPlaceField);
EditInPlaceArea.prototype.createElements = function(id){
    this.containerElement = document.createElement('div');
    this.parentElement.appendChild(this.containerElement);

    this.staticElement = document.createElement('p');
    this.containerElement.appendChild(this.staticElement);
    this.staticElement.innerHTML = this.value;

    this.fieldElement = document.createElement('textarea');
    this.fieldElement.type = 'text';
    this.fieldElement.value = this.value;
    this.containerElement.appendChild(this.fieldElement);

    this.saveButton = document.createElement('input');
    this.saveButton.type='button';
    this.saveButton.value="Save";
    this.containerElement.appendChild(this.saveButton);

    this.cancelBtton = document.createElement('input');
    this.cancelBtton.type = 'button';
    this.cancelBtton.value = 'Cancel';
    this.containerElement.appendChild(this.cancelBtton);
    this.convertToText();
};
EditInPlaceArea.prototype.convertToEditable = function(){
    this.staticElement.style.display = 'none';
    this.fieldElement.style.display = 'block';
    this.saveButton.style.display = 'inline';
    this.cancelBtton.style.display = 'inline';

    this.setValue(this.value);
};
EditInPlaceArea.prototype.convertToText = function(){
    this.fieldElement.style.display = 'none';
    this.saveButton.style.display = 'none';
    this.cancelBtton.style.display = 'none';
    this.staticElement.style.display = 'block';

    this.setValue(this.value);
};

API的依赖与调用

addEvent依赖

function addEvent(el, ty, fn){
    if(el.addEvetListener){
        el.addEvetListener(ty, fn, false);
    }else if(el.attachEvent){
        el.attachEvent('on'+ty, fn);
    }else{
        el['on'+ty] = fn;
    }
}

extend依赖

function extend(subClass, superClass){
    var F = function(){};
    F.prototype = superClass.prototype;
    subClass.prototype = new F();
    subClass.prototype.constructor = subClass;
    subClass.superclass = superClass.prototype;
    if(superClass.prototype.constructor == Object.prototype.constructor){
        superClass.prototype.constructor = superClass;
    }
}

API的调用

var titleClassical = new EditInPlaceField('titleClassical', document.getElementById('titleClassical').parentNode, 'Title here');
var bodyClassical =new EditInPlaceArea('bodyClassical', document.getElementById('bodyClassical').parentNode, 'Body here');

效果展示

最开始时

点击后

保存后

取消后

原型式继承和掺元类

基本代码就那些,原型式继承和掺元类的实现只是模式的不同,所以就不再给出具体代码了。

posted @ 2014-03-14 16:31  JChen___  阅读(1051)  评论(0编辑  收藏  举报