优秀的编程知识分享平台

网站首页 > 技术文章 正文

JS原生练习题:第六课1~3节(原生js实现promise.all)

nanyue 2024-07-18 22:13:17 技术文章 8 ℃

第一节:完美拖拽

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>1) 完美拖拽</title>
    <link rel="stylesheet" href="../css/common.css">
    <style>
        .wrap{
            width: 300px;
            height: 200px;
            position: absolute;
            left: 50%;
            top: 50%;
            margin: -100px 0 0 -150px;
            border: 2px solid black;
        }
        h1{
            text-align: right;
            height: 30px;
            border-bottom: 2px solid black;
            line-height: 30px;
            font-size: 14px;
        }
        a{
            cursor: pointer;
        }
        ul{
            padding: 20px;
        }
        li{
            line-height: 30px;
            font-size: 14px;
        }
    </style>
</head>
<body>
<div class="wrap">
    <h1><a>点击可回放拖拽轨迹</a></h1>
    <ul>
        <li>Drag:false</li>
        <li>offsetTop:</li>
        <li>offsetLeft:</li>
    </ul>
</div>
<script>
    window.onload = function () {
        var isBox = document.getElementsByClassName("wrap")[0];
        var isBack = document.getElementsByTagName("a")[0];
        var isCon = document.getElementsByTagName("li");
        var drag = false,isNum = [],time = null;
        isCon[1].innerHTML = "offsetTop:" + isBox.offsetTop;
        isCon[2].innerHTML = "offsetLeft:" + isBox.offsetLeft;
        isBox.onmousedown = function () {
            drag = true;
            isCon[0].innerHTML = "Drag:" + drag;
        };
        document.onmouseup = window.onblur = isBox.onlosecapture = function () {
            drag = false;
            isCon[0].innerHTML = "Drag:" + drag;
        };
        document.onmousemove = function (event) {
            //不拖拽时事件不触发
            if (!drag) {return false;}
            // 获取视口属性值
            var isEvent = event || window.event;
            var boxLeft = isEvent.clientX;
            var boxTop = isEvent.clientY;
            var rightLimit = document.documentElement.clientWidth - isBox.offsetWidth;
            var bottomLimit = document.documentElement.clientHeight - isBox.offsetHeight;
            //拖拽并限制宽高
            isBox.style.left = boxLeft + 150 + 'px';
            (rightLimit <= isBox.offsetLeft) && (isBox.style.left = rightLimit + 150 + 'px');
            (isBox.offsetLeft <= 0) && (isBox.style.left = boxLeft + 150 + 'px');
            isBox.style.top = boxTop + 100 + 'px';
            (bottomLimit <= isBox.offsetTop) && (isBox.style.top = bottomLimit + 100 + 'px');
            (isBox.offsetTop <= 0) && (isBox.style.top = 100 + 'px');
            //输出宽高,并计入宽高
            isCon[1].innerHTML = "offsetTop:" + isBox.offsetTop;
            isCon[2].innerHTML = "offsetLeft:" + isBox.offsetLeft;
            isNum.push([isBox.offsetTop,isBox.offsetLeft]);
            return false
        };
        //拖拽回放
        isBack.onclick = function () {
          clearInterval(time);
          time = setInterval(function () {
             var num = isNum.pop();
              if (isNum.length >= 1) {
                  isBox.style.top = num[0] + 100 + 'px';
                  isBox.style.left = num[1] + 150 + 'px';
                  isCon[1].innerHTML = "offsetTop:" + isBox.offsetTop;
                  isCon[2].innerHTML = "offsetLeft:" + isBox.offsetLeft;
              }else {
                  clearInterval(time);
              }
          }, 30);
        }
    }
</script>
</body>
</html>

我自己是一名从事了多年开发的web前端老程序员,目前辞职在做自己的web前端私人定制课程,今年我花了一个月整理了一份最适合2020年学习的web前端学习干货,各种框架都有整理,送给每一位前端小伙伴,想要获取的可以关注我的头条号并在后台私信我:前端,即可免费获取。

第二节:仿腾讯微博特效

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>仿腾讯微博特效</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        body {
            color: #333;
            font: 12px/1.5 \5b8b\4f53;
        }

        a {
            text-decoration: none;
        }

        ul {
            list-style: none;
        }

        .clearfix:after {
            clear: both;
            content: '';
            display: block;
            visibility: hidden;
            height: 0;
            line-height: 0;
        }

        .wrap {
            width: 600px;
            padding: 10px;
            margin: 0 auto;
            background: #3c3a3b;
        }

        .msg-box {
            width: 500px;
            padding-top: 10px;
            border-radius: 5px;
            margin: 10px auto;
            background: #fff;
        }

        .msg-box img {
            border-radius: 3px;
        }

        .msg-box input,
        textarea,
        button {
            outline: none;
        }

        .msg-box form {
            background: url(https://pandoraui.github.io/learning-javascript/lesson6/img/boxBG.jpg) repeat-x 0 bottom;
            padding: 0 20px 15px;
        }

        .msg-box form h2 {
            font-weight: 400;
            font: 400 18px/1.5 \5fae\8f6f\96c5\9ed1;
        }

        .msg-box form .row {
            position: relative;
            margin-top: 10px;
        }

        #user-name-input {
            height: 20px;
        }

        #user-name-input,
        #msg-field {
            padding: 3px 5px;
            border: 1px solid #d0d0d0;
            border-radius: 6px;
            background: #fff url(https://pandoraui.github.io/learning-javascript/lesson6/img/inputBG.png) repeat-x;
            font: 14px/1.5 arial;
            color: #777;
        }

        #user-name-input:focus,
        #msg-field:focus {
            border: 1px solid #7abb2c;
        }

        #heads {
            position: absolute;
            top: 0;
            left: 180px;
            font-size: 0;
        }

        #heads img {
            width: 30px;
            height: 30px;
            margin-left: 5px;
            opacity: 0.5;
            cursor: pointer;
        }

        #heads img:hover,
        #heads img.current {
            width: 28px;
            height: 28px;
            border: 1px solid #f60;
            opacity: 1;
        }

        #msg-field {
            width: 448px;
            height: 65px;
            resize: none;
            overflow: auto;
        }

        .submit>div {
            float: right;
            height: 30px;
            line-height: 30px;
            color: #999;
        }

        .submit>div strong,
        span {
            vertical-align: top;
        }

        .submit>div strong {
            font: 26px Georgia, Tahoma, Arial;
            padding: 0 5px;
        }

        .submit>div strong.overflow {
            color: #FF6600;
        }

        #submit-btn {
            display: inline-block;
            width: 112px;
            height: 30px;
            border: 0;
            margin-left: 10px;
            background: url(https://pandoraui.github.io/learning-javascript/lesson6/img/btn.png) no-repeat;
            cursor: pointer;
        }

        #submit-btn:hover {
            background-position: 0 -30px;
        }

        .msg-list {
            padding: 10px;
        }

        .msg-list h3 {
            position: relative;
            height: 33px;
            border: 1px solid #dee4e7;
            font-size: 14px;
            font-weight: 400;
            background: #e3eaec;
        }

        .msg-list h3 span {
            position: absolute;
            left: 6px;
            top: 6px;
            padding: 0 15px;
            background: #fff;
            line-height: 28px;
        }

        .msg-list ul li {
            float: left;
            width: 100%;
            padding: 10px 0;
            border-bottom: 1px dashed #d8d8d8;
            background: #fff;
        }

        .msg-list ul li:hover {
            background: #f5f5f5;
        }

        .msg-list ul li .user-head {
            float: left;
            width: 50px;
            height: 50px;
            border: 1px solid #ccc;
            border-radius: 3px;
            margin-left: 10px;
        }

        .msg-list ul li .content {
            float: left;
            width: 400px;
            margin-left: 10px;
            font-size: 14px;
            font-family: arial;
            word-wrap: break-word;
        }

        .msg-list ul li .user-name {
            padding-right: 5px;
        }

        .msg-list ul li .user-name a {
            color: #2b4a78;
        }

        .msg-list ul li .user-name a:hover {
            text-decoration: underline;
        }

        .msg-list ul li .msg-info {
            word-wrap: break-word;
        }

        .msg-list ul li .bottom {
            margin-top: 5px;
            color: #889db6;
            font: 12px/18px arial;
        }

        .msg-list ul li .time {
            float: left;
        }

        .msg-list ul li .del {
            float: right;
            color: #889db6;
            display: none;
        }

        .msg-list ul li .del:hover {
            text-decoration: underline;
        }

        .msg-list ul li:hover .del {
            display: block;
        }
    </style>
</head>

<body>
    <div class="wrap">
        <div class="msg-box" id="msg-box">
            <form>
                <h2>来 , 说说你在做什么 , 想什么</h2>
                <div class="row">
                    <input type="text" name="user-name" id="user-name-input">
                    <div id="heads">
                        <img src="https://pandoraui.github.io/learning-javascript/lesson6/img/face1.gif" alt="head"
                            class="current">
                        <img src="https://pandoraui.github.io/learning-javascript/lesson6/img/face2.gif" alt="head">
                        <img src="https://pandoraui.github.io/learning-javascript/lesson6/img/face3.gif" alt="head">
                        <img src="https://pandoraui.github.io/learning-javascript/lesson6/img/face4.gif" alt="head">
                        <img src="https://pandoraui.github.io/learning-javascript/lesson6/img/face5.gif" alt="head">
                        <img src="https://pandoraui.github.io/learning-javascript/lesson6/img/face6.gif" alt="head">
                        <img src="https://pandoraui.github.io/learning-javascript/lesson6/img/face7.gif" alt="head">
                        <img src="https://pandoraui.github.io/learning-javascript/lesson6/img/face8.gif" alt="head">
                    </div>
                </div>
                <div class="row">
                    <textarea name="msg" id="msg-field"></textarea>
                </div>
                <div class="row submit clearfix">
                    <div>
                        <span>还能输入</span><strong>140</strong><span>个字</span>
                        <button type="button" title="快捷键Ctrl+Enter" id="submit-btn">发送</button>
                    </div>
                </div>
            </form>
            <div class="msg-list">
                <h3><span>大家在说</span></h3>
                <ul class="clearfix">
                    <li>
                        <div class="user-head"><img
                                src="https://pandoraui.github.io/learning-javascript/lesson6/img/face.gif" alt="head">
                        </div>
                        <div class="content">
                            <p class="msg-info"><span class="user-name"><a
                                        href="javascript:void(0);">levon</a>:</span>加了点动画效果。</p>
                            <div class="bottom"><span class="time">07月05日 15:14</span><a href="javascript:void(0);"
                                    class="del">删除</a></div>
                        </div>
                    </li>
                    <li>
                        <div class="user-head"><img
                                src="https://pandoraui.github.io/learning-javascript/lesson6/img/face.gif" alt="head">
                        </div>
                        <div class="content">
                            <p class="msg-info"><span class="user-name"><a
                                        href="javascript:void(0);">levon</a>:</span>新增Ctrl+Enter快捷键发送广播。</p>
                            <div class="bottom"><span class="time">07月05日 15:14</span><a href="javascript:void(0);"
                                    class="del">删除</a></div>
                        </div>
                    </li>
                    <li>
                        <div class="user-head"><img
                                src="https://pandoraui.github.io/learning-javascript/lesson6/img/face.gif" alt="head">
                        </div>
                        <div class="content">
                            <p class="msg-info"><span class="user-name"><a
                                        href="javascript:void(0);">levon</a>:</span>增加了输入字符检测功能,英文/半角为半个字符汉字/全角为一个字符。
                            </p>
                            <div class="bottom"><span class="time">07月05日 15:14</span><a href="javascript:void(0);"
                                    class="del">删除</a></div>
                        </div>
                    </li>
                    <li>
                        <div class="user-head"><img
                                src="https://pandoraui.github.io/learning-javascript/lesson6/img/face.gif" alt="head">
                        </div>
                        <div class="content">
                            <p class="msg-info"><span class="user-name"><a
                                        href="javascript:void(0);">levon</a>:</span>新增删除广播功能。</p>
                            <div class="bottom"><span class="time">07月05日 15:14</span><a href="javascript:void(0);"
                                    class="del">删除</a></div>
                        </div>
                    </li>
                    <li>
                        <div class="user-head"><img
                                src="https://pandoraui.github.io/learning-javascript/lesson6/img/face.gif" alt="head">
                        </div>
                        <div class="content">
                            <p class="msg-info"><span class="user-name"><a
                                        href="javascript:void(0);">levon</a>:</span>新增选择头像功能。</p>
                            <div class="bottom"><span class="time">07月05日 15:14</span><a href="javascript:void(0);"
                                    class="del">删除</a></div>
                        </div>
                    </li>
                    <li>
                        <div class="user-head"><img
                                src="https://pandoraui.github.io/learning-javascript/lesson6/img/face.gif" alt="head">
                        </div>
                        <div class="content">
                            <p class="msg-info"><span class="user-name"><a
                                        href="javascript:void(0);">levon</a>:</span>增加了记录广播时间的功能。</p>
                            <div class="bottom"><span class="time">07月05日 15:14</span><a href="javascript:void(0);"
                                    class="del">删除</a></div>
                        </div>
                    </li>
                    <li>
                        <div class="user-head"><img
                                src="https://pandoraui.github.io/learning-javascript/lesson6/img/face.gif" alt="head">
                        </div>
                        <div class="content">
                            <p class="msg-info"><span class="user-name"><a
                                        href="javascript:void(0);">levon</a>:</span>可以发送广播啦!</p>
                            <div class="bottom"><span class="time">07月05日 15:14</span><a href="javascript:void(0);"
                                    class="del">删除</a></div>
                        </div>
                    </li>
                </ul>
            </div>
        </div>
    </div>
</body>
<script>
    function hasClass(element, className) {
        return (new RegExp('(^|\\s)' + className + '($|\\s)')).test(element.className);
    }

    function addClass(element, newClassName) {
        if (!hasClass(element, newClassName)) {
            element.className += element.className ? (' ' + newClassName) : newClassName;
        }
    }

    function removeClass(element, oldClassName) {
        if (hasClass(element, oldClassName)) {
            element.className = element.className.replace(new RegExp('(^|\\s)' + oldClassName + '($|\\s)'), ' ').trim();
        }
    }

    function delegateEvent(delegateElement, targetTag, eventName, handler) {
        delegateElement.addEventListener(eventName, function (event) {
            var target = event.target;
            if (target.tagName.toLowerCase() === targetTag.toLowerCase()) {
                return handler(event);
            }
        }, false);
    }

    var msgBox = document.getElementById('msg-box');

    // 发送表单单例
    var MsgForm = function (msgBox) {
        var form = msgBox.getElementsByTagName('form')[0];

        var heads = document.getElementById('heads');
        var headImgs = heads.getElementsByTagName('img');

        var msgField = form.msg;

        var submit = form.getElementsByClassName('submit')[0];
        var submitBtn = form['submit-btn'];

        var isPressCtrl = false;

        function getMsgLength(msg) {
            var len = 0;
            for (var i = msg.length - 1; i >= 0; i--) {
                // 英文算半个字符,中文和全角字符算一个字符
                if (/[\u4e00-\u9fa5\u3000-\u301e\ufe10-\ufe19\ufe30-\ufe44\ufe50-\ufe6b\uff01-\uffee]/.test(msg[i])) {
                    len++;
                } else {
                    len += 0.5;
                }
            }

            return Math.ceil(len);
        }

        function validate(form) {
            var result = [];

            var userName = form['user-name'].value.trim();
            if (userName === '') {
                result[0] = false;
                result[1] = '请填写用户名!';
                return result;
            } else if (!/^[\w\u4e00-\u9fa5]{2,8}$/.test(userName)) {
                result[0] = false;
                result[1] = '用户名由2-8位字母、数字、下划线、汉字组成!';
                return result;
            }

            var msg = form.msg.value;
            // 防止输入的全是空字符
            if (msg.trim() === '') {
                result[0] = false;
                result[1] = '随便说点什么吧!';
                return result;
            } else if (getMsgLength(msg) > 140) {
                result[0] = false;
                result[1] = '你输入的内容已超出限制,请检查!';
                return result;
            }

            result[0] = true;
            result[1] = {
                userName: userName,
                content: msg,
            };

            return result;
        }

        function getHeadUrl() {
            for (var i = headImgs.length - 1; i >= 0; i--) {
                if (hasClass(headImgs[i], 'current')) {
                    return headImgs[i].src;
                }
            }
        }

        //格式化时间, 如果为一位数时补0
        function format(str) {
            return str.toString().replace(/^(\d)$/, "0$1");
        }

        function getFormatDate() {
            var now = new Date();
            return format(now.getMonth() + 1) + '月' +
                format(now.getDate()) + '日 ' +
                format(now.getHours()) + ':' +
                format(now.getMinutes());
        }

        function sendMsg() {
            var validateResult = validate(form);

            if (validateResult[0] === false) {
                alert(validateResult[1]);
                return;
            } else {
                var massage = {
                    userName: validateResult[1].userName,
                    userHeadSrc: getHeadUrl(),
                    content: validateResult[1].content,
                    time: getFormatDate()
                };

                // 把验证通过的消息发出来
                MsgList.addMsgItem(massage);
                // 清空消息输入框
                msgField.value = '';
            }
        }

        function init() {
            // 头像图片的选择功能
            delegateEvent(heads, 'img', 'click', function (event) {
                var target = event.target;
                for (var i = headImgs.length - 1; i >= 0; i--) {
                    removeClass(headImgs[i], 'current');
                }
                addClass(target, 'current');
            });

            // 判断输入字符功能
            msgField.addEventListener('keyup', function (event) {
                var msg = msgField.value;
                var releaseLen = 140 - getMsgLength(msg);

                var release = submit.getElementsByTagName('strong')[0];
                var info = submit.getElementsByTagName('span')[0];
                if (releaseLen < 0) {
                    addClass(release, 'overflow');
                    release.textContent = -releaseLen;
                    info.textContent = '已超出';
                } else {
                    removeClass(release, 'overflow');
                    release.textContent = releaseLen;
                    info.textContent = '还能输入';
                }
            }, false);

            // 发布微博功能
            submitBtn.addEventListener('click', sendMsg, false);
            msgField.addEventListener('keydown', function (event) {
                // 键盘事件的event.ctrlKey也是能用的
                if (event.keyCode === 13 && event.ctrlKey) {
                    sendMsg();
                }
            }, false);
        }

        return {
            init: init
        };
    }(msgBox);

    // 消息列表单例
    var MsgList = function (msgBox) {
        var list = msgBox.getElementsByClassName('msg-list')[0].getElementsByTagName('ul')[0];

        function createMsgItem(massage) {
            var li = document.createElement('li');

            var userHead = document.createElement('div');
            addClass(userHead, 'user-head');
            var head = document.createElement('img');
            head.src = massage.userHeadSrc;
            head.alt = 'head';
            userHead.appendChild(head);
            li.appendChild(userHead);

            var content = document.createElement('div');
            addClass(content, 'content');
            var msgInfo = document.createElement('p');
            addClass(msgInfo, 'msg-info');
            msgInfo.innerHTML = '<span class="user-name"><a href="javascript:void(0);">' + massage.userName +
                '</a>:</span>' + massage.content;
            content.appendChild(msgInfo);

            var bottom = document.createElement('div');
            addClass(bottom, 'bottom');
            bottom.innerHTML = '<span class="time">' + massage.time + '</span><a href="javascript:void(0);" class="del">删除</a>';
            content.appendChild(bottom);
            li.appendChild(content);

            return li;
        }

        // 先增高度,再增加透明度的动画效果
        function showMsgItem(item, timeout) {
            // css样式的值全是字符串,所以得先转为数字才能运算
            var oldHeight = parseInt(window.getComputedStyle(item).height);
            var oldOpacity = parseFloat(window.getComputedStyle(item).opacity);
            item.style.height = 0;
            item.style.opacity = 0;

            function showOpacity() {
                var opacity = parseFloat(item.style.opacity);
                if (opacity < oldOpacity) {
                    item.style.opacity = opacity + oldOpacity / 10;
                    setTimeout(showOpacity, timeout / 20);
                } else {
                    item.style.opacity = '';
                }
            }

            function showHeight() {
                var height = parseInt(item.style.height);
                if (height < oldHeight) {
                    item.style.height = (height + oldHeight / 10) + 'px';
                    setTimeout(showHeight, timeout / 20);
                } else {
                    item.style.height = '';
                    setTimeout(showOpacity, timeout / 20);
                }
            }

            showHeight();
        }

        // 先减高度,再减透明度的动画效果
        function hideMsgItem(item, timeout) {
            var oldHeight = parseInt(window.getComputedStyle(item).height);
            var oldOpacity = parseFloat(window.getComputedStyle(item).opacity);
            item.style.height = oldHeight + 'px';
            item.style.opacity = oldOpacity;

            function hideOpacity() {
                var opacity = parseFloat(item.style.opacity);
                if (opacity > 0) {
                    item.style.opacity = opacity - oldOpacity / 10;
                    setTimeout(hideOpacity, timeout / 20);
                } else {
                    item.style.opacity = 0;
                    setTimeout(hideHeight, timeout / 20);
                }
            }

            function hideHeight() {
                var height = parseInt(item.style.height);
                // 时间不够高度减到0,故终止的标准要做点改变
                if (height > 5) {
                    item.style.height = (height - oldHeight / 10) + 'px';
                    setTimeout(hideHeight, timeout / 20);
                } else {
                    item.style.height = 0;
                    list.removeChild(item);
                }
            }

            hideOpacity();
        }

        return {
            addMsgItem: function (massage) {
                var item = createMsgItem(massage);
                list.insertBefore(item, list.getElementsByTagName('li')[0]);
                showMsgItem(item, 500);
            },

            removeMsgItem: function (item) {
                hideMsgItem(item, 500);
            },

            init: function () {
                // 代理MsgList上的点击事件
                list.addEventListener('click', function (event) {
                    var target = event.target;
                    if (hasClass(target, 'del')) {
                        var item = target.parentNode;
                        while (item.tagName.toLowerCase() !== 'li') {
                            item = item.parentNode;
                        }
                        this.removeMsgItem(item);
                    }
                }.bind(this), false);
            }
        };
    }(msgBox);

    MsgForm.init();
    MsgList.init();

</script>

</html>

第三节:自定义多级右键菜单

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自定义多级右键菜单</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        body {
            font: 12px/1.5 \5fae\8f6f\96c5\9ed1;
        }

        ul {
            list-style: none;
        }

        #container {
            position: relative;
            width: 980px;
            height: 500px;
            margin: 0 auto;
            background-color: #ff9;
        }

        #container h2 {
            text-align: center;
        }

        #menu,
        #menu ul {
            display: none;
            position: absolute;
            padding: 2px;
            border: 1px solid #979797;
            background-color: #f1f1f1;
            box-shadow: 2px 2px 2px rgba(0, 0, 0, .6);
        }

        #menu li {
            height: 24px;
            padding: 0 30px;
            line-height: 24px;
            white-space: nowrap;
            color: #000;
        }

        #menu li:hover {
            background-color: #8f8f8f;
            color: #fff;
            cursor: pointer;
        }

        #menu li.has-sub:hover>ul {
            display: block;
        }

        #menu li.has-sub {
            background-image: url(https://pandoraui.github.io/learning-javascript/lesson6/img/arrow.png);
            background-repeat: no-repeat;
            background-position: right 9px;
        }
    </style>
</head>

<body>
    <div id="container">
        <h2>自定义多级右键菜单,在这个黄色区域内点右键试试~</h2>
        <ul id="menu">
            <li><strong>Javascript学习</strong></li>
            <li class="has-sub">第一课
                <ul>
                    <li>网页特效原理分析</li>
                    <li>响应用户操作</li>
                    <li>提示框效果</li>
                    <li>事件驱动</li>
                    <li>元素属性操作</li>
                </ul>
            </li>
            <li class="has-sub">第二课
                <ul>
                    <li>改变网页背景颜色</li>
                    <li>函数传参</li>
                    <li>高重用性函数的编写</li>
                    <li>126邮箱全选效果</li>
                    <li>循环及遍历操作</li>
                </ul>
            </li>
            <li class="has-sub">第三课
                <ul>
                    <li class="has-sub">JavaScript组成
                        <ul>
                            <li>ECMAScript</li>
                            <li>DOM</li>
                            <li>BOM</li>
                            <li>JavaScript兼容性来源</li>
                        </ul>
                    </li>
                    <li>JavaScript出现的位置、优缺点</li>
                    <li>变量、类型、typeof、数据类型转换、变量作用域</li>
                    <li class="has-sub">闭包
                        <ul>
                            <li>什么是闭包</li>
                            <li>简单应用</li>
                            <li>闭包缺点</li>
                        </ul>
                    </li>
                    <li>运算符</li>
                    <li>程序流程控制</li>
                    <li class="has-sub">定时器的使用
                        <ul>
                            <li>setInterval</li>
                            <li>setTimeout</li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </div>
</body>
<script>
    function hasClass(element, className) {
        return (new RegExp('(^|\\s)' + className + '($|\\s)')).test(element.className);
    }

    var container = document.getElementById('container');
    var menu = document.getElementById('menu');

    container.oncontextmenu = function (event) {
        event.preventDefault();

        // 因为需要菜单的宽高来定位,所以必须先保证菜单显现出来拥有宽高
        menu.style.display = 'block';

        // 校正坐标
        var clickX = event.clientX - container.offsetLeft;
        var clickY = event.clientY - container.offsetTop;
        // 依剩余空间决定菜单出现的位置
        var rightRoom = container.offsetWidth - event.clientX;
        var bottomRoom = container.offsetHeight - event.clientY;
        var posX = (rightRoom < menu.offsetWidth ? clickX - menu.offsetWidth : clickX) + 'px';
        var posY = (bottomRoom < menu.offsetHeight ? clickY - menu.offsetHeight : clickY) + 'px';
        menu.style.left = posX;
        menu.style.top = posY;
    };

    container.onclick = function () {
        menu.style.display = '';
    };

    menu.onmouseover = function (event) {
        var target = event.target;
        if (hasClass(target, 'has-sub')) {
            var parentItem = target;
            var subList = parentItem.getElementsByTagName('ul')[0];
            var parentList = parentItem.parentNode;

            // 获得上级菜单的左侧、顶部在容器中的位置
            var ancestorList = parentList;
            var allOffsetLeft = ancestorList.offsetLeft;
            var allOffsetTop = ancestorList.offsetTop;
            while (ancestorList !== menu) {
                ancestorList = ancestorList.parentNode.parentNode;
                allOffsetLeft += ancestorList.offsetLeft;
                allOffsetTop += ancestorList.offsetTop;
            }
            // 依剩余空间决定菜单出现的位置
            var rightRoom = container.offsetWidth - allOffsetLeft - parentList.offsetWidth;
            var bottomRoom = container.offsetHeight - allOffsetTop - parentItem.offsetTop;
            if (rightRoom < subList.offsetWidth) {
                // 子列表右端对齐父元素右部
                subList.style.right = parentItem.offsetWidth + 'px';
                subList.style.left = '';
            } else {
                // 子列表左端对齐父元素左部
                subList.style.left = parentItem.offsetWidth + 'px';
                subList.style.right = '';
            }
            if (bottomRoom < subList.offsetHeight) {
                // 子列表底端对齐父元素底部
                subList.style.bottom = parentList.offsetHeight - parentItem.offsetTop - parentItem.offsetHeight + 'px';
                subList.style.top = '';
            } else {
                // 子列表顶端对齐父元素顶部
                subList.style.top = parentItem.offsetTop + 'px';
                subList.style.bottom = '';
            }
        }
    };

</script>

</html>
最近发表
标签列表