`

js实现鼠标右键菜单及淡入淡出消息窗口

    博客分类:
  • web
 
阅读更多

js学习笔记。

鼠标右键菜单和消息窗口是由div+css样式组成,由js控制生成。不足之处在于宽度写死,如果大家有什么好的做法或者想法,或者在网上看到的好的例子,好的想法,都可以拿出来大家讨论。内容不多为了方便阅读,我将所有的代码都放在了一个html里面,包括css样式和js脚本。

遇到的一些问题和值得讨的地方都写在注释里头,在这里就不再说了。

代码在IE8, Firefox12.0, Chrome20.0.1132.5测试通过,但是不同的浏览器显示的有些许不同。

请指教!

 

<html>
  <head>
    <title>鼠标右键菜单及淡入淡出消息窗口测试</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    
    <style stype="text/css">
        body{
            text-align:center; /* 此设置只在IE中起效,在chrome20.0.1132.57里不能居中,只好使用<center>标签*/
        }
        
        /*鼠标右键菜单样式,主要样式如下
          菜单宽度200px,高度自适应,浮动,默认隐藏,包含菜单项;
          菜单项宽度100%,高度20px,包含图标、菜单名、右侧HTML元素;
          菜单项图标宽度40px,高度100%,左侧浮动;
          菜单名宽度130px,高度100%,距左40px;
          右侧HTML宽度30px,高度100%,右侧浮动,距左170px
        */
        .menu{
            background-color:#c0c0c0;
            border:1px solid #888888;
            border-bottom:0px;
            position:absolute;
            width:200px;
            height:auto;
            display:none;
            text-align:left;
            padding:0px;
        }
        .menuItem{
            border-bottom:1px solid #888888;
            width:100%;
            height:20px;
            padding:0px;
            margin:0px;
        }
        .menuItemOnMouseOver{
            background:green;
        }
        .menuItemIcon{
            position:absolute;
            width:40px;
            height:100%;
            text-align:center;
            padding:0px;
            margin:0px;
        }
        .menuItemName{
            position:absolute;
            width:130px;
            height:100%;
            margin-left:40px;
            padding-left:2px;
            text-align:left;
        }
        .menuItemRight{
            position:absolute;
            width:30px;
            height:100%;
            margin-left:170px;
            padding:0px;
            text-align:center;
        }
        
        /*浮动消息窗口菜单样式,主要样式如下:
          窗口,宽度300px,高度自适应,浮动,,默认隐藏,包含窗口标题、消息内容;
          窗口标题,宽度100%,高度20px,包含标题文本、关闭按钮;
          标题文本,宽高度默认,靠左;
          关闭按钮,宽度20px,高度默认,鼠标上移样式为手形;
          消息内容,宽度100%,高度自适应,文本换行。
        */
        .msgDialog{
            position:absolute;
            width:300;
            heigth:auto;
            background-color:#c0c0c0;
            text-align:left;
            dislay:none;
        }
        .msgDialogTitle{
            width:100%;
            heigth:20px;
            font-weight:bold;
            background-color:#0000ff;
            color:#ffffff;
            text-align:left;
        }
        .msgDialogTitleText{
            padding-left:3px;
            /*msgDialogTitleText和dialogTitleClose同时使用display:inline;在IE中则可以使两个div在同一行上,msgDialogTitleText的宽度用js可以改变,
            但是在chrome,forefox里,可以显示在同一行上,却不能修改宽度,为兼容需要,放弃这种用法,改为dialogTitleClose浮动position:absolute;*/
            /*display:inline;*/
            text-align:left;
            margin-left:0px;
        }
        .dialogTitleClose{
            position:absolute;
            /*display:inline;*/
            text-align:center;
            width:20px;
            cursor:hand;
            margin-left:280px;
            margin-top:-19px;
        }
        .dialogTitleCtrlOver{
            background-color:#00eeff;
        }
        .msgDialogIcon{
            position:absolute;
            width:26px;
            heigth:auto;
            margin-top:3px;
            text-align:center;
        }
        .msgDialogContent{
            width:100%;
            height:auto;
            text-align:left;
            padding:3px;
            word-break:break-all
        }
        
        /**测试区域样式**/
        .testDiv{
            border:1px solid #ff0000;
            position:absolute;
            width:100px;
            height:100px;
        }
        #testArea{
            width:500px;
            height:300px;
            border:1px solid #00ff00;
            text-align:left;
        }
        #remark{position:absolute;}
        #divOne{margin-left:50px;margin-top:50px;}
        #divTow{margin-left:350px;margin-top:50px;}
    </style>
    <script type="text/javascript">
      // 鼠标右键菜单对象
      var mouseMenu;
      
      /**创建菜单项,返回DIV对象
      * @param options 菜单配置项,目前只配置
            1、菜单项ID itemId,
            2、菜单项图标资源路径icon,
            3、菜单项显示的名称name,
            4、菜单项右边的html块区域内容rightHtml,可嵌入checkbox和radio等html元素,
            5、菜单项点击事件处理函数onclick,
            6、菜单项鼠标经过事件处理函数onmouseover,
            7、菜单项鼠标移出事件处理函数onmouseout
      */
      function createMenuItem(options){
          if(!options){
              throw "创建菜单项createMenuItem函数参数非法,必须设置菜单项参数!";
          }
          
          var itemIcon = document.createElement("div");
          itemIcon.className = "menuItemIcon";
          
          var itemIconImg = document.createElement("img");
          itemIconImg.src = options.icon;
          
          var itemName = document.createElement("div");
          itemName.className = "menuItemName";
          itemName.innerHTML = options.name;// firfox不支持innerText
          
          var itemRight = document.createElement("div");
          itemRight.className = "menuItemRight";
          itemRight.innerHTML = options.rightHtml; 
          
          var item = document.createElement("div");
          item.id = options.itemId;
          item.className = "menuItem";
          
          itemIcon.appendChild(itemIconImg);
          item.appendChild(itemIcon);
          item.appendChild(itemName);
          item.appendChild(itemRight);
          
          item.onclick = options.onclick;
          item.onmouseover = options.onmouseover;
          item.onmouseout = options.onmouseout;
          
          return item;
      }
      
      /**初始化鼠标右键菜单,返回DIV对象**/
      function doGetMenu(){
          // 如果已初始化鼠标右键菜单,则直接返回
          if(mouseMenu){
              return mouseMenu;
          }

          mouseMenu = document.createElement("div");
          mouseMenu.id = "menu";
          mouseMenu.className = "menu";

          var onclick = function(event){
              msgDialog("淡出淡入消息框", "还没有做完呢,这么着急点干嘛...", "4.gif", 3000);
              stopBubble(event);
          }
          var onmouseover = function(event){
              this.className = "menuItem menuItemOnMouseOver";
          }
          var onmouseout = function(event){
              this.className = "menuItem";
          }
          
          mouseMenu.appendChild(createMenuItem({itemId:"newItem", icon:"4.gif", name:"新建", rightHtml:"", onclick:onclick, onmouseover:onmouseover, onmouseout:onmouseout}));
          mouseMenu.appendChild(createMenuItem({itemId:"openItem", icon:"4.gif", name:"打开", rightHtml:"", onclick:onclick, onmouseover:onmouseover, onmouseout:onmouseout}));
          mouseMenu.appendChild(createMenuItem({itemId:"editItem", icon:"4.gif", name:"编辑", rightHtml:"", onclick:onclick, onmouseover:onmouseover, onmouseout:onmouseout}));
          mouseMenu.appendChild(createMenuItem({itemId:"encoding", icon:"4.gif", name:"编码UTF-8", rightHtml:"<input type='checkbox' />", onclick:onclick, onmouseover:onmouseover, onmouseout:onmouseout}));
          mouseMenu.appendChild(createMenuItem({itemId:"IE", icon:"4.gif", name:"使用IE", rightHtml:"<input type='checkbox' />", onclick:onclick, onmouseover:onmouseover, onmouseout:onmouseout}));

          document.body.appendChild(mouseMenu);

          return mouseMenu;
      }

      function showMenu(){
          doGetMenu().style.display = "block";
      }

      function hideMenu(){
          doGetMenu().style.display = "none";
      }
      
      /**阻断事件冒泡传递
      * @param evt 事件
      */
      function stopBubble(evt) {
          var e = evt ? evt : window.event;// 兼容IE,Firefox,Chrome
          if (window.event) {
              e.cancelBubble = true; 
          } else {
              //e.preventDefault(); 
              e.stopPropagation(); 
          } 
      }
      
      /**鼠标右键监听器
      * @param evt 点击事件
      */
      function onMouseupListener(evt){
          var event = evt?evt:window.event; // 兼容IE,Firefox,Chrome
          
          if (event.button != 2) {
              return ;
          }
          
          // 获取鼠标离窗口右下角的X和Y轴距离(与滚动无关)
          var redge=document.body.clientWidth-event.clientX;
          var bedge=document.body.clientHeight-event.clientY;
          
          var mn = doGetMenu();
          
          // 如果当前点击点到窗口右侧的距离小于菜单宽度,则将菜单向左弹出,否则向右弹出
          if (redge<mn.offsetWidth)
          {
              mn.style.left=document.body.scrollLeft + event.clientX-mn.offsetWidth
          }
          else
          {
              mn.style.left=document.body.scrollLeft + event.clientX
              showMenu();
          }
          
          // 如果当前点击点到窗口下侧的距离小于菜单高度,则将菜单向上弹出,否则向下弹出
          if (bedge<mn.offsetHeight)
          {
              mn.style.top=document.body.scrollTop + event.clientY - mn.offsetHeight
          }
          else
          {
              mn.style.top = document.body.scrollTop + event.clientY
               showMenu();
          }

          // 阻断事件冒泡传递,这一步必须
          stopBubble(evt);
      }
      
      // 淡出淡入速度常量
      var FADE_SPEED_MOSTFAST = 10;
      var FADE_SPEED_FAST = 50;
      var FADE_SPEED_NORMAL = 100;
      var FADE_SPEED_SLOW = 200;
      var FADE_SPEED_MOSTSLOW = 500;
      
      /**元素淡入
      * @param el 必填项,淡入的元素DOM对象,该元素position样式必须是absolute
      * @param maxOpacity 元素el最大不透明度值(1~100)
      * @param opacity 元素el下一个的不透明度值(1~100)
      * @param callback 无参数回调函数
      * @param fadeSpeed 谈入速度,可使用FADE_SPEED_FAST、FADE_SPEED_NORMAL和FADE_SPEED_SLOW,也可以自定义值(非负非零整数),值越大,速度越小
      */
      function fadeIn(el, maxOpacity, opacity, callback, fadeSpeed){
          if(!el){
              return;
          }
          if(!maxOpacity){
              maxOpacity = 100;
          }
          if(!opacity){
              opacity = 0;
          }
          if(!fadeSpeed){
              fadeSpeed = FADE_SPEED_NORMAL;
          }
          
          if(el.style.display == "none"){
              el.style.display = "block";
          }
          
          opacity+=10;
          if(opacity > maxOpacity){
              opacity = maxOpacity;
          }
              

          el.style.filter="alpha(opacity="+opacity+")";

          el.style.opacity=opacity/100;

          if(opacity<maxOpacity){
              setTimeout(function(){fadeIn(el, maxOpacity, opacity, callback, fadeSpeed);},fadeSpeed);
          }else{
              clearTimeout();
              if(callback){
                  callback();
              }
          }
      }
      
      /**元素淡出
      * @param el 必填项,淡出的元素DOM对象,该元素position样式必须是absolute且元素可见(display不为none)
      * @param minOpacity 元素el最小不透明度值(1~100)
      * @param opacity 元素el下一个的不透明度值(1~100)
      * @param callback 无参数回调函数
      * @param fadeSpeed 谈入速度,可使用FADE_SPEED_FAST、FADE_SPEED_NORMAL和FADE_SPEED_SLOW,也可以自定义值(非负非零整数),值越大,速度越小
      */
      function fadeOut(el, minOpacity, opacity, callback, fadeSpeed){
          if(!el || (el.style.display == "none")){
              return;
          }
          if(!minOpacity){
              minOpacity = 0;
          }
          if(!opacity){
              opacity = 100;
          }
          if(!fadeSpeed){
              fadeSpeed = FADE_SPEED_NORMAL;
          }
          
          opacity-=10;
          if(opacity < minOpacity){
              opacity = minOpacity;
          }

          el.style.filter="alpha(opacity="+opacity+")";

          el.style.opacity=opacity/100;

          if(opacity>minOpacity){
              setTimeout(function(){fadeOut(el, minOpacity, opacity, callback, fadeSpeed);},fadeSpeed);
          }
          else{
              clearTimeout();
              if(opacity == 0){
                  el.style.display = "none";
              }              
              if(callback){
                  callback();
              }
          }
      }
      
      /**淡出淡入非模式消息窗口,目前消息窗口的宽度在样式中写死,未做自适应大小(根据消息内容宽度可变)
      * @param title 消息窗口标题
      * @param msg 消息窗口内容
      * @param icon 消息窗口图片
      * @param stayTime 消息窗口停留时间(ms)
      */
      function msgDialog(title, msg, icon, stayTime){
          if(!title){
              title = "message";
          }
          if(!stayTime){
              stayTime = 1000;
          }
          
          // 消息窗口主体
          var dialog = document.createElement("div");
          dialog.className = "msgDialog";
          
          // 消息窗口标题栏文本元素
          var dialogTitleText = document.createElement("div");
          dialogTitleText.className = "msgDialogTitleText";
          dialogTitleText.innerHTML = title;
          
          // 消息窗口标题栏关闭元素
          var dialogTitleClose = document.createElement("div");
          dialogTitleClose.className = "dialogTitleClose";
          dialogTitleClose.innerHTML = "X";
          dialogTitleClose.onmouseover = function(event){
              this.className = "dialogTitleClose dialogTitleCtrlOver";
          }
          dialogTitleClose.onmouseout = function(event){
              this.className = "dialogTitleClose";
          }
          dialogTitleClose.onclick = function(event){
              fadeOut(dialog, 0, dialog.style.opacity*100, function(){
                  dialog = null;
              }, FADE_SPEED_FAST);
          }
          
          // 消息窗口标题栏
          var dialogTitle = document.createElement("div");
          dialogTitle.className = "msgDialogTitle";
          
          dialogTitle.appendChild(dialogTitleText);
          dialogTitle.appendChild(dialogTitleClose);
          
          dialog.appendChild(dialogTitle);
          
          // 消息窗口消息图标,
          if(icon){
              var dialogIconImg = document.createElement("img");
              dialogIconImg.src = icon;

              var dialogIcon = document.createElement("div");
              dialogIcon.className = "msgDialogIcon";
              
              dialogIcon.appendChild(dialogIconImg);
              dialog.appendChild(dialogIcon);
          }
          
          // 消息窗口消息内容
          var dialogContent = document.createElement("div");
          dialogContent.className = "msgDialogContent";
          dialogContent.innerHTML = (icon ? "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" : "") + msg;
          
          dialog.appendChild(dialogContent);
          document.body.appendChild(dialog);
          
          // 调整消息窗口标题中的标题元素宽度,需要添加到body之后才能获取offsetWidth。
          // dialogTitleText和dialogTitleClose同时使用display:inline时,在IE中下面的句子可以修改dialogTitleClose的宽度,但是在firefox和chrome里则不行。
          // 为了浏览器兼容,所以改为dialogTitleClose样式position:absolute,并在样式中写死宽度。
          // ps:这样子搞,会疯掉的。
          //dialogTitleClose.style.width = dialogTitle.offsetWidth - dialogTitleClose.offsetWidth;
          
          // 调整消息窗口位置居中
          dialog.style.left = (document.body.clientWidth-dialog.offsetWidth)/2;
          dialog.style.top = (document.body.clientHeight-dialog.offsetHeight)/2;

          // 消息窗口淡入
          fadeIn(dialog, 100,0, function(){
              // 消息窗口停留stayTime毫秒后淡出
              setTimeout(function(){
                  fadeOut(dialog, 0, 100, function(){
                      dialog = null;
                  }, FADE_SPEED_FAST);
              }, stayTime);
          }, FADE_SPEED_NORMAL);
      }
      
    </script>
  </head>

  <body>
    <center>
      <div id="testArea">
        <div id="remark">
            测试区域,右击div块弹出菜单,点击菜单项弹出淡出淡入消息框。<br/>
            本程序的测试浏览器环境:IE8, Firefox12.0, Chrome20.0.1132.5<br>
            <a href="http://bing-zz.iteye.com/" title="今天比昨天好" style="text-decoration:none;color:#888888;width:200px;position:absolute;margin-top:240px;margin-left:280px;">http://bing-zz.iteye.com/</a>
        <div>
        <div id="divOne" class="testDiv">
          div块一<br/>id:divOne
        </div>
        <div id="divTow" class="testDiv">
          div块二<br/>id:divTow
        </div>
      </div>
    </center>
    
  </body>
</html>

<script type="text/javascript">

    document.oncontextmenu = function(){return false;}; // 屏蔽窗口右键菜单
    document.getElementById("divOne").onmouseup = onMouseupListener;
    document.getElementById("divTow").onmouseup = onMouseupListener;
    // 窗口单击隐藏鼠标右键菜单,IE可以设置到document一层,而firefox不行,似乎在firefox里不能阻止事件传递到document
    document.body.onclick = function(event){hideMenu();}

</script>
 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics