/*!
* Copyright 2011 Guangzhou Donghong Software Technology Inc.
* Licensed under the www.jxstar.org
*/
/**
* 对ExtJs部分组件功能进行扩展或完善。
*
* @author TonyTan
* @version 1.0, 2010-01-01
*/
JxExt = {};
(function(){
//浏览器端信息
var ua = navigator.userAgent.toLowerCase();
var isTrident = function(){
var re = /trident/;
return re.test(ua);
};
//是否IE浏览器内核
Ext.isTrident = isTrident();
JxExt.isIE = isTrident()||Ext.isIE;
//取高版本IE号
JxExt.getIE = function(){
var i = ua.indexOf('msie ');
if (i >= 0) {
var s = ua.substring(i, ua.length).split(';');
if (s[0] && s[0].length > 6) {
s = s[0].split(' ');
var no = s[s.length-1];
return parseInt(no);
}
} else if (Ext.isTrident) {
i = ua.indexOf('rv:');
var s = ua.substring(i, ua.length).split(')');
if (s[0] && s[0].length > 4) {
s = s[0].split(':');
var no = s[s.length-1];
return parseInt(no);
}
}
return -1;
};
if (Ext.isTrident) {
var c = document.body || document.getElementsByTagName("body")[0];
Ext.fly(c, "_internal").replaceClass('ext-gecko ext-gecko3', 'ext-ie');
}
//IE9 不支持classList属性
window.HTMLElement = window.HTMLElement || Element;
if (!("classList" in document.documentElement)) {
Object.defineProperty(HTMLElement.prototype, 'classList', {
get: function() {
var self = this;
function update(fn) {
return function(value) {
var classes = self.className.split(/\s+/g),
index = classes.indexOf(value);
fn(classes, index, value);
self.className = classes.join(" ");
}
}
return {
add: update(function(classes, index, value) {
if (!~index) classes.push(value);
}),
remove: update(function(classes, index) {
if (~index) classes.splice(index, 1);
}),
toggle: update(function(classes, index, value) {
if (~index)
classes.splice(index, 1);
else
classes.push(value);
}),
contains: function(value) {
return !!~self.className.split(/\s+/g).indexOf(value);
},
item: function(i) {
return self.className.split(/\s+/g)[i] || null;
}
};
}
});
}
//是否启用XSS过滤
var filterXSS = function() {
var filter_re1 = /[=][\s]*on/gi;//过滤所有 = onxxx 前台方法;
var filter_re2 = /(script)|(eval)|(frame)|(src)|(cookie)|(style)|(expression)/gi;//过滤这些关键字
//前面那些数据库相关的关键字在java后台有处理;中间那些运算符号不处理,会影响系统运行,那些没有安全问题;
var xss_filter = function(str) {
var s = "";
if (typeof str == "undefined" || str.length == 0) return "";
s = str.replace(filter_re1, "");
s = s.replace(filter_re2, "");
return s;
};
/**
* 是否启用XSS过滤检查。
**/
Ext.form.Field.prototype.beforeBlur = function() {
var v = this.getValue();
if(typeof v == "string"){
v = xss_filter(v);
this.setValue(v);
}
};
};
setTimeout(function(){
if (Jxstar.systemVar) {
var fxss = Jxstar.systemVar.page__filter__xss;
if (fxss == '1') filterXSS();
}
}, 2000);
})();
/**
* 新增方法:在数组中插入对象
* index -- 指要插入的位置,从0开始,如果是负数,则从尾部开始
* item -- 指要插入的项目
**/
Array.prototype.insert = function(index, item) {
if (index >= this.length) {
this[this.length] = item;
return this;
}
if (index < 0) {
index = this.length + index;
}
for(var i = this.length-1; i >= index; i--) {
this[i+1] = this[i];
}
this[index] = item;
return this;
};
/**
* 解决在IE10下菜单与标签打不开的问题
**/
Ext.Element.prototype.getAttribute = Ext.isIE ? function(name, ns){
var d = this.dom;
//add by tony.tan IE10 use
if (d.getAttribute(name)) return d.getAttribute(name);
if (d.getAttribute(ns + ":" + name)) return d.getAttribute(ns + ":" + name);
//---------------
var type = typeof d[ns + ":" + name];
if(['undefined', 'unknown'].indexOf(type) == -1){
return d[ns + ":" + name];
}
return d[name];
} : function(name, ns){
var d = this.dom;
return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name) || d.getAttribute(name) || d[name];
};
/**
* 修改属性:定期清理孤立节点
**/
Ext.enableListenerCollection = true;
/**
* ext-3.3.1
* 修改方法:把Date对象格式化yyyy-mm-dd格式的字符串。
**/
Ext.urlEncode = function(o, pre){
var empty, buf = [], e = encodeURIComponent;
Ext.iterate(o, function(key, item){
empty = Ext.isEmpty(item);
Ext.each(empty ? key : item, function(val){
//Ext.encode(val).replace(/"/g, '') --> val.dateFormat('Y-m-d H:i:s') //modify by tony
buf.push('&', e(key), '=', (!Ext.isEmpty(val) && (val != key || !empty)) ? (Ext.isDate(val) ? val.dateFormat('Y-m-d H:i:s') : e(val)) : '');
});
});
if(!pre){
buf.shift();
pre = '';
}
return pre + buf.join('');
};
/* 调整样式后,对话框中不需要边框,避免btns显示错位 */
Ext.Window.prototype.border = false;
/**
* ext-3.3.1
* 修改方法:分页栏刷新数据时加上上次的参数。
**/
Ext.PagingToolbar.prototype.doLoad = function(start){
var o = {};
var options = this.store.lastOptions;//---add by tony
if (options && options.params) {
o = options.params;
}//---add by
var pn = this.getParams();
o[pn.start] = start;
o[pn.limit] = this.pageSize;
if(this.fireEvent('beforechange', this, o) !== false){
this.store.load({params:o});
}
//---add by tony, store.load set startno = 0
Jxstar.startNo = start;
};
Ext.PagingToolbar.prototype.onLoad = function(store, r, o){
/*if(!this.rendered){
this.dsLoaded = [store, r, o];
return;
}*/
var p = this.getParams();
this.cursor = (o.params && o.params[p.start]) ? o.params[p.start] : 0;
var d = this.getPageData(), ap = d.activePage, ps = d.pages;
if(!this.rendered){
this.dsLoaded = [store, r, o];
this.fireEvent('change', this, d);//add by tony.tan 方便用分页工具栏模型,不显示对象
return;
}
this.afterTextItem.setText(String.format(this.afterPageText, d.pages));
this.inputItem.setValue(ap);
this.first.setDisabled(ap == 1);
this.prev.setDisabled(ap == 1);
this.next.setDisabled(ap == ps);
this.last.setDisabled(ap == ps);
this.refresh.enable();
this.updateInfo();
this.fireEvent('change', this, d);
};
Ext.PagingToolbar.prototype.cls = 'x-pagebar';
/**
* ext-3.3.1
* 修改方法:设置表格行号列的缺省宽度为40
**/
Ext.grid.RowNumberer.prototype.width = 40;
//通过GridView.getColumnStyle的方法会把样式添加到序号列中
var rownumwidth = (Ext.isGecko) ? 39 : 41;
Ext.grid.RowNumberer.prototype.css = 'width:'+ rownumwidth +'px !important;';
/**
* ext-3.3.1
* 修改方法:支持设置表格头部的样式
**/
Ext.grid.GridView.prototype.getColumnStyle = function(colIndex, isHeader){
var colModel = this.cm,
colConfig = colModel.config,
style = isHeader ? colConfig[colIndex].hcss || '' : colConfig[colIndex].css || '',//添加了属性:colConfig[colIndex].hcss ||
align = colConfig[colIndex].align;
style += String.format("width: {0};", this.getColumnWidth(colIndex));
if (colModel.isHidden(colIndex)) {
style += 'display: none; ';
}
if (align) {
style += String.format("text-align: {0};", align);
}
return style;
};
/**
* ext-3.3.1
* 修改方法:表格在编辑时表头不能排序
**/
Ext.grid.GridView.prototype.onHeaderClick = function(g, index) {
if (this.headersDisabled || !this.cm.isSortable(index)) {
return;
}
//add by tony
if (g.store.getModifiedRecords().length > 0) return;
g.stopEditing(true);
g.store.sort(this.cm.getDataIndex(index));
};
/**
* ext-3.3.1
* 修改方法:修改表格单元可选择字符,1行增加:x-selectable,二行删除:unselectable="on",原:
* '
',
* ' {value} ',
* ' | '
**/
Ext.grid.GridView.prototype.cellTpl = new Ext.Template(
'',
' {value} ',
' | '
);
/**
* ext-3.3.1
* 修改方法:去掉属性表格中按属性名排序的特性
**/
Ext.grid.PropertyGrid.prototype.initComponent = function(){
this.customRenderers = this.customRenderers || {};
this.customEditors = this.customEditors || {};
this.lastEditRow = null;
var store = new Ext.grid.PropertyStore(this);
this.propStore = store;
var cm = new Ext.grid.PropertyColumnModel(this, store);
//store.store.sort('name', 'ASC'); //delete by tony
this.addEvents(
'beforepropertychange',
'propertychange'
);
this.cm = cm;
this.ds = store.store;
Ext.grid.PropertyGrid.superclass.initComponent.call(this);
this.mon(this.selModel, 'beforecellselect', function(sm, rowIndex, colIndex){
if(colIndex === 0){
this.startEditing.defer(200, this, [rowIndex, 1]);
return false;
}
}, this);
};
/**
* ext-3.3.1
* 修改方法:把返回结果中的树形数据作为响应数据
**/
Ext.tree.TreeLoader.prototype.handleResponse = function(response){
this.transId = false;
var a = response.argument;
//---add by tony
//-------------------前端分页取数------------------
var node = a.node;
var getPageData = function(datas, node){
var p = node.queryParams;
if (!p) return datas;
if (!node.total) return datas;
var start = p.start;
var limit = p.limit;
var rets = [];
if (node.count < limit) {
rets = datas.slice(start);
} else {
rets = datas.slice(start, start+limit);
}
//alert('total:'+node.total+'; start:'+start+'; limit:'+limit+'; rets='+rets.length);
return rets;
};
//如果有数据后取分页数据
if (node.myResults) {
response.responseData = getPageData(node.myResults, node);
//-------------------end------------------
} else {
var tranFn = this.treeDataFn;//支持把数组转换为tree
var f = Ext.decode(response.responseText);
var d = f.data;
if (d != null) {
if (tranFn) {
response.responseData = tranFn(d, node);
} else {
if (d.total && d.root) {
node.total = d.total||0;
node.count = d.root.length;
response.responseData = d.root;
} else {
response.responseData = d;
}
}
} else {
if (tranFn) {
response.responseData = tranFn(f, node);
} else {
response.responseData = f;
}
}
//保存结果集到节点对象
if (node.loadRemote === false) {
node.myResults = response.responseData;
//只取第一页的数据
response.responseData = getPageData(node.myResults, node);
}
//----add end
}
this.processResponse(response, node, a.callback, a.scope);
this.fireEvent("load", this, node, response);
};
Ext.tree.TreeLoader.prototype.getParams = function(node){
var bp = Ext.apply({}, this.baseParams),
np = this.nodeParameter;
np && (bp[ np ] = node.id);
//分页参数
if (node.queryParams) {
bp = Ext.apply(bp, node.queryParams);
}
return bp;
};
//为实现支持前端分页效果,重构此方法
Ext.tree.TreeLoader.prototype.requestData = function(node, callback, scope){
if(this.fireEvent("beforeload", this, node, callback) !== false){
if(this.directFn){
var args = this.getParams(node);
args.push(this.processDirectResponse.createDelegate(this, [{callback: callback, node: node, scope: scope}], true));
this.directFn.apply(window, args);
}else{
//false表示前端分页取数,有数据后就不调用后台了
if (node.loadRemote === false && node.myResults) {
this.handleResponse({
responseData: node.myResults,
responseText: null,
argument: {callback: callback, node: node, scope: scope}
});//add by
} else {
this.transId = Ext.Ajax.request({
timeout:this.timeout || 100000,//add by tony
method:this.requestMethod,
url: this.dataUrl||this.url,
success: this.handleResponse,
failure: this.handleFailure,
scope: this,
argument: {callback: callback, node: node, scope: scope},
params: this.getParams(node)
});
}
}
}else{
// if the load is cancelled, make sure we notify
// the node that we are done
this.runCallback(callback, scope || node, []);
}
};
/**
* 新增方法:模拟record的set/get方法,在JxSelect.setSelectData中使用。
**/
Ext.form.BasicForm.prototype.set = function(name, value) {
var f = this.findField(name);
if(f){
var oldValue = f.getValue();
f.setValue(value);
//处理字段值修改标记
f.fireEvent('change', f, oldValue, value);
}
return this;
};
/**
* 新增方法:模拟record的set/get方法,在JxSelect.setSelectData中使用。
**/
Ext.form.BasicForm.prototype.get = function(name) {
var f = this.findField(name);
if(f){
return f.getValue();
}
return '';
};
/**
* 新增方法:取数值。
**/
Ext.form.BasicForm.prototype.getNum = function(name) {
var value = '';
var f = this.findField(name);
if(f){
value = f.getValue();
}
if (value == null || value.length == 0) return 0;
return parseFloat(value);
};
/**
* 新增方法:保证修改字段值后不标记为脏数据。
**/
Ext.form.BasicForm.prototype.oset = function(name, value) {
var f = this.findField(name);
if(f){
var oldValue = f.getValue();
f.setValue(value);
//取消字段修改痕迹,设置修改值为原值
f.originalValue = value;
}
return this;
};
/**
* 新增方法:取当前表单的所有字段,含组合字段内的字段
**/
Ext.form.BasicForm.prototype.fieldItems = function() {
var fields = new Ext.util.MixedCollection(false, function(o){
return o.getItemId();
});
this.items.each(function(field){
if (field.isComposite) {
field.items.each(function(f){
fields.add(f.getItemId(), f);
});
} else {
fields.add(field.getItemId(), field);
}
});
return fields;
};
/**
* ext-3.3.1
* 修改方法:必须有name属性的字段才判断是否有值修改
**/
Ext.form.BasicForm.prototype.isDirty = function() {
var dirty = false;
this.items.each(function(f){
if(!Ext.isEmpty(f.name) && f.isDirty()){
dirty = true;
return false;
}
});
return dirty;
};
/**
* 新增方法:保证修改字段值后不标记为脏数据。
**/
Ext.form.ComboBox.prototype.restrictHeight = function(){
this.innerList.dom.style.height = '';
var inner = this.innerList.dom,
pad = this.list.getFrameWidth('tb') + (this.resizable ? this.handleHeight : 0) + this.assetHeight,
h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight),
ha = this.getPosition()[1]-Ext.getBody().getScroll().top,
hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height,
space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadowOffset-pad-5;
h = Math.min(h, space, this.maxHeight);
//如果是IE,当有X方向的滚动条时显示不全了,则添加高度18,其它浏览器添加1
if (Ext.isIE) {
var cw = inner.clientWidth, ow = inner.offsetWidth;
if (cw < ow) {
h += 18;
}
} else {
h += 1;
}
//add by tony.tan
this.innerList.setHeight(h);
this.list.beginUpdate();
this.list.setHeight(h+pad);
this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
this.list.endUpdate();
};
/**
* 修改方法:如果值为'请选择',则为空。
**/
Ext.form.ComboBox.prototype.getValue = function(){
var v = '';
if(this.valueField){
v = Ext.isDefined(this.value) ? this.value : '';
}else{
v = Ext.form.ComboBox.superclass.getValue.call(this);
}
if(v == jx.star.select) {//添加这个判断,this.emptyText为空了
v = '';
this.value = '';
this.originalValue = '';
}
return v;
};
/**
* ext-3.3.1
* 修改方法:取checkbox的值时取 0 或 1,而不是true false。
**/
Ext.form.Checkbox.prototype.getValue = function(){
if(this.rendered && this.el){
return this.el.dom.checked ? '1' : '0';
} else {
return this.checked ? '1' : '0';
}
};
Ext.form.Checkbox.prototype.isDirty = function(){
if(this.disabled || !this.rendered) {
return false;
}
//console.log('...........isDirty inputValue='+this.inputValue+', '+String(this.getValue())+';'+String(this.originalValue));
return String(this.getValue()) !== String(this.originalValue);
};
/**
* ext-3.3.1
* 修改方法:返回 null 改为 ''。
**/
Ext.form.RadioGroup.prototype.getValue = function() {
var val = '';
this.eachItem(function (item) {
if (item.checked) {
val = item.inputValue;
return false;
}
});
return val;
};
/**
* ext-3.3.1
* 修改方法:支持多个值拼从字符串。
**/
Ext.form.CheckboxGroup.prototype.getValue = function() {
var val = '';
this.eachItem(function (item) {
if (item.checked) {
val += item.inputValue + ',';
}
});
val = val.slice(0, val.length - 1);
return val;
};
/**
* ext-3.3.1
* 修改方法:设置未勾选值显示空
**/
Ext.form.CheckboxGroup.prototype.setValueForItem = function(val){
this.originalValue = val;//add by
val = String(val).split(',');
this.eachItem(function(item){
if(val.indexOf(item.inputValue)> -1){
item.setValue(true);
} else {
item.setValue(false);//add by
}
});
};
Ext.form.CheckboxGroup.prototype.isDirty = function(){
//override the behaviour to check sub items.
if (this.disabled || !this.rendered) {
return false;
}
/*
var dirty = false;
this.eachItem(function(item){
if(item.isDirty()){
dirty = true;
return false;
}
});*/
return String(this.getValue()) !== String(this.originalValue);
};
/**
* ext-3.3.1
* 修改方法:支持多个值拼从字符串。
**/
Ext.form.BasicForm.prototype.updateRecord = function(record){
record.beginEdit();
var fs = record.fields,
field,
value;
fs.each(function(f){
field = this.findField(f.name);
if(field){
value = field.getValue();
if (typeof value != undefined && value.getGroupValue) {
value = value.getGroupValue();
} /*else if (field.eachItem) {//这类控都自定义了取值方法,修改支持CheckboxGroup控件
value = [];
field.eachItem(function(item){
value.push(item.getValue());
});
}*/
record.set(f.name, value);
}
}, this);
record.endEdit();
return this;
};
/**
* 新增方法:保证修改字段值后不标记为脏数据。
**/
Ext.form.Field.prototype.osetValue = function(value){
this.setValue(value);
this.originalValue = value;
};
/**
* ext-3.3.1
* 修改方法:支持在选择日期的时候,自动带上时间值,设置样式:Y-m-d H:i,就支持显示时间。
**/
Ext.form.DateField.prototype.onSelect = function(m, d){
if (Ext.isDate(d)) {//---add by tony
var curd = new Date();
d.setHours(curd.getHours(), curd.getMinutes(), curd.getSeconds());
}//---add by
this.setValue(d);
this.fireEvent('select', this, d);
this.menu.hide();
};
/**
* ext-3.3.1
* 修改方法:如果是样式Y-m,在显示日期值取的是当前日,应该取1号
**/
Ext.form.DateField.prototype.parseDate = function(value) {
if(!value || Ext.isDate(value)){
return value;
}
if (!Ext.isEmpty(value) && value.length == 7 && this.format == 'Y-m') {//---add by tony
return Date.parseDate(value+'-01', 'Y-m-d');
}//---add by
var v = this.safeParse(value, this.format),
af = this.altFormats,
afa = this.altFormatsArray;
if (!v && af) {
afa = afa || af.split("|");
for (var i = 0, len = afa.length; i < len && !v; i++) {
v = this.safeParse(value, afa[i]);
}
}
return v;
},
/**
* 修改属性:FormLayout的标签描述不添加':'符号。
**/
Ext.layout.FormLayout.prototype.labelSeparator = '';
/**
* 修改属性:NumberField缺省不允许输入负数。
**/
//Ext.form.NumberField.prototype.allowNegative = false;
/**
* 修改属性:NumberField聚焦则全选。
**/
Ext.form.NumberField.prototype.selectOnFocus = true;
/**
* 修改属性:TextField聚焦则全选。
**/
Ext.form.TextField.prototype.selectOnFocus = true;
/**
* 修改属性:BasicForm加载数据后设置为初始值。
**/
Ext.form.BasicForm.prototype.trackResetOnLoad = true;
/**
* 修改属性:Component状态支持缺省值为否,设置所有控件都不保存状态。
**/
Ext.Component.prototype.stateful = false;
/**
* 修改属性:对话框的缺省标题。
**/
/*Ext.Window.prototype.iconCls = 'eb_win';*/
/**
* 修改属性:对话框的缺省不带阴影。
**/
Ext.Window.prototype.shadow = false;
/**
* ext-3.3.1
* 修改方法:处理重复打开combogrid页面时报下面的错误。
**/
Ext.layout.MenuLayout.prototype.isValidParent = function(c, target) {
var el = c.el.up('li.x-menu-list-item', 5);
if (Ext.isEmpty(el)) return false;//add by tony
return el.dom.parentNode === (target.dom || target);
};
/**
* ext-3.3.1
* 修改方法:如果是只读,则需要添加只读样式。
**/
Ext.form.Field.prototype.setReadOnly = function(readOnly){
if(this.rendered && this.el){
this.el.dom.readOnly = readOnly;
if (readOnly) {//---add by tony
this.el.addClass('x-field-only');
} else {
this.el.removeClass('x-field-only');
}//---add by
}
this.readOnly = readOnly;
};
Ext.form.TriggerField.prototype.setReadOnly = function(readOnly){
if(readOnly != this.readOnly && this.el){
if (readOnly) {//---add by tony
this.el.addClass('x-field-only');
} else {
this.el.removeClass('x-field-only');
}//---add by
this.readOnly = readOnly;
this.updateEditState();
}
};
/**
* ext-3.3.1
* 修改方法:如果是只读,则需要添加只读样式。
**/
Ext.form.TriggerField.prototype.updateEditState = function(){
if(this.rendered && this.el){
if (this.readOnly) {
this.el.dom.readOnly = true;
this.el.addClass('x-field-only');//add by tony.tan
this.el.addClass('x-trigger-noedit');
this.mun(this.el, 'click', this.onTriggerClick, this);
//this.trigger.setDisplayed(false);
this.emptyText = '';//add by tony.tan
} else {
if (!this.editable) {
this.el.dom.readOnly = true;
this.el.addClass('x-trigger-noedit');
this.mon(this.el, 'click', this.onTriggerClick, this);
} else {
this.el.dom.readOnly = false;
this.el.removeClass('x-field-only');//add by tony.tan
this.el.removeClass('x-trigger-noedit');
this.mun(this.el, 'click', this.onTriggerClick, this);
}
//this.trigger.setDisplayed(!this.hideTrigger);
}
//del by tony.tan 它会造成控件很窄
//this.onResize(this.width || this.wrap.getWidth());
}
};
/**
* ext-3.3.1
* 修改方法:处理日期控件的按钮只读后还可以选择的问题
**/
Ext.form.DateField.prototype.onTriggerClick = function(){
if(this.readOnly || this.disabled){//modify by tony.tan add 'this.readOnly || '
return;
}
if(this.menu == null){
this.menu = new Ext.menu.DateMenu({
hideOnClick: false,
focusOnSelect: false
});
}
this.onFocus();
Ext.apply(this.menu.picker, {
minDate : this.minValue,
maxDate : this.maxValue,
disabledDatesRE : this.disabledDatesRE,
disabledDatesText : this.disabledDatesText,
disabledDays : this.disabledDays,
disabledDaysText : this.disabledDaysText,
format : this.format,
showToday : this.showToday,
startDay: this.startDay,
minText : String.format(this.minText, this.formatDate(this.minValue)),
maxText : String.format(this.maxText, this.formatDate(this.maxValue))
});
this.menu.picker.setValue(this.getValue() || new Date());
this.menu.show(this.el, "tl-bl?");
this.menuEvents('on');
};
/**
* 修改日期字段控件的样式,显示居中。
**/
Ext.form.DateField.prototype.fieldClass = 'x-field-d';
/**
* 修改数字字段控件的样式,显示居右。
**/
Ext.form.NumberField.prototype.fieldClass = 'x-field-n';
/**
* ext-3.3.1
* 修改方法:添加F1 -- F12为特殊键,用于处理字段的帮助信息CTRL+F1。
**/
Ext.EventObjectImpl.prototype.isSpecialKey = function(){
var k = this.normalizeKey(this.keyCode);
return (this.type == 'keypress' && this.ctrlKey) ||
this.isNavKeyPress() ||
(k == this.BACKSPACE) || // Backspace
(k >= 16 && k <= 20) || // Shift, Ctrl, Alt, Pause, Caps Lock
(k >= 44 && k <= 46) || // Print Screen, Insert, Delete
(k >= 112 && k <= 123); // F1 -- F12
};
/**
* 新增方法:用来解决RowEditor类中这行ed = c.getEditor(); is not a function的错误
**/
Ext.grid.RowSelectionModel.prototype.getEditor = Ext.emptyFn;
/**
* ext-3.3.1
* 问题:如果int,float类型的值为null时,在record中取到后为0;
* 分析:在Ext.data.JsonReader.extractValues中转换值时改变了,分析是Types.INT FLOAT的两个方法转换了,增加了this.useNull判断
* 实际上是判断field对象的属性useNull,所以增加下面的一行,保留数值可以显示null
* 如果设置useNull值,会造成输出值为null,在grid编辑中还会出现异常,所以直接替换INT\FLOAT这两个方法
**/
//Ext.data.Field.prototype.useNull = true;
Ext.data.Types.INT = {
convert: function(v){
return v !== undefined && v !== null && v !== '' ?
parseInt(String(v).replace(Ext.data.Types.stripRe, ''), 10) : '';//(this.useNull ? null : 0) --> ''
},
sortType: Ext.data.SortTypes.none,
type: 'int'
};
Ext.data.Types.FLOAT = {
convert: function(v){
return v !== undefined && v !== null && v !== '' ?
parseFloat(String(v).replace(Ext.data.Types.stripRe, ''), 10) : '';//(this.useNull ? null : 0) --> ''
},
sortType: Ext.data.SortTypes.none,
type: 'float'
};
//在editgrid,如果可编辑字段为date类型,且值为空,则点击可编辑单元,光标离开时会给脏标记,
//是因为startValue=null,而当前值为空,所以值改变了。特修改如下:如果值为空,则返回''
Ext.data.Types.DATE = {
convert: function(v){
var df = this.dateFormat;
if(!v){
return '';//null -->''
}
if(Ext.isDate(v)){
return v;
}
if(df){
if(df == 'timestamp'){
return new Date(v*1000);
}
if(df == 'time'){
return new Date(parseInt(v, 10));
}
return Date.parseDate(v, df);
} else {
//调整后台输出的日期对象为字符串,如: 2016-04-01 12:02:01;支持JSON标准格式
if (Ext.isString(v) && v.length == 19) {
return Date.parseDate(v, 'Y-m-d H:i:s');
}
}
var parsed = Date.parse(v);
return parsed ? new Date(parsed) : '';//null -->''
},
sortType: Ext.data.SortTypes.asDate,
type: 'date'
};
/**
* ext-3.3.1
* 新增属性:添加24小时制时间格式校验
**/
Ext.apply(Ext.form.VTypes, {
//24小时制时间格式校验
time24: function(val, field) {
var time24Test = /^([0-9]|0[0-9]|1[0-9]|2[0-3]):([0-5][0-9])$/i;
return time24Test.test(val);
},
//错误提示
time24Text: jx.base.timetext //'无效时间格式,格式如:"22:34"'
});
/**
* 新增方法:给Record对象添加一个取数字的方法。
**/
Ext.data.Record.prototype.getNum = function(name){
var value = this.data[name];
if (value == null || value.length == 0) return 0;
return parseFloat(value);
};
Ext.data.Record.prototype.set = function(name, value){
//add by tony.tan 处理json数据用字符串赋值给date字段的问题
//---------------------------------------------------------
if (this.fields) {
var f = this.fields.get(name);
if (f && f.type.type == 'date') {
if (Ext.isString(value) && value.length == 19) {
value = Date.parseDate(value, 'Y-m-d H:i:s');
}
}
}
//---------------------------------------------------------
var encode = Ext.isPrimitive(value) ? String : Ext.encode;
if(encode(this.data[name]) == encode(value)) {
return;
}
this.dirty = true;
if(!this.modified){
this.modified = {};
}
if(this.modified[name] === undefined){
this.modified[name] = this.data[name];
}
this.data[name] = value;
if(!this.editing){
this.afterEdit();
}
};
//如果是日期对象赋值,则会显示错误字符串
Ext.form.Hidden.prototype.setValue = function(v){
if (!Ext.isEmpty(v) && Ext.isDate(v)) {
v = v.dateFormat('Y-m-d H:i:s');
}
this.value = v;
if(this.rendered){
this.el.dom.value = (Ext.isEmpty(v) ? '' : v);
this.validate();
}
return this;
};
/**
* ext-3.3.1
* 修改方法:修改取字符长度的方法,如果是汉字则是两个字节。
**/
Ext.form.TextField.prototype.getErrors = function(value) {
var errors = Ext.form.TextField.superclass.getErrors.apply(this, arguments);
value = Ext.isDefined(value) ? value : this.processValue(this.getRawValue());
if (Ext.isFunction(this.validator)) {
var msg = this.validator(value);
if (msg !== true) {
errors.push(msg);
}
}
if (value.length < 1 || value === this.emptyText) {
if (this.allowBlank) {
//if value is blank and allowBlank is true, there cannot be any additional errors
return errors;
} else {
if (!this.isBlankCheck) {//add by tony.tan
errors.push(this.blankText);
}
}
}
//modify by Tony.Tan
if (!this.isBlankCheck && !this.allowBlank && (value.length < 1 || value === this.emptyText)) { // if it's blank
errors.push(this.blankText);
}
//modify by Tony.Tan
if (JxUtil.strlen(value) < this.minLength) {
errors.push(String.format(this.minLengthText, this.minLength));
}
//modify by Tony.Tan
if (JxUtil.strlen(value) > this.maxLength) {
errors.push(String.format(this.maxLengthText, this.maxLength));
}
if (this.vtype) {
var vt = Ext.form.VTypes;
if(!vt[this.vtype](value, this)){
errors.push(this.vtypeText || vt[this.vtype +'Text']);
}
}
if (this.regex && !this.regex.test(value)) {
errors.push(this.regexText);
}
return errors;
};
/**
* ext-3.3.1
* 增加方法:增加一种不检查必填项的校验方法
**/
Ext.form.BasicForm.prototype.isValidBlank = function(){
var valid = true;
this.items.each(function(f){
f.isBlankCheck = true; //add by tony.tan
if(!f.validate()){
valid = false;
}
delete f.isBlankCheck; //add by tony.tan
});
return valid;
};
/**
* ext-3.3.1
* 修改方法:在导航图设计器中添加“提交”事件,JxAttach.js
* var formPanel = formTab.getComponent(0);执行时报items is null的错误
**/
Ext.Container.prototype.getComponent = function(comp){
if(Ext.isObject(comp)){
comp = comp.getItemId();
}
//add by tony.tan
if (this.items == null) return null;
return this.items.get(comp);
};
/**
* ext-3.3.1
* 修改方法:设置form中的字段,回车跳转到下一个控件的效果
**/
Ext.form.Field.prototype.afterRender = function(){
Ext.form.Field.superclass.afterRender.call(this);
this.initEvents();
this.initValue();
//add by tony.tan
var fn = function(e, t){
if (e.getKey() == e.ENTER) {
var me = this;
var fp = me.findParentByType('form');
if (Ext.isEmpty(fp)) return;
var items = fp.form.items;
//记录第一个有效字段的位置、当前字段的位置、当前字段的下一个位置
//必须记录位置,而不能记录控件f,不然循环结束后取不到真实控件
var i = 0, first = -1, index = -1, next = -1;
items.each(function(f){
//textarea控件中回车是文字换行
if (f.isFormField && f.rendered && f.name &&
!f.isXType('hidden') && !f.isXType('textarea')) {
if (first < 0) first = i;
if (f.name == me.name) {
index = i;
} else {
if (index >= 0) {
next = i;
return false;
}
}
}
i++;
});
//JxHint.hint(index+';'+next+';'+first);
//如果找到了当前位置,当没有找到下一个有效位置,则取第一个位置
if (index >= 0 && next < 0) next = first;
if (next >= 0) {
var fn = items.get(next);
if (fn) fn.focus(true);
}
}
};
//回车进入下一控件的开关
var isEnter = Jxstar.systemVar.edit__field__next;
if (isEnter == '1') {
this.mon(this.el, Ext.EventManager.getKeyEvent(), fn, this);
}
};
/**
* ext-3.3.1
* 修改方法:修改表格行选状态时,回车跳转到下一个控件的效果
**/
Ext.grid.RowSelectionModel.prototype.onEditorKey = function(field, e){
var k = e.getKey(),
newCell,
g = this.grid,
last = g.lastEdit,
ed = g.activeEditor,
shift = e.shiftKey,
ae, last, r, c;
//回车键开关
var isEnter = (Jxstar.systemVar.edit__field__next == '1');
//针对单个表格可以关闭此效果
if (g.isNextField != null) isEnter = g.isNextField;
if (isEnter) {//is enter
if(k == e.ENTER){//modify, ed.row --> last.row, last.col
//e.stopEvent();
//ed.completeEdit(); //ENTER is completeEdited
if(shift){
newCell = g.walkCells(last.row, last.col-1, -1, this.acceptsNav, this);
}else{
newCell = g.walkCells(last.row, last.col+1, 1, this.acceptsNav, this);
}
}else if(k == e.TAB){//modify
e.stopEvent();//add
ed.completeEdit();//add
if(this.moveEditorOnEnter !== false){
if(shift){
newCell = g.walkCells(last.row - 1, last.col, -1, this.acceptsNav, this);
}else{
newCell = g.walkCells(last.row + 1, last.col, 1, this.acceptsNav, this);
}
}
}
} else {//is old
if(k == e.TAB){
e.stopEvent();
ed.completeEdit();
if(shift){
newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
}else{
newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
}
}else if(k == e.ENTER){
if(this.moveEditorOnEnter !== false){
if(shift){
newCell = g.walkCells(last.row - 1, last.col, -1, this.acceptsNav, this);
}else{
newCell = g.walkCells(last.row + 1, last.col, 1, this.acceptsNav, this);
}
}
}
}
if(newCell){
r = newCell[0];
c = newCell[1];
this.onEditorSelect(r, last.row);
if(g.isEditor && g.editing){ // *** handle tabbing while editorgrid is in edit mode
ae = g.activeEditor;
if(ae && ae.field.triggerBlur){
// *** if activeEditor is a TriggerField, explicitly call its triggerBlur() method
ae.field.triggerBlur();
}
}
g.startEditing(r, c);
}
//add by tony 按下ctrl+alt键则完成编辑状态,用于执行表格快捷键
if (e.ctrlKey && e.altKey && ed) {
ed.completeEdit();
}
};
/**
* ext-3.3.1
* 修改方法:在firefox、chrome中点击表格cell时没聚焦editor
**/
Ext.Editor.prototype.onShow = function(){
this.el.show();
if(this.hideEl !== false){
this.boundEl.hide();
}
if (Ext.isIE) {
this.field.show().focus(false, true);
} else {
//add tony.tan 解决在firefox、chrome中点击表格cell没聚焦的问题
this.field.show().focus(false, 100);
}
this.fireEvent("startedit", this.boundEl, this.startValue);
};
/**
* ext-3.3.1
* 添加控件:工具栏中的支持快捷键设置的控件
**/
Ext.ux.ToolbarKeyMap = Ext.extend(Object, (function() {
var kb, owner, mappings;
var addKeyBinding = function(c) {
if (kb = c.keyBinding) {
delete c.keyBinding;
if (!kb.fn && c.handler) {
kb.fn = function(k, e) {
e.preventDefault();
e.stopEvent();
c.handler.call(c.scope, c, e);
}
}
mappings.push(kb);
}
if ((c instanceof Ext.Button) && c.menu) {
c.menu.cascade(addKeyBinding);
}
};
var findKeyNavs = function() {
delete this.onRender;
if (owner = this.ownerCt) {
mappings = [];
this.cascade(addKeyBinding);
if (!owner.menuKeyMap) {
owner.menuKeyMap = new Ext.KeyMap(owner.el, mappings);
owner.el.dom.tabIndex = 0;
} else {
owner.menuKeyMap.addBinding(mappings);
}
}
};
return {
init: function(toolbar) {
toolbar.onRender = toolbar.onRender.createSequence(findKeyNavs);
toolbar.doLayout = toolbar.doLayout.createSequence(findKeyNavs);
}
};
})());
/************* 为实现表单 NumberField 的千分位现实效果 *************/
Ext.form.NumberField.prototype.parseValue = function(value) {
value = String(value).replace(/,/g, '');//去格式化
value = parseFloat(String(value).replace(this.decimalSeparator, "."));
return isNaN(value) ? '' : value;
};
Ext.form.NumberField.prototype.setValue = function(v) {
v = String(v).replace(/,/g, '');//会重复赋值,需要去格式化
v = this.fixPrecision(v);
v = Ext.isNumber(v) ? v : parseFloat(String(v).replace(this.decimalSeparator, "."));
v = isNaN(v) ? '' : String(v).replace(".", this.decimalSeparator);
if (this.renderer) {//加格式化
v = this.renderer(v);
}
return Ext.form.NumberField.superclass.setValue.call(this, v);
};
Ext.form.NumberField.prototype.getErrors = function(value) {
var errors = Ext.form.NumberField.superclass.getErrors.apply(this, arguments);
value = Ext.isDefined(value) ? value : this.processValue(this.getRawValue());
if (value.length < 1) { // if it's blank and textfield didn't flag it then it's valid
return errors;
}
value = String(value).replace(this.decimalSeparator, ".");
value = String(value).replace(/,/g, '');//去格式化
if(isNaN(value)){
errors.push(String.format(this.nanText, value));
}
var num = this.parseValue(value);
if (num < this.minValue) {
errors.push(String.format(this.minText, this.minValue));
}
if (num > this.maxValue) {
errors.push(String.format(this.maxText, this.maxValue));
}
//如果录入了汉字,就清空
if (errors && errors.length > 0) this.setValue('');
return errors;
};
JxExt.bbsurl = function(keyid) {
var imgurl = "./fileAction.do?funid=sys_attach&pagetype=editgrid&eventcode=down&nousercheck=1&dataType=byte&keyid="+keyid;
return imgurl;
};
//不用超链接的href,则采用click是防止页面跳转,退出系统
JxExt.bbsfile = function(a) {
var iframe = document.getElementById('frmhidden');
iframe.src = JxExt.bbsurl(a.id);
};
//给HtmlEditor控件添加图片的方法
ImgHtmlEditor = Ext.extend(Ext.form.HtmlEditor, {
enableAlignments : false,
enableColors : false,
enableFont : false,
enableFontSize : false,
enableFormat : false,
enableLinks : false,
enableLists : false,
enableSourceEdit: true,
//fileType 文件类型:1 图片、0 文件
addImage : function(fileType) {
var editor = this;
var fileForm = editor.findParentByType('form');
if (Ext.isEmpty(fileForm)) {
return;
}
var form = fileForm.getForm();
var define = fileForm.formNode.define;
var dataFunId = define.nodeid;
var tableName = define.tablename;
var dataId = form.get(define.pkcol);
var formItems = [{
xtype: 'fileuploadfield',
useType: 'file',
maxLength: 200,
fieldLabel: jx.event.selfile,//'选择文件',
name: 'attach_path',
buttonText: '',
buttonCfg: {
iconCls: 'upload_icon'
},
listeners:{
fileselected: function(f, path) {
var len = path.length;
if (len > 0) {
var pos = path.lastIndexOf('\\');
if (pos >= 0) {
path = path.substr(pos+1, len);
}
}
imgform.getForm().findField('attach_name').setValue(path);
}
}
},{
xtype: 'hidden',
name: 'attach_name'
}];
var imgform = new Ext.form.FormPanel({
layout:'form',
labelAlign:'right',
labelWidth:80,
border:false,
baseCls:'x-plain',
autoHeight: true,
bodyStyle: 'padding: 20px 10px 0 10px;',
defaults: {
anchor: '95%',
allowBlank: false,
msgTarget: 'side'
},
items : formItems
});
var win = new Ext.Window({
title : jx.plet.text18,//"上传文件",
width : 400,
height : 170,
modal : true,
closeAction:'close',
items:[imgform],
buttons: [{
text : jx.bus.text48,//'上传',
type : 'submit',
handler : function() {
var form = imgform.form;
//上传参数
var params = 'funid=sys_attach&pagetype=editgrid';
params += '&attach_field=&dataid='+ dataId +'&datafunid='+ dataFunId;
params += '&eventcode=create';
//上传成功后关闭窗口并刷新数据
var hdCall = function(data) {
if (Ext.isEmpty(data)) {
JxHint.alert(jx.util.attfa);//'文件上传失败!'
return;
}
var html;
if (fileType == '1') {//上传图片
html = '';
} else {//上传文件
html = '';
}
editor.focus();
editor.insertAtCursor(html);
win.close();
};
//上传附件
Request.fileRequest(form, params, hdCall);
}
}, {
text : jx.base.close,//'关闭',
handler : function() {
win.close();
}
}]
});
win.show();
},
createToolbar : function(editor) {
ImgHtmlEditor.superclass.createToolbar.call(this, editor);
this.tb.insertButton(0, {
iconCls : "fa-image blue",
tooltip:jx.plet.text16,//'添加图片',
handler : function(){this.addImage('1');},
scope : this
});
this.tb.insertButton(0, {
iconCls : "fa-paperclip blue",
tooltip:jx.plet.text17,//'添加文件',
handler : function(){this.addImage('0');},
scope : this
});
//this.tb.getComponent(0).hide();
//this.tb.getComponent(1).hide();
},
initEditor : function() {
ImgHtmlEditor.superclass.initEditor.call(this);
this.getDoc().body.style.lineHeight = '28px';//设置文字行高
}
});
Ext.reg('imghtmleditor', ImgHtmlEditor);
//处理LODOP设计器隐藏,现实对话框的效果
Ext.Window.prototype.show = function(animateTarget, cb, scope){
if (window.LODOP_SHOW) {
window.LODOP_SHOW.style.visibility = 'hidden';
}
//------------------
if(!this.rendered){
this.render(Ext.getBody());
}
if(this.hidden === false){
this.toFront();
return this;
}
if(this.fireEvent('beforeshow', this) === false){
return this;
}
if(cb){
this.on('show', cb, scope, {single:true});
}
this.hidden = false;
if(Ext.isDefined(animateTarget)){
this.setAnimateTarget(animateTarget);
}
this.beforeShow();
if(this.animateTarget){
this.animShow();
}else{
this.afterShow();
}
return this;
};
Ext.Window.prototype.doClose = function(){
if (window.LODOP_SHOW) {
window.LODOP_SHOW.style.visibility = 'visible';
}
//------------------
this.fireEvent('close', this);
this.destroy();
};
Ext.Button.buttonTemplate = new Ext.Template(//add by tony.tan
'');
Ext.Button.prototype.setIconClass = function(cls){
this.iconCls = cls;
//add by tony.tan
if(this.el && cls){
var c = 'x-fa fa ' + cls;
var t = this.getText();
if (!t || t.length == 0) {//如果没有标题就用特殊样式,并去掉button中间的空格
c = 'x-icon-only fa ' + cls;
this.btnEl.update('');
}
this.btnEl.insertHtml('afterBegin', '');
this.setButtonClass();
}
/*if(this.el){
this.btnEl.dom.className = '';
this.btnEl.addClass(['x-btn-text', cls || '']);
this.setButtonClass();
}*/
return this;
};
Ext.Panel.prototype.setIconClass = function(cls){
var istog = (cls == 'x-tool-toggle');
var old = this.iconCls;
this.iconCls = cls;
if(this.rendered && this.header){
if(this.frame){
this.header.addClass('x-panel-icon');
this.header.replaceClass(old, this.iconCls);
}else{
var hd = this.header, img;
//img = hd.child('img.x-panel-inline-icon');
//add by tony.tan
if (istog) {
img = hd.child('button.x-tool');
} else {
img = hd.child('div.x-tool');
}
if(img){
Ext.fly(img).replaceClass(old, this.iconCls);
}else{
var hdspan = hd.child('span.' + this.headerTextCls);
if (hdspan && (!istog || (istog && this.collapsible))) {
var cfg = {tag: "div", cls: "x-panel-inline-icon", html:""};//add by tony.tan
if (istog) {
cfg = {tag: "button", cls: "x-tool x-panel-inline-icon", html:""};//add by tony.tan
}
var n = Ext.DomHelper.insertBefore(hdspan.dom, cfg //add by tony.tan
//{tag:'img', alt: '', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls}
);
//add by tony.tan, 如果用click在字段回车时会触发
if (istog) {
Ext.get(n).on('mousedown', this.toggleCollapse, this);
setTimeout(function(){//删除自动创建的toggle按钮
var t = hd.child('button.x-tool>i.toggle');
if (t && t.dom.parentNode) Ext.get(t.dom.parentNode).remove();
}, 500);
}
}
}
}
}
this.fireEvent('iconchange', this, cls, old);
//add by tony.tan
/*this.header.on('click', function(){
if (this.collapsed) {
this.expand(true);
} else {
this.collapse(true);
}
}, this);*/
};
Ext.form.TriggerField.prototype.onRender = function(ct, position){
this.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();
Ext.form.TriggerField.superclass.onRender.call(this, ct, position);
this.wrap = this.el.wrap({cls: 'x-form-field-wrap x-form-field-trigger-wrap'});
this.trigger = this.wrap.createChild(this.triggerConfig ||
//{tag: "img", src: Ext.BLANK_IMAGE_URL, alt: "", cls: "x-form-trigger " + this.triggerClass}
{tag: "a", cls: "x-form-trigger", html:""}//add by tony.tan
);
this.initTrigger();
if(!this.width){
this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
}
this.resizeEl = this.positionEl = this.wrap;
};
Ext.Panel.prototype.toolTemplate = new Ext.XTemplate(
'',
'
',
'',
'',
'',
'',
'',
//'
'
'',
''
);
Ext.TabPanel.prototype.itemTpl = new Ext.Template(
'',
'{text}',
''
);
Ext.Panel.prototype.border = false;
Ext.menu.Menu.prototype.shadow = false;