您的位置:首页 > 其它

让UpdatePanel支持文件上传(3):客户端组件

2007-04-06 10:10 393 查看
我们继续编写客户端的部分。
  我们的UpdatePanelIFrameExecutor继承了WebRequestExecutor,因此需要实现许多方法和属性。但是我们事实上不用完整地实现所有的成员,因为客户端的异步刷信机制只会访问其中的一部分。以下是异步刷信过程中会使用的成员列表,我们必须正确地实现它们:

get_started: 表示一个Executor是否已经开始 了。
get_responseAvailable: 表示一个请求是否成功。
get_timedOut: 表示一个请求是否超时。
get_aborted: 表示一个请求是否被取消了。
get_responseData: 获得文本形式的Response Body。
get_statusCode: 获得Response的状态代码
executeRequest: 执行一个请求。
abort: 停止正在运行的请求。

  UploadPanelIFrameExecutor依旧非常简单,只是定义了一些私有变量:
UpdatePanelIFrameExecutor构造函数
Jeffz.Web.UpdatePanelIFrameExecutor = function(sourceElement)
{
Jeffz.Web.UpdatePanelIFrameExecutor.initializeBase(this);
// for properties
this._started = false;
this._responseAvailable = false;
this._timedOut = false;
this._aborted = false;
this._responseData = null;
this._statusCode = null;

// the element initiated the async postback
this._sourceElement = sourceElement;
// the form in the page.
this._form = Sys.WebForms.PageRequestManager.getInstance()._form;
// the handler to execute when the page in iframe loaded.
this._iframeLoadCompleteHandler = Function.createDelegate(
this, this._iframeLoadComplete);
}


  当executeRequest方法被调用时,我们会准备一个隐藏的iframe和所有的附加的隐藏输入元素,并将form的target指向iframe。当然,其他一些工作也是必须的,例如准备一个衡量超时的计时器:
executeRequest方法
executeRequest : function()
{
// create an hidden iframe
this._iframe = this._createIFrame();

// all the additional hidden input elements
this._addAdditionalHiddenElements();

// point the form's target to the iframe
this._form.target = this._iframe.id;
this._form.encType = "multipart/form-data";

// set up the timeout counter.
var timeout = this._webRequest.get_timeout();
if (timeout > 0)
{
this._timer = window.setTimeout(
Function.createDelegate(this, this._onTimeout), timeout);
}

this._started = true;

// restore the status of the element after submitting the form
setTimeout(Function.createDelegate(this, this._restoreElements), 0);
// sumbit the form
this._form.submit();
},


  建立一个隐藏得iframe元素很简单,但是我们该创建哪些附加的隐藏输入元素呢?自然我们表示“异步回送”的自定义标记是其中之一,那么剩下的还需要哪些呢?似乎我们只能通过阅读PageRequestManager的代码来找到问题的答案。还好,似乎阅读下面的代码并不困难:
_onFormSubmit方法
function Sys$WebForms$PageRequestManager$_onFormSubmit(evt)
{
// ...

// Construct the form body
var formBody = new Sys.StringBuilder();
formBody.append(this._scriptManagerID + '=' + this._postBackSettings.panelID + '&');
var count = form.elements.length;
for (var i = 0; i < count; i++)
{
// ...
// Traverse the input elements to construct the form body
// ...
}
if (if._additionalInput)
{
formBody.append(this._additionalInput);
this._additionalInput = null;
}
var request = new Sys.Net.WebRequest();
// ...
// prepare the web request object
// ...
var handler = this._get_eventHandlerList().getHandler("initializeRequest");
if (handler)    {
var eventArgs = new Sys.WebForms.InitializeRequestEventArgs(
request, this._postBackSettings.sourceElement);
handler(this, eventArgs);
continueSubmit = !eventArgs.get_cancel();
}
// ...
this._request = request;
request.invoke();
// ...
}


  请注意红色部分的代码。可以发现有两种数据需要被添加为隐藏的输入元素。其一是ScriptManager相关的信息(第一部分的红色代码),其二则是变量“_additionalInput”的内容。我们很容易得到前者的值,但是后者的内容究竟是什么呢?我们继续阅读代码:
_onFormElementClick方法
function Sys$WebForms$PageRequestManager$_onFormElementClick(evt)
{
var element = evt.target;
if (element.disabled) {
return;
}
// Check if the element that was clicked on should cause an async postback
this._postBackSettings = this._getPostBackSettings(element, element.name);
if (element.name)
{
if (element.tagName === 'INPUT')
{
var type = element.type;
if (type === 'submit')
{
this._additionalInput =
element.name + '=' + encodeURIComponent(element.value);
}
else if (type === 'image')
{
var x = evt.offsetX;
var y = evt.offsetY;
this._additionalInput =
element.name + '.x=' + x + '&' + element.name + '.y=' + y;
}
}
else if ((element.tagName === 'BUTTON') &&
(element.name.length !== 0) && (element.type === 'submit'))
{
this._additionalInput = element.name + '=' + encodeURIComponent(element.value);
}
}
}


  _onFormElmentClick方法会在用户点击form中特定元素时执行。方法会提供变量“_additionalInput”的内容,然后紧接着,我们之前分析过的_onFormSubmit方法会被调用。现在我们就能够轻松地为form添加额外的隐藏输入元素了:
_addAdditionalHiddenElements方法
_addAdditionalHiddenElements : function()
{
var prm = Sys.WebForms.PageRequestManager.getInstance();

// clear the array of hidden input elements
this._hiddens = [];

// custom sign to indicate an async postback
this._addHiddenElement("__AjaxFileUploading__", "__IsInAjaxFileUploading__");
// the value related to the ScriptManager
this._addHiddenElement(prm._scriptManagerID, prm._postBackSettings.panelID);

// find the additional data
var additionalInput = null;
var element = this._sourceElement;
if (element.name)
{
var requestBody = this.get_webRequest().get_body();

if (element.tagName === 'INPUT')
{
var type = element.type;
if (type === 'submit')
{
var index = requestBody.lastIndexOf("&" + element.name + "=");
additionalInput = requestBody.substring(index + 1);
}
else if (type === 'image')
{
var index = requestBody.lastIndexOf("&" + element.name + ".x=");
additionalInput = requestBody.substring(index + 1);
}
}
else if ((element.tagName === 'BUTTON') &&
(element.name.length !== 0) && (element.type === 'submit'))
{
var index = requestBody.lastIndexOf("&" + element.name + "=");
additionalInput = requestBody.substring(index + 1);
}
}

// parse the additional data
if (additionalInput)
{
var inputArray = additionalInput.split("&");
for (var i = 0; i < inputArray.length; i++)
{
var nameValue = inputArray[i].split("=");
this._addHiddenElement(nameValue[0], decodeURIComponent(nameValue[1]));
}
}
},
_addHiddenElement : function(name, value)
{
var hidden = document.createElement("input");
hidden.name = name;
hidden.value = value;
hidden.type = "hidden";
this._form.appendChild(hidden);
Array.add(this._hiddens, hidden);
},


  除去附加的隐藏输入元素非常简单,不值一提。另外iframe在加载结束后的逻辑也很容易理解——不过解析内容的机制就另当别论了:
_iframeLoadComplete方法
_iframeLoadComplete : function()
{
var iframe = this._iframe;
delete this._iframe;

var responseText = null;
try
{
// ...
// retrieve the data we need
// ...

this._statusCode = 200;
this._responseAvailable = true;
}
catch (e)
{
this._statusCode = 500;
this._responseAvailable = false;
}

$removeHandler(iframe, "load", this._iframeLoadCompleteHandler);
iframe.parentNode.removeChild(iframe);
this._clearTimer();
this.get_webRequest().completed(Sys.EventArgs.Empty);
},


  我们已经快完成我们的项目了。:)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息