论坛首页 AJAX版

edit_in_place : ajax_field.js

浏览 1815 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
最后更新时间:2007-07-17 关键字: ajax
暂时只提供输入框的切换功能,以后实现属性的Ajax.update功能

/*  Ajax Field , version 1.0.0
*  (c) 2006 discolt <discolt@sohu.com>
*
*  Team by Vnetoo
/*--------------------------------------------------------------------------*/

AjaxField = Class.create();

AjaxField.prototype = {

initialize: function(input) {
    this.field = input;
    this.wrapper = null;
    this.injectWrapper();
    this.addHandleEvent();
  },
 
  // 插入Wrapper对象到页面
  injectWrapper: function() {
    this.createWrapper();
    this.positionWrapper();
  },
 
  // 创建Wrapper对象
  createWrapper: function() {
    this.wrapper = document.createElement("span");
    this.setWrapperValue();
    this.field.parentNode.appendChild(this.wrapper);
  },
 
  // 定位Wrapper到属性的位置
  positionWrapper: function() {
  var wrapperStyle = this.wrapper.style;
  wrapperStyle.textDecoration = 'underline';
  wrapperStyle.position = 'absolute';
  var fieldPos = RicoUtil.toDocumentPosition(this.field);
  wrapperStyle.top = fieldPos.y + 'px';
  wrapperStyle.left = fieldPos.x + 'px';
  wrapperStyle.width = this.field.offsetWidth + '100px';
  this.hideField();
  },
 
  // 设置Wrapper值,如果值没改变返回false
  setWrapperValue: function() {
  var text = this.field.tagName == 'SELECT' ? this.field[this.field.selectedIndex].text : this.field.value;
  if (text.length == 0) {
  text = "-请输入-";
  }
  if (text != this.wrapper.innerHTML) {
  this.wrapper.innerHTML = text;
  return true;
  } else {
  return false;
    }
  },
 
  // 隐藏Field
  hideField: function() {
  this.field.style.display = 'none';
  this.wrapper.style.display = '';
  },
 
  // 添加事件
  addHandleEvent: function() {
 
  var field = this.field;
  var wrapper = this.wrapper;
  var ajaxField = this;
 
  // 覆盖类被双击时
  // 隐藏Wrapper对象并显示元素
  this.wrapper.ondblclick = function() {
  wrapper.style.display='none';
  field.style.display = '';
  field.focus();
  };
 
  // 当元素失去焦点时,设置覆盖类的值,并隐藏元素,显示覆盖类
  this.field.onblur=function() {
  if (ajaxField.setWrapperValue()) {
  //alert('ajax updating ...');
  alert(field.form.name + " submit : for " + field.form.action + " update field:" + field.name + " to value:" + field.value);
  }
  field.style.display='none';
  wrapper.style.display='';
  };
 
  }
}


var __EDITABLE_CLASS_NAME = 'editable';
/** makeEditable */
function makeEditable() {
var inputs = document.getElementsByClassName(__EDITABLE_CLASS_NAME);
inputs.each(function(el) {
  new AjaxField(el);
  });
}
Event.observe(window, 'load', makeEditable, false);
   
最后更新时间:2006-11-23
-- 结合Validator


Validator = Class.create();
Validator.prototype = {
initialize : function(className, error, test, options) {
this.options = Object.extend({}, options || {});
this._test = test ? test : function(v,elm){ return true };
this.error = error ? error : 'Validation failed.';
this.className = className;
},
test : function(v, elm) {
return this._test(v,elm);
}
}

var Validation = Class.create();
Validation.prototype = {
initialize : function(form, options){
this.options = Object.extend({
editable : false, // by discolt
onSubmit : true,
stopOnFirst : false,
immediate : false,
focusOnError : true,
useTitles : false,
onFormValidate : function(result, form) {},
onElementValidate : function(result, elm) {}
}, options || {});
this.form = $(form);

// Submit event
if(this.options.onSubmit) {
Event.observe(this.form,'submit',this.onSubmit.bind(this),false);
}

// immediate
if(this.options.immediate) {
var useTitles = this.options.useTitles;
var callback = this.options.onElementValidate;
Form.getElements(this.form).each(function(input) { // Thanks Mike!
Event.observe(input, 'keyup', function(ev) {
Validation.validate(Event.element(ev),{useTitle : useTitles, onElementValidate : callback});
});
});
}

// editable
if(this.options.editable) {
Form.getElements(this.form).each(function(input) {
var field = new AjaxField(input);
Event.observe(input, 'blur', function(ev) {
if (Validation.validate(input)) field.fieldUpdateHandle(ev);
});
});
}
},

onSubmit :  function(ev){
if(!this.validate()) {
Event.stop(ev);
}
},

validate : function() {
var result = false;
var useTitles = this.options.useTitles;
var callback = this.options.onElementValidate;
if(this.options.stopOnFirst) {
result = Form.getElements(this.form).all(function(elm) {
return Validation.validate(elm,{useTitle : useTitles, onElementValidate : callback});
});
} else {
result = Form.getElements(this.form).collect(function(elm) {
return Validation.validate(elm,{useTitle : useTitles, onElementValidate : callback});
}).all();
}
if(!result && this.options.focusOnError) {
Form.getElements(this.form).findAll(
function(elm){
return $(elm).hasClassName('validation-failed')
}).first().focus()
}
this.options.onFormValidate(result, this.form);
return result;
},

reset : function() {
Form.getElements(this.form).each(Validation.reset);
}
}

Object.extend(Validation, {
validate : function(elm, options){
options = Object.extend({
useTitle : false,
onElementValidate : function(result, elm) {}
}, options || {});
elm = $(elm);
var cn = elm.classNames();
return result = cn.all(function(value) {
var test = Validation.test(value,elm,options.useTitle);
options.onElementValidate(test, elm);
return test;
});
},

test : function(name, elm, useTitle) {
var v = Validation.get(name);
var prop = '__advice'+name.camelize();
if(Validation.isVisible(elm) && !v.test($F(elm), elm)) {
if(!elm[prop]) {
var advice = Validation.getAdvice(name, elm);
if(typeof advice == 'undefined') {
var errorMsg = useTitle ? ((elm && elm.title) ? elm.title : v.error) : v.error;
var adviceId = 'advice-' + name + '-' + Validation.getElmID(elm);
advice = OrangeUtils.insertBack(elm, errorMsg);
advice.className = 'validation-advice';
advice.style.display = 'none';
advice.id = adviceId;
}
if(typeof Effect == 'undefined') {
advice.style.display = 'block';
} else {
new Effect.Appear(advice, {duration : 0.3});
}
}
elm[prop] = true;
elm.removeClassName('validation-passed');
elm.addClassName('validation-failed');
return false;
} else {
var advice = Validation.getAdvice(name, elm);
if(typeof advice != 'undefined') advice.hide();
elm[prop] = '';
elm.removeClassName('validation-failed');
elm.addClassName('validation-passed');
return true;
}
},
isVisible : function(elm) {
while(elm.tagName != 'BODY') {
if(!$(elm).visible()) return false;
elm = elm.parentNode;
}
return true;
},
getAdvice : function(name, elm) {
return Try.these(
function(){ return $('advice-' + name + '-' + Validation.getElmID(elm)) },
function(){ return $('advice-' + Validation.getElmID(elm)) }
);
},
getElmID : function(elm) {
return elm.id ? elm.id : elm.name;
},
reset : function(elm) {
elm = $(elm);
var cn = elm.classNames();
cn.each(function(value) {
var prop = '__advice'+value.camelize();
if(elm[prop]) {
var advice = Validation.getAdvice(value, elm);
advice.hide();
elm[prop] = '';
}
elm.removeClassName('validation-failed');
elm.removeClassName('validation-passed');
});
},
add : function(className, error, test, options) {
var nv = {};
nv[className] = new Validator(className, error, test, options);
Object.extend(Validation.methods, nv);
},
addAllThese : function(validators) {
var nv = {};
$A(validators).each(function(value) {
nv[value[0]] = new Validator(value[0], value[1], value[2], (value.length > 3 ? value[3] : {}));
});
Object.extend(Validation.methods, nv);
},
get : function(name) {
return  Validation.methods[name] ? Validation.methods[name] : new Validator();
},
methods : {}
});

Validation.add('IsEmpty', '', function(v) {
return  ((v == null) || (v.length == 0)); // || /^\s+$/.test(v));
});

Validation.addAllThese([
['required', 'must be not null', function(v) {
return !Validation.get('IsEmpty').test(v);
}],
['validate-number', 'Please enter a valid number in this field.', function(v) {
return Validation.get('IsEmpty').test(v) || (!isNaN(v) && !/^\s+$/.test(v));
}],
['validate-digits', 'Please use numbers only in this field. please avoid spaces or other characters such as dots or commas.', function(v) {
return Validation.get('IsEmpty').test(v) ||  !/[^\d]/.test(v);
}],
['validate-alpha', 'Please use letters only (a-z) in this field.', function (v) {
return Validation.get('IsEmpty').test(v) ||  /^[a-zA-Z]+$/.test(v)
}],
['validate-alphanum', 'Please use only letters (a-z) or numbers (0-9) only in this field. No spaces or other characters are allowed.', function(v) {
return Validation.get('IsEmpty').test(v) ||  !/\W/.test(v)
}],
['validate-date', 'Please enter a valid date.', function(v) {
var test = new Date(v);
return Validation.get('IsEmpty').test(v) || !isNaN(test);
}],
['validate-email', 'Please enter a valid email address. For example fred@domain.com .', function (v) {
return Validation.get('IsEmpty').test(v) || /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/.test(v)
}],
['validate-url', 'Please enter a valid URL.', function (v) {
return Validation.get('IsEmpty').test(v) || /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i.test(v)
}],
['validate-date-au', 'Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.', function(v) {
if(Validation.get('IsEmpty').test(v)) return true;
var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
if(!regex.test(v)) return false;
var d = new Date(v.replace(regex, '$2/$1/$3'));
return ( parseInt(RegExp.$2, 10) == (1+d.getMonth()) ) &&
(parseInt(RegExp.$1, 10) == d.getDate()) &&
(parseInt(RegExp.$3, 10) == d.getFullYear() );
}],
['validate-currency-dollar', 'Please enter a valid $ amount. For example $100.00 .', function(v) {
// [$]1[##][,###]+[.##]
// [$]1###+[.##]
// [$]0.##
// [$].##
return Validation.get('IsEmpty').test(v) ||  /^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/.test(v)
}],
['validate-one-required', 'Please select one of the above options.', function (v,elm) {
var p = elm.parentNode;
var options = p.getElementsByTagName('INPUT');
return $A(options).any(function(elm) {
return $F(elm);
});
}]
]);



/*--------------------------------------------------------------------------*/

AjaxField = Class.create();
AjaxField.prototype = {
  // construct
  initialize: function(input) {
    this.field = input;
    this.wrapper = null;
if (this.available()) {
    this.injectWrapper();
    this.addHandleEvent();
}
  },

available: function() {
var tagName = this.field.tagName.toLowerCase();
var typeName = this.field.type.toLowerCase();
if (tagName == 'select' || tagName == 'input' || tagName == 'textarea') {
if (typeName != 'submit') {
return true;
}
}
return false;
},

// 插入Wrapper
  injectWrapper: function() {
    this.createWrapper();
    this.positionWrapper();
  },

// 创建Wrapper
  createWrapper: function() {
    this.wrapper = document.createElement("span");
    this.field.parentNode.appendChild(this.wrapper);
this.setWrapperValue();
  },

// 定位Wrapper
  positionWrapper: function() {
  var wrapperStyle = this.wrapper.style;
  wrapperStyle.textDecoration = 'underline';
  wrapperStyle.position = 'absolute';
  var fieldPos = RicoUtil.toDocumentPosition(this.field);
  wrapperStyle.top = fieldPos.y + 'px';
  wrapperStyle.left = fieldPos.x + 'px';
  this.fieldDisable();
  },

// 设置Wrapper值
  setWrapperValue: function() {
  var text = this.field.tagName.toLowerCase() == 'select' ? this.field[this.field.selectedIndex].text : this.field.value;
  if (text.length == 0) {
text = 'null';
}
  if (text != this.wrapper.innerHTML) {
  this.wrapper.name = this.field.name + '-wrapper';
    this.wrapper.innerHTML = text;
  return true;
  } else {
  return false;
    }
  },

// 隐藏Field
  fieldDisable: function() {
  this.field.style.display = 'none';
  this.wrapper.style.display = '';
  },

// 显示Field
  fieldEnable: function() {
  this.wrapper.style.display = 'none';
this.field.style.display = '';
this.field.focus();
  },

// 添加事件处理器
addHandleEvent: function() {
Event.observe(this.wrapper, 'dblclick', this.fieldEditableHandle.bind(this), false);
},

// 属性可编辑事件处理
fieldEditableHandle: function(e) {
this.fieldEnable();
},

// 属性更新事件处理
fieldUpdateHandle: function(e) {
var oldValue = this.wrapper.innerHTML;
var ajaxField = this;
if (this.setWrapperValue()) {
}
ajaxField.fieldDisable();
}

};
   
0 请登录后投票
最后更新时间:2006-11-23
var OrangeUtils = {
insertBack: function(elm, text) {
var insertDiv = document.createElement("span");
  insertDiv.innerHTML = text;
  document.body.appendChild(insertDiv);
var insertDivStyle = insertDiv.style;
var elementPosition = RicoUtil.toDocumentPosition(elm);
insertDivStyle.position = "absolute";
insertDivStyle.top = elementPosition.y + 'px';
insertDivStyle.left = elementPosition.x + elm.offsetWidth + 5 + 'px';
return insertDiv;
}
}
   
0 请登录后投票
论坛首页 AJAX版

跳转论坛:
JavaEye推荐