1+ "use strict" ;
12// ==UserScript==
23// @name Auto import ID number
34// @namespace http://tampermonkey.net/
4- // @version 0 .1
5+ // @version 1 .1
56// @description when opening PDF auto import ID number.
67// @author Adokun
78// @match https://mail.google.com/*
89// @grant none
910// ==/UserScript==
1011
12+ // 將IDNumber改成自己的身分證
13+ const IDNumber = "A1234567890" ;
1114
12- ( function ( ) {
13- // 將IDNumber改成自己的身分證
14- const IDNumber = 'A1234567890' ;
15-
16- document . addEventListener ( 'DOMSubtreeModified' , ( event ) => {
17- if ( event . target . getAttribute ( 'role' ) === 'dialog' && event . target . classList . contains ( 'aLF-aPX-axU' ) ) {
18- setTimeout ( ( ) => {
19- let J = JSON . parse ( document . querySelector ( '#drive-active-item-info' ) . innerText ) ;
20- if ( / \. p d f $ / i. test ( J . title ) ) {
21- let inputEl = event . target . querySelector ( '[type="password"]' ) ;
22-
23- inputEl . value = IDNumber ;
24- inputEl . dispatchEvent ( new Event ( 'change' ) ) ;
15+ function handlePasswordDialog ( dialogElement ) {
16+ observer . disconnect ( ) ;
17+ setTimeout ( ( ) => {
18+ try {
19+ const driveInfoElement = document . querySelector ( '#drive-active-item-info' ) ;
20+ if ( ! driveInfoElement ) {
21+ console . warn ( "警告:未找到元素 #drive-active-item-info。" ) ;
22+ return ;
23+ }
24+ const fileInfo = JSON . parse ( driveInfoElement . innerText ) ;
25+ if ( fileInfo && typeof fileInfo . title === 'string' && / \. p d f $ / i. test ( fileInfo . title ) ) {
26+ const passwordInput = dialogElement . querySelector ( '[type="password"]' ) ;
27+ if ( passwordInput ) {
28+ // console.log(`偵測到 PDF 檔案:${fileInfo.title}。正在嘗試自動填入密碼。`);
29+ passwordInput . value = IDNumber ; // 填入密碼。
30+ passwordInput . dispatchEvent ( new Event ( 'change' ) ) ; // 觸發 'change' 事件,模擬使用者輸入。
31+ // console.log("密碼欄位已成功填入並觸發 change 事件。");
2532 }
26- } , 1000 ) ;
27-
28- let submitEl = event . target . querySelector ( '[role="button"]' ) ;
29-
30- // submitEl.addEventListener('click',function () {
31- // }, false);
32-
33- setTimeout ( ( ) => {
34- // submitEl.dispatchEvent(new Event('click'));
35- submitEl . click ( ) ;
36- } , 3000 ) ;
33+ else {
34+ console . warn ( "警告:在 PDF 密碼對話框中未找到密碼輸入元素。" ) ;
35+ }
36+ }
3737 }
38- } ) ;
39- } ) ( ) ;
40-
41- /**
42- * @description 在 inputEl 觸發 keydown event (key = 'Enter'),會因為isTrusted = false失敗
43- */
44- // inputEl.addEventListener('change', function (bb) {
45- // console.log(bb);
46- // setTimeout(() => {
47- // var e = new Event("keydown");
48- // // e.key = "Enter";
49- // // e.code = "Enter";
50- // // e.which = 13;
51- // // e.keyCode = 13;
52- // // e.bubbles = true;
53- // // e.cancelBubble = true;
54- // // e.cancelable = true;
55- // // e.composed = true;
56- // // e.location = 3;
57- // /**
58- // * The isTrusted read-only property of the Event interface is a boolean that is true when the event was generated by a user action,
59- // * and false when the event was created or modified by a script or dispatched via dispatchEvent.
60- // */
61- // // e.isTrusted = true;
62- // inputEl.dispatchEvent(e);
63- // }, 1000);
64- // }, false);
65-
66-
67- /**
68- * @description submitEl(送出的按鈕) 是使用<div role="button"> 但沒有click event或其他event 送出密碼
69- */
70-
71- // setTimeout(() => {
72- // let submitEl = ev.target.querySelector('.aLF-aPX-a1E-JD-Zc');
73- // // submitEl.addEventListener('click', function (e) {
74- // // console.log(e);
75- // // }, false);
76-
77- // // submitEl.dispatchEvent('click');
78-
79- // for (var key in submitEl) {
80- // if (key.search('on') === 0) {
81- // submitEl.addEventListener(key.slice(2), function (e) {
82- // console.log(e);
83- // }, false)
84- // }
85- // }
86- // //console.log(submitEl);
87- // }, 3000);
38+ catch ( error ) {
39+ console . error ( "錯誤:處理 PDF 密碼對話框時發生問題。" , error ) ;
40+ }
41+ finally {
42+ // 無論是否發生錯誤,都重新連接觀察器,繼續監聽 DOM 變化。
43+ observer . observe ( document . body , { childList : true , subtree : true , attributes : true } ) ;
44+ }
45+ } , 1500 ) ;
46+ }
47+ // 創建一個 MutationObserver 實例來監聽 DOM 樹的變化。
48+ // MutationObserver 比 DOMSubtreeModified 更加高效和推薦。
49+ const observer = new MutationObserver ( ( mutationsList ) => {
50+ for ( const mutation of mutationsList ) {
51+ if ( mutation . type === 'childList' || mutation . type === 'attributes' ) {
52+ // 檢查被修改的目標元素本身是否為對話框。
53+ const targetElement = mutation . target instanceof Element ? mutation . target : null ;
54+ if ( targetElement && targetElement . getAttribute ( 'role' ) === 'dialog' && targetElement . classList . contains ( 'aLF-aPX-axU' ) ) {
55+ handlePasswordDialog ( targetElement ) ;
56+ return ;
57+ }
58+ // 檢查所有新加入的節點,看是否有符合條件的對話框。
59+ mutation . addedNodes . forEach ( node => {
60+ if ( node instanceof Element && node . getAttribute ( 'role' ) === 'dialog' && node . classList . contains ( 'aLF-aPX-axU' ) ) {
61+ handlePasswordDialog ( node ) ;
62+ return ;
63+ }
64+ } ) ;
65+ }
66+ }
67+ } ) ;
68+ // 開始觀察整個 document body,監聽其子節點、所有後代子樹以及屬性的變化。
69+ observer . observe ( document . body , { childList : true , subtree : true , attributes : true } ) ;
0 commit comments