好久没来简书发文了,惭愧惭愧。主要是因为我自7月份左右将自建的博客弄到了网上,所以一直在自己的博客上写。至于为什么不同时发到简书,主要是因为我懒……不过,自己的博客建的对SEO很不友好,没人到我博客上,所以我又回到简书了,哈哈。
废话不多说,今天写的东西是我在做毕设的时候弄出来的,是三个JS插件,分别是 自定义单选框 , 自定义下拉列表 , 自定义日历卡片 。先放出预览图:
不要吐槽我的审美……作品链接就放到最底下了,大家可以下下来看看,我做了部分兼容(火狐,chrome,Edge)。另外不准备详细说明做法,更多的是说说想法。
单选框
这个最简单,我的想法是
- 通过传递的dom元素(其中包含
input#radio
)来找寻其中的input#radio
节点- 生成一个元素(如
i
),用它来替换原radio元素(隐藏原radio)- 将原radio中的属性复制到新radio中
- 添加事件,保证新生成的radio是单选
最后生成的dom,如下面dom节点:
代码如下:
function selfRadio(dom) {
// 该dom元素不存在
if(typeof dom == 'undefined' || dom.length == 0) return false;
// 获取该dom下面的input#radio元素
var oInput = dom.getElementsByTagName('input');
var aRadio = [];
for (var i = 0,j=0; i < oInput.length; i++) {
if(oInput[i].getAttribute('type') == 'radio') {
// 获取上一级节点
var oParNode = oInput[i].parentNode;
// 采用i作为新的input#radio
var oRadio = document.createElement('i');
oRadio.setAttribute('name' , oInput[i].getAttribute('name'));
oRadio.setAttribute('value' , oInput[i].getAttribute('value'));
oRadio.setAttribute('class' , 'selfradio');
// 隐藏原来的input#radio
oInput[i].style.display = 'none';
// 插入到web中
oParNode.insertBefore(oRadio , oInput[i]);
// 将节点存储 便于建立事件
aRadio[j++] = oRadio;
}
}
for(var i = 0; i < aRadio.length; i++) {
aRadio[i].index = i;
// 建立点击事件
aRadio[i].addEventListener('click' , function() {
for (var i = 0; i < aRadio.length; i++) {
if(i != this.index) {
aRadio[i].setAttribute('class' , 'selfradio');
}
}
aRadio[this.index].setAttribute('class' , 'selfradio change');
});
}
}
下拉列表
通过传递的dom元素,找出该dom下所有的select元素
// 获取select节点
var oSelect = dom.getElementsByTagName('select');
然后,循环的去重建select
元素。在创建中第一部分,我称为标题,结构如下:
<div class="title" value="">
<em>请选择</em>
<i class="iconfont icon-xiala"></i>
</div>
第二部分就是原来的option
,结构如下
<div class="option">
<ul class="option_ul">
<li value="1">游戏1</li>
<!-- 更多的li -->
</ul>
</div>
而新建的option展现内容的获取与自定义的单选框类似,都是将原来dom中的属性复制过来。
最后,重要的是将事件添加上去,保证点击标题展开option,点击option该option被选中
// 下拉图标切换
oSelfTitle.addEventListener('click' , function() {
oSelfSelect.setAttribute('class' , 'selfselect auto');
oSelfIcon.setAttribute('class' , 'iconfont icon-xiala-copy');
});
// 下拉列表选择
var oLi = oSelfUl.getElementsByTagName('li');
for (var i = 0; i < oLi.length; i++) {
oLi[i].index = i;
oLi[i].addEventListener('click' , function() {
oSelfSelect.setAttribute('value' , oLi[this.index].getAttribute('value'));
oSelfText.innerHTML = oLi[this.index].innerHTML;
oSelfSelect.setAttribute('class' , 'selfselect');
oSelfIcon.setAttribute('class' , 'iconfont icon-xiala');
});
}
日历
自定义日历控件一开始是采用过程式来写的,后来换成了面向对象的方式。还是简单的说说我的想法,毕竟不是很复杂的东西。
日历的生成主要分成三个部分,年,月,日。年和月的创建比较简单,利用for循环就可以了,然后添加个点击事件,用于获取你选择的年和月。
稍微麻烦的是具体日期的生成,你需要注意本月开始的星期数。
这里对JS的时间对象的应用很重要,否则不仅本月开始的星期数以计算,你还要注意闰平年的问题,而有了时间对象都不是问题。
通过时间对象中的getDay
函数可以获取一周是哪一天(0为周末),如果希望知道 2016年11月 从星期几开始,只要传递 2016年11月1日 给时间对象,并利用getDay
来获取即可
// 注意JS时间对象月计算是从0开始
var sNowWeek = new Date(2016,10,1).getDay();
console.log(sNowWeek); // 2
同样的获取每月的具体有多少天,就利用getDate
,它返回一个月中某一天:
// 想要返回一月天数,时间对象中天数参数以0代替
var sNowDays = new Date(2016,10,0).getDate();
console.log(sNowDays); // 30
获取了一月的天数就可以利用for循环创建了,当然不要忘了添加事件(当时做的时候我是利用for循环一个个添加事件的,现在想来比较蠢,可以用事件委托来完成,以后修改吧……)