[Deprecated] Advanced Mention Name Reminder

Shows the title of each advanced mention’s target entity in Summernote, next to the entity ID (or in a tooltip on hover).

  1. // ==UserScript==
  2. // @name [Deprecated] Advanced Mention Name Reminder
  3. // @namespace http://tampermonkey.net/
  4. // @license MIT
  5. // @version 1.1
  6. // @description Shows the title of each advanced mention’s target entity in Summernote, next to the entity ID (or in a tooltip on hover).
  7. // @author Salvatos
  8. // @match https://kanka.io/*
  9. // @icon https://www.google.com/s2/favicons?domain=kanka.io
  10. // @grant GM_xmlhttpRequest
  11. // @grant GM_addStyle
  12. // @connect kanka.io
  13. // ==/UserScript==
  14.  
  15. // Get campaign ID from URL
  16. var campaignID = window.location.href.match(/campaign\/(\d+)/);
  17. campaignID = campaignID[1].split("/")[0];
  18.  
  19. function addMentionName (thisEditor, entityId) {
  20. var apiURL = `https://kanka.io/en/campaign/${campaignID}/entities/${entityId}/json-export`;
  21.  
  22. var xhr = new XMLHttpRequest();
  23. xhr.open("GET", apiURL, true);
  24. xhr.responseType = 'json';
  25. xhr.onload = function (e) {
  26. if (xhr.readyState === 4) {
  27. if (xhr.status === 200) {
  28. //console.log(xhr.response);
  29. // Set dfn title to entity name for all mentions to this ID
  30. thisEditor.find( "dfn[entity-id='" + entityId + "']" ).attr("title", xhr.response.data.name);
  31. } else {
  32. console.error(entityId + " returned an error: " + xhr.statusText);
  33. thisEditor.find( "dfn[entity-id='" + entityId + "']" ).attr("title", "Unknown");
  34. }
  35. }
  36. };
  37. xhr.onerror = function (e) {
  38. console.error(xhr.statusText);
  39. };
  40. xhr.send(null);
  41. }
  42.  
  43. // Wait for Summernote to initialize
  44. $('.html-editor').on('summernote.init', function() {
  45. // optimization (use $this in subsequent selectors so it doesn’t search the whole DOM multiple times, but don’t create a new $(object) every time)
  46. let $thisEditor = $( this ).siblings(".note-editor").find(".note-editable");
  47. // Track IDs so we only process each once
  48. let entityIDs = [];
  49.  
  50. // Wrap the entity part of mentions in <dfn>s and replace editor content
  51. $thisEditor.html( $thisEditor.html().replaceAll(/\[(\w+:)(\d+)(.*?)\]/g, "[<dfn entity-id='$2'>$1$2</dfn>$3]") );
  52.  
  53. // Fetch the name of each dfn’s entity id
  54. $thisEditor.find( "dfn" ).each(function() {
  55. let entityId = $( this ).attr("entity-id");
  56.  
  57. // If we haven’t seen this ID yet, add its title to all relevant mentions, and mark it done
  58. if ($.inArray(entityId, entityIDs) == -1) {
  59. addMentionName($thisEditor, entityId);
  60. entityIDs.push(entityId);
  61. }
  62. }, $thisEditor, entityIDs); // (pass $thisEditor along so the function doesn’t look for the editor in the DOM every time it’s called)
  63. });
  64.  
  65. GM_addStyle ( `
  66. .note-editable dfn {
  67. font-style: normal;
  68. }
  69. .note-editable dfn::after {
  70. content: " ("attr(title)") ";
  71. vertical-align: super;
  72. font-size: 11px;
  73. }
  74. /* Uncomment this to show only a tooltip, and no superscript
  75. .note-editable dfn {
  76. text-decoration: underline dotted;
  77. }
  78. .note-editable dfn::after {
  79. content: "";
  80. }
  81. */
  82. ` );