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