prototype 源码解读的第二部分 - Ajax.js
/**
* 定义 Ajax 对象, 静态方法 getTransport 方法返回一个 XMLHttp 对象
*/
var Ajax = {
getTransport: function() {
return Try.these(
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
function() {return new ActiveXObject('Microsoft.XMLHTTP')},
function() {return new XMLHttpRequest()}
) || false;
},
emptyFunction: function() {}
}

/**
* 我以为此时的Ajax对象起到命名空间的作用。
* Ajax.Base 声明为一个基础对象类型
* 注意 Ajax.Base 并没有使用 Class.create() 的方式来创建,我想是因为作者并不希望 Ajax.Base 被库使用者实例化。
* 作者在其他对象类型的声明中,将会继承于它。
* 就好像 java 中的私有抽象类
*/
Ajax.Base = function() {};
Ajax.Base.prototype = {
/**
* extend (见prototype.js中的定义) 的用法真是让人耳目一新
* options 首先设置默认属性,然后再 extend 参数对象,那么参数对象中也有同名的属性,那么就覆盖默认属性值。
* 想想如果我写这样的实现,应该类似如下:
setOptions: function(options) {
this.options.methed = options.methed? options.methed : 'post';


.
}
我想很多时候,java 限制了 js 的创意。
*/
setOptions: function(options) {
this.options = {
method: 'post',
asynchronous: true,
parameters: ''
}.extend(options || {});
}
}


/**
* Ajax.Request 封装 XmlHttp
*/
Ajax.Request = Class.create();

/**
* 定义四种事件(状态), 参考http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/readystate_1.asp
*/
Ajax.Request.Events =
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];

/**
*
*/
Ajax.Request.prototype = (new Ajax.Base()).extend({
initialize: function(url, options) {
this.transport = Ajax.getTransport();
this.setOptions(options);
try {
if (this.options.method == 'get')
url += '?' + this.options.parameters + '&_=';
/**
* 此处好像强制使用了异步方式,而不是依照 this.options.asynchronous 的值
*/
this.transport.open(this.options.method, url, true);
/**
* 这里提供了 XmlHttp 传输过程中每个步骤的回调函数
*/
if (this.options.asynchronous) {
this.transport.onreadystatechange = this.onStateChange.bind(this);
setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
}
this.transport.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
this.transport.setRequestHeader('X-Prototype-Version', Prototype.Version);

if (this.options.method == 'post') {
this.transport.setRequestHeader('Connection', 'close');
this.transport.setRequestHeader('Content-type',
'application/x-www-form-urlencoded');
}
this.transport.send(this.options.method == 'post' ?
this.options.parameters + '&_=' : null);
} catch (e) {
}
},
onStateChange: function() {
var readyState = this.transport.readyState;
/**
* 如果不是 Loading 状态,就调用回调函数
*/
if (readyState != 1)
this.respondToReadyState(this.transport.readyState);
},
/**
* 回调函数定义在 this.options 属性中,比如:
var option = {
onLoaded : function(req) {
};


}
new Ajax.Request(url, option);
*/
respondToReadyState: function(readyState) {
var event = Ajax.Request.Events[readyState];
(this.options['on' + event] || Ajax.emptyFunction)(this.transport);
}
});

/**
* Ajax.Updater 用于绑定一个html元素与 XmlHttp调用的返回值。类似与 buffalo 的 bind。
* 如果 options 中有 insertion(from dom.js) 对象的话, insertion 能提供更多的插入控制。
*/
Ajax.Updater = Class.create();
Ajax.Updater.prototype = (new Ajax.Base()).extend({
initialize: function(container, url, options) {
this.container = $(container);
this.setOptions(options);
if (this.options.asynchronous) {
this.onComplete = this.options.onComplete;
this.options.onComplete = this.updateContent.bind(this);
}
this.request = new Ajax.Request(url, this.options);
if (!this.options.asynchronous)
this.updateContent();
},
updateContent: function() {
if (this.options.insertion) {
new this.options.insertion(this.container,
this.request.transport.responseText);
} else {
this.container.innerHTML = this.request.transport.responseText;
}

if (this.onComplete) {
setTimeout((function() {this.onComplete(this.request)}).bind(this), 10);
}
}
});
Ajax.js
/**
* 定义 Ajax 对象, 静态方法 getTransport 方法返回一个 XMLHttp 对象
*/
var Ajax = {
getTransport: function() {
return Try.these(
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
function() {return new ActiveXObject('Microsoft.XMLHTTP')},
function() {return new XMLHttpRequest()}
) || false;
},
emptyFunction: function() {}
}
/**
* 我以为此时的Ajax对象起到命名空间的作用。
* Ajax.Base 声明为一个基础对象类型
* 注意 Ajax.Base 并没有使用 Class.create() 的方式来创建,我想是因为作者并不希望 Ajax.Base 被库使用者实例化。
* 作者在其他对象类型的声明中,将会继承于它。
* 就好像 java 中的私有抽象类
*/
Ajax.Base = function() {};
Ajax.Base.prototype = {
/**
* extend (见prototype.js中的定义) 的用法真是让人耳目一新
* options 首先设置默认属性,然后再 extend 参数对象,那么参数对象中也有同名的属性,那么就覆盖默认属性值。
* 想想如果我写这样的实现,应该类似如下:
setOptions: function(options) {
this.options.methed = options.methed? options.methed : 'post';


.
}
我想很多时候,java 限制了 js 的创意。
*/
setOptions: function(options) {
this.options = {
method: 'post',
asynchronous: true,
parameters: ''
}.extend(options || {});
}
}

/**
* Ajax.Request 封装 XmlHttp
*/
Ajax.Request = Class.create();
/**
* 定义四种事件(状态), 参考http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/readystate_1.asp
*/
Ajax.Request.Events =
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
/**
*
*/
Ajax.Request.prototype = (new Ajax.Base()).extend({
initialize: function(url, options) {
this.transport = Ajax.getTransport();
this.setOptions(options);
try {
if (this.options.method == 'get')
url += '?' + this.options.parameters + '&_=';
/**
* 此处好像强制使用了异步方式,而不是依照 this.options.asynchronous 的值
*/
this.transport.open(this.options.method, url, true);
/**
* 这里提供了 XmlHttp 传输过程中每个步骤的回调函数
*/
if (this.options.asynchronous) {
this.transport.onreadystatechange = this.onStateChange.bind(this);
setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
}
this.transport.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
this.transport.setRequestHeader('X-Prototype-Version', Prototype.Version);
if (this.options.method == 'post') {
this.transport.setRequestHeader('Connection', 'close');
this.transport.setRequestHeader('Content-type',
'application/x-www-form-urlencoded');
}
this.transport.send(this.options.method == 'post' ?
this.options.parameters + '&_=' : null);
} catch (e) {
}
},
onStateChange: function() {
var readyState = this.transport.readyState;
/**
* 如果不是 Loading 状态,就调用回调函数
*/
if (readyState != 1)
this.respondToReadyState(this.transport.readyState);
},
/**
* 回调函数定义在 this.options 属性中,比如:
var option = {
onLoaded : function(req) {
};


}
new Ajax.Request(url, option);
*/
respondToReadyState: function(readyState) {
var event = Ajax.Request.Events[readyState];
(this.options['on' + event] || Ajax.emptyFunction)(this.transport);
}
});
/**
* Ajax.Updater 用于绑定一个html元素与 XmlHttp调用的返回值。类似与 buffalo 的 bind。
* 如果 options 中有 insertion(from dom.js) 对象的话, insertion 能提供更多的插入控制。
*/
Ajax.Updater = Class.create();
Ajax.Updater.prototype = (new Ajax.Base()).extend({
initialize: function(container, url, options) {
this.container = $(container);
this.setOptions(options);
if (this.options.asynchronous) {
this.onComplete = this.options.onComplete;
this.options.onComplete = this.updateContent.bind(this);
}
this.request = new Ajax.Request(url, this.options);
if (!this.options.asynchronous)
this.updateContent();
},
updateContent: function() {
if (this.options.insertion) {
new this.options.insertion(this.container,
this.request.transport.responseText);
} else {
this.container.innerHTML = this.request.transport.responseText;
}
if (this.onComplete) {
setTimeout((function() {this.onComplete(this.request)}).bind(this), 10);
}
}
});

getTransport:
浙公网安备 33010602011771号