测试效果如图:


当鼠标划过的时候,需要显示更多的信息,因为GridPanel表格显示区域不够,所以把部分信息移动到 Tip 中显示。代码如下:

store: {
  type: 'EduCartoonStore',
  autoLoad: false,
  listeners: {
      'load': function() {
          // 得到当前的Gird
          var grid = Ext.getCmp('eduCartoonListGrid');
          var view = grid.getView();
          // 创建一个 Tip
          var tip = Ext.create('Ext.tip.ToolTip', {
              target: view.el,
              delegate: view.itemSelector,
              trackMouse: true,
              renderTo: Ext.getBody(),
              listeners: {
                  // 显示Tip
                  beforeshow: function updateTipBody(tip) {
                      var record = view.getRecord(tip.triggerElement);
                      var state = '';
                      var createTime = '';
                      var packageTime = '-';
                      var showHtml = '';
                      // 状态
                      if (record.data.status === 0) {
                        state = "<span style='color:red'>待审核</span>";
                      } else if (record.data.status === 1) {
                        state = "<span style='color:green'>已审核</span>";
                      } else if (record.data.status === -1) {
                        state = "<span style='color:grey'>已关闭</span>";
                      }
                      // 创建时间
                      createTime = formatDate(record.data.ctime);
                      // 打包时间
                      if (record.data.zipGenerateTime !== undefined) {
                        packageTime = formatDate(record.data.zipGenerateTime)
                      }
                      showHtml += '<p><b>ID编号</b>:' + record.data.id + '</p>';
                      showHtml += '<p><b>状态</b>:' + state + '</p>';
                      showHtml += '<p><b>创建时间</b>:' + createTime + '</p>';
                      showHtml += '<p><b>打包时间</b>:' + packageTime + '</p>';
                      tip.update(showHtml);
                  }
              }
          });
      }
  }
}

因业务需要,只能动手来研究一个拖拽模块。研究之前觉得很简单,在我印象里好想类似的 Vue,jQuery 的插件非常多。应该是分分钟就可以搞定。结果花了很长的时间来研究这个玩意。现在把思路记下来方便下次查阅。

  • 创建拖拽对象
  • 确定“接受拖拽对象的”区域
  • 新建一个类,用于实现 ExtJS 中关于 “拖拽” 方法的实现
  • 使用新编写带有实现的类应用到拖拽对象中
  • 编写CSS来提升用户体验
  • 拖拽结束之后的节点复制和移动

基本上就是上述的几个步骤,为了方便查阅我把所有的脚本都构建在一个 JS 文件中,若真用到项目中,请严格按照 Sencha ExtJS 的 MVC 标准做代码的分离。代码如下:

/*
 * author:      liucan
 * email:       [email protected]
 * description: 系统顶部模块
 */

// 在这里需要重写拖拽的方法,基础的 API 并没有基于业务的实现。
// 拖拽完成,必须要判定是否拖放在指定的区域中,并且长宽要一致
// 对其当前的容器元素,TOP,LEFT 必须为 0
var overrides = {
    startDrag: function () {
        this.originalXY = this.el.getXY();
    },
    onDrag: function () {
        this.el.addCls('item-draging');
    },
    onDragEnter: function (e, id) {
        // console.log('onDragEnter');
        if(id != this.el.dom.parentNode.id){
            this.el.addCls('item-drag-ok');
        }else{
            this.onDragOut();
        }
    },
    onDragOver: function (e, id) {
    },
    onDragOut: function (e, id) {
        this.el.removeCls('item-drag-ok');
    },
    onDragDrop: function (e, id) {
    },
    onInvalidDrop: function () {
        // 无效拖动,需要使用动画还原。
        this.invalidDrop = true;
        this.el.removeCls('item-draging');    
    },
    endDrag: function (e, id) {
        this.el.removeCls('item-draging');
        if(this.invalidDrop === true){
            // 无效的移动
            var animCfgObj = {
                easing: 'elasticOut',
                duration: 1,
                scope: this,
                callback: function(){
                    this.el.dom.style.postion = '';
                }
            }
            this.el.setXY(this.originalXY);
            delete this.invalidDrop;
        }else{
            // 判定 TARGET 的值,并且做好磁力贴效果
            // 复制节点到指定元素,删除原有节点
            var newNode = this.el;
            if(e.item){
                e.item.firstChild.append(newNode.dom)
                newNode.dom.style = "";
            }
        }
    }
};

var pinyinTpl = new Ext.XTemplate(
    '<div id="pinyin_panel" class="pinyin-panel">',
        '<tpl for=".">',
            '<div class="pinyin-item">{.}<div class="reset-this">x</div></div>',
        '</tpl>',
    '</div>'
);
var fontTpl = new Ext.XTemplate(
    '<div class="font-panel">',
        '<tpl for=".">',
            '<div class="thumb-wrap">',
                '<div class="thumb-pinyin"></div>',
                '<div class="thumb-font">{.}</div>',
            '</div>',
        '</tpl>',
        '<div style="clear: both"></div>',
    '</div>'
);

Ext.define('xjcms.view.util.Pinyin', {
    extend: 'Ext.window.Window',
    alias: 'widget.Pinyin',
    title: '生成拼音',
    requires: [
        'xjcms.view.util.pinyin.PinyinController',
        'xjcms.view.util.pinyin.PinyinModel'
    ],
    controller: {
        type: 'pinyin'
    },
    viewModel: 'pinyin',
    width: 600,
    minHeight: 320,
    layout: 'fit',
    scrollable: false,
    // 遮罩层
    modal: true,
    constrain: true,
    closable: true,
    autoDestroy: true,
    draggable: true,
    resizable: false,
    items: [{
        xtype: 'form',
        bodyPadding: '10 10 10 10',
        items: [{
            xtype: 'container',
            layout: 'hbox',
            items: [{
                xtype: 'textfield',
                fieldLabel: '文字',
                labelWidth: 60,
                width: 500,
                emptyText: '请输入文字',
                regex: /^([\u4e00-\u9fa5]+)/,
                regexText: '该输入框仅仅只支持输入汉字',
                value: ''
            }, {
                xtype: 'button',
                text: '生成拼音',
                handler: function () {
                    // word-lib/convert2Pinyin
                    var text = this.prev().getValue();
                    var vm = this.up('window').getViewModel();
                    var vmStores = vm.storeInfo;
                    var fontData = [];
                    text = Ext.util.Format.trim(text);
                    // 请求数据
                    Ext.Ajax.request({
                        url: 'https://easy-mock.com/mock/5ae02d829c4a407f53115d81/rms/py',
                        method: 'GET',
                        params: {
                            font: text
                        },
                        success: function (response, opts) {
                            var obj = Ext.decode(response.responseText);
                            // 中文字和拼音字母
                            var font = obj.data.font;
                            var py = obj.data.py;
                            vmStores['fontStore'] = Ext.create('Ext.data.Store', {
                                data: font
                            });
                            vmStores['pinyinStore'] = Ext.create('Ext.data.Store', {
                                data: py
                            });
                            vm.setStores(vmStores);
                        },
                        failure: function (response, opts) {
                            console.log('server-side failure with status code ' + response.status);
                        }
                    });
                }
            }]
        }, {
            xtype: 'dataview',
            tpl: pinyinTpl,
            itemSelector: 'div.pinyin-item',
            bind: {store: '{pinyinStore}'},
            listeners: {
                'refresh': function () {
                    var pinyins = Ext.select('.pinyin-item');
                    Ext.each(pinyins.elements, function (el) {
                        // 第一步,创建可拖动的元素
                        var dd = Ext.create('Ext.dd.DD', el, 'pyDDGroup', {
                            isTarget: false
                        });
                        Ext.apply(dd, overrides);
                    })
                }
            }
        }, {
            // 拼音的拖拽区域
            xtype: 'dataview',
            tpl: fontTpl,
            bind: {store: '{fontStore}'},
            itemSelector: 'div.thumb-wrap',
            emptyText: '<div class="font-none-data">暂时还没有任何文字哦</div>',
            listeners: {
                'refresh': function () {
                    var thumbWrap = Ext.select('.thumb-wrap');
                    // 第二步,创建可以用于接收的元素
                    Ext.each(thumbWrap.elements, function (el) {
                        var thumbWrapDDTarget = Ext.create('Ext.dd.DDTarget', el, 'pyDDGroup', {
                            ignoreSelf: false
                        });
                    })
                },
                'itemclick': function(thisViewObj, record, item, index, e, eOpts){
                    var clsName = e.target.className;
                    if(clsName === 'reset-this'){
                        // 移除这个元素
                        var pNode = e.target.parentNode;
                        // console.dir(pNode);
                        Ext.get('pinyin_panel').appendChild(pNode);
                    }
                }
            }
        }],
        buttons: [{
            xtype: 'button',
            text: '确定'
        }, {
            xtype: 'button',
            text: '取消',
            handler: function () {
                this.up('window').destroy();
            }
        }]
    }]
});

Sencha ExtJS 开发中一个比较多的功能就是在编辑某条数据列的时候如果有 datefield 控件时间无法加载入正确的栏目中。

1

而 textfield 控件则能够通过服务器端返回的数据正确加载到相应的控件中,通过官网的论坛给出的答案是:需要修改服务器端返回的时间格式


{
desc: "成功",
totalResult: 9,
items: [
	{
		userId: "null1383919764373",
		userAccount: "yz",
		userIcon: "",
		userMobile: "13888889991",
		userNick: "园长",
		userType: "3",
		regTime: "2013-11-08 22:09:24",
		updateTime: "2013-11-08 22:09:24",
		status: "0",
		point: 0,
		realName: "园长",
		email: "[email protected]",
		sex: "0",
		birthday: "2013-11-06 00:00:00",
		orgs: [{
			updateTime: "2013-11-08 22:09:24",
			status: "0"
		}]
	}
	...
Ext.getCmp('base_form').getForm().on({
        actioncomplete: function(form, action) {
            if (action.type === 'load') {
                if (action.result.success) {
                    //绑定开始时间
                    var date = new Date(action.result.data.regTime);
                    var edate = new Date(action.result.data.updateTime);
                    form.setValues({
                        regTime: Ext.Date.format(date,"Y-m-d"),
                        updateTime: Ext.Date.format(edate,"Y-m-d")
                    });
                }
            }
        }
    });

通过使用 Ext.Date.format(框架内置)方法格式化返回的时间格式就能够正常的把时间设置进入控件中。

话不多说,直接上图:

1

搜了一把皮肤制作,大多数都是英文文档,看了几遍差不多熟练了之后就把皮肤问题得以搞定,记录下来方便下次使用。

步骤:

1.?安装环境,JDK、ruby、compass、sass (JDK 通过下载安装,RUBY 通过下载安装- http://rubyinstaller.og ,sass 通过Ruby 中的 gem 能够自动安装)

2.?下载 SenchaCmd-3.1.2.342-windows.exe 、SenchaSDKTools-2.0.0-beta3-windows.exe (Linux 环境请自行下载安装包,配置PATH)

3. 环境搭建完毕之后,开始构建工程,使用命令
sencha –sdk /extjs的路径/ generate app 工程名 工程存放的路径
2

3

Continue reading

最近一直在使用Sencha进行前端开发,单独开一个帖子,用于常见问题的整理。会陆陆续续往里面添加一些内容,同时也希望能够帮助到大家。

ExtJS submit 提交导致 emptyText 提交进入表单:

win.form.submit({
     submitEmptyText: false,
     url : 'xxxxx',
     method : 'post'
});

ExtJS 限制text最大字符数。

{
	fieldLabel: '教育证号',
	name:"teacher.educationCardNo",
	emptyText:'请输入教育证号',
	enforceMaxLength:true,   //关键是这个
	maxLength:18,
	value:""
}

ExtJS Ajax 提交SESSION失效的问题。

1. 首先通过后端返回 session timeout 的 header 信息,再通过 response.getResponseHeader 来判断是否存在这样的信息来确定session是否失效,代码如下:

Ext.onReady(function(){
	//请求超时的处理开始
	Ext.Ajax.on('requestcomplete', checkUserSessionStatus, this);
	function checkUserSessionStatus(conn, response, options) {
	    var sessionStatus = response.getResponseHeader("sessionstatus");
	    if (typeof(sessionStatus) != "undefined") {
	        Ext.Msg.alert('提示', '会话超时,请重新登录!',
	        function(btn, text) {
	            if (btn == 'ok') {
	                var redirect = root_path;
	                window.location = redirect;
	            }
	        });
	    }
	};
......

Ajax 的提交失败问题。

Ext.Ajax.request 提交与 Ext.Form.panel 中的 submit 都是属于 Ajax 提交,但是前者判断返回不是由服务器端的 { success :false …} 来决定,而是通过返回的 responseText 中的返回值来判断, from 中的提交,可通过?failure 函数来判定。代码如下:Continue reading

优化了一下代码,结果如下。

调用:

<script type="text/javascript">
function aaa(){
	var student_panel = new WX.student.AddStudent({
		callback_fun:function(){
			alert("我是页面的方法");
		}
	}).show();
}
</script>

组件定义

Ext.define('WX.student.AddStudent', {
	
    extend: 'Ext.window.Window',

    modal:true,
    height: 585,
    width: 590,
    layout: {
        type: 'fit'
    },
    title: '新增学生',
    //用于组件函数回调
    callback_fun:function(){},
    initComponent: function() {
    	
        var me = this;
        
        Ext.applyIf(me, {
            items: [
                {
                    waitTitle: '加载中...',
                    items: [
                        ......
                    ],
                    buttons:[{
                    	text:'保存',
                    	scope:this,                  // <============== 关键参数 
                    	handler:function(){
                    		//DO SOMETHING...
                    		alert("组件的事件");
                    		this.callback_fun();
                    	}
                    }]
                }
            ]
        });
        me.callParent(arguments);
    }

});

工程里用到了Sencha ExtJs,因为特定的组件原因,导致很多组件得自己。组件定义完成之后的 Success_callback 因为之前没做过,所以这次把它记录下来方便以后查阅。直接上代码:

界面调用

<script type="text/javascript">
function aaa(){
	var student_panel = new WX.student.AddStudent({
		//传入回调函数,直接显示。
		callback_fun:function(){
			alert('我是界面的回调函数');
		}
	}).show();
}
</script>

组件部分代码

Ext.define('WX.student.AddStudent', {

    extend: 'Ext.window.Window',

    modal:true,
    height: 585,
    width: 684,
    layout: {
        type: 'fit'
    },
    title: '新增学生',
    bodyPadding:'10 10 10 10',
    //用于组件函数回调
    callback_fun:function(){},
    initComponent: function() {
        var me = this;
        ......
        // Panel 组件
        buttons:[{
                text:'保存',
                handler:function(){
                     //发送Ajax请求保存用户数据.

                    //调用STORE之后的自定义回调函数
                    this.callback_fun
                }
        }]
    }
.....

这里的做法有点类似Java的接口回调,在自定义模块中定义方法,提供按钮回调,界面初始化组件的时候用方法覆盖组件中的回调方法,达到回调的目的。

早就要传上了……

最近几天,服务商不知道怎么的.一直传不了..鄙视一个!!!!!

ExtJs 给我的感觉还是不错.相对jquery这样的东西来说,还确实适合mis的开发.语言结构都比较简练.赞一个……