您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
try to take over the world
当前为
// ==UserScript== // @name Keka Log Duration by Jp // @namespace http://tampermonkey.net/ // @version 1.4 // @description try to take over the world // @author You // @match https://ezeetechnosys.keka.com/ // @icon https://www.google.com/s2/favicons?sz=64&domain=keka.com // @grant none // @license MIT // ==/UserScript== (function () { 'use strict'; const channel = new BroadcastChannel('keka-duration'); let fistDuration; let secondDuration; let thirdDuration; let fourthDuration; let fifthDuration; function parseTime(timeStr) { const parts = timeStr.split(':'); return parseInt(parts[0]) * 3600000 + parseInt(parts[1]) * 60000 + parseInt(parts[2]) * 1000; } let lastLogIndex=0; function calculateTotalDuration(duration1Str, duration2Str, duration3Str, duration4Str, duration5Str) { // Initialize total hours and minutes let totalHours = 0; let totalMinutes = 0; // Array of all duration strings const durations = [duration1Str, duration2Str, duration3Str, duration4Str, duration5Str]; // Loop through each duration string durations.forEach(durationStr => { if (durationStr) { // Check if the duration string is not empty const [hours, minutes] = durationStr.match(/\d+/g).map(Number); totalHours += hours; totalMinutes += minutes; } }); // Add overflow from minutes to hours totalHours += Math.floor(totalMinutes / 60); totalMinutes = totalMinutes % 60; // Format the total duration string const totalDurationStr = `${totalHours} Hr ${totalMinutes} Min`; return totalDurationStr; } function calculateDuration(startTimeSpan, endTimeSpan) { const startTimeStr = startTimeSpan.textContent.trim(); const endTimeStr = endTimeSpan.textContent.trim(); // If end time is empty, use current time const endTime = endTimeStr != "MISSING" ? endTimeStr : new Date().toLocaleTimeString('en-US', { hour12: true }); console.log("TIMES", startTimeStr, endTime); // Parse time strings into Date objects const startTime = new Date(`2023-12-27 ${startTimeStr}`); // Assuming today's date const endTimeDate = new Date(`2023-12-27 ${endTime}`); // Calculate duration in milliseconds const durationMillis = endTimeDate.getTime() - startTime.getTime(); // Convert milliseconds to hours and minutes const durationHours = Math.floor(durationMillis / (3600 * 1000)); const durationMinutes = Math.floor((durationMillis % (3600 * 1000)) / (60 * 1000)); // Formatted duration string const durationStr = `${durationHours} Hr ${durationMinutes} Min`; return durationStr; } function watchForModals() { const modals = document.querySelectorAll('body > modal-container > div.modal-dialog.small-modal > div > attendance-adjustment-request > div.modal-body > form > div.mt-20 > div > div:nth-child(2) > div'); console.log("Modals", modals) modals.forEach(modal => { const modalsArray = Array.from(modals); const dayIndex = modalsArray.indexOf(modal) + 1; // Determine the day index (1, 2, or 3) const displaySpanXPath = `/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div/div[1]/span[1]`; const displaySpan = document.evaluate( displaySpanXPath, modal, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null ).snapshotItem(0); const startTimeSpan = document.evaluate( '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[1]/div[1]/div[2]/span[2]', modal, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; const endTimeSpan = document.evaluate( '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[1]/div[1]/div[3]/span[2]', modal, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; const startTimeSpan1 = document.evaluate( '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[2]/div[1]/div[2]/span[2]', modal, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; const endTimeSpan1 = document.evaluate( '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[2]/div[1]/div[3]/span[2]', modal, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; const startTimeSpan2 = document.evaluate( '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[3]/div[1]/div[2]/span[2]', modal, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; const endTimeSpan2 = document.evaluate( '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[3]/div[1]/div[3]/span[2]', modal, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; const startTimeSpan3 = document.evaluate( '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[4]/div[1]/div[2]/span[2]', modal, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; const endTimeSpan3 = document.evaluate( '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[4]/div[1]/div[3]/span[2]', modal, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; const startTimeSpan4 = document.evaluate( '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[5]/div[1]/div[2]/span[2]', modal, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; const endTimeSpan4 = document.evaluate( '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[5]/div[1]/div[3]/span[2]', modal, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; if (startTimeSpan && endTimeSpan) { const durationStr = calculateDuration(startTimeSpan, endTimeSpan); fistDuration = durationStr const durationDisplaySpan = document.querySelector('.d-flex.align-items-center.ml-10'); window.postMessage({ type: 'duration', value: durationStr }, '*'); console.log("POSTED-DURATION") // Check for existing duration span: const existingDurationSpan = durationDisplaySpan.querySelector('.duration-span-1'); if (!existingDurationSpan) { // Create span only if it doesn't exist const durationSpan = document.createElement('span'); durationSpan.classList.add('duration-span-1'); // Add class for identification durationSpan.textContent = durationStr; durationSpan.style.fontWeight = 'bold'; durationSpan.style.paddingLeft = '17px'; durationSpan.style.color = 'darkred'; durationDisplaySpan.insertAdjacentElement('afterend', durationSpan); } else { console.log("Duration span already exists, skipping creation."); } var parentDivs = document.querySelectorAll('div.mb-30.ng-untouched.ng-pristine.ng-valid'); if (parentDivs.length > 1) { // Targeting the second div as per your requirement var targetDiv = parentDivs[1]; var pElement = targetDiv.querySelector('p.text-large'); // Assuming the span is the one you've added var spanElement = document.createElement('span'); // Texts array for the morphing effect const texts = ["Log Duration", " By @Jaydeep😶"]; let textIndex = 0; // Function to update the text with a morphing effect function updateText() { const nextText = texts[textIndex % texts.length]; textIndex++; // Applying a fade-out effect spanElement.style.opacity = '0'; spanElement.style.transition = 'opacity 0.5s ease-out'; // After fade-out, change the text and fade it back in setTimeout(() => { spanElement.textContent = nextText; // Applying blur during transition spanElement.style.filter = 'blur(2px)'; spanElement.style.opacity = '1'; spanElement.style.transition = 'opacity 0.5s ease-in, filter 0.5s ease'; // Removing blur after a moment setTimeout(() => { spanElement.style.filter = 'none'; }, 500); // Match the transition time }, 500); // Wait for the fade-out to complete } // Starting the text update process spanElement.style.fontWeight = 'bold'; spanElement.style.color = 'rgb(0, 123, 255)'; spanElement.style.padding = '5px'; spanElement.style.borderRadius = '5px'; spanElement.style.fontSize = '16px'; spanElement.style.marginLeft = '262px'; spanElement.textContent = texts[textIndex % texts.length]; textIndex++; pElement.appendChild(spanElement); setInterval(updateText, 2000); } } if (startTimeSpan1 && endTimeSpan1) { lastLogIndex = 1; console.log("11111111--11111", startTimeSpan1, endTimeSpan1) const durationStr = calculateDuration(startTimeSpan1, endTimeSpan1); secondDuration = durationStr; const durationDisplaySpan = document.querySelector('body > modal-container > div.modal-dialog.small-modal > div > attendance-adjustment-request > div.modal-body > form > div.mt-20 > div > div:nth-child(2) > div > div > div:nth-child(2) > div.d-flex.align-items-center.ng-untouched.ng-pristine.ng-valid > div.d-flex.align-items-center.ml-10'); console.log("durationDisplaySpan", durationDisplaySpan) // Check for existing duration span: const existingDurationSpan = durationDisplaySpan.querySelector('.duration-span-2'); if (!existingDurationSpan) { // Create span only if it doesn't exist const durationSpan = document.createElement('span'); durationSpan.classList.add('duration-span-2'); // Add class for identification durationSpan.textContent = durationStr; durationSpan.style.fontWeight = 'bold'; durationSpan.style.paddingLeft = '17px'; durationSpan.style.color = 'darkred'; durationDisplaySpan.insertAdjacentElement('afterend', durationSpan); } else { console.log("Duration span already exists, skipping creation."); } } if (startTimeSpan2 && endTimeSpan2) { lastLogIndex = 2; console.log("11111111--11111", startTimeSpan2, endTimeSpan2) const durationStr = calculateDuration(startTimeSpan2, endTimeSpan2); thirdDuration = durationStr; const durationDisplaySpan = document.querySelector('body > modal-container > div.modal-dialog.small-modal > div > attendance-adjustment-request > div.modal-body > form > div.mt-20 > div > div:nth-child(2) > div > div > div:nth-child(3) > div.d-flex.align-items-center.ng-untouched.ng-pristine.ng-valid > div.d-flex.align-items-center.ml-10'); console.log("durationDisplaySpan", durationDisplaySpan) // Check for existing duration span: const existingDurationSpan = durationDisplaySpan.querySelector('.duration-span-3'); if (!existingDurationSpan) { // Create span only if it doesn't exist const durationSpan = document.createElement('span'); durationSpan.classList.add('duration-span-3'); // Add class for identification durationSpan.textContent = durationStr; durationSpan.style.fontWeight = 'bold'; durationSpan.style.paddingLeft = '17px'; durationSpan.style.color = 'darkred'; durationDisplaySpan.insertAdjacentElement('afterend', durationSpan); } else { console.log("Duration span already exists, skipping creation."); } } if (startTimeSpan3 && endTimeSpan3) { lastLogIndex = 3; console.log("11111111--11111", startTimeSpan3, endTimeSpan3) const durationStr = calculateDuration(startTimeSpan3, endTimeSpan3); fourthDuration = durationStr; const durationDisplaySpan = document.querySelector('body > modal-container > div.modal-dialog.small-modal > div > attendance-adjustment-request > div.modal-body > form > div.mt-20 > div > div:nth-child(2) > div > div > div:nth-child(3) > div.d-flex.align-items-center.ng-untouched.ng-pristine.ng-valid > div.d-flex.align-items-center.ml-10'); console.log("durationDisplaySpan", durationDisplaySpan) // Check for existing duration span: const existingDurationSpan = durationDisplaySpan.querySelector('.duration-span-3'); if (!existingDurationSpan) { // Create span only if it doesn't exist const durationSpan = document.createElement('span'); durationSpan.classList.add('duration-span-3'); // Add class for identification durationSpan.textContent = durationStr; durationSpan.style.fontWeight = 'bold'; durationSpan.style.paddingLeft = '17px'; durationSpan.style.color = 'darkred'; durationDisplaySpan.insertAdjacentElement('afterend', durationSpan); } else { console.log("Duration span already exists, skipping creation."); } } if (startTimeSpan4 && endTimeSpan4) { lastLogIndex = 4; console.log("11111111--11111", startTimeSpan4, endTimeSpan4) const durationStr = calculateDuration(startTimeSpan4, endTimeSpan4); fifthDuration = durationStr; const durationDisplaySpan = document.querySelector('body > modal-container > div.modal-dialog.small-modal > div > attendance-adjustment-request > div.modal-body > form > div.mt-20 > div > div:nth-child(2) > div > div > div:nth-child(4) > div.d-flex.align-items-center.ng-untouched.ng-pristine.ng-valid > div.d-flex.align-items-center.ml-10'); console.log("durationDisplaySpan", durationDisplaySpan) // Check for existing duration span: const existingDurationSpan = durationDisplaySpan.querySelector('.duration-span-4'); if (!existingDurationSpan) { // Create span only if it doesn't exist const durationSpan = document.createElement('span'); durationSpan.classList.add('duration-span-4'); // Add class for identification durationSpan.textContent = durationStr; durationSpan.style.fontWeight = 'bold'; durationSpan.style.paddingLeft = '17px'; durationSpan.style.color = 'darkred'; durationDisplaySpan.insertAdjacentElement('afterend', durationSpan); } else { console.log("Duration span already exists, skipping creation."); } } if(lastLogIndex) { const totaldurationDisplaySpan = document.querySelector(`body > modal-container > div.modal-dialog.small-modal > div > attendance-adjustment-request > div.modal-body > form > div.mt-20 > div > div:nth-child(2) > div > div > div:nth-child(${lastLogIndex+1}) > div.d-flex.align-items-center.ng-untouched.ng-pristine.ng-valid`); console.log(fistDuration, secondDuration,"3",thirdDuration,'4',fourthDuration,'5',fifthDuration, "#################111") const total = calculateTotalDuration( fistDuration, startTimeSpan1 ? secondDuration : 0, startTimeSpan2 ? thirdDuration : 0, startTimeSpan3 ? fourthDuration : 0, startTimeSpan4 ? fifthDuration : 0 ); console.log("total", total) // Check for existing total duration span: const existingTotalDurationSpan = totaldurationDisplaySpan.querySelector('.total-duration-span'); if (!existingTotalDurationSpan) { // Create span only if it doesn't exist const TotaldurationSpan = document.createElement('span'); // Added closing parenthesis TotaldurationSpan.classList.add('total-duration-span'); // Add class for identification TotaldurationSpan.textContent = total; TotaldurationSpan.style.fontWeight = 'bold'; // TotaldurationSpan.style.paddingLeft = '17px'; TotaldurationSpan.style.color = '#0600ff'; TotaldurationSpan.style.float = 'right'; TotaldurationSpan.style.padding = '5px'; TotaldurationSpan.style.background = 'lightblue'; TotaldurationSpan.style.marginRight = '150px'; TotaldurationSpan.style.borderRadius = '5px'; TotaldurationSpan.style.borderTop = '3px solid #888' totaldurationDisplaySpan.insertAdjacentElement('afterend', TotaldurationSpan); } } }) }; const observer = new MutationObserver(mutations => { console.log("Observing.....") const modalTriggerElements = document.querySelectorAll('employee-attendance-list-view .attendance-logs-row'); modalTriggerElements.forEach(element => { element.addEventListener('click', watchForModals); }); }); observer.observe(document.body, { childList: true, subtree: false }); })(); // Closed parenthesis for the immediately invoked function expression