[转帖]Mootools源码分析-34 -- Request.HTML
原帖地址:http://space.flash8.net/space/?uid-18713-action-viewspace-itemid-407193
原作者:我佛山人
//响应输出为HTML的Ajax请求类
Request.HTML = new Class({
//继承自Request类
Extends: Request,
options: {
//是否更新
update: false,
//是否解释执行字符脚本
evalscrīpts: true,
//是否过滤
filter: false
},
//处理HTML代码
processHTML: function(text) {
//如果请求为完整的HTML页
var match = text.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
//取<body>与</body>之间的字符
text = (match) ? match[1] : text;
//创建html的容器节点
var container = new Element('div');
//返回容器节点,先尝试使用XMLDOM解释HTML节点,失败的话直接设置innerHTML
return $try(function() {
//构造一个根节点,因为必须保证让XML片段有根节点
var root = '<root>' + text + '</root>', doc;
//IE的处理
if (Browser.Engine.trident) {
//使用ActiveX控件解释
doc = new ActiveXObject('Microsoft.XMLDOM');
//同步加载
doc.async = false;
doc.loadXML(root);
} else {
//使用标准DOM解释器解释
doc = new DOMParser().parseFromString(root, 'text/xml');
}
//取根节点句柄
root = doc.getElementsByTagName('root')[0];
//通过遍历节点,复制到container容器中
for (var i = 0, k = root.childNodes.length; i < k; i++) {
var child = Element.clone(root.childNodes[i], true, true);
if (child) container.grab(child);
}
return container;
//XMLDOM解释失败的话直接设置innerHTML
}) || container.set('html', text);
},
//请求成功,覆盖Request类的同名方法
success: function(text) {
var options = this.options, response = this.response;
//解释出脚本,之后剩下HTML
response.html = text.stripscrīpts(function(scrīpt) {
response.javascrīpt = scrīpt;
});
//处理HTML中的节点
var temp = this.processHTML(response.html);
//绑定节点到返回的对象
response.tree = temp.childNodes;
response.elements = temp.getElements('*');
//如果提供过滤标签名,过滤树节点
if (options.filter) response.tree = response.elements.filter(options.filter);
//如果指定需要更新的Element,将响应更新到Element
if (options.update) $(options.update).empty().adopt(response.tree);
//如果指定解释脚本
if (options.evalscrīpts) $exec(response.javascrīpt);
//调用父类方法,触发成功事件
this.onSuccess(response.tree, response.elements, response.html, response.javascrīpt);
}
});
//为Element添加load属性的setter和getter
Element.Properties.load = {
//setter
set: function(options) {
//从临时对象取Request.HTML
var load = this.retrieve('load');
//如果对象存在,取消(这里的send貌似是load的手误?)
if (load) send.cancel();
//缓存Request.HTML的配置参数
return this.eliminate('load').store('load:options', $extend({data: this, link: 'cancel', update: this, method: 'get'}, options));
},
//getter
get: function(options) {
//如果提供配置参数或者不存在缓存
if (options || ! this.retrieve('load')) {
//缓存配置参数
if (options || !this.retrieve('load:options')) this.set('load', options);
//缓存Request.HTML对象
this.store('load', new Request.HTML(this.retrieve('load:options')));
}
//返回缓存的Request.HTML对象
return this.retrieve('load');
}
};
//为Element增加load方法
Element.implement({
//加载远程页面节点到当前Element内
load: function() {
//上面的准备工作合取load能得到Request.HTML实例,然后发送
//注意Array.link的使用,使send的两个参数可以任意排列,并且可选
this.get('load').send(Array.link(arguments, {data: Object.type, url: String.type}));
return this;
}
});
Request.HTML = new Class({
//继承自Request类
Extends: Request,
options: {
//是否更新
update: false,
//是否解释执行字符脚本
evalscrīpts: true,
//是否过滤
filter: false
},
//处理HTML代码
processHTML: function(text) {
//如果请求为完整的HTML页
var match = text.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
//取<body>与</body>之间的字符
text = (match) ? match[1] : text;
//创建html的容器节点
var container = new Element('div');
//返回容器节点,先尝试使用XMLDOM解释HTML节点,失败的话直接设置innerHTML
return $try(function() {
//构造一个根节点,因为必须保证让XML片段有根节点
var root = '<root>' + text + '</root>', doc;
//IE的处理
if (Browser.Engine.trident) {
//使用ActiveX控件解释
doc = new ActiveXObject('Microsoft.XMLDOM');
//同步加载
doc.async = false;
doc.loadXML(root);
} else {
//使用标准DOM解释器解释
doc = new DOMParser().parseFromString(root, 'text/xml');
}
//取根节点句柄
root = doc.getElementsByTagName('root')[0];
//通过遍历节点,复制到container容器中
for (var i = 0, k = root.childNodes.length; i < k; i++) {
var child = Element.clone(root.childNodes[i], true, true);
if (child) container.grab(child);
}
return container;
//XMLDOM解释失败的话直接设置innerHTML
}) || container.set('html', text);
},
//请求成功,覆盖Request类的同名方法
success: function(text) {
var options = this.options, response = this.response;
//解释出脚本,之后剩下HTML
response.html = text.stripscrīpts(function(scrīpt) {
response.javascrīpt = scrīpt;
});
//处理HTML中的节点
var temp = this.processHTML(response.html);
//绑定节点到返回的对象
response.tree = temp.childNodes;
response.elements = temp.getElements('*');
//如果提供过滤标签名,过滤树节点
if (options.filter) response.tree = response.elements.filter(options.filter);
//如果指定需要更新的Element,将响应更新到Element
if (options.update) $(options.update).empty().adopt(response.tree);
//如果指定解释脚本
if (options.evalscrīpts) $exec(response.javascrīpt);
//调用父类方法,触发成功事件
this.onSuccess(response.tree, response.elements, response.html, response.javascrīpt);
}
});
//为Element添加load属性的setter和getter
Element.Properties.load = {
//setter
set: function(options) {
//从临时对象取Request.HTML
var load = this.retrieve('load');
//如果对象存在,取消(这里的send貌似是load的手误?)
if (load) send.cancel();
//缓存Request.HTML的配置参数
return this.eliminate('load').store('load:options', $extend({data: this, link: 'cancel', update: this, method: 'get'}, options));
},
//getter
get: function(options) {
//如果提供配置参数或者不存在缓存
if (options || ! this.retrieve('load')) {
//缓存配置参数
if (options || !this.retrieve('load:options')) this.set('load', options);
//缓存Request.HTML对象
this.store('load', new Request.HTML(this.retrieve('load:options')));
}
//返回缓存的Request.HTML对象
return this.retrieve('load');
}
};
//为Element增加load方法
Element.implement({
//加载远程页面节点到当前Element内
load: function() {
//上面的准备工作合取load能得到Request.HTML实例,然后发送
//注意Array.link的使用,使send的两个参数可以任意排列,并且可选
this.get('load').send(Array.link(arguments, {data: Object.type, url: String.type}));
return this;
}
});