소개
웹 애플리케이션의 양식 제출 프로세스 중에, 특히 제출 프로세스에 시간이 오래 걸릴 때 "잠시 기다려 주십시오" 메시지나 애니메이션 GIF 이미지를 표시하는 것이 유용한 경우가 많습니다. 저는 최근 내부 사용자가 웹 페이지를 통해 Excel 스프레드시트를 업로드하는 설문조사 제출 프로그램을 개발했습니다. 프로그램은 업로드된 스프레드시트 데이터를 데이터베이스에 삽입합니다. 이 과정은 몇 초밖에 걸리지 않지만, 비록 몇 초라고 해도 웹페이지 입장에서는 너무나 당연한 대기 과정이다. 프로그램을 테스트하는 동안 일부 사용자가 업로드 버튼을 반복적으로 클릭했습니다. 따라서 업로드가 진행 중임을 사람들에게 알리는 시각적 메시지를 제공하는 것이 유용합니다. 그리고 다중 클릭을 방지하기 위해 업로드 버튼을 동시에 숨깁니다. 여기에 소개된 컨트롤은 Button 컨트롤의 하위 클래스로, 클라이언트측 JavaScript 코드를 ASP.NET 서버 컨트롤에 캡슐화하여 편리한 기능을 제공하는 방법을 보여줍니다.
이를 수행하기 위한 많은 JavaScript 예제가 있지만 이러한 함수를 ASP.NET 컨트롤에 캡슐화하려고 할 때 몇 가지 문제를 발견했습니다. 먼저 javascript onclick 핸들러를 통해 버튼을 무효화하고 다른 텍스트로 바꾸려고 했습니다. 그러나 나는 그것이 asp.net 서버 측의 클릭 이벤트 기능을 방해하기 때문에 매우 까다롭다는 것을 알았습니다. 마침내 효과가 있었고 다양한 브라우저를 잘 지원한 것은 div 태그에 버튼을 렌더링하는 것이었습니다. div는 숨겨지고 asp.net의 클릭 이벤트를 방해할 수 있습니다.
컨트롤 사용
일반 버튼 컨트롤의 파생형인 PleaseWaitButton의 기능은 기본적으로 동일합니다. 세 가지 추가 속성을 사용하여 버튼을 클릭할 때 "잠시 기다려 주십시오" 메시지나 이미지 표시를 관리합니다.
잠시만 기다려주세요텍스트
이는 표시되는 클라이언트 측 텍스트 메시지이며, 있는 경우 버튼을 클릭할 때 버튼을 대체합니다.
잠시만 기다려주세요이미지
이는 표시되는 이미지 파일(예: 애니메이션 GIF 이미지)이며, 있는 경우 클릭할 때 버튼을 대체합니다. 이 속성은 <img> 태그의 src 속성이 됩니다.
잠시만 기다려주세요유형
PleaseWaitTypeEnum 열거형 값 중 하나: TextOnly, ImageOnly, TextThenImage 또는 ImageThenText. 메시지와 이미지의 레이아웃을 제어합니다.
다음은 PleaseWaitText 및 PleaseWaitImage가 설정된 PleastWaitButton을 보여주는 예제 .aspx 파일입니다.
<%@ 페이지 언어="C#" %>
<%@ TagPrefix="cc1" Namespace="JavaScriptControls" 등록
Assembly="PleaseWaitButton" %>
<script runat="서버">
개인 무효 PleaseWaitButton1_Click(개체 전송자, System.EventArgs e)
{
// 서버측 클릭 이벤트 핸들러;
// 시간이 오래 걸릴 수 있는 것을 시뮬레이션합니다.
// 파일 업로드나 시간이 많이 걸리는 서버 처리 등
DateTime dt = DateTime.Now.AddSeconds(5);
동안(DateTime.Now < dt)
{
// 아무것도 하지 않고 5초 동안 일시 정지합니다.
}
// 루프가 끝나면 성공 메시지가 표시됩니다.
// 제출 양식을 숨깁니다.
panelSuccess.Visible = true;
PleaseWaitButton1.Visible = false;
}
</script>
<html>
<머리>
<title>PleaseWaitButton 테스트 중</title>
</head>
<본문>
<form id="Form1" method="post" runat="서버">
<P>PleaseWaitButton 컨트롤을 테스트하는 중입니다.</p>
<cc1:PleaseWaitButton id="PleaseWaitButton1" runat="서버"
Text="시간이 많이 걸리는 프로세스를 시작하려면 나를 클릭하세요."
PleaseWaitText="잠시만 기다려주세요"
PleaseWaitImage="잠시만 기다려주세요.gif"
OnClick="PleaseWaitButton1_Click" />
<asp:패널 id="panelSuccess" runat="서버"
표시 = "거짓">
이 양식을 제출해 주셔서 감사합니다.
내가 봉사하는 즐거움을 누린 가장 멋진 사용자입니다.
아니, 정말로요. 물론 다른 사람들도 있었죠.
하지만 당신은 정말 혼자 수업을 듣고 있어요.
</asp:패널>
</form>
</body>
</html>
작동 방식
PleaseWaitButton 컨트롤은 <div> 태그 내에 표준 ASP.NET 버튼을 렌더링합니다. 또한 정보/이미지에 대해 빈 <div> 태그를 렌더링합니다. 버튼을 클릭하면 버튼 숨김과 정보 표시가 Javascript 기능에 의해 제어됩니다(아래 클라이언트 기능 참조). 편의를 위해 필요한 모든 자바스크립트 클라이언트 코드의 구현은 PleaseWaitButton 서버 컨트롤에 의해 처리됩니다.
PleaseWaitButton은 자체 자바스크립트 onclick 핸들러를 구현하므로 원래 onclick 핸들러를 보존하고 컨트롤이 일부 클라이언트측 유효성 검사 코드를 깔끔하게 실행할 수 있도록 몇 가지 추가 단계를 수행해야 합니다. 이 목표를 달성하기 위해 먼저 Button 기본 클래스를 문자열 버퍼로 복원한 다음 정의한 onclick 코드를 포함하도록 능숙하게 처리합니다.
보호된 재정의 무효 렌더링(HtmlTextWriter 출력)
{
// 버튼의 HTML을 출력합니다(속성 포함).
// 더미 HtmlTextWriter로
StringWriter sw = 새로운 StringWriter();
HtmlTextWriter wr = new HtmlTextWriter(sw);
베이스.렌더링(wr);
문자열 sButtonHtml = sw.ToString();
wr.Close();
sw.닫기();
// 이제 "onclick" 핸들러를 포함하도록 코드를 수정합니다.
// PleaseWait() 함수가 적절하게 호출됨
// 클라이언트 측 유효성 검사 후.
sButtonHtml = ModifyJavaScriptOnClick(sButtonHtml);
// 버튼을 렌더링하기 전에 빈 <div>를 출력합니다.
// 자바스크립트를 통해 클라이언트측에 채워질 것입니다.
// "잠시만 기다려주세요" 메시지와 함께"
출력.쓰기(string.Format("<div id='pleaseWaitButtonDiv2_{0}'>",
this.클라이언트ID));
output.Write("</div>");
// 자체 <div> 태그를 캡슐화하여 버튼을 렌더링합니다.
output.Write(string.Format("<div id='pleaseWaitButtonDiv_{0}'>",
this.클라이언트ID));
출력.쓰기(sButtonHtml);
출력.쓰기("</div>");
}
버튼을 문자열 버퍼로 줄이고 onclick 콘텐츠를 처리하는 이 기술은 확실히 해킹입니다. 그러나 이를 통해 상위 버튼 클래스에 표준 유효성 검사 코드를 구현한 다음 PleaseWait() Javascript 함수 호출을 구현할 수 있습니다. 이렇게 하지 않으면 부모 Button 클래스 속성의 렌더링을 완전히 재정의하지 않는 한 유효성 검사 코드 앞의 onclick 속성에서 PleaseWait() 함수 호출을 구현해야 합니다. 이렇게 하면 페이지에 입력 오류가 있어도 버튼이 숨겨지고 원하지 않는 "잠시 기다려주세요" 메시지가 표시되는 효과가 있습니다. 따라서 클라이언트 페이지 유효성 검사 후에 onclick 핸들러의 클라이언트 PleaseWait() 함수가 나타나도록 강제해야 합니다.
onclick 속성 수정은 ModifyJavaScriptOnClick() 함수에서 발생합니다. 이 함수는 버튼에 의해 렌더링된 HTML 문자열을 가져오고 onclick 속성이 있는지 확인합니다. 그렇다면 이 함수는 클라이언트 측 유효성 검사 코드가 사용되는지 확인합니다. 이 경우, 우리가 정의한 PleaseWait() 함수는 클라이언트가 확인한 부린 변수 Page_IsValid 바로 뒤에 기존 onclick 코드 끝 부분에 추가됩니다. 이 변수는 유효성 검사 컨트롤이 사용되는지 여부를 나타냅니다. Page_IsValid 값이 false이면 "잠시 기다려 주십시오."라는 메시지가 표시되지 않습니다. True인 경우 표시됩니다.
개인 문자열 ModifyJavaScriptOnClick(string sHtml)
{
// CodeProject 회원 KJELLSJ(Kjell-Sverre Jerijaervi)에게 감사드립니다.
// 버튼이 클라이언트 측 유효성 검사
문자열과 함께 작동할 수 있도록 하는 코드 아이디어 sReturn = "";
string sPleaseWaitCode = generatePleaseWaitJavascript();
// 기존 onclick 속성이 있습니까?
Regex rOnclick = new Regex("onclick="(?<onclick>[^"]*)");
mOnclick 일치 = rOnclick.Match(sHtml);
if(mOnclick.성공)
{
// 기존 onclick 속성이 있습니다.
// 클라이언트측인 경우 끝에 코드를 추가합니다.
// 유효성 검사가 렌더링되었습니다. 확인하세요.
// 페이지가 유효한지 확인합니다.
string sExisting = mOnclick.Groups["onclick"].Value;
문자열 sReplace = sExisting
+ (sExisting.Trim().EndsWith(";") ? "" : "; ");
if (IsValidatorIncludeScript() && this.CausesValidation)
{
// 페이지가 유효한지 확인하는 코드를 포함합니다.
문자열 sCode = "if (Page_IsValid) " + sPleaseWaitCode
+ " Page_IsValid를 반환합니다;";
// 기존 onclick 코드 끝에 코드를 추가합니다.
sReplace = sReplace + sCode;
}
또 다른
{
// 페이지가 유효한지 걱정하지 마세요.
sReplace = sReplace + sPleaseWaitCode;
}
// 이제 onclick 코드를 대체합니다.
sReplace = "onclick="" + sReplace;
sReturn = rOnclick.Replace(sHtml, sReplace);
}
또 다른
{
// 기존 onclick 속성이 없습니다.
// 우리 것을 추가
int i = sHtml.Trim().Length - 2;
string sInsert = " onclick="" + sPleaseWaitCode + "" ";
sReturn = sHtml.Insert(i, sInsert);
}
return sReturn;
}
IsValidatorIncludeScript()는 위의 검사를 사용하여 페이지에 등록된 asp.net 유효성 검사 컨트롤에 대한 표준 Javascript 코드 블록이 있는지 확인합니다. 다음은 간단한 방법을 사용하여 Page_IsValid와 같은 유효성 검사 코드 및 변수가 있는지 테스트합니다.
개인 부울 IsValidatorIncludeScript()
{
// 이 페이지에 자바스크립트가 등록되어 있으면 TRUE를 반환합니다.
// 클라이언트 측 유효성 검사를 위해 이 코드는 등록되지 않을 수 있습니다.
// ASP.NET이 자신이 생각하는 바를 감지한 경우(올바른 또는 잘못된)
// 하위 수준 브라우저입니다.
return this.Page.IsStartupScriptRegistered("ValidatorIncludeScript");
} 다음 generatePleaseWaitJavascript()는 onclick 속성에 포함된 PleaseWait() Javascript 함수를 구성합니다. 컨트롤의 속성을 검사하여 원하는 레이아웃을 결정할 수 있습니다.
개인 문자열 생성PleaseWaitJavascript()
{
// JavaScript "PleaseWait()" 함수 호출 생성
// onclick 이벤트 핸들러에 사용하기에 적합합니다
. string sMessage = "";
문자열 sText = _pleaseWaitText;
문자열 sImage = (_pleaseWaitImage != String.Empty
? 문자열.형식(
"<img src="{0}" align="absmiddle" alt="{1}"/>"
, _pleaseWaitImage, _pleaseWaitText )
: String.Empty);
// PleaseWaitType을 기반으로 레이아웃을 설정합니다.
스위치(_pleaseWaitType)
{
Case PleaseWaitTypeEnum.TextThenImage:
sMessage = sText + sImage;
부서지다;
Case PleaseWaitTypeEnum.ImageThenText:
sMessage = sImage + sText;
부서지다;
Case PleaseWaitTypeEnum.TextOnly:
sMessage = sText;
부서지다;
Case PleaseWaitTypeEnum.ImageOnly:
sMessage = s이미지;
부서지다;
}
// 최종 코드 청크를 반환합니다.
문자열 sCode = 문자열.형식(
"PleaseWait('PleaseWaitButtonDiv_{0}',
'PleaseWaitButtonDiv2_{1}', '{2}');"
, this.ClientID, this.ClientID, sMessage);
sCode = sCode.Replace(""", """);
return sCode;
}
PleaseWaitImage를 지정하는 경우 이미지를 미리 로드하도록 클라이언트에 알리는 추가 Javascript 코드를 포함해야 합니다. 이 스크립트의 등록은 재정의된 OnPreRender 메서드에 나타나야 합니다. 등록된 키는 이미지의 이름입니다. 여러 버튼이 동일한 이미지를 사용하는 경우 사전 로드 스크립트는 한 번만 구현하면 됩니다. 여기서는 특수 문자(예: 파일 경로의 슬래시)가 밑줄로 변환되도록 Javascript 이미지 변수를 생성하기 위해 정규식을 사용합니다.
보호된 재정의 무효 OnPreRender(EventArgs e)
{
base.OnPreRender (e);
// 이미지를 사용한다면 자바스크립트를 등록하세요.
// 클라이언트측 이미지 미리 로드용
if (_pleaseWaitImage != String.Empty
&& _pleaseWaitType != PleaseWaitTypeEnum.TextOnly)
RegisterJavascriptPreloadImage(_pleaseWaitImage);
}
개인 무효 RegisterJavascriptPreloadImage(문자열 sImage)
{
정규식 rex = new Regex("[^a-zA-Z0-9]");
string sImgName = "img_" + rex.Replace(sImage, "_")
StringBuilder sb = new StringBuilder();
sb.Append("<script 언어='JavaScript'>");
sb.Append("if (document.images) { ");
sb.AppendFormat("{0} = new Image();", sImgName);
sb.AppendFormat("{0}.src = "{1}";", sImgName, sImage);
sb.Append(" } ");
sb.Append("</script>");
this.Page.RegisterClientScriptBlock(sImgName + "_PreloadScript",
sb.ToString());
}
클라이언트 측 기능
포함된 텍스트 파일인 javascript.txt에는 버튼을 숨기는 <div>와 "잠시 기다려 주십시오" 메시지나 이미지를 표시하는 클라이언트 측 코드가 포함되어 있습니다. 이러한 코드는 재정의된 OnInit() 메서드에서 호출되는 전용 메서드 RegisterJavascriptFromResource()에 로드됩니다. 이 메서드는 파일을 소스로 로드하고 콘텐츠를 문자열로 반환하는 일반 메서드 GetEmbeddedTextFile()을 호출합니다.
보호된 재정의 void OnInit(EventArgs e)
{
base.OnInit(e);
// 클라이언트 측 자바스크립트 코드가 유지됩니다.
// 포함된 리소스에서 스크립트를 로드합니다.
// 페이지에 등록합니다.
RegisterJavascriptFromResource();
}
개인 무효 RegisterJavascriptFromResource()
{
// 삽입된 텍스트 파일 "javascript.txt"를 로드합니다.
// 그 내용을 클라이언트측 스크립트로 등록합니다.
string sScript = GetEmbeddedTextFile("javascript.txt");
this.Page.RegisterClientScriptBlock("PleaseWaitButtonScript", sScript);
}
개인 문자열 GetEmbeddedTextFile(string sTextFile)
{
// 내용을 검색하는 일반 함수
// 포함된 텍스트 파일 리소스를 문자열로
// 실행 중인 어셈블리를 가져오고 파생시킵니다.
// 어셈블리의 첫 번째 유형을 사용하는 네임스페이스
어셈블리 a = Assembly.GetExecutingAssembly();
String sNamespace = a.GetTypes()[0].Namespace;
// 어셈블리와 네임스페이스를 사용하여
//리소스를 스트림으로 삽입
스트림 s = a.GetManifestResourceStream(
string.Format("{0}.{1}", sNamespace, sTextFile)
);
// 스트림의 내용을 문자열로 읽어옵니다.
StreamReader sr = 새로운 StreamReader;
문자열 sContents = sr.ReadToEnd()
;
s.Close();
sContents를 반환합니다.
}
javascript.txt 내장 리소스에는 버튼의 Javascript onclick 핸들러에서 실행되는 클라이언트측 메서드 PleaseWait()가 포함되어 있습니다. 또한 이 코드는 클라이언트 측 메서드 HideDiv()를 호출하여 버튼의 컨테이너 <div>를 숨긴 다음 innerHTML 속성을 설정하여 이전에 비어 있던 <div> 태그에 정보나 이미지를 조합합니다. 보조 함수 GetDiv()는 document.getElementById, document.all 및 document.layers를 확인하여 ID가 있는 <div> 객체를 반환하여 다양한 브라우저와의 호환성을 보장합니다. 다음은 javascript.txt의 전체 코드입니다.
<스크립트 언어="자바스크립트">
함수 GetDiv(sDiv)
{
바르디브;
if(document.getElementById)
div = document.getElementById(sDiv);
else if (document.all)
div = eval("window." + sDiv);
그렇지 않은 경우(document.layers)
div = document.layers[sDiv];
또 다른
div = null을
반환;
}
함수 HideDiv(sDiv)
{
d = GetDiv(sDiv);
만약(디)
{
if (document.layers) d.visibility = "hide";
else d.style.visibility = "숨김";
}
}
함수 PleaseWait(sDivButton, sDivMessage, sInnerHtml)
{
HideDiv(sDivButton);
var d = GetDiv(sDivMessage);
if (d) d.innerHTML = sInnerHtml;
}
</script>
원본 링크: http://www.codeproject.com/aspnet/PleaseWaitButton.asp
소스 프로젝트 다운로드 - 7Kb
데모 프로젝트 다운로드 - 30Kb
http://www.cnblogs.com/jeffamy/archive/2006/08/20/481952.html