using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
public class LongExecutionSidekick
{
private Page _page = null;
public LongExecutionSidekick()
{
_page = HttpContext.Current.CurrentHandler as Page;
if (_page == null)
throw new ApplicationException(
"Only ASP.NET Page HttpHandler is supported!");
_page.ClientScript.RegisterClientScriptBlock(_page.GetType(),
"afalesk_script", @"
$(function() {
function show(evt, data) {
$('.afa-status-' + data.callerId).html(data.msg);
}
$('body').append('<iframe name=""afa_target"" style=""display:none"" />');
var $form = $('form:first');
$form.bind('afales.update afales.init afales.end', show);
function pack(callerId, msg) {
return { callerId:callerId, msg:msg };
}
$('input[data-caller-id]').click(function() {
if ($form.attr('target') != 'afa_target') {
$form.data('orig-target', $form.attr('target') || '_self');
$form.attr('target', 'afa_target');
}
var $btn = $(this);
$form.trigger('afales.init',
pack($btn.data('callerId'),
$btn.data('initMsg') || 'Start'));
setTimeout(function() {
$('input[data-caller-id]').attr('disabled', true);
}, 500);
});
window.afales_init = function(callerId, msg) {
$form.trigger('afales.init', pack(callerId, msg));
}
window.afales_restarget = function() {
$form.attr('target', $form.data('orig-target'));
}
window.afales_end = function(callerId, msg) {
$form.trigger('afales.end', pack(callerId, msg));
$('input[data-caller-id]').removeAttr('disabled');
}
window.afales_update = function(callerId, msg) {
$form.trigger('afales.update', pack(callerId, msg));
}
});", true);
}
public delegate void ReportProgress(string msg);
private void OutputScript(string script)
{
_page.Response.Write(
"<script type='text/javascript'>" + script + "</script>");
_page.Response.Flush();
}
private string GetMsgAttr(Button btn, string catg)
{
string key = "data-" + catg + "-msg";
if (btn.Attributes[key] == null)
return catg == "init" ? "Start" : "Done";
else return JSStringEscape(btn.Attributes[key], false);
}
public void Execute(Button btn, Action<ReportProgress> cb)
{
if (btn.Attributes["data-caller-id"] == null)
throw new ArgumentException("No data-caller-id attribute!");
string callerId = btn.Attributes["data-caller-id"];
_page.Response.Clear();
_page.Response.BufferOutput = false;
_page.Response.Write("<html><head><meta http-equiv=\"Content-Type\" " +
"content=\"text/html; charset=UTF-8\" /></head><body>");
OutputScript("parent.window.afales_restarget();");
ReportProgress updateProgress =
new ReportProgress(
(m) => OutputScript(string.Format(
"parent.window.afales_update('{0}', '{1}');",
callerId, JSStringEscape(m, false)))
);
cb(updateProgress);
OutputScript(string.Format(
"parent.window.afales_end('{0}', '{1}');",
callerId, GetMsgAttr(btn, "end")));
_page.Response.Write("</body></html>");
_page.Response.End();
}
private string JSStringEscape(string raw, bool inHtmlAttribute)
{
raw = raw.Replace("\r\n", "\\n").Replace("\r", "").Replace("\n", "\\n");
return inHtmlAttribute ? raw.Replace("\"", """).Replace("'", "\\'") :
raw = raw.Replace("'", "\\'").Replace("\"", "\\\"");
}
}