<body>
<div>状态:</div>
<form action="http://cloudgamer.cnblogs.com/" target="ifr">
</form>
</body>
<script>
var msg = document.getElementById("msg");
var iframe = document.createElement("iframe");
iframe.name = "ifr";
iframe.onload = function(){ msg.innerHTML += "onload,"; }
document.body.appendChild(iframe);
msg.innerHTML += "submit,";
document.forms[0].submit();
</script>
ie和ff显示submit,onload,safari和chrome显示的是onload,submit,onload,跟上面的分析一致。
而opera却显示submit,onload,onload,两次onload都是在submit之后触发的。
这个情况就不能单纯用_sending来解决了。
是不是submit不能使iframe取消加载呢?
在appendChild之前设一个src,结果正常的只触发onload一次,看来是可以的啊。
虽然不知道原因,办法还是有的,一个是appendChild前设一个src,还可以在第一次onload中重新设置onload,像程序那样。
但这两个方法都存在不确定性,不能完全解决问题,但也找不到更好的方法了。
ff的onload还有一个问题,在出现ERROR_INTERNET_CONNECTION_RESET(文件大小超过服务器限制)之类的服务器错误时,即使加载完成也不会触发onload,暂时找不到解决办法。
iframe有一个缺陷是只能用onload判断加载完成,但没有办法判断是否加载成功。
没有类似XMLHTTP的status的东西,遇上404之类的错误也没办法判别出来。
在使用时要做好这方面的处理,例如说明允许上传文件大小,超时时间,如何处理长时间无响应等。
【form】
程序使用_setForm函数来创建用来提交数据的form。
要实现无刷新上传,要对form进行特殊的处理:
复制代码 代码如下:
$$.extend(form, {
target: this._iframe.name, method: "post", encoding: "multipart/form-data"
});
ps:详细看这里的无刷新上传部分。
由于form是手动插入的,为了不影响原来页面布局还要设置一下form样式,使它“隐形”起来:
复制代码 代码如下:
$$D.setStyle(form, {
padding: 0, margin: 0, border: 0,
backgroundColor: "transparent", display: "inline"
});
还要注意的是,同一个表单控件只能对应一个form。
如果file控件本身已经有一个form的话,必须在提交前移除:
file.form && $$E.addEvent(file.form, "submit", $$F.bind(this.dispose, this));
dispose方法是用来销毁程序的,包括移除form。
ps:如果提交前submit被覆盖的话要手动执行一次dispose方法。
最后把form插入到dom:
file.parentNode.insertBefore(form, file).appendChild(file);
先把form插入到file控件之前,然后把file插入到form,这样就能保证file在原来的位置上了。
【input】
如果有其他参数要传递,程序会使用_setInput函数来创建传递数据的表单控件。
由于生成的form里面只有file控件,要传递其他参数只能用程序生成了。
程序用一个_inputs集合来保存当前在form中生成的表单控件。
首先根据自定义的parameter属性创建表单控件:
复制代码 代码如下:
for ( name in this.parameter ) {
var input = form[name];
if ( !input ) {
input = document.createElement("input");
input.name = name; input.type = "hidden";
form.appendChild(input);
}
input.value = this.parameter[name];
newInputs[name] = input;
delete oldInputs[name];
}
当form中没有对应name的控件时,会自动生成一个hidden控件插入到form中。
其中newInputs是用来记录当前生成的控件的,而oldInputs就是_inputs集合。
当设置过对应name的控件后,就从oldInputs中删除对应控件的关联。
然后移除oldInputs关联的控件:
for ( name in oldInputs ) { form.removeChild( oldInputs[name] ); }
这样就能移除上一次生成的无用的控件了。
最后重新记录当前控件到_inputs方便下次使用。
【stop】
如果想停止当前上传操作,可以调用stop方法。
一般来说当iframe发生重载时,会取消上一次的载入,那么只要重新设置src就能取消上传了。
测试以下代码:
复制代码 代码如下:
<body>
<iframe></iframe>
<form action="http://cloudgamer.cnblogs.com/" target="ifr">
</form>
</body>
<script>
document.forms[0].submit();
document.getElementById("ifr").src = "";
</script>
结果都能取消加载,除了opera,未知什么原因。
有两个方法解决,一个是通过form随便用一个action提交一次,还有就是直接移除iframe。
后一个方法比较方便,程序中用_removeIframe方法直接移除iframe。
ps:有更好方法的话记得告诉我。
【dispose】
当使用结束或其他原因要销毁程序时,可以调用dispose方法。
dispose里面主要做的是移除iframe和form。
移除iframe用的是_removeIframe方法,首先把onload移除,再把iframe从body移除:
var iframe = this._iframe;
$$B.ie ? iframe.detachEvent( "onload", this._fFINISH ) : ( iframe.onload = null );
document.body.removeChild(iframe); this._iframe = null;
十分简单,但在ff有一个问题,测试以下代码:
复制代码 代码如下: