您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
try to take over the world
- // ==UserScript==
- // @name Keka Log Duration by Jp
- // @namespace http://tampermonkey.net/
- // @version 1.7
- // @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';
- function calculateTotalDuration(durationsArray) {
- let totalHours = 0;
- let totalMinutes = 0;
- durationsArray.forEach(durationStr => {
- if (durationStr) {
- 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 });
- // 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 durations = [];
- let N = 1;
- let lastDurationDisplaySpan = null;
- while (true) {
- // Construct XPath expressions
- const startTimeSpanXPath = `/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[${N}]/div[1]/div[2]/span[2]`;
- const endTimeSpanXPath = `/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[${N}]/div[1]/div[3]/span[2]`;
- // Fetch elements
- const startTimeSpan = document.evaluate(startTimeSpanXPath, modal, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
- const endTimeSpan = document.evaluate(endTimeSpanXPath, modal, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
- if (!startTimeSpan || !endTimeSpan) {
- // No more durations
- break;
- }
- // Calculate duration
- const durationStr = calculateDuration(startTimeSpan, endTimeSpan);
- // Store durationStr
- durations.push(durationStr);
- // Create or update the duration display span
- 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(${N}) > div.d-flex.align-items-center.ng-untouched.ng-pristine.ng-valid > div.d-flex.align-items-center.ml-10`);
- if (durationDisplaySpan) {
- // Check if duration span already exists
- let existingDurationSpan = durationDisplaySpan.querySelector(`.duration-span-${N}`);
- if (!existingDurationSpan) {
- // Create duration span
- existingDurationSpan = document.createElement('span');
- existingDurationSpan.classList.add(`duration-span-${N}`);
- existingDurationSpan.style.fontWeight = 'bold';
- existingDurationSpan.style.paddingLeft = '17px';
- existingDurationSpan.style.color = 'darkred';
- durationDisplaySpan.insertAdjacentElement('afterend', existingDurationSpan);
- }
- existingDurationSpan.textContent = durationStr;
- // Keep track of the last valid durationDisplaySpan
- lastDurationDisplaySpan = durationDisplaySpan;
- } else {
- console.warn(`durationDisplaySpan not found for N = ${N}`);
- }
- N++;
- }
- // Decrement N to point to the last valid index
- N--;
- // Only display total duration if more than one duration exists
- if (durations.length > 1 && lastDurationDisplaySpan) {
- const totalDurationStr = calculateTotalDuration(durations);
- // Display total duration
- const totalDurationDisplaySpanSelector = `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(${N + 1}) > div.d-flex.align-items-center.ng-untouched.ng-pristine.ng-valid`;
- let totalDurationDisplaySpan = document.querySelector(totalDurationDisplaySpanSelector);
- // If the element doesn't exist, create it
- if (!totalDurationDisplaySpan) {
- totalDurationDisplaySpan = document.createElement('div');
- totalDurationDisplaySpan.classList.add('d-flex', 'align-items-center', 'ng-untouched', 'ng-pristine', 'ng-valid');
- const parentElementSelector = `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`;
- const parentElement = document.querySelector(parentElementSelector);
- if (parentElement) {
- parentElement.appendChild(totalDurationDisplaySpan);
- } else {
- console.warn('Parent element for total duration not found.');
- }
- }
- // Check for existing total duration span:
- let existingTotalDurationSpan = totalDurationDisplaySpan.querySelector('.total-duration-span');
- if (!existingTotalDurationSpan) {
- existingTotalDurationSpan = document.createElement('span');
- existingTotalDurationSpan.classList.add('total-duration-span');
- existingTotalDurationSpan.style.fontWeight = 'bold';
- existingTotalDurationSpan.style.color = '#0600ff';
- existingTotalDurationSpan.style.float = 'right';
- existingTotalDurationSpan.style.padding = '5px';
- existingTotalDurationSpan.style.marginLeft = '375px'; // Adjusted as per your script
- existingTotalDurationSpan.style.background = 'lightblue';
- existingTotalDurationSpan.style.borderRadius = '5px';
- existingTotalDurationSpan.style.borderTop = '3px solid #888';
- totalDurationDisplaySpan.appendChild(existingTotalDurationSpan);
- }
- existingTotalDurationSpan.textContent = totalDurationStr;
- } else {
- console.warn('No durations found or only one duration present. Total duration will not be displayed.');
- }
- // Add morphing text effect
- addMorphingTextEffect();
- });
- }
- function addMorphingTextEffect() {
- const parentDivs = document.querySelectorAll('div.mb-30.ng-untouched.ng-pristine.ng-valid');
- if (parentDivs.length > 1) {
- // Targeting the second div as per your requirement
- const targetDiv = parentDivs[1];
- const pElement = targetDiv.querySelector('p.text-large'); // Assuming the span is the one you've added
- if (!pElement) {
- console.warn('p.text-large element not found.');
- return;
- }
- let spanElement = pElement.querySelector('.morphing-text-span');
- if (!spanElement) {
- spanElement = document.createElement('span');
- spanElement.classList.add('morphing-text-span');
- // 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';
- pElement.appendChild(spanElement);
- }
- // 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
- }
- // Initialize the text content
- spanElement.textContent = texts[textIndex % texts.length];
- textIndex++;
- // Start the interval for morphing text
- setInterval(updateText, 2000);
- }
- }
- 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 });
- })();