就地编辑--(使用类式继承,原型式继承和掺元类三种不同解决方案)

html:
<!DOCTYPE HTML>
<html lang="en-US">
<head>
    <meta charset="UTF-8">
    <title></title>

</head>
<body>
<p id="test"><span id="titleClassical">this an editable text content</span></p>

<p id="test2"><span id="titleClassica2">this an editable text content</span></p>
<script src="common.js"></script>
<!--

类式继承解决方案,适用于相似度较大的类,和原型式继承可以互相转换

<script src="edit-in-place-1.js"></script>
<script>
    var titleClassical = new EditInPlaceField('titleClassical', $('test'), 'this is a text');
    // 通过继承
    var test2 = new EditInPlaceArea('titleClassical2', $('test2'), 'this is text2 content');
</script>

-->

<!--

原型式继承解决方案

<script src="edit-in-place-2.js"></script>
<script>
    EditInPlaceField.configure('titleClassical', $('test'), 'this is a text');

    EditInPlaceArea.configure('titleClassical2', $('test2'), 'this is text2 content');
</script>
-->

<script src="edit-in-place-3.js"></script>
<script>
    //掺元类,适用于各类对象中的通用方法的共享
    var titleClassical = new EditInPlaceField('titleClassical', $('test'), 'this is a text');

    var test2 = new EditInPlaceArea('titleClassical2', $('test2'), 'this is text2 content');
</script>
</body>
</html>


comon js:
function addEvent(obj, type, fn) {
    if (obj.addEventListener) {
        obj.addEventListener(type, fn, false);
        EventCache.add(obj, type, fn);
    }
    else if (obj.attachEvent) {
        obj["e" + type + fn] = fn;
        obj[type + fn] = function () {
            obj["e" + type + fn](window.event);
        };
        obj.attachEvent("on" + type, obj[type + fn]);
        EventCache.add(obj, type, fn);
    }
    else {
        obj["on" + type] = obj["e" + type + fn];
    }
}
function $() {
    var elements = new Array();
    for (var i = 0; i < arguments.length; i++) {
        var element = arguments[i];
        if (typeof element == 'string')
            element = document.getElementById(element);
        if (arguments.length == 1)
            return element;
        elements.push(element);
    }
    return elements;
} 
function clone(object) {
    function F() {
    }

    F.prototype = object;
    return new F();
}

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;
    }
}

function augment(receivingClass, givingClass) {
    if (arguments[2]) { // Only give certain methods.
        for (var i = 2, len = arguments.length; i < len; i++) {
            receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]];
        }
    }
    else { // Give all methods.
        for (methodName in givingClass.prototype) {
            if (!receivingClass.prototype[methodName]) {
                receivingClass.prototype[methodName] = givingClass.prototype[methodName];
            }
        }
    }
}

var Ajax = {
    createXHR:function () {
        if (typeof XMLHttpRequest !== 'undefined') {
            return new XMLHttpRequest();
        } else if (typeof ActiveXObject !== 'undefined') {
            if (typeof arguments.callee.activeXString !== 'string') {
                var versions = ['MSXML2.XMLHttp.6.0', 'MSXML2.XMLHttp.3.0', 'MSXML2.XMLHttp'];
                for (var i = 0, len = versions.length; i < len; i++) {
                    try {
                        var xhr = new ActiveXObject(versions[i]);
                        arguments.callee.activeXString = versions[i];
                        return xhr;
                    } catch (ex) {

                    }
                }
            }
            return new ActiveXObject(arguments.callee.activeXString);
        } else {
            throw new Error('No xhr object available');
        }
    },
    responseType:function (request) {
        var _responseType = request.getResponseHeader('Content-Type');
        switch (_responseType) {
            case 'text/xml':
                return request.responseXML;
            case 'text/json':
            case 'text/javascript':
            case 'application/javascript':
            case 'application/x-javascript':
                return eval('(' + request.responseText + ')');
            default:
                return request.responseText;
        }
    },
    encodeFormData:function (data) {
        var _pairs = [];
        var _regexp = /%20/g;
        for (var name in data) {
            var _value = data[name].toString();
            var _pair = encodeURIComponent(name).replace(_regexp, '+') + '=' + encodeURIComponent(_value).replace(_regexp, '+');
            _pairs.push(_pair);
        }
        return _pair.join('&');
    },
    /**
     * 执行ajax请求
     * @param {String} method 'GET' || 'POST'
     * @param {String} url
     * @param {Boolean} asyn 是否异步加载
     * @param {Object} callback {success,failure} 回调对象,存放函数
     * @param value
     */
    ajaxRequest:function (method, url, asyn, callback, value) {
        var _xhr = this.createXHR();
        _xhr.onreadystatechange = function () {
            if (_xhr.readyState === 4) {
                if (_xhr.status >= 200 && _xhr.status < 300 || _xhr.status === 300) {
                    callback.success(this.responseType(_xhr));
                } else {
                    if (callback.failure) {
                        callback.failure(_xhr.status, _xhr.statusText);
                    }
                }
            }
        };

        _xhr.open(method, url, asyn);

        if (method === 'GET') {
            _xhr.send(null);
        } else if (method === 'POST') {
            _xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            _xhr.send(this.encodeFormData(value));
        }
    }
};



edit-in-place-1.js 
 /**
 * Created with JetBrains WebStorm.
 * User: lindongpeng
 * Date: 12-12-1
 * Time: 下午10:05
 */

/* EditInPlaceField class */

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 (id) {
        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.cancelButton = document.createElement('input');
        this.cancelButton.type = 'button';
        this.cancelButton.value = 'Cancel';
        this.containerElement.appendChild(this.cancelButton);

        this.convertToText();
    },
    /**
     * 添加事件
     */
    attachEvents:function () {
        var that = this;
        addEvent(this.staticElement, 'click', function () {
            that.convertToEditable();
        });
        addEvent(this.saveButton, 'click', function () {
            that.save();
        });
        addEvent(this.cancelButton, 'click', function () {
            that.cancel();
        });
    },
    /**
     * 转换成可编辑状态
     */
    convertToEditable:function () {
        this.staticElement.style.display = 'none';
        this.fieldElement.style.display = 'inline';
        this.saveButton.style.display = 'inline';
        this.cancelButton.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');
            }
        };
        Ajax.ajaxRequest('GET', 'save.php?id=' + this.id + '&value=' + this.value, true, callback);
    },
    //取消编辑
    cancel:function () {
        this.convertToText();
    },
    convertToText:function () {
        this.fieldElement.style.display = 'none';
        this.saveButton.style.display = 'none';
        this.cancelButton.style.display = 'none';
        this.staticElement.style.display = 'inline';

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

// EditInPlaceArea class
function EditInPlaceArea(id,parent,value){
    EditInPlaceArea.superclass.constructor.call(this,id,parent,value);
}

extend(EditInPlaceArea,EditInPlaceField);

// Override certain methods
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.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.cancelButton=document.createElement('input');
    this.cancelButton.type='button';
    this.cancelButton.value='Cancel';
    this.containerElement.appendChild(this.cancelButton);

    this.convertToText();
};

EditInPlaceArea.prototype.convertToEditable=function(){
    this.staticElement.style.display='none';
    this.fieldElement.style.display='block';
    this.saveButton.style.display='inline';
    this.cancelButton.style.display='inline';

    this.setValue(this.value);
};

EditInPlaceArea.prototype.convertToText=function(){
    this.staticElement.style.display='block';
    this.fieldElement.style.display='none';
    this.saveButton.style.display='none';
    this.cancelButton.style.display='none';

    this.setValue(this.value);
};

edit-in-place-2.js
/**
 * Created with JetBrains WebStorm.
 * User: lindongpeng
 * Date: 12-12-2
 * Time: 下午8:17
 */

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

        this.createElements(this.id);
        this.attachEvents();
    },
    createElements:function (id) {
        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.cancelButton = document.createElement('input');
        this.cancelButton.type = 'button';
        this.cancelButton.value = 'Cancel';
        this.containerElement.appendChild(this.cancelButton);

        this.convertToText();
    },
    attachEvents:function () {
        var that = this;
        addEvent(this.staticElement, 'click', function () {
            that.convertToEditable();
        });
        addEvent(this.saveButton, 'click', function () {
            that.save();
        });
        addEvent(this.cancelButton, 'click', function () {
            that.cancel();
        });
    },
    convertToEditable:function () {
        this.staticElement.style.display = 'none';
        this.fieldElement.style.display = 'inline';
        this.saveButton.style.display = 'inline';
        this.cancelButton.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');
            }
        };
        Ajax.ajaxRequest('GET', 'save.php?id=' + this.id + '&value=' + this.value, true, callback);
    },
    cancel:function () {
        this.convertToText();
    },
    convertToText:function () {
        this.fieldElement.style.display = 'none';
        this.saveButton.style.display = 'none';
        this.cancelButton.style.display = 'none';
        this.staticElement.style.display = 'inline';

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

var EditInPlaceArea = clone(EditInPlaceField);

EditInPlaceArea.createElements = function () {
    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.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.cancelButton = document.createElement('input');
    this.cancelButton.type = 'button';
    this.cancelButton.value = 'Cancel';
    this.containerElement.appendChild(this.cancelButton);

    this.convertToText();
};
EditInPlaceArea.convertToEditable = function () {
    this.staticElement.style.display = 'none';
    this.fieldElement.style.display = 'block';
    this.saveButton.style.display = 'inline';
    this.cancelButton.style.display = 'inline';

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

    this.setValue(this.value);
};

edit-in-place-3.js 
 /**
 * Created with JetBrains WebStorm.
 * User: lindongpeng
 * Date: 12-12-2
 * Time: 下午9:01
 */

var EditInPlaceMixin = function () {
};
EditInPlaceMixin.prototype = {
    createElements:function (id) {
        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.cancelButton = document.createElement('input');
        this.cancelButton.type = 'button';
        this.cancelButton.value = 'Cancel';
        this.containerElement.appendChild(this.cancelButton);

        this.convertToText();
    },
    attachEvents:function () {
        var that = this;
        addEvent(this.staticElement, 'click', function () {
            that.convertToEditable();
        });
        addEvent(this.saveButton, 'click', function () {
            that.save();
        });
        addEvent(this.cancelButton, 'click', function () {
            that.cancel();
        });
    },
    convertToEditable:function () {
        this.staticElement.style.display = 'none';
        this.fieldElement.style.display = 'inline';
        this.saveButton.style.display = 'inline';
        this.cancelButton.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');
            }
        };
        Ajax.ajaxRequest('GET', 'save.php?id=' + this.id + '&value=' + this.value, true, callback);
    },
    cancel:function () {
        this.convertToText();
    },
    convertToText:function () {
        this.fieldElement.style.display = 'none';
        this.saveButton.style.display = 'none';
        this.cancelButton.style.display = 'none';
        this.staticElement.style.display = 'inline';

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

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

    this.createElements(this.id);
    this.attachEvents();
}
augment(EditInPlaceField, EditInPlaceMixin);


/* EditInPlaceArea class */
function EditInPlaceArea(id, parent, value) {
    this.id = id;
    this.value = value || 'default value';
    this.parentElement = parent;

    this.createElements(this.id);
    this.attachEvents();
}

// add certain method so that augment won't include them
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.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.cancelButton = document.createElement('input');
    this.cancelButton.type = 'button';
    this.cancelButton.value = 'Cancel';
    this.containerElement.appendChild(this.cancelButton);

    this.convertToText();
};
EditInPlaceArea.prototype.convertToEditable = function () {
    this.staticElement.style.display = 'none';
    this.fieldElement.style.display = 'block';
    this.saveButton.style.display = 'inline';
    this.cancelButton.style.display = 'inline';

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

    this.setValue(this.value);
};

augment(EditInPlaceArea, EditInPlaceMixin);

  

posted @ 2012-12-16 13:19  LukeLin  阅读(300)  评论(0编辑  收藏  举报