DHTML时钟控制

分享于 

13分钟阅读

Web开发

  繁體

Sample Image - DHTMLDigitalClock.gif

介绍

这个小小的小部件作为一个简单的概念开始,并且被升级到最初期望的位置。 不要介意- 我学习了一个或者两个过程。 我想要动态更新一个DHTML时钟,但是一个将. NET DateTimeFormatInfo 格式的Pattern 作为参数,所以允许显示一些范围。 我还需要它在区域上独立,所以依赖开发人员来决定全球化设置。

服务器端

实际的网页控制很简单。 有 2个 public 属性,DateTimeFormat 是要分割到 datetime/text Pattern的字符串,Interval 是一个整数,表示在更新时钟之前等待的时间。 在内部,private 字符串 array DateTimeFormatArray 使用 DateTimeFormat 字符串,并使用方法 FormatPatternSplitter 对它的进行。

FormatPattern拆分器

FormatPatternSplitter 通过检查输入字符串是否是转义格式字符开始,如果它是:

if(s.Length==2)
{
 if(s.Substring(0,1)=="%")
 {
 return s.Substring(1,1).Split( );
 }
}

然后检查输入字符串是否为转义格式字符,如果是,则将它的转换为相应的格式 Pattern:

if(s.Length==1)
{
 DateTimeFormatInfo dtfi = new DateTimeFormatInfo();
 s = dtfi.GetAllDateTimePatterns(Convert.ToChar(s))[0];
 if(s.Length==0)
 {
 return s.Split( );
 }
}

现在,我们将格式模式和文本的结果字符串与这个正则表达式进行。 ( 正规表达式的black 艺术有时候比我还多。 如果有人能够想到一种更有效的执行这个方法的方法,我很有兴趣知道。

System.Text.RegularExpressions.Regex rgx = 
 new Regex(@"(?<dtf>(d{1,4})|(M{1,4})|(y{1,4})|(gg)" + 
 "|(h{1,2})|(H{1,2})|(m{1,2})|(s{1,2})|(f{1,7})|" + 
 "(t{1,2})|(z{1,3}))|(?<spc>(s+))|" + 
 "(?<spt>([^1]))");
System.Text.RegularExpressions.MatchCollection rgxMatches = rgx.Matches(s);

然后遍历 MATCHES 检查是否有任何字符被转义,并将结果添加到 ArrayList,然后 finally 返回结果 array。

foreach(Match rgxMatch in rgxMatches)
{
 match = rgxMatch.Value;
 if(match==@"")
 {
 if(backslashFlag)
 {
 formatPattern.Add(@"");
 }
 backslashFlag = true;
 }
 else {
 if(backslashFlag)
 {
 formatPattern.Add(@"" + match);
 }
 else {
 formatPattern.Add(match);
 }
 backslashFlag = false;
 }
 backslashFlag = (match==@"");
}return (string[])formatPattern.ToArray(System.Type.GetType("System.String"));

回到控件后,得到的字符串 array 会给出一些调整,以确保客户端JavaScript不会导致( 例如 )。 转义单个引号和反斜杠。

for(int i=0;i<dateTimeFormatArray.Length;i++)
{
 if((dateTimeFormatArray[i]!=null)&&(dateTimeFormatArray[i].IndexOf("'")==-1))
 {
 dateTimeFormatArray[i] = dateTimeFormatArray[i].Replace(@"", @"");
 }
}

重写 OnPreRender

我使用了 Riley JavaScript的Paul 来设置客户端代码,它看起来像这样:

#if DEBUGHYL.Utilities.Javascript.JavaScriptBuilder jsb = 
 new HYL.Utilities.Javascript.JavaScriptBuilder(true);#elseHYL.Utilities.Javascript.JavaScriptBuilder jsb = 
 new HYL.Utilities.Javascript.JavaScriptBuilder();#endifDateTimeFormatInfo dtfi = new DateTimeFormatInfo();
jsb.AddLine("var aDayNames =", 
 HYL.Utilities.Javascript.JavascriptUtilities.FormatAsArray(dtfi.DayNames), ";");
jsb.AddLine("var aMonthNames =", 
 HYL.Utilities.Javascript.JavascriptUtilities.FormatAsArray(dtfi.MonthNames), ";");
jsb.AddLine("var sAMDesignator = '", dtfi.AMDesignator, "';");
jsb.AddLine("var sPMDesignator = '", dtfi.PMDesignator, "';");
jsb.AddLine("var sEraName = '", 
 dtfi.GetEraName(dtfi.Calendar.GetEra(System.DateTime.Today)), "';");
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(jsb.ToString());
sb.Append("<SCRIPT language="'""javascript"' src='"clock.js"'></SCRIPT>");
this.Page.RegisterClientScriptBlock(pageJSKey, sb.ToString());

我肯定会推荐查看paul文章,它简化了在你的控制中编写客户端代码,因为你可能意识到可以快速地变成混乱的业务代码。 注意,在呈现时钟脚本文件之前,我们声明了特定于全球化的变量。 因为这个代码是使用 Page.RegisterClientScriptBlock 方法注册的,它确保它只在页面上出现一次。

重写渲染

然后呈现控件。 首先,将保存时钟的span 标记,我们用格式化的datetime字符串填充:

output.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
output.RenderBeginTag(HtmlTextWriterTag.Span);
output.Write("{0:" + this.DateTimeFormat + "}", DateTime.Now);
output.RenderEndTag();

然后,创建新的客户端 Clock 实例,传递控制属性 ClientID,这样控件可以识别为客户端代码,这样控件可以识别为客户端代码,而不包含任何数学级别,即 1秒,秒。

output.Write("<SCRIPT language="'""javascript"'><!--n");
output.Write("new Clock('");
output.Write(this.ClientID);
output.Write("', ");
output.Write(HYL.Utilities.Javascript.JavascriptUtilities.FormatAsArray(
 this.DateTimeFormatArray));
output.Write(", ");
output.Write(this.Interval.ToString());
output.Write(");");
output.Write("n//--></SCRIPT>");

现在需要做的是在你的web表单中包含一个引用:

<hyl:clockid="clock1"runat="server"DateTimeFormat="hello, the date is dd.MM.yyyy"></hyl:clock>

客户端

客户端对象有 2个方法。

Load 使用 window.setInterval 方法在每个 n 毫秒( 其中 n 是更新间隔属性) 中触发 Update 方法。

this.Load = function()
{
 setInterval('aClockCollection['+this.Index+'].Update()', this.Interval);
}

然后 Update 方法用 GetDateTime 函数的结果重写控件的内部 HTML。

this.Update = function()
{
 var el;
 if(document.getElementById)
 {
 el = document.getElementById(this.ReturnElement);
 el.innerHTML = ''; // Mac IE5.1+ bugfix by Richard Meijer el.innerHTML = GetDateTime(this.FormatPattern);
 }
 elseif(document.all)
 {
 el = document.all[this.ReturnElement];
 el.innerHTML = GetDateTime(this.FormatPattern);
 }
}

注意 relative的简洁性和优雅性当NN4完全被忽略时。"。 无论如何,GetDateTime 函数在当前时间创建用日期时间格式字符填充的array:

var d = now.getDate();
aFormatPattern['d'] = d;
aFormatPattern['dd'] = (d<=9)?'0'+d:d;var iDay = now.getDay();
aFormatPattern['ddd'] = aDayNames[iDay].substr(0,3);
aFormatPattern['dddd'] = aDayNames[iDay];var M = now.getMonth();
aFormatPattern['MMM'] = aMonthNames[M].substr(0,3);
aFormatPattern['MMMM'] = aMonthNames[M];
M++;
aFormatPattern['M'] = M;
aFormatPattern['MM'] = (M<=9)?'0'+M:M;var yyyy = now.getFullYear();
aFormatPattern['yyyy'] = yyyy;
aFormatPattern['yy'] = (''+yyyy).substring(2);
aFormatPattern['y'] = Math.abs(aFormatPattern['yy']);
aFormatPattern['g'] = sEraName;var H = now.getHours();
aFormatPattern['H'] = H;
aFormatPattern['HH'] = (H<=9)?'0'+H:H;var h = (H>12)?H-12:H;
aFormatPattern['h'] = h;
aFormatPattern['hh'] = (h<=9)?'0'+h:h;var m = now.getMinutes();
aFormatPattern['m'] = m;
aFormatPattern['mm'] = (m<=9)?'0'+m:m;var s = now.getSeconds();
aFormatPattern['s'] = s;
aFormatPattern['ss'] = (s<=9)?'0'+s:s;var f = now.getMilliseconds()+'000000';
aFormatPattern['f'] = f.substr(0,1);
aFormatPattern['ff'] = f.substr(0,2);
aFormatPattern['fff'] = f.substr(0,3);
aFormatPattern['ffff'] = f.substr(0,4);
aFormatPattern['fffff'] = f.substr(0,5);
aFormatPattern['ffffff'] = f.substr(0,6);
aFormatPattern['fffffff'] = f.substr(0,7);var tt = ((H>=0)&&(H<12))?sAMDesignator:sPMDesignator;
aFormatPattern['tt'] = tt;
aFormatPattern['t'] = tt.substr(0,1);var z = now.getISOTimezoneOffset();
aFormatPattern['z'] = z.substr(0,1)+(''+parseInt(z.substr(1,2)));
aFormatPattern['zz'] = z.substr(0,1)+(''+z.substr(1,2));
aFormatPattern['zzz'] = z;

注意,每个元素的索引是格式字符,这将使以后的事情变得更加容易。 另外,注意扩展本机 Date 对象Prototype的新 getISOTimezoneOffset 方法。 JavaScript方法 getTimezoneOffset 只是让我迷惑,似乎是有点 buggy,所以这个新方法返回了一个timezone偏移量,它与 with offset。 网络

function getISOTimezoneOffset()
{
 var dif = this.getHours()-this.getUTCHours();
 var hDif = Math.abs(dif);
 var m = this.getMinutes();
 var mUTC = this.getUTCMinutes();
 if(m!=mUTC&&mUTC<30&&dif<0){ hDif--; }
 if(m!=mUTC&&mUTC>30&&dif>0){ hDif--; }
 return(((dif<0)?'-':'+')+((hDif<10)?'0'+hDif:''+hDif)+':'+((m!=mUTC)?'30':'00'));
}
Date.prototype.getISOTimezoneOffset = getISOTimezoneOffset;

GetDateTime 函数采用时钟 Pattern 格式,因此我们现在需要做的就是循环使用 Pattern 格式的元素作为当前时间格式格式的索引,构建返回字符串的返回字符串如下:

var sBackslash = String.fromCharCode(92);for(i=0;i<_formatPattern.length;i++)
{
 if(_formatPattern[i].substr(0,1)==sBackslash)
 {
 sRetVal += _formatPattern[i].substring(1);
 }
 else {
 sPattern = aFormatPattern[_formatPattern[i]];
 if(typeof(sPattern)!='undefined')
 {
 sRetVal += sPattern;
 }
 else {
 sRetVal += _formatPattern[i];
 }
 }
}return sRetVal;

注意,如果输入字符已经被反斜杠转义,我们检查输入字符,如果它有。

剩下的工作就是在 onload 处理程序中初始化页面上的时钟:

var aClockCollection = new Array();function InitClocks()
{
 for(var clockCount=0;clockCount<aClockCollection.length;clockCount++)
 {
 aClockCollection[clockCount].Load();
 }
}
safeAddEventListener(window, 'load', InitClocks, false);

array aClockCollection 包含页面( 你可能已经注意到 Clock 对象中对它的引用) 上的所有时钟。 InitClocks 循环遍历这个 array 并调用每个函数的Load 方法。 函数 safeAddEventListener 只是用于触发方法的跨浏览器 包装器工具,它在源代码中。

摘要

就像我之前提到的,如果你想要的只是一个简单的时钟,但是我在其他几个项目中使用了 FormatPatternSplitter,那么完全过分了,我很喜欢它的简单。 NET格式的Pattern 模型,因此在所有方面都没有完全的损失。

褐色鼻子

这是我的第一篇文章,我在去年的文章中写了大量的和. NET 知识,这是我写的第一篇文章。

cheers!


控制  cloc  时钟  DHT  Dhtml  
相关文章