ASP.NET 开发者 JavaScript 技巧 - 第一部分






4.48/5 (20投票s)
2007 年 9 月 3 日
7分钟阅读

81396

461
ASP.NET 开发者 JavaScript 技巧
引言
本文是为 ASP.NET 开发者提供 JavaScript 技巧的系列文章的第一部分。您也可以阅读第二部分。
背景
毫无疑问,ASP.NET 服务器控件让您在服务器端的工作变得轻松。像 Karamasoft UISuite™ 这样的第三方组件让服务器端和客户端的工作都变得轻松得多。但是,您可能仍然需要一些客户端编程知识,才能为您的网站访问者提供强大的用户界面。
JavaScript 是最常用的客户端编程语言,无论您的服务器端开发环境如何。尽管本文可能适用于其他语言和框架,但它更适合 ASP.NET 开发者,因为大多数技巧都附有 ASPX 和 C# 的示例代码。
使用代码
-
用一个简单的方法获取 DOM 元素
-
添加/删除事件处理程序
-
查看页面当前的 HTML 状态
-
点击后禁用按钮,以防止后续回发到服务器
-
使用对深度嵌套对象的引用
-
创建自己的水印文本框
-
将窗口居中显示在屏幕上
-
验证文本区域的最大字符长度
-
在页面关闭前显示确认信息
-
格式化数字
-
11. 在客户端交换表格行
1. 用一个简单的方法获取 DOM 元素
document 对象有一个跨浏览器的 getElementById 方法,它
返回对具有指定 ID 属性值的对象的引用。Prototype
JavaScript 框架 (http://www.prototypejs.org) 提供了一个方便的 JavaScript
具有短名称的方法来返回 DOM 元素
function $() {
var elements = new Array();
for (var i = 0; i < arguments.length; i++) {
var element = arguments[i];
if (typeof element == 'string')
element = document.getElementById(element);
if (arguments.length == 1)
return element;
elements.push(element);
}
return elements;
}
这个方法的一个优点是你可以传递一个参数或多个
参数。如果传递一个参数,它将返回对具有指定 ID 值的对象的引用。
指定 ID 值。否则,它将返回一个对象引用数组,其中包含
指定的 ID 值。这个方法的另一个优点是它接受对象作为参数,以及
以及字符串作为参数。
而不是以下内容
var elem = document.getElementById('TextBox1');
您现在可以按如下方式调用 $ 方法
var elem = $('TextBox1');
或者您可以通过一个简单的方法调用返回多个 DOM 元素
var elemArr = $('TextBox1', 'TextBox2');
2. 添加/删除事件处理程序
您可以轻松地将函数绑定/解绑到事件,以便在
事件在对象上触发时调用。
Internet Explorer DOM(文档对象模型)提供 attachEvent 和
detachEvent 方法,而 Mozilla DOM 提供 addEventListener 和
removeEventListener 方法来添加/删除事件处理程序。
您可以使用以下跨浏览器 JavaScript 方法来添加/删除您的事件
handlers
function AddEventHandler(obj, eventName, functionNotify) { if (obj.attachEvent) { obj.attachEvent('on' + eventName, functionNotify); } else if (obj.addEventListener) { obj.addEventListener(eventName, functionNotify, true); } else { obj['on' + eventName] = functionNotify; } }
function RemoveEventHandler(obj, eventName, functionNotify) { if (obj.detachEvent) { obj.detachEvent('on' + eventName, functionNotify); } else if (obj.removeEventListener) { obj.removeEventListener(eventName, functionNotify, true); } else { obj['on' + eventName] = null; } }
您可以按如下方式调用上述方法
JavaScript
function AddKeyDownEventHandler(obj) { AddEventHandler(obj, 'keydown', KeyDownEventHandler); }
function KeyDownEventHandler(evnt) { alert('Event key code: ' + GetEventKeyCode(evnt)); }
function GetEventKeyCode(evnt) { return evnt.keyCode ? evnt.keyCode : evnt.charCode ? evnt.charCode : evnt.which ? evnt.which : void 0; }
function BodyOnloadHandler() { AddKeyDownEventHandler(document.getElementById('<%=txtKeyDown.ClientID%>')); }
ASPX
<body onload="BodyOnloadHandler()"> <asp:TextBox ID="txtKeyDown" runat="server" CssClass="TextBox"></asp:TextBox>
3. 查看页面当前的 HTML 状态
当您在浏览器中查看源代码时,它会显示页面加载时的状态。
页面加载。但是,当您的页面中有动态内容时,尤其是在
AJAX 环境中,您可能需要查看页面的当前源代码。
在地址栏中输入以下内容并按回车。
Internet Explorer
javascript:'<xmp>'+window.document.body.outerHTML+'</xmp>'
Firefox
javascript:'<xmp>'+document.getElementsByTagName('html')[0].innerHTML+'</xmp>'
或者您可以将这两个合并为一个 JavaScript 语句,使其跨浏览器
javascript:'<xmp>'+((document.all) ? window.document.body.outerHTML : document.getElementsByTagName('html')[0].innerHTML)+'</xmp>'
4. 点击后禁用按钮,以防止后续回发到服务器
作为开发人员,您可能永远不会双击提交按钮,但您的网站用户
可能会这样做,并两次执行提交按钮代码。他们也可能会在
仍在进行中时多次点击。如果您在按钮点击处理程序上运行数据库操作或发送电子邮件,
双击可能会在您的系统中产生不必要的结果。
即使您没有做任何关键的事情,它也会用不必要的调用使您的服务器超载。
调用。
为了防止后续回发到服务器,一旦用户点击提交按钮,
您可以在 onclick 事件处理程序中禁用它并更改其文本,如下所示
JavaScript
function DisableButton(buttonElem) { buttonElem.value = 'Please Wait...'; buttonElem.disabled = true; }
ASPX
<asp:button id="btnSubmit" runat="server" Text="Submit" />
C#
protected void Page_Load(object sender, EventArgs e) { btnSubmit.Attributes.Add("onclick", "DisableButton(this);" + Page.ClientScript.GetPostBackEventReference(this, btnSubmit.ID.ToString())); }
5. 使用对深度嵌套对象的引用
JavaScript 对象可以使用点运算符嵌套,如下所示
tableElem.rows[0].cells[0]
如果您对上述结构进行多次操作,最好定义一个变量来引用它,因为每个点运算符都会导致一次操作来检索该属性。例如,如果您需要在 for 循环中处理表格单元格,请定义一个局部变量来引用单元格集合,并改用它,如下所示
var cellsColl = tableElem.rows[0].cells; for (var i = 0; i < cellsColl.length; i++) { cellsColl[i].style.backgroundColor = '#FF0000'; }
尽管上述代码通过局部变量引用了单元格集合,但它仍在循环的每一步中检查单元格集合的 length 属性。因此,
最好将 cellsColl.length 属性存储在一个局部变量中,一次性获取其值,如下所示
for (var i = 0, loopCnt = cellsColl.length; i < loopCnt; i++)
6. 创建自己的水印文本框
水印的主要目的是在不使页面混乱的情况下向用户提供有关文本框的信息。您可能已经在网站的搜索文本框中看到过许多此类示例。当水印文本框为空时,它会向用户显示一条消息。一旦用户在文本框中输入一些文本,水印文本就会消失。当用户离开文本框时,如果文本框的内容为空,水印文本会再次出现。
您可以通过添加 onfocus 和 onblur 事件处理程序轻松地将文本框更改为提供水印行为。在焦点事件中,如果文本框的文本与水印文本匹配,则清除文本框。在模糊事件中,如果文本框为空,则将文本重新设置为水印文本。
JavaScript
function WatermarkFocus(txtElem, strWatermark) { if (txtElem.value == strWatermark) txtElem.value = ''; }
function WatermarkBlur(txtElem, strWatermark) { if (txtElem.value == '') txtElem.value = strWatermark; }
ASPX
<asp:TextBox ID="txtWatermark" runat="server" />
C#
protected void Page_Load(object sender, EventArgs e) { string strWatermark = "Search Karamasoft.com"; txtWatermark.Text = strWatermark; txtWatermark.Attributes.Add("onfocus", "WatermarkFocus(this, '" + strWatermark + "');"); txtWatermark.Attributes.Add("onblur", "WatermarkBlur(this, '" + strWatermark + "');"); }
7. 将窗口居中显示在屏幕上
您可以使用 window.open 方法打开的窗口居中显示在屏幕上。Internet Explorer 和 Mozilla DOM 都提供 window.screen 对象,该对象具有 availWidth 和 availHeight 属性,用于检索系统屏幕工作区域的宽度和高度。您需要做的就是获取屏幕宽度(或高度)值与窗口宽度(或高度)值之间的差值,并将其除以 2。
由于您可能希望此功能可重用,因此您可以创建一个包装方法来调用 window.open 方法,替换其 features 参数,该参数包含宽度和高度等属性。您可以解析 features 参数值中的宽度和高度属性,并找到适当的 left 和 top 值以使窗口居中,然后将 left 和 top 属性附加到 features 参数值。
features 参数通常如下所示
'width=400,height=300,location=no,menubar=no,resizable=no,scrollbars=no,status=yes,toolbars=no'
首先,我们需要创建一个方法来解析 features 字符串中的宽度和高度值。由于我们可能希望将此方法用于其他目的,以分割名称/值对,例如解析查询字符串以查找查询字符串值,因此我们将其设为一个通用方法。
function GetAttributeValue(attribList, attribName, firstDelim, secondDelim) { var attribNameLowerCase = attribName.toLowerCase(); if (attribList) { var attribArr = attribList.split(firstDelim); for (var i = 0, loopCnt = attribArr.length; i < loopCnt; i++) { var nameValueArr = attribArr[i].split(secondDelim); for (var j = 0, loopCnt2 = nameValueArr.length; j < loopCnt2; j++) { if (nameValueArr[0].toLowerCase().replace(/\s/g, '') == attribNameLowerCase && loopCnt2 > 1) { return nameValueArr[1]; } } } } }
此方法接受三个参数:名称/值对列表、要检索其值的属性名称、第一个分隔符和第二个分隔符。在这种情况下,第一个分隔符将是逗号,第二个分隔符将是等号。为了解析查询字符串变量,第一个分隔符将是和号,第二个分隔符将是等号。
然后定义检索可用屏幕宽度和高度值的方法。
function GetScreenWidth() {
return window.screen.availWidth;
}
function GetScreenHeight() {
return window.screen.availHeight;
}
我们现在可以使用这些方法创建我们的 window.open 包装方法来居中窗口。
function WindowOpenHelper(sURL, sName, sFeatures, centerWindow) { var windowLeft = ''; var windowTop = ''; if (centerWindow) { var windowWidth = GetAttributeValue(sFeatures, 'width', ',', '='); windowLeft = (typeof(windowWidth) != 'undefined') ? ',left=' + ((GetScreenWidth() - windowWidth) / 2) : ''; var windowHeight = GetAttributeValue(sFeatures, 'height', ',', '='); windowTop = (typeof(windowHeight) != 'undefined') ? ',top=' + ((GetScreenHeight() - windowHeight) / 2) : ''; } window.open(sURL, sName, sFeatures + windowLeft + windowTop); }
此方法接受四个参数:要显示的文档的 URL、窗口的名称、功能项列表以及一个布尔值,指示窗口是否应居中。
您现在可以在页面中调用 WindowOpenHelper 方法。
JavaScript
function OpenWindowCentered(windowWidth, windowHeight) { WindowOpenHelper('http://www.karamasoft.com', 'WindowCentered', 'width=400,height=300,location=no,menubar=no, resizable=no,scrollbars=no,status=yes,toolbars=no', true); }
ASPX
<asp:LinkButton ID="lbOpenWindowCentered" runat="server" OnClientClick="OpenWindowCentered(); return false;">Open window centered</asp:LinkButton>
8. 验证文本区域的最大字符长度
HTML input type 为 text 的元素提供了一个内置的 MaxLength 属性来设置用户可以输入的最大字符数。但是,TextArea 元素没有这样的属性来限制可以输入的字符数。当您的网页中有一个 TextMode="MultiLine" 的 ASP.NET TextBox 控件时,它会被渲染为 HTML TextArea 元素,并且您不能使用 MaxLength 属性来设置最大字符数。
您可以做的是为 TextBox 控件定义一个 keypress 事件处理程序,以检查文本区域内文本的长度,并在达到 MaxLength 时取消该事件。
JavaScript
function ValidateMaxLength(evnt, str, maxLength) { var evntKeyCode = GetEventKeyCode(evnt); // Ignore keys such as Delete, Backspace, Shift, Ctrl, // Alt, Insert, Delete, Home, End, // Page Up, Page Down and arrow keys var escChars = ",8,17,18,19,33,34,35,36,37,38,39,40,45,46,"; if (escChars.indexOf(',' + evntKeyCode + ',') == -1) { if (str.length >= maxLength) { alert("You cannot enter more than " + maxLength + "characters."); return false; } } return true; }
ASPX
<asp:TextBox ID="txtValidateMaxLength" runat="server" TextMode="MultiLine" />
C#
protected void Page_Load(object sender, EventArgs e) { txtValidateMaxLength.Attributes.Add("onkeypress", "return ValidateMaxLength((window.event) ? window.event : arguments[0], this.value, 5)"); }
9. 在页面关闭前显示确认信息
如果您需要在用户关闭窗口之前显示确认信息,可以使用 window 对象的 beforeunload 事件来显示确认消息。
JavaScript
function AddUnloadHandler() { AddEventHandler(window, 'beforeunload', HandleUnload); }
function HandleUnload() { var strConfirm = 'Please make sure you saved your changes before closing the page.'; if (document.all) { window.event.returnValue = strConfirm; } else { alert(strConfirm); var evnt = arguments[0]; evnt.stopPropagation(); evnt.preventDefault(); } }
ASPX
<body onload="AddUnloadHandler()">
10. 格式化数字
您可以使用以下方法来格式化您的数字或货币值。它接受四个参数:要格式化的数字、小数位数、一个布尔值指示是否应追加零,以及一个布尔值指示是否应插入逗号以分隔千位。
function FormatNumber(num, decimalPlaces, appendZeros, insertCommas) { var powerOfTen = Math.pow(10, decimalPlaces); var num = Math.round(num * powerOfTen) / powerOfTen; if (!appendZeros && !insertCommas) { return num; } else { var strNum = num.toString(); var posDecimal = strNum.indexOf("."); if (appendZeros) { var zeroToAppendCnt = 0; if (posDecimal < 0) { strNum += "."; zeroToAppendCnt = decimalPlaces; } else { zeroToAppendCnt = decimalPlaces - (strNum.length - posDecimal - 1); } for (var i = 0; i < zeroToAppendCnt; i++) { strNum += "0"; } } if (insertCommas && (Math.abs(num) >= 1000)) { var i = strNum.indexOf("."); if (i < 0) { i = strNum.length; } i -= 3; while (i >= 1) { strNum = strNum.substring(0, i) + ',' + strNum.substring(i, strNum.length); i -= 3; } } return strNum; } }
11. 在客户端交换表格行
您可以通过交换当前行和要交换行的单元格内容来在客户端交换表格行。以下方法接受三个参数:当前表格行元素、一个布尔值指示行是否应向上移动,以及一个布尔值指示是否应忽略第一行。
function SwapRows(rowElem, dirUp, ignoreFirstRow) { var rowElemToSwap = (dirUp) ? rowElem.previousSibling : rowElem.nextSibling; // Firefox returns a blank text node for the sibling while (rowElemToSwap && rowElemToSwap.nodeType != 1) { rowElemToSwap = (dirUp) ? rowElemToSwap.previousSibling : rowElemToSwap.nextSibling; } if (rowElemToSwap && !(ignoreFirstRow && rowElemToSwap.rowIndex == 0)) { var rowCells = rowElem.cells; var colInner; for (var i = 0, loopCnt = rowCells.length; i < loopCnt; i++) { colInner = rowCells[i].innerHTML; rowCells[i].innerHTML = rowElemToSwap.cells[i].innerHTML; rowElemToSwap.cells[i].innerHTML = colInner; } } }