转载自我的个人博客
欢迎大家批评指正
包括5部分:
小练习1-处理用户输入
小练习2-日期对象的使用
小练习3:轮播图
小练习4:输入提示框
小练习5:界面拖拽交互
源码地址
task0002 在线Demo
小练习1:处理用户输入
这里直接可以利用原来写过的
util.js
。所以应该不是特别难。主要考察对字符串的操作,以及正则表达式的使用
任务描述
在task0002
目录下创建一个task0002_1.html
文件,以及一个js
目录和css
目录,在js
目录中创建task0002_1.js
,并将之前写的util.js
也拷贝到js
目录下。然后完成以下需求。
第一阶段
在页面中,有一个单行输入框,一个按钮,输入框中用来输入用户的兴趣爱好,允许用户用半角逗号来作为不同爱好的分隔。
当点击按钮时,把用户输入的兴趣爱好,按照上面所说的分隔符分开后保存到一个数组,过滤掉空的、重复的爱好,在按钮下方创建一个段落显示处理后的爱好。
实现
根据题目要求,这个地方比较简单,可以直接利用前面写过的一些函数,分成四步,进行。
使用正则表达式来对字符串进行分割操作。
uniqArray
函数进行去重操作。for循环,
trim
函数对数组项进行去除首尾空格,用来处理,该项为空的情况。innerHTML进行输出。
html:
task0002_1.js
中的js:
//自执行的匿名函数
(function handle_1() {//其实这里没必要使用id因为数据那么少$函数直接获取标签就行var inp = $("#user_input");var out = $("#user_output");$.click("#btn", function () {var value = inp.value.split(/\,|\,/); //1.根据半角逗号分割成数组。var unValue = uniqArray(value); //2.数组去重for (var i = 0, len = unValue.length; i
})();
第二阶段
单行变成多行输入框,一个按钮,输入框中用来输入用户的兴趣爱好,允许用户用换行、空格(全角/半角)、逗号(全角/半角)、顿号、分号来作为不同爱好的分隔。
当点击按钮时的行为同上
实现
看题目描述,主要是对于第一步进行修改,第一阶段只要求对半角逗号进行处理,但是在第二阶段中,需要对“换行、空格(全角/半角)、逗号(全角/半角)、顿号、分号”进行处理。
主要是考察对于正则表达式的应用。
只需要对var value = inp.value.split(/\,|\,/);
进行更改如下:
var value = inp.value.split(/\n|\s+|\,|\,|\、|\;|\;/);
需要注意的是:在正则表达式进行匹配这些符号时最好是前面加上转义字符。
第三阶段
用户输入的爱好数量不能超过10个,也不能什么都不输入。当发生异常时,在按钮上方显示一段红色的错误提示文字,并且不继续执行后面的行为;当输入正确时,提示文字消失。
同时,当点击按钮时,不再是输出到一个段落,而是每一个爱好输出成为一个checkbox,爱好内容作为checkbox的label。
实现
嗯,其实这里按照题目要求应该要实时监听输入值变化,但是那样太麻烦了,,所以就直接在点击按钮的时候判断了。
直接判断数组长度就行了。。输入为空时,判断字符串=“”。
输出
checkbox
这里不过多的设置了,只是演示。
最终完成
html:
输入的爱好数量不能超过10个,或什么都不输入
js:
(function handle_1() {var inp = $("#user_input");var out = $("#user_output");$.click("#btn", function () {var value = inp.value.split(/\n|\s+|\,|\,|\、|\;|\;/); //分割成数组。var unValue = uniqArray(value); //数组去重var i = 0;var len = unValue.length;if (len > 10 || unValue == "") {$("p").style.disautoPlay = "block";} else {$("p").style.disautoPlay = "none";for (; i
})();
在线演示:小练习1:处理兴趣列表
小练习2:日期对象的使用
任务描述
在和上一任务同一目录下面创建一个task0002_2.html
文件,在js
目录中创建task0002_2.js
,并在其中编码,实现一个倒计时功能。
界面首先有一个文本输入框,允许按照特定的格式
YYYY-MM-DD
输入年月日;输入框旁有一个按钮,点击按钮后,计算当前距离输入的日期的00:00:00有多少时间差
在页面中显示,距离YYYY年MM月DD日还有XX天XX小时XX分XX秒
每一秒钟更新倒计时上显示的数
如果时差为0,则倒计时停止
实现思路
了解日期对象
这里主要是考察的对于日期对象的使用。
new Date()
。如果没有输入任何参数,则Date的构造器会依据系统设置的当前时间来创建一个Date对象。表示当前系统时间。
//时间对象创建的几种方式。
var today = new Date();
var birthday = new Date("December 17, 1995 03:24:00");
var birthday = new Date("1995-12-17T03:24:00");
var birthday = new Date(1995,11,17);
var birthday = new Date(1995,11,17,3,24,0);
Date对象中处理时间和日期的常用方法:详细内容在MDN上
实现思路
这里我并没有一开始就直接进行数据获取的部分,而是进行了任务分解,如下:
第一阶段
先在使用写好的
ul>li
标签下,。添加3个事件mouseover
、mouseout
、click
。实现点击li使其值变成输入框内的值。(直接使用事件代理)-
对输入框添加键盘事件(对,你没看错,只有在聚焦在输入框时才触发)
获取当前高亮的li。没有则设第一个为高亮
active
。判断
keyCode
使用键盘下键,使用nextElementSibling
方法获取下一个节点(向上同理),取消当前的active
,设置下一个为active
。(使用键盘上下选中的效果,处理完成)判断
keyCode
,获取当前状态为active
的值,实现回车时,把其设为input
的值。
-
需要注意的地方:
在移除高亮状态时,最好是遍历一遍。因为键盘与鼠标划过有可能同时触发,导致有多个高亮。
错误处理
第二阶段
删除原来的
ul>li
html部分的li
。添加对于输入框进行实时监听(这部分不在这里展开讲,如何实现大家去google吧,因为一展开就太多要说的了)。
给个参考:实时监听输入框值变化
使用AJAX获取服务器上的数据,解析,遍历,并进行数据匹配。
匹配成功显示
ul
,否则设为none
。使用正则表达式的
match
方法,来获取匹配成功的把部分,使用span
进行高亮显示。并且插入ul
改造第一阶段的函数:
因为是使用的事件代理,直接对
ul
添加事件,所以需要修改的部分不是很多。click
和enter
部分获取的值,因为span
标签的存在,需要使用正则进行处理,输出删除span
后的值。
在线演示:小练习4:输入框即时提示
小练习5:界面拖拽交互
实现一个可拖拽交互的界面
如示例图,左右两侧各有一个容器,里面的选项可以通过拖拽来左右移动
被选择拖拽的容器在拖拽过程后,在原容器中消失,跟随鼠标移动
注意拖拽释放后,要添加到准确的位置
拖拽到什么位置认为是可以添加到新容器的规则自己定
注意交互中良好的用户体验和使用引导
实现思路:
第一步:封装拖拽函数
开一个DEMO页面,实践如下:
了解应该用到的事件,
onmousedown
、onmousemove
、onmouseup
。-
思考对谁添加事件?
在鼠标点击
div
时,对div
添加onmousedown
,表示鼠标按下。在事件内给
document
添加onmousemove
。(为啥给document
加呢?因为给div
加在移动过快时会跳出去)表示鼠标移动。并且添加
document
添加onmouseup
,表示鼠标已经抬起,清除移动事件,以及本身。
-
思考如何设置对象的位置?
直接获取鼠标的位置并设置给
div
行不行呢?试试吧!显然,会出现问题,点击鼠标就到div
左上角去了。那么怎么改变呢?获取鼠标在
div
中的位置?对。就这样,在鼠标按下时记录鼠标在div
中的位置.在鼠标移动时,用当前的位置,减去刚刚的位置,这就是应该的值!
别忘了鼠标抬起时,需要清除事件,不然鼠标就粘住了。
这里用到了event,事件对象的相关概念,推荐观看慕课网的视频。DOM事件探秘
善用this。
扩展
/*** 鼠标拖拽函数。* @param {HTMLElement} element 需要拖拽的对象*/
function setDrag(element) {addEvent(element, "mousedown", onmousedown);//鼠标按下function onmousedown(ev) {var oEvent = ev || event;var disX = oEvent.clientX - this.offsetLeft;var disY = oEvent.clientY - this.offsetTop;var that = this;addEvent(document, "mousemove", onmousemove);addEvent(document, "mouseup", onmouseup);/*** 鼠标移动*/function onmousemove(ev) {var oEvent = ev || event;that.style.left = oEvent.clientX - disX + "px";that.style.top = oEvent.clientY - disY + "px"}/*** 鼠标抬起删除事件*/function onmouseup() {removeEvent(document, "mousemove", onmousemove);removeEvent(document, "mouseup", onmouseup);}}
}
第二步:布局转换函数
两个参数,第一个参数,传入父级对象。第二个参数传入标签名,
循环,使用数组,对象,获取标签当前元素的位置
left
,top
。(offsetLeft
)。这里不能使用获取实际样式函数,因为本身就需要获取其相对父元素的位置。-
第二个循环
设置
left
,top
值。设置绝对定位。
取消原有的
margin
值。
调用函数,把对象从文档流布局,变成绝对定位布局。
/*** 布局转换函数* @param {HTMLElment} element HTML对象* @param {string} childEle 其内需要转换的标签名*/
function toPosition(element, childEle) {var eleArr = element.getElementsByTagName(childEle);var aPos = [];//for (var i = 0, len = eleArr.length; i
在线演示:小练习5:拖拽交互
第三步:实现拖拽
前面我们已经实现了
setDrag(element)
函数,常规方法就是直使用循环,然后传入element
。
但是,为什么不用事件代理呢?
特别简单,只需要对上面写的函数进行一些简单的改装。
delegateEvent(parentElement, "li", "mousedown", function (ev) {
//此处是原函数中的内容。
}
现在知道为什么上面的函数会用到this了吧?
第四步:碰撞检测函数
先来看张图:
是不是有瞬间豁然开朗的感觉呢?
获取相关值,只需要考虑不碰不上的情况就行了!。如下:
/*** 碰撞检测函数* @param {object} obj1 对象1* @param {object} obj2 对象2* @returns {boolean} 碰撞时返回true,否则反正false*/
function hitDetection(obj1, obj2) {//对象1的相关值var l1 = obj1.offsetLeft;var r1 = obj1.offsetLeft + obj1.offsetWidth;var t1 = obj1.offsetTop;var b1 = obj1.offsetTop + obj1.offsetHeight;//对象2的相关值var l2 = obj2.offsetLeft;var r2 = obj2.offsetLeft + obj2.offsetWidth;var t2 = obj2.offsetTop;var b2 = obj2.offsetTop + obj2.offsetHeight;if (r1
}
第五步:处理各种碰撞情况
这里讲起来就太复杂了。源代码中注释还是比较详细的,有兴趣可以看下