/*!
* 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);
};
var getVerNo = function(){
var ps = ua.split('rv:');
if (ps.length < 2) return 0;
return parseInt(ps[1].split('.')[0]);
};
//取Firefox的版本号
JxExt.GeckoNum = getVerNo();
//是否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)|(on[\D]+[\s]*[=])/gi;//过滤所有 (= onxxx) 或 (onxxx =) 前台方法
var filter_re2 = /(script)|(eval)|(frame)|(src)|(cookie)|(style)|(expression)|(prompt)|(confirm)|(
= 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 ct = this.ownerCt;
if (ct && ct.isXType('grid') && ct.gridNode) {
var type = ct.gridNode.pageType;
if (type == 'subgrid' || type == 'subeditgrid') {
if (!ct.fkValue || ct.fkValue.length == 0 ||
!o.server_param || o.server_param.length == 0) {
//子表没有查询条件,请检查!
JxHint.alert(jx.base.suberror);
return;
}
}
}
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
* 修改方法:加密传输通用查询的排序参数
**/
Ext.data.Store.prototype.load = function(options) {
options = Ext.apply({}, options);
this.storeOptions(options);
if(this.sortInfo && this.remoteSort){
var pn = this.paramNames;
options.params = Ext.apply({}, options.params);
var url = this.proxy.url;
//加密传输参数,避免SQL注入 add by tony.tan
if (JxUtil.use64() && url && (url.indexOf('eventcode=query_data') >= 0)) {
options.params[pn.sort] = JxUtil.base64(this.sortInfo.field);
options.params[pn.dir] = JxUtil.base64(this.sortInfo.direction);
} else {
options.params[pn.sort] = this.sortInfo.field;
options.params[pn.dir] = this.sortInfo.direction;
}
}
try {
return this.execute('read', null, options); // <-- null represents rs. No rs for load actions.
} catch(e) {
this.handleException(e);
return false;
}
};
/**
* 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
* 修改方法:按 Delete 键或 Backspace 键清除数据
**/
Ext.form.ComboBox.prototype.enableKeyEvents = true;
Ext.form.ComboBox.prototype.onRender = function(ct, position){
if(this.hiddenName && !Ext.isDefined(this.submitValue)){
this.submitValue = false;
}
Ext.form.ComboBox.superclass.onRender.call(this, ct, position);
if(this.hiddenName){
this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName,
id: (this.hiddenId || Ext.id())}, 'before', true);
}
if(Ext.isGecko){
this.el.dom.setAttribute('autocomplete', 'off');
}
if(!this.lazyInit){
this.initList();
}else{
this.on('focus', this.initList, this, {single: true});
//按 Delete 键或 Backspace 键清除数据
this.on('keydown', function(t, e){
var k = e.getKey();
if (!this.readOnly && (k == 46 || k == 8)) this.setValue('');
});
}
};
/**
* ext-3.3.1
* 修改方法:取checkbox的值时取 0 或 1,而不是true false。
**/
Ext.form.Checkbox.prototype.getValue = function(){
//加这个判断解决:RadioGroup控件的选项值有0、1时,选项值不准的问题
if (this.getXType() == 'radio' && this.inputValue != undefined) {
return String(this.inputValue);
}
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 = String(val);//add by
val = String(val).split(',');
this.eachItem(function(item){
if(val.indexOf(String(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;
};
/**
* 修改方法:给Field控件添加placeholder属性
**/
Ext.form.Field.prototype.onRender = function(ct, position){
if(!this.el){
var cfg = this.getAutoCreate();
if(!cfg.name){
cfg.name = this.name || this.id;
}
if(this.inputType){
cfg.type = this.inputType;
}
this.autoEl = cfg;
}
Ext.form.Field.superclass.onRender.call(this, ct, position);
if(this.submitValue === false){
this.el.dom.removeAttribute('name');
}
var type = this.el.dom.type;
if(type){
if(type == 'password'){
type = 'text';
}
this.el.addClass('x-form-'+type);
}
if(this.readOnly){
this.setReadOnly(true);
}
if(this.tabIndex !== undefined){
this.el.dom.setAttribute('tabIndex', this.tabIndex);
}
//---add by tony
if (this.placeholder !== undefined) {
this.el.dom.setAttribute('placeholder', this.placeholder);
}//---end
this.el.addClass([this.fieldClass, this.cls]);
};
/**
* 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());
//trim blank add by tony.tan
if (value && value.length > 0) value = value.trim();
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();
}
//避免第一次打开trigger控件时被挡住一部分
if (this.field.isXType('trigger')) {
if (!this.field.isNotFirst) {
var w = this.field.getWidth()+18;
this.el.setWidth(w);
this.field.setWidth(w);
this.field.isNotFirst = true;
}
}
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.Editor.prototype.setSize = function(w, h){
delete this.field.lastSize;
//this.field.setSize(w, h);
if(this.el){
// IE7 in strict mode doesn't size properly.
if(Ext.isGecko2 || Ext.isOpera || (Ext.isIE7 && Ext.isStrict)){
// prevent layer scrollbars
this.el.setSize(w, h);
}
this.el.sync();
}
//add tony.tan 解决datetimefield在表格中显示不全的问题
if (this.field.isXType('datetimefield')) {
var me = this;
JxUtil.delay(10, function(){
me.el.setSize(w, h);
me.field.setSize(w, h);
});
} else {
this.field.setSize(w, h);
}
};
/**
* 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 (value == '-') value = '0';//避免输入-时自动去掉了
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;
};
Ext.form.NumberField.prototype.beforeBlur = function() {
var v = this.parseValue(this.getRawValue());
//if (!Ext.isEmpty(v)) {//避免单个-字符还可以保存
this.setValue(v);
//}
};
JxExt.bbsurl = function(keyid) {
var imgurl = "./fileAction.do?funid=sys_attach&pagetype=editgrid&eventcode=down&dataType=byte&keyid="+keyid+'&user_id='+Jxstar.session['user_id'];
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);
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.layout.FormLayout.prototype.getTemplateArgs = function(field) {
var noLabelSep = !field.fieldLabel || field.hideLabel;
//---------------------------替换颜色---------------------------------
if (field.labelSeparator == '*' && field.labelStyle == 'color:#0077FF;') {
var color = Jxstar.systemVar.page__form__labcolor||'#0077FF';
field.labelStyle = 'color:'+color+';';//替换为红色
}//-------------
return {
id : field.id,
label : field.fieldLabel,
itemCls : (field.itemCls || this.container.itemCls || '') + (field.hideLabel ? ' x-hide-label' : ''),
clearCls : field.clearCls || 'x-form-clear-left',
labelStyle : this.getLabelStyle(field.labelStyle),
elementStyle : this.elementStyle || '',
labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator)
};
};
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;
/************************* 支持树形节点查询 author: simon.chen ************************/
JxExt.treeAddQuery = function(tree, tbar, nodeId) {
var searchField = new Ext.form.TextField({
maxLength:20,
name:'tree_search_field',
width:75,
cls:'bd-rd5',
style:'margin:0 0 0 5;color:#808080;font-size:13px;',
emptyText:'回车搜索',
enableKeyEvents:true
});
/**
* 思路:根据搜索条件searchCondition去后台获取所有匹配的节点集S1,对S1的每个节点A,获取A到根节点R的路径上所有节点,
* 组成集合S2,对A到R上的所有节点进行处理,如节点B,如果B存在子节点C是S2的元素,那么删除除C外的所有B的子节点,否则,
* 收起B即可先刷新根节点R,然后从后台获取与搜索条件匹配的节点ID,在根据节点ID从根节点展开至此节点A;展开后对节点A
* 到根节点路径上所有节点B进行过滤,如B所有子节点均不在需展示的节点集合内,则收起B节点的所有子节点,否则,移除B
* 节点所有不在需展示的节点集合内的子节点
*/
searchField.onKeyDown=function(e){
if(e.keyCode == e.ENTER){
var searchCondition = this.getValue();
tree = this.ownerCt.ownerCt.root.ownerTree;
tree.getRootNode().reload(function(){
var callback = function(datas){
if(datas instanceof Array){
var exist = function(id){
if(datas.length>0){
for(var i=0;i0&&filterNodes.indexOf(node.id)==-1){
for(var i=0;i'+childNode.text.substr(index,searchCondition.length)+''+childNode.text.substring(index+searchCondition.length);
childNode.setText(text);
}
}
}
filterNodes.push(node.id);
var remove = function(childNodes){
if(childNodes.length>0){
for(var i=0;i0){
for(var i=0;i 0) {
content = content.substring(0, content.length-1);
}
}
return content;
};
//把状态信息字符串转换为对象
var getGridState = function(state) {
var cs = state.split('-');//n:dataIndex, w:width, h:hidden, x:index
var s, c, d, os = [cs.length];
for(var i = 0, len = cs.length; i < len; i++){
s = cs[i].substring(1, cs[i].length-1);
c = s.split(',');
var o = {};
for(var j = 0; j < c.length; j++){
d = c[j];
o[d.substr(0, 1)] = d.substr(2, d.length-2);
}
os[i] = o;
}
return os;
};
//加载表格标题的位置与宽度
var applyColumnState = function(g, state) {
if (!g || !state) return;
var cs = getGridState(state);//n:dataIndex, w:width, h:hidden, x:index
var cm = g.colModel, s, c, x;
for(var i = 0, len = cs.length; i < len; i++){
s = cs[i];
c = cm.findColumnIndex(s.n);
if (c > -1) {
cm.setHidden(c, (s.h=='true'));
cm.setColumnWidth(c, parseInt(s.w));
x = parseInt(s.x);
//alert(c+'//'+x+'//'+s.n);
if(x != c){
cm.moveColumn(c, x);
}
}
}
};
//避免重复执行的标志
var _sing = false;
//列状态保存
var col_save = function(id, ct) {
//console.log('...........col_save ' + id);
var params = 'funid=sys_query&eventcode=col_save&grid_id='+ id +'&grid_state='+ ct;
Request.dataRequest(params, function(){
_sing = false;
});
};
//列状态查询
var col_qry = function(id, fn) {
//console.log('...........col_qry ' + id);
var params = 'funid=sys_query&eventcode=col_qry&grid_id='+ id;
Request.dataRequest(params, fn);
};
//列状态恢复
var col_del = function(id, fn) {
//console.log('...........col_del ' + id);
var params = 'funid=sys_query&eventcode=col_del&grid_id='+ id;
Request.dataRequest(params, fn);
};
/**
* 绑定列移动、调整宽度事件,保存状态信息;在表格对象呈现时再加载状态信息。
**/
JxExt.gridStateEvent = function(g, nostate) {
//构建状态标识
var _fid = function(){
var gn = g.gridNode;
return gn.nodeId+'@@'+gn.pageType+'@@grid';
};
//列位置调整时保存状态信息
var fn = function(){
if (_sing) return;
_sing = true;
var ct = saveColumnState(g);
col_save(_fid(), ct);
};
g.on('columnmove', fn);
g.on('columnresize', fn);
var oldstate = '';
//表格呈现时加载列位置状态
var fx = function(){
var fn = function(data){
var ct;
if (data && data.cfg_cont) ct = data.cfg_cont;
if (ct && ct.length > 0) {
//console.log('...........col_qry ' + ct);
//保存原来的效果
oldstate = saveColumnState(g);
//应用表格自定义
applyColumnState(g, ct);
}
};
col_qry(_fid(), fn);
};
g.on('render', fx);
//显示设置按钮
g.on('headerclick', function(g, index){
var id = g.colModel.getColumnId(index);
if (id != 'numberer') return;
var addlock = function(){
if (!g.locker) return [];
var cols = g.getColumnModel().config;
var c, its = [];
its.push({text:'解锁列', handler:function(){
var l = g.locker;
if (!l) return;
l.unlock();
}}, '-');
var fn = function(){
var id = this.colid;
var l = g.locker;
if (!l) return;
//如果是同一列,则不用重新锁定
if (l.lockColId == id) return;
l.unlock();
l.lock(id);
};
//支持锁定:第3显示列 - 第6显示列
for (var i = 0, j = 0; i < cols.length; i++) {
c = cols[i];
if (c && !c.hidden) {
j++;
if (j >= 3 && j <= 6) {
var s = c.header.replace('*', '');
var t = '锁定列-' + s;
its.push({text:t, colid:c.id, handler:fn});
}
}
}
its.push('-');
return its;
};
var dv = g.getView().getHeaderCell(index);
var dx = Ext.get(dv);
if (!g.setmenu) {
var items = addlock();
if (!nostate) {//不需要显示列恢复操作
var its = [
{text:'恢复列位置', handler:function(){
col_del(_fid(), function(){
//加载原设置
if (oldstate.length > 0) {
applyColumnState(g, oldstate);
JxUtil.delay(500, function(){col_del(_fid());});//恢复设置时也会触发保存事件
}
});
}}
];
items = items.concat(its);
}
g.setmenu = new Ext.menu.Menu({items:items});
}
g.setmenu.showAt([dx.getX()+15, dx.getY()+30]);
});
};
})();
/******************************* 表格列锁定控件 *****************************/
GridLocker = function(config){
this.grid = config.grid;
this.lockBody = null;//模拟锁定层
this.lockInner = null;//内容区域,滑动区
this.scrollBar = null;//模拟滚动条
this.locked = false;//当前是否锁定列状态
this.lockNum = 0;//锁定显示列数
this.lockColId = null;//锁定列ID
var grid = config.grid;
//重建锁定区
var relock = function(g){
var l = g.locker;
if (l && l.locked){
var ln = l.lockColId;
l.unlock();
l.lock(ln);
}
};
//调整锁定区的位置与大小
grid.on('resize', relock);
grid.getStore().on('load', function(){
relock(grid);
});
//上下滚动同时滚动模拟层
var scrollFn = function(scrollLeft, scrollTop){
var l = this.locker;
if (l && l.locked){
l.lockInner.scrollTo('top', scrollTop);
}
};
grid.on('bodyscroll', scrollFn);
};
GridLocker.prototype.getLockWidth = function(colid){
var w = 0, c, j = 0;
var cols = this.grid.getColumnModel().config;
//根据指定列ID来计算宽度
for (var i = 0; i < cols.length; i++) {
c = cols[i];
if (c.width && !c.hidden) {
w += c.width;
j++;
}
if (c.id == colid) {
this.lockNum = j;
return w;
}
}
};
GridLocker.prototype.copyHead = function(colIndex){
var hd = this.grid.getView().innerHd;
var tds = Ext.get(hd).query('td.x-grid3-hd');
if (tds.length == 0) return;
var ct = this.lockBody.child('tr.x-grid3-hd-row');
var cols = this.grid.getColumnModel().config;
var ht = '', c, w = 0;
for (var i = 0, j = 0; j < colIndex; i++) {
c = cols[i];
ht += tds[i].outerHTML;
if (c && c.width && !c.hidden) {
w += c.width;
j++;
}
}
ct.update(ht);
//设置table宽度保证标题不晃动
var t = ct.up('table', 2);
var wb = this.lockBody.getWidth() - 0.6;
t.setWidth(wb);
};
//复制第二行标题
GridLocker.prototype.copyHead2 = function(colIndex){
var hd = this.grid.getView().innerHd;
var tbls = Ext.get(hd).query('table');//取第二行标题复制
if (tbls.length < 2) return;
var tds = Ext.get(tbls[1]).query('td.x-grid3-hd');//---------
if (tds.length == 0) return;
var tbs = this.lockBody.query('.x-grid3-header-offset table');//取第二行标题复制
if (tbs.length < 2) return;
var ct = Ext.get(tbs[1]).child('tr.x-grid3-hd-row');//---------
var cols = this.grid.getColumnModel().config;
var ht = '', c, w = 0;
for (var i = 0, j = 0; j < colIndex; i++) {
c = cols[i];
/*if (i == 0) {
ht += tds[i].outerHTML.replace('
', '');
} else {
ht += tds[i].outerHTML;
}*/
ht += tds[i].outerHTML;
if (c && c.width && !c.hidden) {
w += c.width;
j++;
}
}
ct.update(ht);
//设置table宽度保证标题不晃动
var t = ct.up('table', 2);
var wb = this.lockBody.getWidth() - 0.6;
t.setWidth(wb);
};
GridLocker.prototype.copyRow = function(){
var ct = this.grid.getView().mainBody;
var ht = ct.dom.innerHTML;
this.lockInner.update(ht);
//标记序号,check选择用
var rows = this.lockInner.dom.childNodes;
for (var i = 0; i < rows.length; i++) {
rows[i].rowIndex = i;
}
};
GridLocker.prototype.lock = function(colId){
if (this.locked) return;
this.locked = true;
this.lockColId = colId;
var me = this;
var grid = this.grid;
var lockWidth = this.getLockWidth(colId);
if (!this.lockBody) {
var ct = grid.body;
var buf = [
'',
'',
'
'
];
if (_hasColumnGroup(grid)) {//含分组标题
buf = [
'',
'',
'
'
];
}
var cf = {tag:'div', cls:'x-grid3-lockdiv', html:buf.join('')};
var lb = ct.createChild(cf);
lb.setHeight(grid.body.getHeight());
lb.setWidth(lockWidth);
this.lockBody = lb;
var xh = 53;
if (_hasColumnGroup(grid)) {//含分组标题
xh += 34;
}
//设置内容区的高度,这样滑动才有效果
var iner = this.lockBody.down('div.x-grid3-body');
iner.setHeight(grid.body.getHeight()-xh);
this.lockInner = iner;
//锁定区光标移动时触发事件
var v = grid.getView();
this.lockInner.on({
mouseover: function(e, target){
v.onRowOver(e, target);
},
mouseout : function(e, target){
v.onRowOut(e, target);
}
});
//拷贝标题
this.copyHead(this.lockNum);
if (_hasColumnGroup(grid)) {//含分组标题
this.copyHead2(this.lockNum);//this.lockSubNum||0
}
//拷贝内容
this.copyRow();
}
if (!this.scrollBar) {
var ct = grid.body;
var buf = ['',
'
',
''];
var cf = {tag:'div', cls:'x-grid3-scrollbar', html:buf.join('')};
var sb = ct.createChild(cf);
var w = grid.body.getWidth();
var h = grid.body.getHeight();
sb.setWidth(w);
sb.setTop((h-16)+'px');
this.scrollBar = sb;
//滑块左占位区
var left = sb.down('div.x-scroll-leftdiv');
left.setWidth(lockWidth);
//滑块右占位区
var right = sb.down('div.x-scroll-rightdiv');
var rw = w - lockWidth;
right.setWidth(rw);
//因为DD.onDrag事件总是造成滑开丢失,所以用系统滑块
var gv = grid.getView();
var cwd = gv.mainBody.getWidth() - lockWidth;
var sbar = sb.child('div.x-scroll-rightbar');
if (rw < cwd) {
//设置滑动块的宽度为真实文档宽度,用系统滚动条触发文档滚动
sbar.setWidth(cwd);
right.on('scroll', function(e){
var sl = right.dom.scrollLeft;
gv.scroller.scrollTo('left', sl);
});
}
}
//设置模拟层的初始滚动位置
var top = this.grid.body.getScroll().top;
this.lockInner.scrollTo('top', top);
};
GridLocker.prototype.unlock = function(){
var grid = this.grid;
this.locked = false;
this.lockNum = 0;
this.lockColId = null;
this.lockInner = null;
if (this.lockBody) {
this.lockBody.remove();
this.lockBody = null;
}
if (this.scrollBar) {
this.scrollBar.remove();
this.scrollBar = null;
}
};
//------------------------ 同步行选择与滑动的光标效果 -----------------------------
var _updateLockRowCls = function(g, rowId, method, cls){
var l = g.locker;
if (l && l.locked){
var rows = l.lockInner.dom.childNodes;
Ext.fly(rows[rowId])[method](cls);
}
};
// 是否有分组标题
var _hasColumnGroup = function(g){
var gv = g.getView();
if (gv && gv.templates) {
return (gv.templates.gcell != null);
} else {
return false;
}
};
// private
Ext.grid.GridView.prototype.addRowClass = function(rowId, cls) {
var row = this.getRow(rowId);
if (row) {
this.fly(row).addClass(cls);
_updateLockRowCls(this.grid, rowId, 'addClass', cls);
}
};
// private
Ext.grid.GridView.prototype.removeRowClass = function(rowId, cls) {
var row = this.getRow(rowId);
if (row) {
this.fly(row).removeClass(cls);
_updateLockRowCls(this.grid, rowId, 'removeClass', cls);
}
}
//------------------------ 添加页面水印效果 -----------------------------
JxExt.WaterMark_Gap = 150; //水印间距
JxExt.WaterMark_Text = 'Jxstar'; //水印文字
JxExt.WaterMark_FontSize = 16; //水印字体大小
/*
* props {fontSize:14, text:'tanzb', gap:100}
* 创建水印图片并且填充
*/
JxExt.appendWaterMark = function(parentDiv, props) {
if (JxExt.isIE) return;//IE浏览器不支持此水印控件
if (!props) {
props = {fontSize:JxExt.WaterMark_FontSize, text0:JxExt.WaterMark_Text0||'', text1:JxExt.WaterMark_Text1||'', text2:JxExt.WaterMark_Text2||'', gap:JxExt.WaterMark_Gap};
}
var data = JxExt.createWaterMark(props);
//console.log('data',data);
JxExt.fillWaterMark(parentDiv, data);
};
/*
* 创建水印图片
*/
JxExt.createWaterMark = function(props) {
const canvas = document.createElement('canvas');
const devicePixelRatio = window.devicePixelRatio || 1;
const fontSize = props.fontSize * devicePixelRatio;
const font = fontSize + 'px serif';
const ctx = canvas.getContext('2d');
ctx.font = font;
let width = ctx.measureText(props.text1).width;
let width2 = ctx.measureText(props.text2).width;
if (width < width2) width = width2;
const canvasSize = Math.max(100, width)+props.gap;
devicePixelRatio;
canvas.width = canvasSize;
canvas.height = canvasSize;
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.rotate((Math.PI / 180) * 315);
ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';
ctx.font = font;
ctx.textAlign = 'left';
ctx.textBaseline = 'middle';
ctx.fillText(props.text0, 0, 0);
ctx.fillText(props.text1, 0, 24);
if (props.text2.length > 0) {
ctx.fillText(props.text2, 0, 48);
}
return {
base64: canvas.toDataURL(),
size: canvasSize,
adaptiveSize: canvasSize / devicePixelRatio
}
};
/*
* 填充整个DIV区域水印图片
*/
JxExt.fillWaterMark = function(parentDiv, data) {
const customDiv = document.createElement('div');
customDiv.className = 'WaterMark';
customDiv.style.backgroundImage = 'url('+data.base64+')';
customDiv.style.backgroundSize = data.adaptiveSize + 'px ' + data.adaptiveSize + 'px';
customDiv.style.backgroundRepeat = 'repeat';
customDiv.style.zIndex = '100';
// 设置绝对定位,以便图片能够填充整个区域
customDiv.style.position = 'absolute';
// 子元素相对于父元素的内边距,设置为0代表子元素完全覆盖父元素
customDiv.style.inset = '0';
// 必须设置此属性,否则水印遮罩层会阻止下层页面的操作事件
customDiv.style.pointerEvents = 'none';
// 360浏览器中不显示,需要添加下面的样式
customDiv.style.width = '100%';
customDiv.style.height = '100%';
customDiv.style.top = 0;
customDiv.style.left = 0;
parentDiv.append(customDiv);
};