Event Merge for Google Calendar™ (by @imightbeAmy)

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

当前为 2016-05-27 提交的版本,查看 最新版本

  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. // @require https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
  9. // @version 1
  10. // @grant none
  11. // @description Script that visually merges the same event on multiple Google Calendars into one event.
  12. // ==/UserScript==
  13.  
  14. 'use strict';
  15.  
  16. function EventMerger(key_function, clean_up_function) {
  17. this.makeKey = key_function;
  18. this.cleanUp = clean_up_function;
  19. }
  20.  
  21. EventMerger.prototype = {
  22. getEventSets: function ($events) {
  23. var event_sets = {},
  24. makeKey = this.makeKey;
  25. $events.each(function () {
  26. var $event = $(this),
  27. key = makeKey($event).replace(/\s/g, '');
  28. event_sets[key] = event_sets[key] || [];
  29. event_sets[key].push($event);
  30. });
  31. return event_sets;
  32. },
  33. makeAltTextColors: function ($element, colors) {
  34. $element.prepend(" ");
  35. $.each(colors.reverse(), function (i, color) {
  36. $element.prepend($("<span>")
  37. .css({
  38. 'background-color': color,
  39. 'width': '4px',
  40. 'height': '12px',
  41. 'display': 'inline-block'
  42. }));
  43. });
  44. },
  45. makeStripes: function ($element, colors) {
  46. var gradient = "repeating-linear-gradient( 45deg,",
  47. pos = 0;
  48. $.each(colors, function (i, color) {
  49. gradient += color + " " + pos + "px,";
  50. pos += 10;
  51. gradient += color + " " + pos + "px,";
  52. });
  53. gradient = gradient.slice(0, -1);
  54. gradient += ")";
  55. $element.css('background-image', gradient);
  56. },
  57. mergeEvents: function (name, event_set) {
  58. if (event_set.length > 1) {
  59.  
  60. var background = $(event_set[0]).css('background-color');
  61. // If the background is transparent, use the text color
  62. var style_type = background.indexOf("rgba") == -1 ?
  63. 'background-color' : 'color';
  64.  
  65. var colors = $.map(event_set, function (event) {
  66. return $(event).css(style_type);
  67. });
  68.  
  69. var keep = event_set.shift();
  70. $(event_set).each(function () {
  71. $(this).parent().css('visibility', 'hidden');
  72. });
  73.  
  74. if (style_type == 'background-color') {
  75. this.makeStripes(keep, colors);
  76. } else {
  77. this.makeAltTextColors(keep, colors);
  78. }
  79. this.cleanUp && this.cleanUp(keep);
  80. }
  81. },
  82. mergeSets: function ($events) {
  83. var sets = this.getEventSets($events);
  84. $.each(sets, $.proxy(this.mergeEvents, this));
  85. }
  86. };
  87.  
  88. /*****************************************************************************/
  89.  
  90. function cleanEventTitle(event_title) {
  91. return event_title.trim()
  92. .replace(/\(.*\)$/, '') // Remove parentheticals at end for 1:1 lab
  93. .replace(/\W/g, ''); // Remove non-ascii chars
  94. }
  95.  
  96. function weekTimedEventKey($event) {
  97. var event_name = cleanEventTitle($event.find('dd span').text()),
  98. event_time = $event.find('dt').text(),
  99. col = $event.parents('.tg-col-eventwrapper').attr('id');
  100. return event_name + event_time + col;
  101. }
  102.  
  103. function tableEventKey($event) {
  104. var event_name = cleanEventTitle($event.text()),
  105. $td = $event.parents('td'),
  106. days = $td.attr("colspan") || 1,
  107. col = $td.position().left;
  108. return event_name + ":" + col + ":" + days;
  109. }
  110.  
  111. function monthAllDayEventKey($event) {
  112. var row = $event.parents('.month-row').index();
  113. return tableEventKey($event) + ":" + row;
  114. }
  115.  
  116. function monthTimedEventKey($event) {
  117. var time = $event.find('.te-t').text();
  118. return monthAllDayEventKey($event) + time;
  119. }
  120.  
  121. function cleanUp($event) {
  122. var chip = $event.parents('.chip');
  123. if (chip[0]) {
  124. var left = Number(chip[0].style.left.replace(/%/g, ''));
  125. chip.css('width', 100 - (isNaN(left) ? 0 : left) + "%");
  126. }
  127. }
  128.  
  129. var weekTimed = new EventMerger(weekTimedEventKey, cleanUp),
  130. weekAllDay = new EventMerger(tableEventKey),
  131. monthTimed = new EventMerger(monthTimedEventKey),
  132. monthAllDay = new EventMerger(monthAllDayEventKey);
  133.  
  134. var merging_main = false;
  135. $(document).on("DOMNodeInserted", "#gridcontainer", function () {
  136. if (!merging_main) {
  137. merging_main = true;
  138. var grid_container = $(this);
  139. weekTimed.mergeSets(grid_container.find('dl'));
  140. weekAllDay.mergeSets(grid_container.find(".wk-weektop .rb-n"));
  141. monthTimed.mergeSets(grid_container.find(".te"));
  142. monthAllDay.mergeSets(grid_container.find(".mv-event-container .rb-n"));
  143. merging_main = false;
  144. }
  145. });
  146.  
  147. var merging_find_time = false;
  148. $(document).on("DOMNodeInserted", "#scTgTable", function (e) {
  149. if (!merging_find_time) {
  150. merging_find_time = true;
  151. var find_time_container = $(this);
  152. weekTimed.mergeSets(find_time_container.find('dl'));
  153. weekAllDay.mergeSets(find_time_container.find(".rb-n"));
  154. merging_find_time = false;
  155. }
  156. });