完整代码可在最后代码块查看呦!!!
※本贴代码,可用用于油猴脚本,支持浏览器F12Console控制台直接运行
有一段时间呢在百度文库查询资料时被限制了复制,说什么复制次数已达上限,那个
难受鸭!!于是我打开了传说中的F12,意外的发现了一个功能
就是很意外的发现我所选中的文字会在我的Console视图中显示于是我去看了一下他是那个JS段中打印出来的
97行Emmmm,好像和百度文库没有什么关系,地址好像是我浏览器的插件,然后我将这个插件装入了其他浏览器,发现会报错,应该是兼容问题,之前也想过获取鼠标选中的文字,一直也没有找到代码意思明确的文章,于是趁此时机,学习一波。
首先分析一下划词取词的过程
- 用户左击鼠标 → 鼠标按下事件
onmousedown
- 鼠标滑过文字 → 文字本身样式改变
- 转中后抬起鼠标左键 → 鼠标抬起事件
onmouseup
,同时返回那些文字有变化
那么首先进行简单的代码主体:
document.onmousedown = function(event) {//监听当前页面鼠标按下事件
var event = event || window.event;//此处考虑兼容问题
if (event.button == "0" || event.button == "1") {//判断按下的按键(0)
document.onmouseup = function(event) {//监听页面中鼠标抬起事件
var txt = "";
if(window.getSelection){//兼容性判断,各浏览器获取有变化处的文字函数不同
txt = window.getSelection();//谷歌等内核浏览器获取方式
}else{
txt = document.selection.createRange().text;//IE普通内核
}
console.log(txt);//控制台打印浏览
}
}
}
可以在页面中添加P标签随便写一些文字,或者放入任意网页console控制台均可,然后鼠标随便选中文字,观察控制台会出现如下内容
恭喜你成功第一步了,那出现了这个当初说好的文字呢???OK其实这个就是文字只是它以一种不同的方式展现了出来,那我们如何得到呢
txt = txt+"";
将变量txt经过这步处理会变为字符串的形式了,这个时候就可以在控制台看到你所选中的文字了,你以为这就完了???不完善一下舒服嘛???冲鸭!!!
继续分析,如果用户点一个按钮,或者选中的是空格怎么办
txt = txt.replace(/^\s+|\s+$/g, "");
if (txt != "") {
console.log(txt);
}
OK,首先一个正则判断,将两端空格去除(带着前面一堆空格获取到的字符串很带劲,试试?滑稽.jpg),之后判断如果为空就不获取,普绕飞科特
划词部分到此结束
接下来需要在选中文字后追加一个div方便用户复制百度文库文字,那么我们可以将其封成一个方法,只要将上面那一步获取到的字符串传入即可
function creatDiv(str) {
var arr = mousePosition();//这是个获取鼠标当前位置的一个方法
var newDiv = document.createElement('div'); //创建一个div元素;
var newContent = document.createTextNode(str);//创建文本内容
newDiv.appendChild(newContent);//将内容放入新创建的div
newDiv.id = "bblock";//添加一个ID方便之后的操作
//可以用下操作设置自己想要的CSS属性
newDiv.style.width = "200px";//设置div宽(视自己需求而定)
newDiv.style.background = "red";//设置背景颜色
newDiv.style.zIndex = "1000";//设置层级保证在最上方
newDiv.style.position = "absolute";//给div添加绝对定位*必有
//此处要加px否则不生效,+20原因 根据自己需要调整
newDiv.style.left = arr[0] + 20 + "px";//距左侧距离
newDiv.style.top = arr[1] + 0 + "px";//具右侧距离
var bo = document.body; //获取body对象.
bo.insertBefore(newDiv, bo.lastChild); //动态插入到body中
}
function mousePosition(evt) { //当前鼠标位于页面位置
evt = evt || window.event;//兼容性判断,满足一个即可有值
//兼容写法,获取当前鼠标横坐标
var xPos = evt.pageX || evt.clientX || evt.offsetX || evt.x;
//兼容写法,获取当前鼠标纵坐标
var yPos = evt.pageY || evt.clientY || evt.offsetY || evt.y;
return [xPos, yPos];//返回数组为当前鼠标横纵坐标
}
你以为这就完了,OK 调BUG阶段
分析:
- 用户每次划词后都要生成一个新的,那么旧的怎么关闭?
- 如果用户在生成的div中进行划词操作,是否也要生成新的div?
- 如果才能判断什么情况下要进行销毁旧的div呢?
解决:
- 最好的关闭体验为:单击其他不是新追加的div区域进行关闭
- 否,新div的目的就是让用户可以在这里进行选中复制的,要加判断
- 根据第一条,得到销毁条件
由此可以得到我们还需要两个判断(判断div关闭,判断div中划词),和一个方法(鼠标是否离开div)
设置两个全局变量
var workType = false; //用户当前是否进行了划词
var workTool = false; //用户划词后是否正在取词
根据之前给的ID监听鼠标是否离开窗口,如果在则设置workTool为ture
function bingDiv() {
document.getElementById("bblock").onmouseover = function() {
workTool = true;
}//鼠标移入事件
document.getElementById("bblock").onmouseout = function() {
workTool = false;
}//鼠标移除事件
}
在划词开始添加判断
if (workTool) { //如果用户在取词则不进行二次划词操作
return 0;
}
//如果div存在且不是在取词操作 根据ID销毁该div
if (document.getElementById("bblock") && !workTool) {
document.body.removeChild(document.getElementById("bblock"));
}
//如果在不是取词操作代码会执行到这里,那么将划词工作状态设为true
workType = true;
添加判断只有在划词操作下,鼠标抬起才会进行获取文字,追加div的操作,而此时鼠标抬起后,划词工作状态结束
document.onmouseup = function(event) {
if (workType) {//是划词状态才进行如下操作
workType = false;//划词状态结束
var txt = "";
if(window.getSelection){
txt = window.getSelection();
}else{
txt = document.selection.createRange().text;
}
txt = txt + "";
txt = txt.replace(/^\s+|\s+$/g, "");
if (txt != "") {
creatDiv(txt);//传入生成div的函数
}
}
}
这里有一个坑,为什么要把判断鼠标是否在新追加的div中封成一个方法呢?
这个大多数新手会遇到的问题,因为网页是动态渲染的,如果你直接写到划词的方法中进行判断,js是获取不到这个节点的,所以需要在每次创建节点后再去判断,防止获取不到
function creatDiv(str) {
var arr = mousePosition();
·
·
·
bo.insertBefore(newDiv, bo.lastChild); //动态插入到body中
bingDiv();//追加完毕后进行判断
}
到这里效果就完全实现了
以下为全部完整代码(可直接打开需要的百度文库,粘贴到console控制台即可使用):
let workType = false; //当前划词状态
let workTool = false; //当前取词状态
document.onmousedown = function(event) {
var event = event || window.event;
if ((event.button == "0" || event.button == "1") && !workTool) {
if (workTool) { //如果用户在取词则不进行二次划词操作
return 0;
}
if (document.getElementById("bblock") && !workTool) {
document.body.removeChild(document.getElementById("bblock"));
}
workType = true;
document.onmouseup = function(event) {
if (workType) {
workType = false;
var txt = window.getSelection ? window.getSelection() : document.selection.createRange().text;
txt = txt + "";
txt = txt.replace(/^\s+|\s+$/g, "");
if (txt != "") {
creatDiv(txt);
}
}
}
}
}
function mousePosition(evt) { //当前鼠标位于页面位置
evt = evt || window.event;
var xPos = evt.pageX || evt.clientX || evt.offsetX || evt.x;
var yPos = evt.pageY || evt.clientY || evt.offsetY || evt.y;
return [xPos, yPos];
}
function creatDiv(str) {
var arr = mousePosition();
var newDiv = document.createElement('div'); //创建一个div元素;
var newContent = document.createTextNode(str);
newDiv.appendChild(newContent);
newDiv.id = "bblock";
newDiv.style.width = "200px";
newDiv.style.background = "red";
newDiv.style.position = "absolute";
newDiv.style.left = arr[0] + 20 + "px";
newDiv.style.top = arr[1]+ 0 + "px";
newDiv.style.zIndex = "1000";
var bo = document.body; //获取body对象
bo.insertBefore(newDiv, bo.lastChild); //动态插入到body中
bingDiv();
}
function bingDiv() {
document.getElementById("bblock").onmouseover = function() {
workTool = true;
}
document.getElementById("bblock").onmouseout = function() {
workTool = false;
}
}
效果:
取词区域的样式可以根据自己需求更改,我就懒一下啦~~~