JS Framework 冲突检阅(FrameworkScanner)

Posted by totodo on February 1st, 2009

09年有个小弟问我:搞软件滴怎么才算强人? 我不知道怎么回答,因为我知道自己不是。

不过现在我知道怎么告诉他了,强人和普通差别就是: 普通人做一件事只解决一个问题,强人做一件事解决一堆问题!

强人Mats Bryntse 就干了这样一个事情, 他做了一个工具。

gloable pollution

http://mankz.com/code/GlobalCheck.htm

这个他能检测目前几乎所有我们经常接触到的JS Framework的 JS  和 CSS 冲突。冲突主要是使用了相同的 Global namespace。

他分析比较功能如下:

  • document
  • Element
  • Document
  • HTMLElement
  • HTMLDocument
  • CSS analysis
  • Analyze your own scripts

唯一遗憾的是,好像不能在IE下使用( Firefox和Chrome都可以,好在平时习惯用他们浏览网页)

在过去的项目中我也曾学人家用了一些JS 的Framwork,然而,由于实际情况的需要,会再后来做一些取舍和新的引入。 新引入的JS 混合使用会和过去的(因为过去在线用的代码的不会立即删除掉)产生冲突 ,一直想比较各类framework之间的冲突关系,然而这是一件非常浩大的工程, 一直都被这个问题困扰着。

不过有强人出现,现在似乎也清晰了不少。人总是踩着别人肩膀前进的嘛:)

ExtJS 设计模式 之一 :单例(singleton)

Posted by totodo on December 29th, 2007

ExtJS 设计模式 之一 (单例)

    Extjs 发展至今,传承了YUI的伟大精髓, YUI得到了Douglas Crockford(任职于 Yahoo! 的一名 JavaScript 传道者和架构师,他是全球最有造诣的 JavaScript 语言专家之一,Blog:http://www.crockford.com/) 大师的赞同,而ExtJS也是将YUI的模式脚本编程学习使用的淋漓尽致,并且还给它做了几套华丽的CSS嫁衣….,   而在ExtJS越发耀眼的同时,我等初学者在使用ExtJs的时候也是晕呼其呼。(好在2.0 推出之后,官方的文档,像雨后春笋一样,开始覆盖到方方面面。)

    其实,拨开ExtJS华丽的外衣,翻阅其体内精致的代码,不难发现一些我们耳熟能详的设计模式。

    在早期1.0,1.1的好多例子中,我们会看到这样风格的代码。

var Oo= function(){
  var x;
  var y;
  return{
  a:function(){
  ...
  },
  b:function(){
  ...
  }
  }
}();

咂一看,不是我们能理解的方式, function(){}(), 是何意?。

//()在这里,意味着方法已经执行,并且return里面的已经产生, 这样可能很难理解,那等同与执行 function oo(){},这样是否好理解些了?

BTW :这里要引入JavaScript的一个高级概念,“闭包”。(具体内容参考《JavaScript The Definitve Guid,5th Eddion》Section 8.8 –Function Scope and Closures ,也是被Douglas Crockford推荐的为数不多的两本书籍之一。), 当然不急着去翻,先把我的废话看完。

    好了,看这种使用别扭的使用方式, 而这种方式,在我们的页面,或者其他类中, 调用Oo的a方法的时候,形式如下

Ext.onReady(Oo.a);

对,正是这样的一种JS编程方式,被Douglas Crockford作为JS的一种单例的实现, 大师还把它叫做“Module Pattern”,

    好,如果我们不用所谓单例呢?, 就看看传统的对象方式,同学们肯定在Pototype盛行的时代,已经弄的一清二楚。

0o = function(){
  this.x;
  this.y;
}
Oo.prototype = {
  a:function(){
  this.x = 100;
  },
  b:function(){
  this.y = 200;
  }
}
//调用方式
Ext.onReady(function(){
  var o = new Oo();
  0.a();
});

    再来,假使是个初学者,不知道对象继承,怎么办。更土的写法,人人都会。

var x,y
function a(){
  x=100;
}
function b(){
  y=200;
}

调用方式。
不用说了,只要a(),就会把x设置, 全世界的开发者都公认 ,全局变量是邪恶的,,而且随着你调用的不注意,将会越来越臃肿,导致Memory Lacks 内存泄露。

    以上几个简单的举例可以看出, 类 比Java 一样, Oo.a直接调用,好比一个静态类,直接访问。 而prototype需要创建对象后访问其成员。
第一种方式,在任何地方都不需要创建(只创建一次),
而第二种方式,需要在每次调用的时候,创建对象。
第三种老土的代码,希望大家尽量少写,这不是程序员风格的体现。

   对于发展到今天,如此庞大的ExtJS2.0,自然也要考虑道自己的运行和调用不要让new 变得太臃肿,在ExtJS中我们发现, 在会被各个组件大量频繁调用到的一些工具类中,单例运用较为频繁。

  Ext 源码中,设计使用单利的代码片段。

//source/core/DomHelper.js
Ext.DomHelper= function() {
  //private attributes
  ..
  return{

}
}();

//source/core/DomQuery.js
Ext.DomQuery =fucntion(){

}();

后记: 由于JavaScript,具有prototype,call,apply来实现继承,面向对象来开发,又有闭包等特性来进行函数编程。有函数编程和面向对象的双重性质, 使得JavaScript格外的灵活,难以驽驾, 开发者选择多种风格来进行编码,在一个整体项目会容易会走向凌乱和灭亡。 这就更需要我们从大师的经验总结,以及ExtJS这种优秀的设计中,去体味学习,站在巨人的肩膀上前进…..

(另外值得一提出的,ExtJs必须要求你的页面为XHTML,当你在别的浏览器下跑的非常顺畅,而唯独IE下有那么点瑕疵(不是脚本报错的),你应当检查下你是否把你的页面定义成XHTML.)。

exjs dwr spring 强强联姻

Posted by admin on July 15th, 2007

ExtJs 在Web UI已经获得很大的殊荣,但单凭借它 Client UI 还无法霸占BS 那么丰富的应用。。他还要选择 一个Web层与后台一起来交互完成一个完美的系统。

Extjs的天生丽质的, 完美了融合JQuery,Prototype,YUI, 和她结合当然也需要出类拔萃,生出名门。 如果采用Java为开发主语言,那么 ExtJS + DWR + SPRING 算是门当户对。

可惜Extjs 的DataStore 的 prxy 并没有DWR一席,因为DWR返回的是Java对象与JSON非常像, 然而DWR 的在于它与Web远程Java方法的直接会话,因此有着非常灵活的一面。所以,有时候使用DWR对于J2EE来说,要更好于JSON,他做了JSON做不到事。

extjs官方论坛里已经有人编写了这样的扩展,后经人丰富,现在基本能满足要求了。
DWR扩展代码如下,创建 Ext.data.DWRProxy类。同样也继承Ext.data.DataProxy ,拿来show着解读一下。

//dwr.js

Ext.data.DWRProxy = function(dwrCall, pagingAndSort){
Ext.data.DWRProxy.superclass.constructor.call(this);
this.dwrCall = dwrCall;
//this.args = args;
this.pagingAndSort = (pagingAndSort!=undefined ? pagingAndSort : true);
};

Ext.extend(Ext.data.DWRProxy, Ext.data.DataProxy, {
load : function(params, reader, callback, scope, arg) {
if(this.fireEvent("beforeload", this, params) !== false) {
var sort;
if(params.sort && params.dir) sort = params.sort + ' ' + params.dir;
else sort = '';
var delegate = this.loadResponse.createDelegate(this, [reader, callback, scope, arg], 1);
var callParams = new Array();
if(arg.arg) {
callParams = arg.arg.slice();
}

if(this.pagingAndSort) {
callParams.push(params.start);
callParams.push(params.limit);
callParams.push(sort);
}

callParams.push(delegate);
this.dwrCall.apply(this, callParams);
} else {
callback.call(scope || this, null, arg, false);
}
},

loadResponse : function(listRange, reader, callback, scope, arg) {
var result;
try {
result = reader.read(listRange);
} catch(e) {
this.fireEvent("loadexception", this, null, response, e);
callback.call(scope, null, arg, false);
return;
}
callback.call(scope, result, arg, true);
},

update : function(dataSet){},

updateResponse : function(dataSet)
{}
});

Ext.data.ListRangeReader = function(meta, recordType){
Ext.data.ListRangeReader.superclass.constructor.call(this, meta, recordType);
this.recordType = recordType;
};
Ext.extend(Ext.data.ListRangeReader, Ext.data.DataReader, {
getJsonAccessor: function(){
var re = /[\[\.]/;
return function(expr) {
try {
return(re.test(expr))
? new Function("obj", "return obj." + expr)
: function(obj){
return obj[expr];
};
} catch(e){}
return Ext.emptyFn;
};
}(),

read : function(o){
var recordType = this.recordType, fields = recordType.prototype.fields;

//Generate extraction functions for the totalProperty, the root, the id, and for each field
if (!this.ef) {
if(this.meta.totalProperty) {
this.getTotal = this.getJsonAccessor(this.meta.totalProperty);
}

if(this.meta.successProperty) {
this.getSuccess = this.getJsonAccessor(this.meta.successProperty);
}

if (this.meta.id) {
var g = this.getJsonAccessor(this.meta.id);
this.getId = function(rec) {
var r = g(rec);
return (r === undefined || r === "") ? null : r;
};
} else {
this.getId = function(){return null;};
}
this.ef = [];
for(var i = 0; i < fields.length; i++){
f = fields.items[i];
var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
this.ef[i] = this.getJsonAccessor(map);
}
}

var records = [];
var root = o.data, c = root.length, totalRecords = c, success = true;

if(this.meta.totalProperty){
var v = parseInt(this.getTotal(o), 10);
if(!isNaN(v)){
totalRecords = v;
}
}

if(this.meta.successProperty){
var v = this.getSuccess(o);
if(v === false || v === 'false'){
success = false;
}
}

for(var i = 0; i < c; i++){
var n = root[i];
var values = {};
var id = this.getId(n);
for(var j = 0; j < fields.length; j++){
f = fields.items[j];
var v = this.ef[j](n);
values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue);
}
var record = new recordType(values, id);
records[i] = record;
}

return {
success : success,
records : records,
totalRecords : totalRecords
};
}
});

经过改造之后,那么DWR可以像JSON一样,返回的数据作为DataStore
代码片断

ds = new Ext.data.Store({
proxy: new Ext.data.DWRProxy(TodoService.getItems, true),
//TotoService.getItems dwr开放出来的Java获取数据方法
reader: new Ext.data.ListRangeReader(
{id:'id', totalProperty:'totalSize'}, recordType),
remoteSort: true
});

Spring实现了强大的管理了后台的JavaBean,干干净净的注入创建了每个对象, DWR天生又是支持Spring,无缝的讲Spring的后台Bean 发布到Web层作为JavaScript对象,和JavaScript方法。中途不需要人工干预写Servlet.

不多说了, 跑了下代码,通过,可以直接下载。
download/ext-dwr-spring.rar

Spket IDE, Ext开发人员的紫色匕首~

Posted by admin on July 14th, 2007

小巧的身躯,强大杀伤力,足以具备紫色装备的特点。

这款利器,专门为 使用 Ext, killer级的AjaxUI设计开发人员配备。

致命点. 体积小巧(3.5M),价格优惠(免费)

官方网站 : http://www.spket.com/

1. Ext 对象的自动完成

 

2. Ext 组件对象的查看

3. JavaScript Lib 对象的自动识别

4. JS文档的智能分析,阅读

Ext 解说(二)

Posted by admin on March 14th, 2007

关于YUI-EXT 变为 EXT的话题让人纷说已久,而又过了短短几日,EXT 又紧锣密鼓的发行了Alpha 3。<从YUI-EXT0.40 到 EXT1.0Alpha2,Jack向YUI挑战 ,EXT lib支持JQuery,可以完全可以独立于YUI了。不过这次,Jack似乎又一次开始新一轮的自我挑战。1.0Alpha3版本开始增加了Prototype 和ScriptAculous,真是让人迫不及待。

好,还是先看看 的例子。 这次不用帖代码了,官方出的指南已经很详细了。
教程:http://www.extjs.com/en/tutorial/introduction-ext

毕竟是个入门性的,要玩些花样还得看API (可惜JACK的API-DOC还没来得及更新到最新) 。

教程中:Grid实现


{

var myData = [

['Apple',29.89,0.24,0.81,'9/1 12:00am'],

['Ext',83.81,0.28,0.34,'9/12 12:00am'],

['Google',71.72,0.02,0.03,'10/1 12:00am'],

['Microsoft',52.55,0.01,0.02,'7/4 12:00am'],

['Yahoo!',29.01,0.42,1.47,'5/22 12:00am']

];

var ds = new Ext.data.Store({

proxy: new Ext.data.MemoryProxy(myData),

reader: new Ext.data.ArrayReader({id: 0}, [

{name: 'company'},

{name: 'price', type: 'float'},

{name: 'change', type: 'float'},

{name: 'pctChange', type: 'float'},

{name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}

])

});

ds.load();

var colModel = new Ext.grid.ColumnModel([

{header: "Company", width: 120, sortable: true, dataIndex: 'company'},

{header: "Price", width: 90, sortable: true, dataIndex: 'price'},

{header: "Change", width: 90, sortable: true, dataIndex: 'change'},

{header: "% Change", width: 90, sortable: true, dataIndex: 'pctChange'},

{header: "Last Updated", width: 120, sortable: true,

renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'}

]);

var grid = new Ext.grid.Grid('grid-example', {ds: ds, cm: colModel});

grid.render();

grid.getSelectionModel().selectFirstRow();

});

Grid变化很大,从这里可以看出它和0.33,0.40的差别了。整个数据的是通过DataStore对象来完成的,数据读取通过XXXReader完

成,(这里是ArrayReader,还有JsonReader,XHReader等)变单元格格式设置ColumnModel完成(任何数据源都一

样),较原来稍有清晰(不然Jack也不会花那么大力气去改了,但真正的出发点是否还有其他??)

那这里也可以很方便的通过通过reader来实现。其他什么超连接啊,input啊都可以那么做。

增加一个function


function renderCheckBox(id){

return String.format(' type="checkbox" id={0} );

// 然后,增加红色部分。这样就会下在 Company每列前面多了个CheckBox

colModel = new Ext.grid.ColumnModel([

{header: "Company", width: 120, sortable: true, dataIndex: 'company',renderer: renderCheckBox},

{header: "Price", width: 90, sortable: true, dataIndex: 'price'},

{header: "Change", width: 90, sortable: true, dataIndex: 'change'},

{header: "% Change", width: 90, sortable: true, dataIndex:

'pctChange'},{header: "Last Updated", width: 120, sortable: true,

renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex:

'lastChange'} ]);

另外我们还可能会用到分页(在官方的Example里面 可以看到例子)。在1.0中,Jack是努力简化了Grid的操作,这里对分页处理也比以前简单了。


var gridFoot = grid.getView().getFooterPanel(true);

var pagbar = new Ext.PagingToolbar(gridFoot, ds, {pageSize: 20});

pagbar.add('-', {pressed: true, enableToggle:true, text: 'Detailed

View',cls: 'x-btn-text-icon details', toggleHandler: toggleCheckBox

});

ds.load({params:{start:0, limit:20}});

可以在官方的例子中看到更详细的。

http://www.yui-ext.com/deploy/ext-1.0-alpha3/examples

如果再玩复杂一点就是一些自定的操作, grid.on的事件操作啊,通篇一律的JS回调操作。

数据更新采用 Ext.data.Connection(); 表单采用 = Ext.form; /

这样几本能完成一个企业级的Grid应用了,分页编辑,提交。 稍微酷一些可结合 GridEditor

Ext 的代码质量也非常不错,可惜大的方面玩玩能揣度个八九不离十,但真要西子到每个API如何使用,为什么这么写,光凭自己现在的JS水平,后面还有很长一段路….先扯到这继续关注。