Event Merge for Google Calendar™ (by @imightbeAmy)

Script that visually merges the same event on multiple Google Calendars into one event.

当前为 2018-02-17 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Event Merge for Google Calendar™ (by @imightbeAmy)
  3. // @namespace gcal-multical-event-merge
  4. // @include https://www.google.com/calendar/*
  5. // @include http://www.google.com/calendar/*
  6. // @include https://calendar.google.com/*
  7. // @include http://calendar.google.com/*
  8. // @version 1
  9. // @grant none
  10. // @description Script that visually merges the same event on multiple Google Calendars into one event.
  11. // ==/UserScript==
  12.  
  13. 'use strict';
  14.  
  15. console.log("event merge");
  16.  
  17. const stripesGradient = (colors) => {
  18. let gradient = "repeating-linear-gradient( 45deg,";
  19. let pos = 0;
  20.  
  21. colors.forEach(color => {
  22. gradient += color + " " + pos + "px,";
  23. pos += 10;
  24. gradient += color + " " + pos + "px,";
  25. });
  26. gradient = gradient.slice(0, -1);
  27. gradient += ")";
  28. return gradient;
  29. };
  30.  
  31. const dragType = e => parseInt(e.dataset.dragsourceType);
  32. const parsePixels = px => parseInt(px.replace('px', ''));
  33.  
  34. const merge = (mainCalender) => {
  35. const eventSets = {};
  36. const days = mainCalender.querySelectorAll("[role=\"gridcell\"]");
  37. days.forEach((day, index) => {
  38. const events = Array.from(day.querySelectorAll("[role=\"button\"]"));
  39. events.forEach(event => {
  40. let eventKey = event.querySelector('[aria-hidden="true"]').textContent.replace(/\\s+/g,"");
  41. eventKey = index + eventKey;
  42. eventSets[eventKey] = eventSets[eventKey] || [];
  43. eventSets[eventKey].push(event);
  44. });
  45. });
  46.  
  47. Object.values(eventSets)
  48. .forEach(events => {
  49. if (events.length > 1) {
  50. const colors = events.map(event => event.style.backgroundColor || event.style.borderColor);
  51. const gradient = stripesGradient(colors);
  52.  
  53. events.sort((e1, e2) => dragType(e1) - dragType(e2));
  54. const styles = events.map(window.getComputedStyle);
  55. const eventToKeep = events.shift();
  56. eventToKeep.style.backgroundImage = gradient;
  57. eventToKeep.style.left = Math.min.apply(Math, styles.map(s => parsePixels(s.left))) + 'px';
  58. eventToKeep.style.right = Math.min.apply(Math, styles.map(s => parsePixels(s.right))) + 'px';
  59. eventToKeep.style.visibility = "visible";
  60. eventToKeep.style.width = null;
  61. eventToKeep.style.border = "solid 1px #FFF"
  62.  
  63. events.forEach(event => {
  64. event.style.visibility = "hidden";
  65. });
  66. } else {
  67. events.forEach(event => {
  68. event.style.visibility = "visible";
  69. });
  70. }
  71. });
  72. }
  73.  
  74. const init = (mutationsList) => {
  75. const main = mutationsList && mutationsList
  76. .map(mutation => mutation.addedNodes[0] || mutation.target)
  77. .filter(node => node.matches && node.matches("[role=\"main\"]"))[0];
  78.  
  79. if (main) {
  80. merge(main);
  81. new MutationObserver(() => merge(main))
  82. .observe(main, { childList: true, subtree: true, attributes: true });
  83. }
  84. }
  85.  
  86. chrome.runtime.sendMessage({}, response => {
  87. if (response.enabled) {
  88. const observer = new MutationObserver(init);
  89. observer.observe(document.querySelector('body'), { childList: true, subtree: true, attributes: true });
  90. }
  91. });

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址