快速用JavaScript實現劃詞取詞,可複製百度文庫文字(獲取滑鼠選中區域文字)
完整程式碼可在最後程式碼塊檢視呦!!!
※本貼程式碼,可用用於油猴指令碼,支援瀏覽器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 調GUG階段
分析:
- 使用者每次劃詞後都要生成一個新的,那麼舊的怎麼關閉?
- 如果使用者在生成的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;
}
}
效果:
取詞區域的樣式可以根據自己需求更改,我就懶一下啦~~~