[转帖]Mootools源码分析-27 -- Swiff
原帖地址:http://space.flash8.net/space/?uid-18713-action-viewspace-itemid-404749
原作者:我佛山人
/*
SWFObject的流行,得益于微软在IE中加了控件激活设置(目前已经去掉限制)
而通过调用外部脚本生成插入Flash的HTML,却能避开激活限制。
通过使用SWFObject,插入Flash已经变得很简单
而moo的Swiff的创意来自SWFObject,正如moo来源于Prototype
通过Swiff类,可以学到封装UI组件,需要提供的基本方法:
1.事件支持(本例使用callback而不是Events的实现,一般情况下使用Events类的接口实现)
2.配置可选项(Options类setOptions的接口实现)
3.将组件添加到DOM中的方法
4.提供UI组件中重要HTML Element的引用
至于如何使用Swiff类,可以看moo的官方Swiff教程
*/
var Swiff = new Class({
//setOptions接口实现,因为本类的特殊性,没有使用Events的事件接口实现
Implements: [Options],
options: {
id: null, //生成object/embed的id
height: 1, //高度
width: 1, //宽度
container: null, //容器
properties: {}, //属性集
params: { //参数集
quality: 'high', //播放质量
allowscrīptAccess: 'always',
wMode: 'transparent', //透明模式
swLiveConnect: true //是否启动Java,以支持fscommand
},
callBacks: {}, //回调方法集
vars: {} //变量集
},
//获取指向的HTML Element对象
toElement: function() {
return this.object;
},
/*
path为swf文件路径
*/
initialize: function(path, options) {
//生成唯一实例名
this.instance = 'Swiff_' + $time();
this.setOptions(options);
options = this.options;
//得到唯一id
var id = this.id = options.id || this.instance;
//容器
var container = $(options.container);
//使用唯一实例名初始化当前对象的回调方法集
Swiff.CallBacks[this.instance] = {};
var params = options.params, vars = options.vars, callBacks = options.callBacks;
var properties = $extend({height: options.height, width: options.width}, options.properties);
//声明局部变量,用于下面的闭包中的引用
var self = this;
//复制回调方法
for (var callBack in callBacks) {
Swiff.CallBacks[this.instance][callBack] = (function(option) {
return function() {
return option.apply(self.object, arguments);
};
})(callBacks[callBack]);
//最终通过flashVars参数传给swf
vars[callBack] = 'Swiff.CallBacks.' + this.instance + '.' + callBack;
}
params.flashVars = Hash.toQueryString(vars);
//IE使用classid,其它浏览器声明contentType,注意文件路径对应的属性
if (Browser.Engine.trident) {
properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
params.movie = path;
} else {
properties.type = 'application/x-shockwave-flash';
properties.data = path;
}
/*
字符串拼接出最终输出的HTML代码
如果要考虑效率,这里应该用数组,否则使用字符串的substitute方法会更优雅
*/
var build = '<object id="' + id + '"';
//遍历拼接属性
for (var property in properties) build += ' ' + property + '="' + properties[property] + '"';
build += '>';
//遍历拼接参数
for (var param in params) {
if (params[param]) build += '<param name="' + param + '" value="' + params[param] + '" />';
}
build += '</object>';
//因为属性和参数太多,如果直接new Element的话会比较烦琐,所以直接new一个临时的div,设置其HTML再返回子节点
this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild;
},
//将当前对象替换element,也许是为了避免模块间藕合太过,所以没有直接使用Element的replaces方法
replaces: function(element) {
element = $(element, true);
element.parentNode.replaceChild(this.toElement(), element);
return this;
},
//附加到element中,这里也没有直接使用Element的inject方法
inject: function(element) {
$(element, true).appendChild(this.toElement());
return this;
},
//方法调用
remote: function() {
return Swiff.remote.apply(Swiff, [this.toElement()].extend(arguments));
}
});
//回调方法集
Swiff.CallBacks = {};
//swf到js的方法调用
Swiff.remote = function(obj, fn) {
var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascrīpt">' + __flash__argumentsToXML(arguments, 2) + '</invoke>');
return eval(rs);
};
SWFObject的流行,得益于微软在IE中加了控件激活设置(目前已经去掉限制)
而通过调用外部脚本生成插入Flash的HTML,却能避开激活限制。
通过使用SWFObject,插入Flash已经变得很简单
而moo的Swiff的创意来自SWFObject,正如moo来源于Prototype
通过Swiff类,可以学到封装UI组件,需要提供的基本方法:
1.事件支持(本例使用callback而不是Events的实现,一般情况下使用Events类的接口实现)
2.配置可选项(Options类setOptions的接口实现)
3.将组件添加到DOM中的方法
4.提供UI组件中重要HTML Element的引用
至于如何使用Swiff类,可以看moo的官方Swiff教程
*/
var Swiff = new Class({
//setOptions接口实现,因为本类的特殊性,没有使用Events的事件接口实现
Implements: [Options],
options: {
id: null, //生成object/embed的id
height: 1, //高度
width: 1, //宽度
container: null, //容器
properties: {}, //属性集
params: { //参数集
quality: 'high', //播放质量
allowscrīptAccess: 'always',
wMode: 'transparent', //透明模式
swLiveConnect: true //是否启动Java,以支持fscommand
},
callBacks: {}, //回调方法集
vars: {} //变量集
},
//获取指向的HTML Element对象
toElement: function() {
return this.object;
},
/*
path为swf文件路径
*/
initialize: function(path, options) {
//生成唯一实例名
this.instance = 'Swiff_' + $time();
this.setOptions(options);
options = this.options;
//得到唯一id
var id = this.id = options.id || this.instance;
//容器
var container = $(options.container);
//使用唯一实例名初始化当前对象的回调方法集
Swiff.CallBacks[this.instance] = {};
var params = options.params, vars = options.vars, callBacks = options.callBacks;
var properties = $extend({height: options.height, width: options.width}, options.properties);
//声明局部变量,用于下面的闭包中的引用
var self = this;
//复制回调方法
for (var callBack in callBacks) {
Swiff.CallBacks[this.instance][callBack] = (function(option) {
return function() {
return option.apply(self.object, arguments);
};
})(callBacks[callBack]);
//最终通过flashVars参数传给swf
vars[callBack] = 'Swiff.CallBacks.' + this.instance + '.' + callBack;
}
params.flashVars = Hash.toQueryString(vars);
//IE使用classid,其它浏览器声明contentType,注意文件路径对应的属性
if (Browser.Engine.trident) {
properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
params.movie = path;
} else {
properties.type = 'application/x-shockwave-flash';
properties.data = path;
}
/*
字符串拼接出最终输出的HTML代码
如果要考虑效率,这里应该用数组,否则使用字符串的substitute方法会更优雅
*/
var build = '<object id="' + id + '"';
//遍历拼接属性
for (var property in properties) build += ' ' + property + '="' + properties[property] + '"';
build += '>';
//遍历拼接参数
for (var param in params) {
if (params[param]) build += '<param name="' + param + '" value="' + params[param] + '" />';
}
build += '</object>';
//因为属性和参数太多,如果直接new Element的话会比较烦琐,所以直接new一个临时的div,设置其HTML再返回子节点
this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild;
},
//将当前对象替换element,也许是为了避免模块间藕合太过,所以没有直接使用Element的replaces方法
replaces: function(element) {
element = $(element, true);
element.parentNode.replaceChild(this.toElement(), element);
return this;
},
//附加到element中,这里也没有直接使用Element的inject方法
inject: function(element) {
$(element, true).appendChild(this.toElement());
return this;
},
//方法调用
remote: function() {
return Swiff.remote.apply(Swiff, [this.toElement()].extend(arguments));
}
});
//回调方法集
Swiff.CallBacks = {};
//swf到js的方法调用
Swiff.remote = function(obj, fn) {
var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascrīpt">' + __flash__argumentsToXML(arguments, 2) + '</invoke>');
return eval(rs);
};