给文章或其他作品打分是很常见的功能,不过我之前做的网站里都没用到这个功能,于是今天自己写了个demo。
可以设置任意颗星星数;
可以设置一开始显示评分还是不显示评分;
每个人只能打分一次。
这个demo一星一分。
代码如下:
<div class="rate" data-value="0"> <i title="1分"></i><i title="2分"></i><i title="3分"></i><i title="4分"></i><i title="5分"></i><i title="6分"></i><i title="7分"></i><i title="8分"></i><i title="9分"></i><i title="10分"></i> </div> <style type="text/css"> .rate{height: 26px;} .rate i{display: inline-block;width: 26px;height: 100%;background-image: url(/f/pixiv_star.png);cursor: pointer;background-position: 0 0;} .rate .bgNone{background-position: 0px 0px;} .rate .bgHover{background-position: -26px 0px;} .rate .bgSure{background-position: -52px 0px;} .cursordef i{cursor:default;} </style> <script src="ratev0.1.js"></script>
外层div有个data-value属性,表示预设评分。设置为0则表示不显示这幅作品的评分,星星都不亮;大于0则为当前得分,并且会亮起对应的星星。
里面的每个i标签是一个星星,数量可以随意调整。
css样式里设置宽高来布局,并设置背景图片。把三种星星样式做到一张图片上,使用背景定位让三个样式显示三种背景图片。分别是bgNone(这个星星不亮的图案),bgHover(鼠标经过时星星亮起来),bgSure(这个星星有评分)。
当用户点击了一个星星后,会产生评分,之后就不能再点击了。
网页评分工具demo
// ==UserScript== // @name 去除贴吧视频 // @namespace http://www.saber.love/?p=3014 // @version 0.1 // @description 去除百度贴吧的视频 // @author 雪见仙尊 // @match http://tieba.baidu.com/* // @grant none // @run-at document-end // ==/UserScript== function removeVideoElement () { var topVideo=document.querySelector(".video_frs_head"); //贴吧顶部的视频区域 if (!!topVideo) { topVideo.parentNode.removeChild(topVideo); } var videoPrve=document.querySelectorAll(".threadlist_video"); //帖子列表里未播放的视频 for (var i = videoPrve.length - 1; i >= 0; i--) { videoPrve[i].parentNode.removeChild(videoPrve[i]); } var videoTag=document.querySelectorAll("video"); //网页上正在播放的视频 for (var i = videoTag.length - 1; i >= 0; i--) { videoTag[i].parentNode.removeChild(videoTag[i]); } } removeVideoElement(); var removeVideoT=setInterval(removeVideoElement,1000);
手机版百度贴吧现在能发视频了,但是百度在电脑端推广视频就太无耻了。
顶部的视频(如剑网三吧顶部就有)竟然自动播放。(这个导致我chrome的gpu加速经常出问题,网页变成一片片的黑块)
帖子列表里的视频,虽然一开始显示的是预览图,但是你鼠标一经过就开始播放了,而且还停不了,必须再点一下,等视频尺寸变大,才又停止播放的按钮。
感觉自己宛如一个智障一样被玩弄,所以写了个脚本去除视频。帖子里的视频也会去掉,断子绝孙好爽的。(优酷土豆等外部视频不受影响)
去除百度贴吧的视频
document.body.insertAdjacentHTML('beforeend', `<div id="shouUrl" style="position: fixed; right: 0px; top: 100px; padding: 15px 20px; background: rgb(46, 178, 234); color: rgb(255, 255, 255); border-radius: 5px; text-align: center; line-height: 24px; font-size: 16px; cursor: pointer;">显示大图url</div>`); document.querySelector("#shouUrl").addEventListener("click", () => { let newW = window.open(); document.querySelectorAll(".img-wrap img").forEach(el => { newW.document.write(/.*(\.jpg|\.png)/.exec(el.src)[0].replace(/p\d.*banciyuan/, 'img-bcy-qn.pstatp.com') + '<br>'); }); });
使用方法:
打开任意的cos作品页面,然后在浏览器的控制台里执行上面的代码。
你也可以在此安装本代码的UserScript版(推荐)。
当手动执行了代码或点击UserScript生成的按钮之后,浏览器会打开一个新的页面,并显示作品上所有图片的url:
复制全部网址,用下载软件批量下载即可。
注意:
1.由于本工具会打开一个新页面并输出url,所以当你遇到脚本运行完了却没有弹出新页面的时候,请看一下是不是弹窗是被浏览器拦截了。
2.由于半次元图片的文件名是随机生成的字符,所以下载下来的图片顺序可能是混乱的。
获取半次元(bcy.net)coser作品的大图网址
计算第二天的日期的要点在于,在跨月时进入下一月,在跨年时进入下一年。其他时间只要天数加1就行。所以找出每个月的最后一天就ok了。
function tomorrow_date (y,m,d){ //参数里的月份需要是自然月。也就是说月份+1这步在传参前就设置好 var run = false; //判断是否是闰年 if (!(y%4)) { //如果年份是4的整数倍 if (!(y%100)) { //如果是整百年 if (!(y%400)) { //如果是400的整数 run = true; } }else{ run = true; } } if(d==28&&m==2){ //2月28日 if(!run) { //非闰年 d=1; m++; }else{ //闰年 d++; } }else if(d==29&&m==2){ //2月29日 d=1; m++; }else if(d==30&&(m==4||m==6||m==9||m==11)){ //30天的月份里的第30天 d=1; m++; }else if(d==31){ //31天的月份里的第31天 d=1; if (m==12){ //如果是12月则进入下一年 m=1; y++; }else{ m++; } }else{ //如果今天不是月份的最后一天 d++; } return "明天是"+y+"年"+m+'月'+d+'日'; } var myDate = new Date(); var y = myDate.getFullYear(); var m = myDate.getMonth()+1; //因为js的月份是从0开始的,所以这里月份+1 var d = myDate.getDate(); document.write(tomorrow_date(y,m,d));
感谢TianMao指出闰年的问题~另外他提出了使用Date对象的setDate方法来计算下一天的办法。这个办法很简便,当我们重设了日期(第几天)后,JavaScript会自动更新Date对象的月份、年份,这样就我们就不用自己写上面的判断了。
var myDate = new Date(); myDate.setDate(myDate.getDate()+1); var y = myDate.getFullYear(); var m = myDate.getMonth()+1; var d = myDate.getDate(); console.log(y,m,d);
JavaScript计算明天的日期
刚才我整理出来了一百多行url,想去掉重复的。于是我到JavaScript里建了个数组,把这些url都转成了数组里的字符串。之后我找到了一个使用hashtable(哈希表)的去重算法,比循环更简便:
function unique(arr) { var result = [], hash = {}; for (var i = 0, elem; (elem = arr[i]) != null; i++) { if (!hash[elem]) { result.push(elem); hash[elem] = true; } } return result; }
上面的方法是有缺陷的,今天在知乎专栏看到了更好的方法,用的是ES6的set类型。set类型不允许添加重复项,所以我们根本不用自己去重了,直接把数组转换文set对象就可以去掉重复项了:
function unique(arr){ var set = new Set(arr); return Array.from(set); }
JavaScript数组去重的一个方案
JavaScript有个叫“变量提升”的特性,意为:
在函数里声明的所有变量会被提升到函数顶部声明(但不涉及到赋值)。
示例:
var a=0; !function(){ alert(a); var a=1; }()
在函数外声明了变量a=0,之后在函数里重新声明了a=1。
在这中间我们弹出a,它的值不是0,而是undefined。这就是变量提升导致的。发生变量提升之后,函数里声明的a被提升到函数顶部声明了(但这并不涉及到赋值),所以代码实际上相当于这样:
var a=0; !function(){ var a; alert(a); a=1; }()
所以如果函数外已经声明了一个变量,那么就不要在函数内重复声明它,这样将会触发变量提前,可能会造成一些问题。
如果需要在函数内重复声明,那么将这些变量在函数顶部先声明但不赋值(就是写得和变量提升后的实际代码一样),可以让代码更直观。
其实这个概念是我昨天发布了搜索bilibili评论工具时,8q给我指出的。今天看书很巧的也看到了这个地方,弄清楚了。
JavaScript中的变量提升
此工具已失效!
我用JavaScript写了一个小工具,在b站视频播放页面执行,可以在当前视频的所有评论里查找指定用户发出的评论。
举个例子:你(或是别人)在某视频下发了一条评论,但没记住楼层。现在,如果你想要在众多评论里找到自己(或其他某个人)发的评论,可以使用本工具。
本工具可以搜索完所有的楼层,但查找楼中楼时,本工具只能查找到每个楼中楼的前5条回复(所以对于楼中楼,可能会有遗漏)。
如果你有油猴扩展,可以到UserScript安装页面安装此用户脚本。
如果你没有油猴扩展,你可以手动执行代码。下面提供两种执行方式:
1.控制台执行以下代码,它会远程加载js文件来执行:
var newscript=document.createElement("script"); newscript.src="/f/bilibili_comment_search.js"; document.body.appendChild(newscript);
这种方法的话,由于我的js的url是http的,所以在B站的https页面里无法执行,可以在地址栏把b站这个页面的网址手动改成http的。
2.下载js文件,然后手动复制其代码到控制台执行。
代码执行之后,在视频上方会出现“查找评论”的文字:
点击它,输入想查找的用户的id(就是打开TA主页时网址里的数字)。之后,每当找到这个人发的一条评论,就会在控制台输出该评论的楼层信息。
注意要在控制台看哦~我们可以根据页数和楼层数提示去找到这条评论。
如果工具搜索完了所有评论,会弹出搜索到了几条结果。如果你想中途停止搜索,点击视频上方的提示文字即可。
Read More →
在bilibili评论区搜索某人评论的工具
假设现在获得了一些格式化的时间/日期字符串,如何用JavaScript对其排序呢?
理想的办法就是用Date.parse()方法将这些字符串解析为时间,直接比较它们的毫秒数。示例如下:
function sortDate(sortby) { return function(object1, object2) { var value1 = Date.parse(object1); var value2 = Date.parse(object2); if(value1>value2){ return (sortby==="desc")?-1:1; }else if(value1<value2){ return (sortby==="desc")?1:-1; } } } var a=["2017/4/20","2016/6/3","2016/7/1","2016/7/27","2017/8/4","2016/10/13","2016/12/27","2017/1/14","2017/2/3","2017/2/3","2017/2/3","2017/2/3","2017/2/3","2017/2/3","2017/2/3","2017/3/1","2017/3/1","2017/3/1","2017/3/1","2017/3/1","2017/3/1","2017/3/1","2017/3/23","2017/3/31","2017/5/19","2017/5/19","2017/6/2","2017/6/24","2017/6/24","2017/6/24","2017/9/1","2017/9/5","2017/12/12","2018/2/19","2018/9/26","2017/5/19","2017/3/9","2017/7/14","2017/5/19","2017/5/19"]; a.sort(sortDate("desc"));
结果如下:
上例定义了一个sortDate函数,我们在数组的sort方法里将它作为参数。如果不手动设置排序参数为desc,那么这个函数将始终按升序排序。
标准的时间/日期格式如下:
"2017/4/20 16:20:30"
当然,只用一部分,或者改变下连接符,也是可以解析的。
Read More →
JavaScript对日期排序
因为JavaScript水平太渣,以前我都是用JQuery来做ajax。现在看了些资料,感觉原生的写法也不难,而且兼容性也已经不错了,所以跟着练一练。
同步的ajax请求:
var xhr=new XMLHttpRequest(); xhr.open("get","http://saber.我爱你/demo/checknew.php",false); xhr.send(null); if (xhr.status===200) { alert(xhr.responseText); }else{ alert("发生了异常,状态码为"+xhr.status+","+xhr.statusText); }
返回的数据里有如下属性:
responseText:作为响应主体被返回的文本。
responseXML:如果响应的内容类型是"text/xml"或"application/xml",这个属性中将保存包含着响应数据的XML DOM 文档。
status:响应的HTTP 状态。
statusText:HTTP 状态的说明。
异步的ajax请求:
var xhr=new XMLHttpRequest(); xhr.onreadystatechange=function(){ if (xhr.readyState===4) { if (xhr.status===200) { alert(xhr.responseText); }else{ alert("发生了异常,状态码为"+xhr.status+","+xhr.statusText); } } } xhr.open("get","http://saber.我爱你/demo/checknew.php",true); xhr.send(null);
检测状态的部分也可以这样写:
xhr.onload=function (argument) { if (this.status == 200) { //…… } }
异步请求除了在xhr.open里将最后的参数设置为true之外,在接收数据时也和同步请求不同。异步请求通过检查xhr对象的readyState属性来判断请求处在哪个阶段。当readyState为4时,表示接收到了数据,并且数据可用。
我们通过onreadystatechange事件来检测readyState的值,当值为4时即可对数据进行处理。
另外,在接收到响应之前还可以调用abort()方法来取消异步请求。即xhr.abort(); 。
原生Ajax的简单实例
<img src="/f/head15.jpg" id="stwRight"> <img src="/f/saber%E8%A1%A8%E6%83%85_1_1.jpg" id="stwCenter"> <img src="/f/x.png" id="swtClose"> <style type="text/css"> #LRdiv0,#LRdiv1{display:none !important;} #stwRight{position: fixed;right: 0;top: 60px;display: none;z-index: 999;cursor: pointer;} #stwCenter{position: fixed;display: none;width: 400px;height: 350px;left: 50%;margin-left: -200px;top: 50%;margin-top: -175px;z-index: 999;cursor: pointer;} #swtClose{position: fixed;display: none;width: 24px;height: 24px;left: 50%;margin-left: 175px;top: 50%;margin-top: -175px;z-index: 9999;cursor: pointer;} </style> <script type="text/javascript"> window.onload=function(){ function showSwtC(){ document.getElementById("stwCenter").style.display="block"; document.getElementById("swtClose").style.display="block"; } function showSwtR(){ document.getElementById("stwRight").style.display="block"; } function hideSwtC(){ document.getElementById("stwCenter").style.display="none"; document.getElementById("swtClose").style.display="none"; } function hideSwtR(){ document.getElementById("stwRight").style.display="none"; } function openSwt(){ LR_HideInvite();openZoosUrl();return false; } showSwtR(); setTimeout(function(){ hideSwtR(); showSwtC(); },4000); document.getElementById("stwRight").onclick=function(){ openSwt(); } document.getElementById("stwCenter").onclick=function(){ hideSwtC(); showSwtR(); openSwt(); setTimeout(function(){ hideSwtR(); showSwtC(); },8000); } document.getElementById("swtClose").onclick=function(){ hideSwtC(); showSwtR(); setTimeout(function(){ hideSwtR(); showSwtC(); },8000); } } </script>
侧边浮窗没做关闭按钮。
因为openSwt()里用了商务通自带的函数openZoosUrl(),所以页面上还是得加载商务通代码。如果把openSwt()改成直接用网址跳转,则不用加载商务通代码。
上面商务通不仅样式是我们自己做的,显示、隐藏的逻辑也需要自己定义。实际上对于有商务通代码的页面,我们可以直接利用商务通自身的函数来“偷梁换柱”,打开我们自己的商务通图片。
var sTimer = setInterval(function(){ if(typeof LR_showInviteDiv != "undefined"){ window.LR_showInviteDiv = function(){ //此处改写了商务通显示邀请框的函数 showSwt(); } clearInterval(sTimer); } },100);
LR_showInviteDiv是显示邀请框的函数,如果页面上有这个函数,则改写它,让它执行showSwt,也就是我们自己定义的一个函数,显示自己的邀请框。
恩……我对这这个代码研究了好久,发现这个办法并没有多方便,浪费时间。唯一的优点是不用写css来隐藏商务通的邀请框了。另外改写商务通的这个函数会导致商务通客户端发送邀请失败。麻烦。