asfman
android developer
posts - 90,  comments - 213,  trackbacks - 0

肯定有这样子的需求:我们希望能用快捷键代替鼠标点击做一些事情,例如一个典型的应用就是论坛上常用的Ctrl + Enter 快捷发帖子。就以Ctrl+Enter快捷发帖子为例,实质上呢,就是通过js脚本,捕获系统的onkeyup事件,判断event.ctrlKey是否为true并且event.keyCode为13,如果满足这个条件,那么就调用按钮对象的click()方法,等同于用鼠标去点击按钮。写个简单的示例代码:

  <html>

 <head>

  <title> 快捷键提交示例代码 </title>
  <link rel="stylesheet" href='css/style.css' type="text/css">
  <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
  <meta name="author" content="宝玉" />

<script language="JavaScript" type="text/javascript">
<!--
// 快捷键响应
// targetObj: 目标对象,如果满足快捷键条件,触发目标对象的click事件
// ctrlKey: 是否按住了Ctrl组合键
// shiftKey: 是否按住了Shift组合键
// altKey: 是否按住了Alt组合键
// keycode: 按键对应的数值
function Hotkey(event, targetObj, ctrlKey, shiftKey, altKey, keycode)
{
 if (
  targetObj
  && event.ctrlKey == ctrlKey
  && event.shiftKey == shiftKey
  && event.altKey == altKey
  && event.keyCode == keycode
  )
  targetObj.click();
}

function fnKeyup(event)
{
 var b = document.getElementById("myButton");
 Hotkey(event, b, true, false, false, 13);
}

// 捕获系统的Keyup事件
// 如果是Mozilla系列浏览器
if (document.addEventListener)
 document.addEventListener("keyup",fnKeyup,true);
else
 document.attachEvent("onkeyup",fnKeyup);

//-->
</script>
 </head>
 
  <body>
<form method="get" action="no.aspx">
<input type="submit"  id="myButton"/>
Ctrl + Enter
</form>

  </body>
 
 </html>
 

上面的脚本可以方便的给指定的按钮加上快捷键。如果现在我们希望应用到我们的服务器端控件当中去,例如Button、Linkbutton、Hyperlink等,因为控件的ID各不相同,而且所对应的快捷键也各不相同,那么我们就需要写一个控件来给他们添加快捷键了。

想想这个控件需要哪些属性?
TargetControlID:string:既然是给其他控件绑定的,那么所要绑定的目标控件ID是少不了了,根据这个控件ID,我们才能确定一个控件,才能知道它输出时的客户端ID,才能根据客户端ID来在脚本里面确定这个对象。
CtrlKey:bool:判断是否用到Ctrl组合键
ShiftKey:bool:判断是否用到Shift组合键
AltKey:bool:判断是否用到Alt组合键
KeyCode:int:和DHTML里面的event.keyCode对应的,例如Enter的keyCode是13。(注:其实这个不是很友好,因为用的时候还要找一下键盘各个按键和keyCode的对应关系,如果结合一个快捷键设置的控件就比较完美了)
Text:string:可能顺便需要一点文字说明什么的

相对来说,这是一个比较简单的用户自定义控件应用,创建一个名字为HotKey的类,继承自System.Web.UI.Controls。根据目标控件ID查找控件对象:this.cachedTargetControl = this.NamingContainer.FindControl(this.TargetControlID);
根据上面属性,我们就可以生成相应的客户端脚本了,然后在重写控件的OnPreRender事件中使用RegisterClientScriptBlock方法输出脚本。

代码相对比较简单:

using System;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;

namespace CommunityServer.Controls
{
 /// <summary>
 /// hotkey
 /// author: dotey
 /// http://www.communityserver.cn
 /// </summary>
 public class Hotkey : Control
 {
  private static readonly String scriptKey = "CommunityServer.Controls.Hotkey";
  
  public Hotkey()
  {
  }

  protected override void OnPreRender(EventArgs e)
  {
   base.OnPreRender (e);

   string hotkeyFunctionScript = @"
<script>
function Hotkey(event, targetObj, ctrlKey, shiftKey, altKey, keycode)
{
 if (
  targetObj
  && event.ctrlKey == ctrlKey
  && event.shiftKey == shiftKey
  && event.altKey == altKey
  && event.keyCode == keycode
  )
  targetObj.click();
}
</script>
";

   if ( !Page.IsClientScriptBlockRegistered( scriptKey ) )
   {
    this.Page.RegisterClientScriptBlock( scriptKey, hotkeyFunctionScript );
   }

   string key = scriptKey + "-" + targetControl.ClientID;
   if ( targetControl != null && !Page.IsClientScriptBlockRegistered( key ) )
   {
    this.Page.RegisterClientScriptBlock( key, CreateScript() );
   }

  }

  protected override void Render(HtmlTextWriter writer)
  {
   base.Render (writer);
   writer.Write(this.Text);
  }

  /// <summary>
  /// 根据属性生成相关脚本
  /// </summary>
  /// <returns></returns>
  private string CreateScript()
  {
   if ( targetControl == null )
    return "";

   string functionName = string.Format("fn{0}Keyup", targetControl.ClientID);

   StringBuilder s = new StringBuilder();
   s.Append("<script>\n");
   s.AppendFormat("function {0}(event)\n", functionName);
   s.Append("{\n");
   s.AppendFormat("\tvar b = document.getElementById('{0}');\n", targetControl.ClientID);
   s.AppendFormat("\tHotkey(event, b, {0}, {1}, {2}, {3});\n",
    this.CtrlKey.ToString().ToLower(),
    this.ShiftKey.ToString().ToLower(),
    this.AltKey.ToString().ToLower(),
    this.KeyCode
    );
   s.Append("}\n");

   s.Append("if (document.addEventListener)\n");
   s.AppendFormat("\tdocument.addEventListener('keyup', {0}, true);\n", functionName);
   s.Append("else\n");
   s.AppendFormat("\tdocument.attachEvent('onkeyup', {0});\n", functionName);
   s.Append("</script>\n");

   return s.ToString();
  }


  /// <summary>
  /// 目标控件
  /// </summary>
  [
  Category("Behavior"),
  DefaultValue(""),
  ]
  public virtual String TargetControlID
  {
   get
   {
    object savedState = this.ViewState["TargetControlID"];
    if ( savedState != null )
    {
     return (String)savedState;
    }
    return "";
   }
   set
   {
    this.ViewState["TargetControlID"] = value;
    this.cachedTargetControl = null;
   }
  }

  /// <summary>
  /// 根据目标控件的ID来找目标控件对象
  /// </summary>
  private Control targetControl
  {
   get
   {
    if ( cachedTargetControl == null )
    {
     this.cachedTargetControl = this.NamingContainer.FindControl(this.TargetControlID);
    }
    return this.cachedTargetControl;
   }
  }
  private Control cachedTargetControl = null;

  /// <summary>
  /// 文字说明
  /// </summary>
  [
  System.ComponentModel.DefaultValue( "Caption" ),
  ]
  public virtual String Text
  {
   get
   {

    Object state = ViewState["Text"];
    if ( state != null )
    {
     return (String)state;
    }
    return "";
   }
   set
   {
    ViewState["Text"] = value;
   }
  }

  /// <summary>
  /// 和DHTML里面的event.keyCode对应的,例如Enter的keyCode是13。
  /// </summary>
  /// <remarks>
  /// 其实这个不是很友好,因为用的时候还要找一下键盘各个按键和keyCode的对应关系,如果结合一个快捷键设置的控件就比较完美了
  /// </remarks>
  public int KeyCode
  {
   get
   {
    int keyCode = 0;
    try
    {
     keyCode = Convert.ToInt32(ViewState["KeyCode"]);
    }
    catch{}

    return keyCode;
   }
   set
   {
    ViewState["KeyCode"] = value;
   }
  }

  /// <summary>
  /// 是否使用Alt复合键
  /// </summary>
  public bool AltKey
  {
   get
   {
    Object state = ViewState["AltKey"];
    if ( state != null )
    {
     return (Boolean)state;
    }
    return false;
   }
   set
   {
    ViewState["AltKey"] = value;
   }
  }

  /// <summary>
  /// 是否使用Shift复合键
  /// </summary>
  public bool ShiftKey
  {
   get
   {
    Object state = ViewState["ShiftKey"];
    if ( state != null )
    {
     return (Boolean)state;
    }
    return false;
   }
   set
   {
    ViewState["ShiftKey"] = value;
   }
  }

  /// <summary>
  /// 是否使用Ctrl复合键
  /// </summary>
  public bool CtrlKey
  {
   get
   {
    Object state = ViewState["CtrlKey"];
    if ( state != null )
    {
     return (Boolean)state;
    }
    return false;
   }
   set
   {
    ViewState["CtrlKey"] = value;
   }
  }

 }
}

最后,调用的时候就比较方便了:
和普通的自定义用户控件一样:
<asp:Button Runat="server" id="PostButton" CssClass="txt3"></asp:Button>
<cs:Hotkey runat="server" TargetControlID="PostButton" KeyCode="13" CtrlKey="True" Text="(Ctrl + Enter)"/>
完整的应用请参考CCS1.1(http://www.communityserver.cn/ )的代码。

posted on 2006-04-03 15:34 汪杰 阅读(180) 评论(0)  编辑 收藏 引用 所属分类: hengxing网站js
只有注册用户登录后才能发表评论。

<2024年5月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

常用链接

留言簿(15)

随笔分类(1)

随笔档案(90)

文章分类(727)

文章档案(712)

相册

收藏夹

http://blog.csdn.net/prodigynonsense

友情链接

最新随笔

搜索

  •  

积分与排名

  • 积分 - 459293
  • 排名 - 6

最新随笔

最新评论

阅读排行榜

评论排行榜