再战JavaScript

下面我们接着介绍创建节点。

创建节点,插入节点的方式,就好像是买一个大袋子,一个大袋子里装着一些小袋子,小袋子里分别装着不同的东西。

我们来看看代码就一目了然了:

<script type="text/javascript">
        //新创建一个元素节点,并把该节点添加为文档中指定节点的子节点
        window.onload = function() {
            //新创建一个元素节点,返回值为指向元素节点的引用
            //<li></li>
            var liNode = document.createElement("li");
            //新创建一个文本节点
            var textNode = document.createTextNode("华盛顿");
            //将文本节点添加到li的子节点
            //<li>华盛顿</li>
            liNode.appendChild(textNode);
            var cityNode = document.getElementById("city");
            //新添加一个子节点,该子节点将会被添加到最后的位置
            cityNode.appendChild(liNode);

        }
    </script>

大袋子(city)里装着很多小袋子(li),小袋子里装着不同的东西(不同的城市名字的文本),没错吧?很简单。

难道JavaScript只能支持这么low的做法吗?当然不是,还可以在现有已经存在的节点中互换双方的位置。当然,需要一个中间变量做转换。

代码如下:

<script type="text/javascript">
    window.onload = function() {
        /*只能实现单向移动,被覆盖的节点还没拷贝
        var bjNode = document.getElementById("bj");
        var newNode = document.createElement("li");

        var cityNode = document.getElementById("city");
        //replaceChild()方法可以实现将"红警"移动到"北京"
        cityNode.replaceChild(newNode, bjNode);
         */

         /*
        var bjNode = document.getElementById("bj");
        var cityNode = document.getElementById("city");

        var hjNode = document.getElementById("hj");
        var gameNode = document.getElementById("game");

        //先将北京节点拷贝下来
        var tempNode = bjNode.cloneNode(true);

        gameNode.replaceChild(tempNode, hjNode);
        cityNode.replaceChild(hjNode, bjNode);
        */
        var bjNode = document.getElementById("bj");
        var hjNode = document.getElementById("hj");
        replaceEach(bjNode, hjNode);
    }
    //自定义互换两个节点的函数
    function replaceEach(aNode, bNode) {
        //1.获取aNode和bNode的父节点,使用parentNode属性
        var aParent = aNode.parentNode;
        var bParent = bNode.parentNode;

        //当父节点存在的情况下才进行互换
        if (aParent && bParent) {
            //2.克隆aNode
            var aNode2 = aNode.cloneNode(true);
            //3.分别调用aNode的父节点和bNode的父节点的peplaceChild()实现互换
            bParent.replaceChild(aNode2, bNode);
            aParent.replaceChild(bNode, aNode);
        }
    }
</script>

下面我们要介绍一下弹出可以选择是和否的对话框,也就是confirm()方法了。

练习需求:为每一个li节点添加一个confirm(),若确定,则删除,结合我们的removeChild()方法,这个练习so easy。

代码如下:

<script type="text/javascript">
    //为每一个li节点添加一个confirm(),若确定,则删除
    window.onload = function() {
        /*
        //测试:removeChild():删除节点
        var cityNode = document.getElementById("city");
        alert(cityNode.parentNode);
        //通过调用父节点的removeChild()来完成,更加快捷、方便
        cityNode.parentNode.removeChild(cityNode);
         */

        var liNodes = document.getElementsByTagName("li");
        var length = liNodes.length;
        for (var i = 0; i < length; i++) {
            liNodes[i].onclick = function() {
                //confirm()方法会返回一个boolean值,选择确定未true,取消为false
                var flag = confirm("确定要删除\"" + this.innerHTML + "\"吗?");
                if (flag) {
                    this.parentNode.removeChild(this);
                }
            }
        }
    }
</script>

JavaScript还提供了insertBefore()方法,允许我们可以将某节点插入到指定节点的前面。

代码如下:

//把#hj插入到#bj的前面
var cityNode = document.getElementById("city");
var bjNode = document.getElementById("bj");
var hjNode = document.getElementById("hj");
cityNode.insertBefore(hjNode, bjNode);

但是并没有提供insertAfter()方法。那我们就自定义一个吧!

思路是这样的:先检查指定节点是否为父节点的最后一个节点。如果是,那就直接appendChild(),因为这个方法默认放到最后;如果不是,那么就获取下一个节点,也就是.nextSibling()方法,然后再使用insertBefore()方法。

代码如下:

<script type="text/javascript">
    window.onload = function() {
        var bjNode = document.getElementById("bj");
        var hjNode = document.getElementById("hj");
        insertAfter(hjNode, bjNode);

    }

    //把newNode插入到refNode的后面
    function insertAfter(newNode, refNode) {
        //1.验证refNode是否为其父节点的最后一个节点
        var parentNode = refNode.parentNode;

        if (parentNode) {
            var lastNode = parentNode.lastChild;
            if (lastNode == refNode) {
                //2.若是,则直接使用父节点的appendChild()将其插入到最后
                parentNode.appendChild(newNode);
            }
            //3.若不是,则先获取refNode的下一个节点,再使用insertBefore()方法插入
            else {
                parentNode.insertBefore(newNode, refNode.nextSibling);
            }
        }
    }
</script>

下面我们要做几个练习,HTML文档如下:

<p>你喜欢哪个城市?</p>
    <ul id="city">
        <li id="bj">北京</li>
        <li>上海</li>
        <li>东京</li>
        <li>首尔</li>
    </ul>
    <br>
    <br>
    <p>你喜欢哪款单击游戏?</p>
    <ul id="game">
        <li id="hj">红警</li>
        <li>实况</li>
        <li>魔兽</li>
        <li>星际</li>
    </ul>
    <br>
    <br>
    <input type="radio" id="myCity" name="myChoose" value="city" />城市
    <input type="radio" id="myGame" name="myChoose" value="game" />游戏
    <p>
        name:<input type="text" id="name" name="name" />
    </p>
    <input type="submit" id="mySubmit" name="mySubmit" value="submit" />

需求如下:需求1:点击submit按钮时,检查是否选择type,若没有选择就给出提示:“请选择类型”;

检查文本框中是否有输入(可以去除前后空格),若没有输入,则给出提示:“请输入内容”;

若检查都通过,则在相应的ul节点中添加对应的li节点;

需求2:使包括新增的li都能响应onclick事件,弹出li的文本值。

根据需求的描述,我们可以知道,其实所有的事件触发都在button上,那么就可以将所有的逻辑判断都加入到button上。

代码如下:

<script type="text/javascript">
    window.onload = function() {
        function showContent(liNode) {
            alert(liNode.innerHTML);
        }
        var liNodes = document.getElementsByTagName("li");
        var liLength = liNodes.length;
        for (var i = 0; i < liLength; i++) {
            liNodes[i].onclick = function() {
                showContent(this);
            }
        }
        //获取到按钮,并添加事件
        var btn = document.getElementById("mySubmit");
        btn.onclick = function() {
            //根据组名获取是否被选中的条件
            var types = document.getElementsByName("myChoose");
            var typeVal = null;
            var name = document.getElementById("name");

            var length = types.length;
            //判断单选按钮是否被选中
            for (var i = 0; i < length; i++) {
                if (types[i].checked) {
                    typeVal = types[i].value;
                    break;
                }
            }
            if (!typeVal) {
                alert("请选择类型");
                return;
            }
            //判断用户是否输入
            if (!name.value) {
                alert("请输入内容");
                return;
            }

            //都通过的情况将添加一条li
            var li = document.createElement("li");
            //获取文本框的内容
            var text = document.createTextNode(name.value);
            //将文本框的内容添加到li
            li.appendChild(text);
            li.onclick = function() {
                showContent(this);
            }
            //将li添加到typeVal指定的ul
            var ulNode = document.getElementById(typeVal);
            ulNode.appendChild(li);
        }
    }
</script>

新的需求如下:需求:为所有的li节点添加onclick响应函数;

   实现city子节点和game子节点对应位置的元素的互换。

思路是这样的:根据标签名获取到所有的li节点,这样一来,li就在一个数组里面有属于自己的下标了。根据提供的HTML文档,我们可以让(0,1,2,3)和+4的交换,让(4,5,6,7)和-4的交换。

交换结束之后,我们不仅仅是交换节点内容,我们还需要重新赋予onclick事件,还需要将新的下标赋予它。

代码如下:

<script type="text/javascript">
    window.onload = function() {
        var liNodes = document.getElementsByTagName("li");
        var length = liNodes.length;
        for (var i = 0; i < length; i++) {
            //使用index储存当前节点的下标,因为在触发事件的时候i的值已经是超过length的那个值了
            liNodes[i].index = i;
            liNodes[i].onclick = function() {
                var targetIndex = 0;
                if (this.index < 4) {
                    targetIndex = this.index + 4;
                } else {
                    targetIndex = this.index - 4;
                }
                replaceEach(this, liNodes[targetIndex]);
            }
        }

        //显示为8,没有局部变量这一说
        //alert(i);
    }
    function replaceEach(aNode, bNode) {
        var aParent = aNode.parentNode;
        var bParent = bNode.parentNode;

        if (aParent && bParent) {
            //拷贝的时候并未将事件、index拷贝
            var aNode2 = aNode.cloneNode(true);
            //alert(aNode.index);
            //alert(aNode2.index);
            //alert(bNode.index);

            //克隆aNode的同时,把onclick事件也复制
            aNode2.onclick = aNode.onclick;
            aNode2.index = bNode.index;
            bNode.index = aNode.index;

            bParent.replaceChild(aNode2, bNode);
            aParent.replaceChild(bNode, aNode);
        }
    }
</script>

很简单吧!

下面我们又来一个一份新的HTML文档,文档如下:

你爱好的运动是?
    <input type="checkbox" id="checkedAll" />全选/全不选
    <br />
    <input type="checkbox" name="items" value="足球" />足球
    <input type="checkbox" name="items" value="篮球" />篮球
    <input type="checkbox" name="items" value="排球" />排球
    <input type="checkbox" name="items" value="乒乓球" />乒乓球
    <br />
    <input type="button" id="btnAll" value="全选" />
    <input type="button" id="btnNo" value="全不选" />
    <input type="button" id="checkedRev" value="反选" />

    <input type="button" id="send" value="提交" />

一看这份文档,我们第一反应肯定是与按钮事件响应有关了。

需求:当点击id为checkedAll的按钮时,先检查下面的爱好选择做出选择:如果爱好全部被选择,那么checkedAll按钮要做的事情就是“全不选”;否则就是“全选”功能。

   下面的button按钮根据名字就可以得知了。

   每当爱好全部被打上钩时,checkedAll按钮也要被打上钩;只要不满足前面的条件,checkedAll按钮不能被打上钩。

看上去很绕,其实理清了思路,非常简单。需求正好就是我们的思路方向。

代码如下:

<script type="text/javascript">
    window.onload = function() {
        var checkedAll = document.getElementById("checkedAll");
        var items = document.getElementsByName("items");
        var length = items.length;
        checkedAll.onclick = function() {
            var flag = 0;
            for (var i = 0; i < length; i++) {
                if (items[i].checked) {
                    //每当一个选项已经被选中时就加1
                    flag += 1;
                }
            }
            //只有当全部选项都被选中时,点击按钮的效果才是“全不选”
            if (flag == length) {
                for (var j = 0; j < length; j++) {
                    items[j].checked = false;
                }
                //记得把按钮本身的状态切换成一致,否则将会出现按钮本身未打钩而爱好的选项全打钩或者反过来的“灵异”现象
                this.checked = false;
            }
            //其余情况下,都是“全选”
            else {
                for (var k = 0; k < length; k++) {
                    items[k].checked = true;
                }
                this.checked = true;
            }
        }

        for (var l = 0; l < length; l++) {
            //给所有的爱好按钮增加事件
            items[l].onclick = function() {
                check();
            }
        }

        var btnAll = document.getElementById("btnAll");
        btnAll.onclick = function() {
            for (var i = 0; i < length; i++) {
                items[i].checked = true;
            }
            check();
        }

        var btnNo = document.getElementById("btnNo");
        btnNo.onclick = function() {
            for (var i = 0; i < length; i++) {
                items[i].checked = false;
            }
            checkedAll.checked = false;
        }

        var checkedRev = document.getElementById("checkedRev");
        checkedRev.onclick = function() {
            for (var i = 0; i < length; i++) {
                if (items[i].checked) {
                    items[i].checked = false;
                } else {
                    items[i].checked = true;
                }
            }
            check();
        }

        var send = document.getElementById("send");
        send.onclick = function() {
            for (var i = 0; i < length; i++) {
                if (items[i].checked) {
                    alert(items[i].value);
                }
            }
        }

        //当所有爱好都打钩时,全选按钮也打上钩,否则就不打钩
        function check() {
            var myFlag = 0;
            for (var m = 0; m < length; m++) {
                if (items[m].checked) {
                    myFlag += 1;
                }
            }
            if (myFlag == length) {
                checkedAll.checked = true;
            } else {
                checkedAll.checked = false;
            }
        }
    }
</script>

最后一份HTML文档从天而降。文档如下:

<p align="center">添加新员工</p>
    <table align="center">
        <tr>
            <td>name:<input type="text" id="name" name="name" /></td>
            <td>email:<input type="text" id="email" name="email" /></td>
            <td>salary:<input type="text" id="salary" name="salary" /></td>
        </tr>
    </table>
    <p align="center">
        <input type="button" id="add" name="add" value="新增" />
    </p>
    <hr>
    <table id="employeeTable" align="center" border="1" cellpadding="5"
        cellspacing="0">
        <tr>
            <th>name</th>
            <th>Email</th>
            <th>Salary</th>
            <th></th>
        </tr>
        <tr>
            <td>Tom</td>
            <td>[email protected]</td>
            <td>5000</td>
            <td><input type="submit" name="delete" value="Delete" /></td>
        </tr>
        <tr>
            <td>Mary</td>
            <td>[email protected]</td>
            <td>10000</td>
            <td><input type="submit" name="delete" value="Delete" /></td>
        </tr>
    </table>

需求:新增按钮:将员工的姓名、邮箱和薪水添加到表格中;

删除按钮:confirm()提示是否将"员工名字"信息删除?确定将整行员工信息删除,否则什么也不做。

新增按钮要做的事情,其实就是文章一开始要叙述的东西,也就是把某物品装进大袋子的事情。

删除按钮,其实只要能获取到它的父节点,也就解决了。

代码如下:

<script type="text/javascript">
    window.onload = function() {
        //删除按钮触发的函数
        function deleteInfo(node) {
            var currentTr = node.parentNode.parentNode;
            var name = currentTr.getElementsByTagName("td")[0];
            var flag = confirm("是否将\"" + name.innerHTML + "\"信息删除?");
            //当点击确定后触发事件
            if (flag) {
                /*
                第一个parentNode是td,第二个parentNode是tr,第三个parentNode是table
                也就是说根据delete按钮所在的列所在的行所在的表格中删除掉整行(很拗口是吧?)
                 */
                node.parentNode.parentNode.parentNode
                        .removeChild(node.parentNode.parentNode);
            }
        }

        var addBtn = document.getElementById("add");
        addBtn.onclick = function() {
            //3个引用的value值可以获取到文本框的值
            var nameNode = document.getElementById("name");
            var emailNode = document.getElementById("email");
            var salaryNode = document.getElementById("salary");

            //获取table元素节点
            var tableNode = document.getElementsByTagName("table")[1];
            //创建一个tr节点,后面会添加到table元素节点中
            var newTrNode = document.createElement("tr");
            //创建一个td节点,后面会添加到tr元素节点中
            var newName = document.createElement("td");
            //创建一个文本节点,添加到td元素节点中
            newName.appendChild(document.createTextNode(nameNode.value));

            var newEmail = document.createElement("td");
            newEmail.appendChild(document.createTextNode(emailNode.value));

            var newSalary = document.createElement("td");
            newSalary.appendChild(document.createTextNode(salaryNode.value));

            var newDelete = document.createElement("td");
            var newDeleteBtn = document.createElement("input");
            newDeleteBtn.type = "button";
            newDeleteBtn.name = "delete";
            newDeleteBtn.value = "Delete";
            //新创建的button也应该能触发删除函数
            newDeleteBtn.onclick = function() {
                deleteInfo(this);
            }
            newDelete.appendChild(newDeleteBtn);

            newTrNode.appendChild(newName);
            newTrNode.appendChild(newEmail);
            newTrNode.appendChild(newSalary);
            newTrNode.appendChild(newDelete);

            tableNode.appendChild(newTrNode);
        }

        //为所有已经存在的删除按钮添加删除函数事件
        var deleteNodes = document.getElementsByName("delete");
        var length = deleteNodes.length;
        for (var i = 0; i < length; i++) {
            deleteNodes[i].onclick = function() {
                deleteInfo(this);
            }
        }
    }
</script>

今天就到这里,我们下次再见!

时间: 2024-10-24 23:25:13

再战JavaScript的相关文章

【UOJ】【UR #2】猪猪侠再战括号序列(splay/贪心)

http://uoj.ac/problem/31 纪念伟大的没有调出来的splay... 竟然那个find那里写错了!!!!!!!!!!!!! 以后要记住:一定要好好想过! (正解的话我就不写了,太简单了.. #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #

uoj #31. 【UR #2】猪猪侠再战括号序列 贪心

#31. [UR #2]猪猪侠再战括号序列 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/31 Description 大家好我是来自百度贴吧的_叫我猪猪侠,英文名叫_CallMeGGBond. 我不曾上过大学,但这不影响我对离散数学.复杂性分析等领域的兴趣:尤其是括号序列理论,一度令我沉浸其中,无法自拔.至于OI算法竞赛,我年轻时确有参加,虽仅获一枚铜牌,但我素性淡泊,毫不在意,毕竟那所谓FFT.仙人掌之类

再谈javascript图片预加载技术

图片预加载技术的典型应用: 如lightbox方式展现照片,无疑需要提前获得大图的尺寸,这样才能居中定位,由于javascript无法获取img文件头数据,必须等待其加载完毕后才能获取真实的大小然后展示出来,所以lightbox显示的图片的速度体验要比直接输出的差很多,而本文说提到的预加载技术主要针对获取图片尺寸. 一段典型的使用预加载获取图片大小的例子: var imgLoad = function (url, callback) {    var img = new Image();   

再战MFC中的消息机制

时间一长就忘记MFC中的很多东西了,所以需要把这些基本的知识理一理,为能深入到MFC内部结果原理,现在需要把这些东西让度娘吐出来: 1.MFC中的消息队列情况(一个消息队列可以容纳多少消息) 原文可以在msdn中搜索"About Messages and Message Queues "找到: The system maintains a single system message queue and one thread-specific message queue for each

[BZOJ 4350]括号序列再战猪猪侠 题解(区间DP)

[BZOJ 4350]括号序列再战猪猪侠 Description 括号序列与猪猪侠又大战了起来. 众所周知,括号序列是一个只有(和)组成的序列,我们称一个括号 序列S合法,当且仅当: 1.( )是一个合法的括号序列. 2.若A是合法的括号序列,则(A)是合法的括号序列. 3.若A,B是合法的括号序列,则AB是合法的括号序列. 我们考虑match[i]表示从左往右数第i个左括号所对应的是第几个右 括号,现在他得到了一个长度为2n的括号序列,给了你m个信息,第i 个信息形如ai,bi,表示match

再战斐波那契-Fibonacci+gcd

再战斐波那契 单点时限: 1.0 sec 内存限制: 512 MB 小z 学会了斐波那契和 gcd 后,老师又给他出了个难题,求第N个和第M个斐波那契数的最大公约数,这可难倒了小z ,不过在小z 的再三请求下,老师又告诉他了个条件,gcd(N,M)∈[1,90].可是,笨拙的小z 还是不会,于是请求你帮他解答这个问题. 输入格式: 输入包括 T 组,T∈[1,10]. 接下来 T 行,每行两个整数 N,M, 表示斐波那契的第 N 项和第 M 项,(N,M∈[1,1018]). 输出格式: 输出包

从抗击SARS到再战新型冠状病毒,中国企业家如何抓住商机?

从抗击SARS到再战新型冠状病毒,中国企业家如何抓住商机?时间倒流17年前,中国遇到了前所未有的魔怔,它使我们惊慌失措,使我们失去了亲人和朋友,使我们企业关门,濒临倒闭.它就是"重症急性呼吸综合征-非典".绝望时刻,不少企业家迎难而上为这场看不见敌人的战争,捐赠物资和人力,给战役一场反击,使得企业转危为安,甚至蓬勃向上.京东如何战胜"SARS事件"据刘强东回忆到:我们也着急,怎么办呢?公司大概能支撑6个月,如果非典六个月之内不过去,京东就会面临第二次的倒闭.第一次就

移花接木—— 再谈javascript中的 call 与 apply

在JavaScript中,call 和 apply 是Function对象自带的两个方法,这两个方法的主要作用是改变函数中的this指向,从而可以达到`接花移木`的效果.本文将对这两个方法进行详细的讲解,并列出几个关于call和apply的经典应用场景. call(thisArgs [,args...]) 该方法可以传递一个thisArgs参数和一个参数列表,thisArgs指定了函数在运行期的调用者,也就是函数中的this对象,而参数列表会被传入调用函数中.thisArgs的取值有以下4种情况

再谈javascript面向对象编程

前言:虽有陈皓<Javascript 面向对象编程>珠玉在前,但是我还是忍不住再画蛇添足的补上一篇文章,主要是因为javascript这门语言魅力.另外这篇文章是一篇入门文章,我也是才开始学习Javascript,有一点心得,才想写一篇这样文章,文章中难免有错误的地方,还请各位不吝吐槽指正 吐槽Javascript 初次接触Javascript,这门语言的确会让很多正规军感到诸多的不适,这种不适来自于Javascript的语法的简练和不严谨,这种不适也 来自Javascript这个悲催的名称,